Line data Source code
1 : //
2 : // This is the most commonly used standard boundary condition implementation.
3 : // The name "Constant" refers to the invariance of the BC value or character along each face
4 : // of the simulation domain; however, you may cause a change in the value with time by using a
5 : // :ref:`Numeric::Interpolator::Linear` string.
6 : //
7 : // The BC on each face is specified with a :code:`type` string that specifies the nature of
8 : // the BC, and a :code:`val` that specifies the value.
9 : // By default, all types are Dirichlet and all values are 0.0.
10 : // The complete list of BC types are below:
11 : //
12 : // .. table::
13 : // :widths: 30 70
14 : //
15 : // +--------------------------+-----------------------------------------------------------------+
16 : // | BC Type | Description |
17 : // +==========================+=================================================================+
18 : // | :code:`Dirichlet` | Standard Dirichlet boundary condition |
19 : // +--------------------------+ (https://en.wikipedia.org/wiki/Dirichlet_boundary_condition). |
20 : // | :code:`dirichlet` | Fixes the value of the **function** at the boundary. |
21 : // +--------------------------+ +
22 : // | :code:`EXT_DIR` | |
23 : // +--------------------------+-----------------------------------------------------------------+
24 : // | :code:`Neumann` | Standard Neumann boundary condition |
25 : // +--------------------------+ (https://en.wikipedia.org/wiki/Neumann_boundary_condition) +
26 : // | :code:`neumann` | |
27 : // +--------------------------+-----------------------------------------------------------------+
28 : // | :code:`Periodic` | Standard periodic boundary condition. |
29 : // +--------------------------+ (https://en.wikipedia.org/wiki/Periodic_boundary_conditions). |
30 : // | :code:`periodic` | **Important**: Ensure that your geometry is specified to be |
31 : // +--------------------------+ periodic using :code:`geometry.is_periodic`. For instance, if |
32 : // | :code:`INT_DIR` | periodic in x, set to :code:`1 0 0` |
33 : // +--------------------------+-----------------------------------------------------------------+
34 : // | :code:`REFLECT_ODD` | Effectively the same as dirichlet but with value fixed to 0 |
35 : // +--------------------------+ +
36 : // | :code:`reflect_odd` | |
37 : // +--------------------------+-----------------------------------------------------------------+
38 : // | :code:`REFLECT_EVEN` | Effectively the same as neumann but with value fixed to 0 |
39 : // +--------------------------+-----------------------------------------------------------------+
40 : // | :code:`BOGUS_BC` | Used for internal operations - not for general use |
41 : // +--------------------------+-----------------------------------------------------------------+
42 : // | :code:`FOEXTRAP` | These are BC types inherited from AMReX and not yet implemented |
43 : // +--------------------------+ in Alamo. If you need BCs of this type, you will need to +
44 : // | :code:`HOEXTRAP` | implement them yourself. |
45 : // +--------------------------+ +
46 : // | :code:`Interior` | |
47 : // +--------------------------+ +
48 : // | :code:`Inflow` | |
49 : // +--------------------------+ +
50 : // | :code:`Outflow` | |
51 : // +--------------------------+ +
52 : // | :code:`Symmetry` | |
53 : // +--------------------------+ +
54 : // | :code:`SlipWall` | |
55 : // +--------------------------+ +
56 : // | :code:`NoSlipWall` | |
57 : // +--------------------------+ +
58 : // | :code:`interior` | |
59 : // +--------------------------+ +
60 : // | :code:`Marshak` | |
61 : // +--------------------------+ +
62 : // | :code:`SanchezPomraning` | |
63 : // +--------------------------+ +
64 : // | :code:`inflow` | |
65 : // +--------------------------+-----------------------------------------------------------------+
66 : //
67 : // The BC values can be specified either as a number (e.g. :code:`1.0`) or using a linear interpolator
68 : // string (e.g. :code:`(0,1:2.3,-0.1)`).
69 : //
70 : // The number of values and types must be either 0 (for defaults), 1 (to set the same for all field components)
71 : // or N (where N=number of field components).
72 : //
73 :
74 : #ifndef BC_CONSTANT_H_
75 : #define BC_CONSTANT_H_
76 :
77 : #include <AMReX_ParallelDescriptor.H>
78 : #include <AMReX_ParmParse.H>
79 : #include <AMReX_BCRec.H>
80 : #include <AMReX_PhysBCFunct.H>
81 : #include <AMReX_Array.H>
82 :
83 : #include "Set/Set.H"
84 : #include "BC/BC.H"
85 : #include "Numeric/Interpolator/Linear.H"
86 :
87 : namespace BC
88 : {
89 : class Constant
90 : : public BC<Set::Scalar>
91 : {
92 :
93 : #if AMREX_SPACEDIM==2
94 : enum Face {
95 : XLO, YLO, XHI, YHI,
96 : INT
97 : };
98 : #elif AMREX_SPACEDIM==3
99 : enum Face {
100 : XLO, YLO, ZLO, XHI, YHI, ZHI, // 6
101 : INT
102 : };
103 : #endif
104 :
105 : public:
106 : static constexpr const char* name = "constant";
107 :
108 : //Constant (amrex::Vector<amrex::Geometry> &_geom) : geom(_geom) {};
109 4 : Constant(int a_ncomp) : m_ncomp(a_ncomp) {};
110 11 : Constant(int a_ncomp, IO::ParmParse& pp, std::string name) : m_ncomp(a_ncomp)
111 : {
112 11 : pp_queryclass(name, *this);
113 11 : };
114 : Constant(int ncomp, amrex::Vector<std::string> bc_hi_str,
115 : amrex::Vector<std::string> bc_lo_str,
116 : AMREX_D_DECL(amrex::Vector<amrex::Real> _bc_lo_1,
117 : amrex::Vector<amrex::Real> _bc_lo_2,
118 : amrex::Vector<amrex::Real> _bc_lo_3),
119 : AMREX_D_DECL(amrex::Vector<amrex::Real> _bc_hi_1,
120 : amrex::Vector<amrex::Real> _bc_hi_2,
121 : amrex::Vector<amrex::Real> _bc_hi_3));
122 :
123 : static Constant ZeroNeumann(int ncomp = 1)
124 : {
125 : Constant ret = Constant(ncomp);
126 :
127 : for (int d = 0; d < m_nfaces; d++)
128 : {
129 : ret.m_bc_type[d].clear();
130 : for (int n = 0; n < ncomp; n++)
131 : {
132 : ret.m_bc_type[d].push_back((int)amrex::LinOpBCType::Neumann);
133 : ret.m_bc_val[d].push_back (0.0);;
134 : }
135 : }
136 :
137 : return ret;
138 : }
139 :
140 : static Constant ZeroDirichlet(int ncomp = 1)
141 : {
142 : Constant ret = Constant(ncomp);
143 :
144 : for (int d = 0; d < m_nfaces; d++)
145 : for (int n = 0; n < ncomp; n++)
146 : {
147 : ret.m_bc_type[n][d] = (int)amrex::LinOpBCType::Dirichlet;
148 : ret.m_bc_val [n][d] = 0.0;
149 : }
150 :
151 : return ret;
152 : }
153 :
154 :
155 18 : virtual ~Constant() {};
156 :
157 : virtual void FillBoundary(amrex::BaseFab<Set::Scalar>& in, const amrex::Box& box,
158 : int ngrow, int dcomp, int ncomp, amrex::Real time,
159 : Orientation face = Orientation::All,
160 : const amrex::Mask* mask = nullptr) override;
161 :
162 : using BC::FillBoundary;
163 :
164 : amrex::BCRec GetBCRec() override;
165 : virtual amrex::Array<int, AMREX_SPACEDIM> IsPeriodic() override;
166 : virtual amrex::Periodicity Periodicity() const override;
167 : virtual amrex::Periodicity Periodicity(const amrex::Box& b) override;
168 :
169 :
170 :
171 : template<class T>
172 : const amrex::Array<amrex::Array<T, AMREX_SPACEDIM>, 2> GetBCTypes()
173 : {
174 : return { {{AMREX_D_DECL((T)m_bc_type[Face::XLO][0],(T)m_bc_type[Face::YLO][0],(T)m_bc_type[Face::ZLO][0])},
175 : {AMREX_D_DECL((T)m_bc_type[Face::XLO][0],(T)m_bc_type[Face::YLO][0],(T)m_bc_type[Face::ZLO][0])}} };
176 : }
177 :
178 :
179 : private:
180 : #if AMREX_SPACEDIM==2
181 : static const int m_nfaces = 4;
182 : #elif AMREX_SPACEDIM==3
183 : static const int m_nfaces = 6;
184 : #endif
185 :
186 : unsigned int m_ncomp = 0;
187 :
188 : //int bc_lo[BL_SPACEDIM];
189 : //int bc_hi[BL_SPACEDIM];
190 : //amrex::Vector<amrex::Real> AMREX_D_DECL(bc_lo_1, bc_lo_2, bc_lo_3);
191 : //amrex::Vector<amrex::Real> AMREX_D_DECL(bc_hi_1, bc_hi_2, bc_hi_3);
192 :
193 : std::array<std::vector<int>, m_nfaces> m_bc_type;
194 : std::array<std::vector<Numeric::Interpolator::Linear<Set::Scalar>>, m_nfaces> m_bc_val;
195 :
196 : public:
197 15 : static void Parse(Constant& value, IO::ParmParse& pp)
198 : {
199 30 : std::map<std::string, int> bcmap;
200 15 : bcmap["BOGUS_BC"] = amrex::BCType::mathematicalBndryTypes::bogus;
201 15 : bcmap["INT_DIR"] = amrex::BCType::mathematicalBndryTypes::int_dir;
202 15 : bcmap["REFLECT_ODD"] = amrex::BCType::mathematicalBndryTypes::reflect_odd;
203 15 : bcmap["INT_DIR"] = amrex::BCType::mathematicalBndryTypes::int_dir;
204 15 : bcmap["REFLECT_EVEN"] = amrex::BCType::mathematicalBndryTypes::reflect_even;
205 15 : bcmap["FOEXTRAP"] = amrex::BCType::mathematicalBndryTypes::foextrap;
206 15 : bcmap["EXT_DIR"] = amrex::BCType::mathematicalBndryTypes::ext_dir;
207 15 : bcmap["HOEXTRAP"] = amrex::BCType::mathematicalBndryTypes::hoextrap;
208 15 : bcmap["Interior"] = amrex::BCType::mathematicalBndryTypes::int_dir;
209 15 : bcmap["Inflow"] = amrex::BCType::mathematicalBndryTypes::ext_dir;
210 15 : bcmap["Outflow"] = amrex::BCType::mathematicalBndryTypes::foextrap;
211 15 : bcmap["Symmetry"] = amrex::BCType::mathematicalBndryTypes::reflect_even;
212 15 : bcmap["SlipWall"] = amrex::BCType::mathematicalBndryTypes::ext_dir;
213 15 : bcmap["NoSlipWall"] = amrex::BCType::mathematicalBndryTypes::ext_dir;
214 : // From <AMReX_LO_BCTYPES.H>
215 15 : bcmap["interior"] = (int)amrex::LinOpBCType::interior;
216 15 : bcmap["Dirichlet"] = (int)amrex::LinOpBCType::Dirichlet;
217 15 : bcmap["dirichlet"] = (int)amrex::LinOpBCType::Dirichlet;
218 15 : bcmap["Neumann"] = (int)amrex::LinOpBCType::Neumann;
219 15 : bcmap["NEUMANN"] = (int)amrex::LinOpBCType::Neumann;
220 15 : bcmap["neumann"] = (int)amrex::LinOpBCType::Neumann;
221 15 : bcmap["reflect_odd"] = (int)amrex::LinOpBCType::reflect_odd;
222 15 : bcmap["Marshak"] = (int)amrex::LinOpBCType::Marshak;
223 15 : bcmap["SanchezPomraning"] = (int)amrex::LinOpBCType::SanchezPomraning;
224 15 : bcmap["inflow"] = (int)amrex::LinOpBCType::inflow;
225 15 : bcmap["Periodic"] = (int)amrex::LinOpBCType::Periodic;
226 15 : bcmap["periodic"] = (int)amrex::LinOpBCType::Periodic;
227 :
228 :
229 :
230 15 : value.m_bc_type[Face::XLO].clear(); value.m_bc_val[Face::XLO].clear();
231 15 : value.m_bc_type[Face::XHI].clear(); value.m_bc_val[Face::XHI].clear();
232 15 : value.m_bc_type[Face::YLO].clear(); value.m_bc_val[Face::YLO].clear();
233 15 : value.m_bc_type[Face::YHI].clear(); value.m_bc_val[Face::YHI].clear();
234 : #if AMREX_SPACEDIM == 3
235 1 : value.m_bc_type[Face::ZLO].clear(); value.m_bc_val[Face::ZLO].clear();
236 1 : value.m_bc_type[Face::ZHI].clear(); value.m_bc_val[Face::ZHI].clear();
237 : #endif
238 :
239 : // TYPES
240 :
241 30 : std::vector<std::string> str;
242 15 : pp_queryarr("type.xlo", str); // BC type on the lower x edge (2d) face (3d)
243 30 : for (unsigned int i = 0; i < str.size(); i++) if (!bcmap.count(str[i])) Util::Exception(INFO, "Invalid BC: ", str[i]);
244 27 : if (str.size() == value.m_ncomp) for (unsigned int i = 0; i < value.m_ncomp; i++) value.m_bc_type[Face::XLO].push_back(bcmap[str[i]]);
245 3 : else if (str.size() == 1) value.m_bc_type[Face::XLO].resize(value.m_ncomp, bcmap[str[0]]);
246 0 : else Util::Exception(INFO, "Incorrect number of ", pp.prefix(), " BC type args: expected ", value.m_ncomp, " or 1 but got ", str.size());
247 15 : pp_queryarr("type.xhi", str); // BC type on the upper x edge (2d) face (3d)
248 30 : for (unsigned int i = 0; i < str.size(); i++) if (!bcmap.count(str[i])) Util::Exception(INFO, "Invalid BC: ", str[i]);
249 27 : if (str.size() == value.m_ncomp) for (unsigned int i = 0; i < value.m_ncomp; i++) value.m_bc_type[Face::XHI].push_back(bcmap[str[i]]);
250 3 : else if (str.size() == 1) value.m_bc_type[Face::XHI].resize(value.m_ncomp, bcmap[str[0]]);
251 0 : else Util::Exception(INFO, "Incorrect number of ", pp.prefix(), " BC type args: expected ", value.m_ncomp, " or 1 but got ", str.size());
252 15 : pp_queryarr("type.ylo", str); // BC type on the lower y edge (2d) face (3d)
253 30 : for (unsigned int i = 0; i < str.size(); i++) if (!bcmap.count(str[i])) Util::Exception(INFO, "Invalid BC: ", str[i]);
254 27 : if (str.size() == value.m_ncomp) for (unsigned int i = 0; i < value.m_ncomp; i++) value.m_bc_type[Face::YLO].push_back(bcmap[str[i]]);
255 3 : else if (str.size() == 1) value.m_bc_type[Face::YLO].resize(value.m_ncomp, bcmap[str[0]]);
256 0 : else Util::Exception(INFO, "Incorrect number of ", pp.prefix(), " BC type args: expected ", value.m_ncomp, " or 1 but got ", str.size());
257 15 : pp_queryarr("type.yhi", str); // BC type on the upper y edge (2d) face (3d)
258 30 : for (unsigned int i = 0; i < str.size(); i++) if (!bcmap.count(str[i])) Util::Exception(INFO, "Invalid BC: ", str[i]);
259 27 : if (str.size() == value.m_ncomp) for (unsigned int i = 0; i < value.m_ncomp; i++) value.m_bc_type[Face::YHI].push_back(bcmap[str[i]]);
260 3 : else if (str.size() == 1) value.m_bc_type[Face::YHI].resize(value.m_ncomp, bcmap[str[0]]);
261 0 : else Util::Exception(INFO, "Incorrect number of ", pp.prefix(), " BC type args: expected ", value.m_ncomp, " or 1 but got ", str.size());
262 15 : pp_queryarr("type.zlo", str); // BC type on the lower z face (processed but ignored in 2d to prevent unused input errors)
263 : #if AMREX_SPACEDIM==3
264 2 : for (unsigned int i = 0; i < str.size(); i++) if (!bcmap.count(str[i])) Util::Exception(INFO, "Invalid BC: ", str[i]);
265 2 : if (str.size() == value.m_ncomp) for (unsigned int i = 0; i < value.m_ncomp; i++) value.m_bc_type[Face::ZLO].push_back(bcmap[str[i]]);
266 0 : else if (str.size() == 1) value.m_bc_type[Face::ZLO].resize(value.m_ncomp, bcmap[str[0]]);
267 0 : else Util::Exception(INFO, "Incorrect number of ", pp.prefix(), " BC type args: expected ", value.m_ncomp, " or 1 but got ", str.size());
268 : #endif
269 15 : pp_queryarr("type.zhi", str); // BC type on the upper z face (processed but ignored in 2d to prevent unused input errors)
270 : #if AMREX_SPACEDIM==3
271 2 : for (unsigned int i = 0; i < str.size(); i++) if (!bcmap.count(str[i])) Util::Exception(INFO, "Invalid BC: ", str[i]);
272 2 : if (str.size() == value.m_ncomp) for (unsigned int i = 0; i < value.m_ncomp; i++) value.m_bc_type[Face::ZHI].push_back(bcmap[str[i]]);
273 0 : else if (str.size() == 1) value.m_bc_type[Face::ZHI].resize(value.m_ncomp, bcmap[str[0]]);
274 0 : else Util::Exception(INFO, "Incorrect number of ", pp.prefix(), " BC type args: expected ", value.m_ncomp, " or 1 but got ", str.size());
275 : #endif
276 :
277 : // VALS
278 16 : std::vector<std::string> val;
279 15 : value.m_bc_val[Face::XLO].clear();
280 15 : pp_queryarr("val.xlo", val); // BC value on the lower x edge (2d) face (3d)
281 24 : if (val.size() == value.m_ncomp) for (unsigned int i = 0; i < value.m_ncomp; i++) value.m_bc_val[Face::XLO].push_back(Numeric::Interpolator::Linear<Set::Scalar>(val[i]));
282 6 : else if (val.size() == 1) value.m_bc_val[Face::XLO].resize(value.m_ncomp, Numeric::Interpolator::Linear<Set::Scalar>(val[0]));
283 6 : else if (val.size() == 0) value.m_bc_val[Face::XLO].resize(value.m_ncomp, 0.0);
284 0 : else Util::Exception(INFO, "Incorrect number of ", pp.prefix(), " BC value args: expected ", value.m_ncomp, " or 0 or 1 but got ", val.size());
285 15 : value.m_bc_val[Face::XHI].clear();
286 15 : pp_queryarr("val.xhi", val); // BC value on the upper x edge (2d) face (3d)
287 24 : if (val.size() == value.m_ncomp) for (unsigned int i = 0; i < value.m_ncomp; i++) value.m_bc_val[Face::XHI].push_back(Numeric::Interpolator::Linear<Set::Scalar>(val[i]));
288 6 : else if (val.size() == 1) value.m_bc_val[Face::XHI].resize(value.m_ncomp, Numeric::Interpolator::Linear<Set::Scalar>(val[0]));
289 6 : else if (val.size() == 0) value.m_bc_val[Face::XHI].resize(value.m_ncomp, 0.0);
290 0 : else Util::Exception(INFO, "Incorrect number of ", pp.prefix(), " BC value args: expected ", value.m_ncomp, " or 0 or 1 but got ", val.size());
291 15 : value.m_bc_val[Face::YLO].clear();
292 15 : pp_queryarr("val.ylo", val); // BC value on the lower y edge (2d) face (3d)
293 26 : if (val.size() == value.m_ncomp) for (unsigned int i = 0; i < value.m_ncomp; i++) value.m_bc_val[Face::YLO].push_back(Numeric::Interpolator::Linear<Set::Scalar>(val[i]));
294 5 : else if (val.size() == 1) value.m_bc_val[Face::YLO].resize(value.m_ncomp, Numeric::Interpolator::Linear<Set::Scalar>(val[0]));
295 5 : else if (val.size() == 0) value.m_bc_val[Face::YLO].resize(value.m_ncomp, 0.0);
296 0 : else Util::Exception(INFO, "Incorrect number of ", pp.prefix(), " BC value args: expected ", value.m_ncomp, " or 0 or 1 but got ", val.size());
297 15 : value.m_bc_val[Face::YHI].clear();
298 15 : pp_queryarr("val.yhi", val); // BC value on the upper y edge (2d) face (3d)
299 26 : if (val.size() == value.m_ncomp) for (unsigned int i = 0; i < value.m_ncomp; i++) value.m_bc_val[Face::YHI].push_back(Numeric::Interpolator::Linear<Set::Scalar>(val[i]));
300 5 : else if (val.size() == 1) value.m_bc_val[Face::YHI].resize(value.m_ncomp, Numeric::Interpolator::Linear<Set::Scalar>(val[0]));
301 5 : else if (val.size() == 0) value.m_bc_val[Face::YHI].resize(value.m_ncomp, 0.0);
302 0 : else Util::Exception(INFO, "Incorrect number of ", pp.prefix(), " BC value args: expected ", value.m_ncomp, " or 0 or 1 but got ", val.size());
303 15 : pp_queryarr("val.zlo", val); // BC value on the lower z face (processed but ignored in 2d to prevent unused input errors)
304 : #if AMREX_SPACEDIM==3
305 1 : value.m_bc_val[Face::ZLO].clear();
306 2 : if (val.size() == value.m_ncomp) for (unsigned int i = 0; i < value.m_ncomp; i++) value.m_bc_val[Face::ZLO].push_back(Numeric::Interpolator::Linear<Set::Scalar>(val[i]));
307 0 : else if (val.size() == 1) value.m_bc_val[Face::ZLO].resize(value.m_ncomp, Numeric::Interpolator::Linear<Set::Scalar>(val[0]));
308 0 : else if (val.size() == 0) value.m_bc_val[Face::ZLO].resize(value.m_ncomp, 0.0);
309 0 : else Util::Exception(INFO, "Incorrect number of ", pp.prefix(), " BC value args: expected ", value.m_ncomp, " or 0 or 1 but got ", val.size());
310 : #endif
311 15 : pp_queryarr("val.zhi", val); // BC value on the upper z face (processed but ignored in 2d to prevent unused input errors)
312 : #if AMREX_SPACEDIM==3
313 1 : value.m_bc_val[Face::ZHI].clear();
314 2 : if (val.size() == value.m_ncomp) for (unsigned int i = 0; i < value.m_ncomp; i++) value.m_bc_val[Face::ZHI].push_back(Numeric::Interpolator::Linear<Set::Scalar>(val[i]));
315 0 : else if (val.size() == 1) value.m_bc_val[Face::ZHI].resize(value.m_ncomp, Numeric::Interpolator::Linear<Set::Scalar>(val[0]));
316 0 : else if (val.size() == 0) value.m_bc_val[Face::ZHI].resize(value.m_ncomp, 0.0);
317 0 : else Util::Exception(INFO, "Incorrect number of ", pp.prefix(), " BC value args: expected ", value.m_ncomp, " or 0 or 1 but got ", val.size());
318 : #endif
319 15 : }
320 :
321 : };
322 : }
323 : #endif
|