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