Line data Source code
1 : //
2 : // Boundary condition similar to BC::Constant, except that "values"
3 : // are given as strings which are functions of x,y,z,t.
4 : //
5 :
6 : #ifndef BC_EXPRESSION_H_
7 : #define BC_EXPRESSION_H_
8 :
9 : #include <AMReX_ParallelDescriptor.H>
10 : #include <AMReX_ParmParse.H>
11 : #include <AMReX_BCRec.H>
12 : #include <AMReX_PhysBCFunct.H>
13 : #include <AMReX_Array.H>
14 : #include <AMReX_Parser.H>
15 :
16 : #include "IO/ParmParse.H"
17 : #include "BC/BC.H"
18 :
19 : namespace BC
20 : {
21 : class Expression
22 : : public BC<Set::Scalar>
23 : {
24 : public:
25 : static constexpr const char* name = "expression";
26 :
27 : //static constexpr const char* const Elastic::strings[];
28 : #if AMREX_SPACEDIM==2
29 : static const constexpr char * const facestr[] = {
30 : "xlo","ylo","xhi","yhi"
31 : };
32 : #elif AMREX_SPACEDIM==3
33 : static const constexpr char * const facestr[] = {
34 : "xlo","ylo","zlo","xhi","yhi","zhi",
35 : };
36 : #endif
37 :
38 : #if AMREX_SPACEDIM==2
39 : enum Face {
40 : XLO, YLO, XHI, YHI,
41 : INT
42 : };
43 : #elif AMREX_SPACEDIM==3
44 : enum Face {
45 : XLO, YLO, ZLO, XHI, YHI, ZHI, // 6
46 : INT
47 : };
48 : #endif
49 :
50 : public:
51 : //Constant (amrex::Vector<amrex::Geometry> &_geom) : geom(_geom) {};
52 : Expression(int a_ncomp) : m_ncomp(a_ncomp) {};
53 0 : Expression(int a_ncomp, IO::ParmParse& pp, std::string name) : m_ncomp(a_ncomp)
54 : {
55 0 : pp_queryclass(name, *this);
56 0 : };
57 0 : Expression(int a_ncomp, Unit /*a_unit*/, IO::ParmParse& pp, std::string name) : m_ncomp(a_ncomp)
58 : {
59 0 : pp_queryclass(name, *this);
60 0 : };
61 :
62 0 : virtual ~Expression() {};
63 :
64 : virtual void FillBoundary(amrex::BaseFab<Set::Scalar>& in, const amrex::Box& box,
65 : int ngrow, int dcomp, int ncomp, amrex::Real time,
66 : Orientation face = Orientation::All,
67 : const amrex::Mask* mask = nullptr) override;
68 :
69 : using BC::FillBoundary;
70 :
71 : amrex::BCRec GetBCRec() override;
72 : virtual amrex::Array<int, AMREX_SPACEDIM> IsPeriodic() override;
73 : virtual amrex::Periodicity Periodicity() const override;
74 : virtual amrex::Periodicity Periodicity(const amrex::Box& b) override;
75 :
76 :
77 :
78 : template<class T>
79 : const amrex::Array<amrex::Array<T, AMREX_SPACEDIM>, 2> GetBCTypes()
80 : {
81 : 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])},
82 : {AMREX_D_DECL((T)m_bc_type[Face::XLO][0],(T)m_bc_type[Face::YLO][0],(T)m_bc_type[Face::ZLO][0])}} };
83 : }
84 :
85 :
86 : private:
87 : #if AMREX_SPACEDIM==2
88 : static const int m_nfaces = 4;
89 : #elif AMREX_SPACEDIM==3
90 : static const int m_nfaces = 6;
91 : #endif
92 :
93 : unsigned int m_ncomp = 0;
94 :
95 : std::array<std::vector<int>, m_nfaces> m_bc_type;
96 : std::array<std::vector<amrex::Parser>, m_nfaces> m_bc_func_parser;
97 : std::array<std::vector<amrex::ParserExecutor<4>>, m_nfaces> m_bc_func;
98 :
99 : //std::array<std::vector<Numeric::Interpolator::Linear<Set::Scalar>>, m_nfaces> m_bc_val;
100 :
101 : public:
102 0 : static void Parse(Expression& value, IO::ParmParse& pp)
103 : {
104 0 : std::map<std::string, int> bcmap;
105 0 : bcmap["BOGUS_BC"] = amrex::BCType::mathematicalBndryTypes::bogus;
106 0 : bcmap["INT_DIR"] = amrex::BCType::mathematicalBndryTypes::int_dir;
107 0 : bcmap["REFLECT_ODD"] = amrex::BCType::mathematicalBndryTypes::reflect_odd;
108 0 : bcmap["INT_DIR"] = amrex::BCType::mathematicalBndryTypes::int_dir;
109 0 : bcmap["REFLECT_EVEN"] = amrex::BCType::mathematicalBndryTypes::reflect_even;
110 0 : bcmap["FOEXTRAP"] = amrex::BCType::mathematicalBndryTypes::foextrap;
111 0 : bcmap["EXT_DIR"] = amrex::BCType::mathematicalBndryTypes::ext_dir;
112 0 : bcmap["HOEXTRAP"] = amrex::BCType::mathematicalBndryTypes::hoextrap;
113 0 : bcmap["Interior"] = amrex::BCType::mathematicalBndryTypes::int_dir;
114 0 : bcmap["Inflow"] = amrex::BCType::mathematicalBndryTypes::ext_dir;
115 0 : bcmap["Outflow"] = amrex::BCType::mathematicalBndryTypes::foextrap;
116 0 : bcmap["Symmetry"] = amrex::BCType::mathematicalBndryTypes::reflect_even;
117 0 : bcmap["SlipWall"] = amrex::BCType::mathematicalBndryTypes::ext_dir;
118 0 : bcmap["NoSlipWall"] = amrex::BCType::mathematicalBndryTypes::ext_dir;
119 : // From <AMReX_LO_BCTYPES.H>
120 0 : bcmap["interior"] = (int)amrex::LinOpBCType::interior;
121 0 : bcmap["Dirichlet"] = (int)amrex::LinOpBCType::Dirichlet;
122 0 : bcmap["dirichlet"] = (int)amrex::LinOpBCType::Dirichlet;
123 0 : bcmap["Neumann"] = (int)amrex::LinOpBCType::Neumann;
124 0 : bcmap["NEUMANN"] = (int)amrex::LinOpBCType::Neumann;
125 0 : bcmap["neumann"] = (int)amrex::LinOpBCType::Neumann;
126 0 : bcmap["reflect_odd"] = (int)amrex::LinOpBCType::reflect_odd;
127 0 : bcmap["Marshak"] = (int)amrex::LinOpBCType::Marshak;
128 0 : bcmap["SanchezPomraning"] = (int)amrex::LinOpBCType::SanchezPomraning;
129 0 : bcmap["inflow"] = (int)amrex::LinOpBCType::inflow;
130 0 : bcmap["Periodic"] = (int)amrex::LinOpBCType::Periodic;
131 0 : bcmap["periodic"] = (int)amrex::LinOpBCType::Periodic;
132 :
133 :
134 :
135 : // TYPES
136 :
137 0 : std::vector<std::string> str;
138 0 : pp.queryarr_default("type.xlo", str,{"dirichlet"}); // BC type on the lower x edge (2d) face (3d)
139 0 : for (unsigned int i = 0; i < str.size(); i++) if (!bcmap.count(str[i])) Util::Abort(INFO, "Invalid BC: ", str[i]);
140 0 : 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]]);
141 0 : else if (str.size() == 1) value.m_bc_type[Face::XLO].resize(value.m_ncomp, bcmap[str[0]]);
142 0 : else Util::Abort(INFO, "Incorrect number of ", pp.prefix(), " BC type args: expected ", value.m_ncomp, " or 1 but got ", str.size());
143 0 : pp.queryarr_default("type.xhi", str,{"dirichlet"}); // BC type on the upper x edge (2d) face (3d)
144 0 : for (unsigned int i = 0; i < str.size(); i++) if (!bcmap.count(str[i])) Util::Abort(INFO, "Invalid BC: ", str[i]);
145 0 : 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]]);
146 0 : else if (str.size() == 1) value.m_bc_type[Face::XHI].resize(value.m_ncomp, bcmap[str[0]]);
147 0 : else Util::Abort(INFO, "Incorrect number of ", pp.prefix(), " BC type args: expected ", value.m_ncomp, " or 1 but got ", str.size());
148 0 : pp.queryarr_default("type.ylo", str,{"dirichlet"}); // BC type on the lower y edge (2d) face (3d)
149 0 : for (unsigned int i = 0; i < str.size(); i++) if (!bcmap.count(str[i])) Util::Abort(INFO, "Invalid BC: ", str[i]);
150 0 : 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]]);
151 0 : else if (str.size() == 1) value.m_bc_type[Face::YLO].resize(value.m_ncomp, bcmap[str[0]]);
152 0 : else Util::Abort(INFO, "Incorrect number of ", pp.prefix(), " BC type args: expected ", value.m_ncomp, " or 1 but got ", str.size());
153 0 : pp.queryarr_default("type.yhi", str,{"dirichlet"}); // BC type on the upper y edge (2d) face (3d)
154 0 : for (unsigned int i = 0; i < str.size(); i++) if (!bcmap.count(str[i])) Util::Abort(INFO, "Invalid BC: ", str[i]);
155 0 : 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]]);
156 0 : else if (str.size() == 1) value.m_bc_type[Face::YHI].resize(value.m_ncomp, bcmap[str[0]]);
157 0 : else Util::Abort(INFO, "Incorrect number of ", pp.prefix(), " BC type args: expected ", value.m_ncomp, " or 1 but got ", str.size());
158 0 : pp.queryarr_default("type.zlo", str,{"dirichlet"}); // BC type on the lower z face (processed but ignored in 2d to prevent unused input errors)
159 : #if AMREX_SPACEDIM==3
160 : for (unsigned int i = 0; i < str.size(); i++) if (!bcmap.count(str[i])) Util::Abort(INFO, "Invalid BC: ", str[i]);
161 : 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]]);
162 : else if (str.size() == 1) value.m_bc_type[Face::ZLO].resize(value.m_ncomp, bcmap[str[0]]);
163 : else Util::Abort(INFO, "Incorrect number of ", pp.prefix(), " BC type args: expected ", value.m_ncomp, " or 1 but got ", str.size());
164 : #endif
165 0 : pp.queryarr_default("type.zhi", str,{"dirichlet"}); // BC type on the upper z face (processed but ignored in 2d to prevent unused input errors)
166 : #if AMREX_SPACEDIM==3
167 : for (unsigned int i = 0; i < str.size(); i++) if (!bcmap.count(str[i])) Util::Abort(INFO, "Invalid BC: ", str[i]);
168 : 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]]);
169 : else if (str.size() == 1) value.m_bc_type[Face::ZHI].resize(value.m_ncomp, bcmap[str[0]]);
170 : else Util::Abort(INFO, "Incorrect number of ", pp.prefix(), " BC type args: expected ", value.m_ncomp, " or 1 but got ", str.size());
171 : #endif
172 :
173 : // VALS
174 0 : std::vector<std::string> val;
175 0 : for (int face = 0; face != Face::INT; face++)
176 : {
177 0 : std::string querystr = std::string("val.") + std::string(facestr[face]);
178 0 : if (pp.contains(querystr.c_str())) pp_queryarr(querystr.c_str(),val);
179 0 : else val.resize(value.m_ncomp,"0.0");
180 0 : if (val.size() != value.m_ncomp) Util::Abort(INFO,"Incorrect number of expressions specified for ",querystr,": expected 1 or ",value.m_ncomp," but received ",val.size());
181 :
182 0 : value.m_bc_func_parser[face].clear();
183 0 : value.m_bc_func[face].clear();
184 0 : for (unsigned int i = 0 ; i < value.m_ncomp; i++)
185 : {
186 0 : value.m_bc_func_parser[face].push_back( amrex::Parser(val[i].c_str()) );
187 0 : value.m_bc_func_parser[face][i].registerVariables({"x","y","z","t"});
188 0 : value.m_bc_func[face].push_back( value.m_bc_func_parser[face][i].compile<4>() );
189 : }
190 0 : }
191 :
192 : #if AMREX_SPACEDIM==2
193 : // We may wish to use an input file that has 3D BC inputs
194 : // This will prevent the parser from complaining that there are unused inputs.
195 : std::vector<std::string> ignore_in_2d = {
196 : "zlo","zhi",
197 : "zhixlo","zloxlo","zhixhi","zloxhi","ylozlo","ylozhi","yhizlo","yhizhi",
198 0 : "xloylozlo","xloylozhi","xloyhizlo","xloyhizhi","xhiylozlo","xhiylozhi","xhiyhizlo","xhiyhizhi"};
199 0 : for (unsigned int n = 0; n < ignore_in_2d.size(); n++)
200 : {
201 0 : std::string querystr = std::string("val.") + ignore_in_2d[n];
202 0 : pp.ignore(querystr);
203 0 : querystr = std::string("type.") + ignore_in_2d[n];
204 0 : pp.ignore(querystr);
205 0 : }
206 : #endif
207 :
208 0 : }
209 : };
210 : }
211 : #endif
|