PetIBM 0.5.4
Toolbox and applications of the immersed-boundary method for distributed-memory architectures
parser.cpp
Go to the documentation of this file.
1
8// STL
9#include <sys/stat.h>
10#include <string>
11#include <vector>
12
13// symengine
14#include <symengine/parser.h>
15#include <symengine/expression.h>
16#include <symengine/lambda_double.h>
17
18// here goes our own headers
19#include <petibm/misc.h>
20#include <petibm/parser.h>
21
22namespace // anonymous namespace for internal linkage
23{
24// private function. Create a directory if not already existing.
25PetscErrorCode createDirectory(const std::string &dir)
26{
27 PetscFunctionBeginUser;
28
29 if (mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1)
30 {
31 if (errno != EEXIST) // if error != "File exists"
32 {
33 SETERRQ2(PETSC_COMM_WORLD, 1,
34 "Could not create the folder \"%s\" (%s).\n", dir.c_str(),
35 strerror(errno));
36 }
37 }
38
39 PetscFunctionReturn(0);
40} // createDirectory
41} // end of anonymous namespace
42
43// A supplement to YAML-CPP that adds converters of our user-defined types.
44namespace YAML
45{
46// converter for `types::Dir`
47template <>
48struct convert<petibm::type::Dir>
49{
50 static Node encode(const petibm::type::Dir &dir)
51 {
52 Node node;
53 node = petibm::type::dir2str[dir];
54 return node;
55 }
56
57 static bool decode(const Node &node, petibm::type::Dir &dir)
58 {
59 if (!node.IsDefined()) return false;
60
61 dir = petibm::type::str2dir[node.as<std::string>()];
62 return true;
63 }
64};
65
66// converter for `types::Field`
67template <>
68struct convert<petibm::type::Field>
69{
70 static Node encode(const petibm::type::Field &vc)
71 {
72 Node node;
73 node = petibm::type::fd2str[vc];
74 return node;
75 }
76
77 static bool decode(const Node &node, petibm::type::Field &vc)
78 {
79 if (!node.IsDefined()) return false;
80
81 vc = petibm::type::str2fd[node.as<std::string>()];
82 return true;
83 }
84};
85
86// converter for `types::BCType`
87template <>
88struct convert<petibm::type::BCType>
89{
90 static Node encode(const petibm::type::BCType &bc)
91 {
92 Node node;
93 node = petibm::type::bt2str[bc];
94 return node;
95 }
96
97 static bool decode(const Node &node, petibm::type::BCType &bc)
98 {
99 if (!node.IsDefined()) return false;
100 bc = petibm::type::str2bt[node.as<std::string>()];
101 return true;
102 }
103};
104
105// converter for `types::BCLoc`
106template <>
107struct convert<petibm::type::BCLoc>
108{
109 static Node encode(const petibm::type::BCLoc &loc)
110 {
111 Node node;
112 node = petibm::type::bl2str[loc];
113 return node;
114 }
115
116 static bool decode(const Node &node, petibm::type::BCLoc &loc)
117 {
118 if (!node.IsDefined()) return false;
119
120 loc = petibm::type::str2bl[node.as<std::string>()];
121 return true;
122 }
123};
124
125// converter for `PetscBool`
126template <>
127struct convert<PetscBool>
128{
129 static Node encode(const PetscBool &b)
130 {
131 YAML::Node node;
132 node = bool(b);
133 return node;
134 }
135
136 static bool decode(const Node &node, PetscBool &b)
137 {
138 if (!node.IsDefined()) return false;
139
140 b = PetscBool(node.as<bool>());
141 return true;
142 }
143};
144
145} // end of namespace YAML
146
147namespace petibm
148{
149namespace parser
150{
151// Load nodes from a given YAML file.
152PetscErrorCode readYAMLFile(const std::string &filePath, YAML::Node &node)
153{
154 YAML::Node tmp;
155
156 PetscFunctionBeginUser;
157
158 // Load the content of the given YAML file.
159 try
160 {
161 tmp = YAML::LoadFile(filePath);
162 }
163 catch (YAML::BadFile &err)
164 {
165 SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_FILE_OPEN, "Unable to open %s",
166 filePath.c_str());
167 }
168 // Add new nodes, overwrite existing ones.
169 for (auto item : tmp) node[item.first.as<std::string>()] = item.second;
170
171 PetscFunctionReturn(0);
172} // readYAMLFile
173
174// Get all settings into a single YAML node.
175PetscErrorCode getSettings(YAML::Node &node)
176{
177 PetscErrorCode ierr;
178 char s[PETSC_MAX_PATH_LEN];
179 PetscBool flag;
180 std::string filePath;
181
182 PetscFunctionBeginUser;
183
184 // Get the working directory; default is the current working directory.
185 node["directory"] = "./";
186 ierr = PetscOptionsGetString(nullptr, nullptr, "-directory", s, sizeof(s),
187 &flag); CHKERRQ(ierr);
188 if (flag) node["directory"] = s;
189
190 // Get the output directory where to save field solutions;
191 // default is the `output` folder under the working directory.
192 // If the user provides a relative path, it is relative to $PWD.
193 node["output"] = node["directory"].as<std::string>() + "/output";
194 ierr =
195 PetscOptionsGetString(nullptr, nullptr, "-output", s, sizeof(s), &flag);
196 CHKERRQ(ierr);
197 if (flag) node["output"] = s;
198 ierr = createDirectory(node["output"].as<std::string>()); CHKERRQ(ierr);
199
200 // Get the directory where to save PETSc logging files;
201 // default is the `logs` folder under the working directory.
202 // TODO: if user provides a relative path, where should it be relative to?
203 node["logs"] = node["output"].as<std::string>() + "/logs";
204 ierr =
205 PetscOptionsGetString(nullptr, nullptr, "-logs", s, sizeof(s), &flag);
206 CHKERRQ(ierr);
207 if (flag) node["logs"] = s;
208 ierr = createDirectory(node["logs"].as<std::string>()); CHKERRQ(ierr);
209
210 // Get the path of the global YAML configuration file;
211 // default is the file `config.yaml` in the working directory.
212 // TODO: if user provides a relative path, where should it be relative to?
213 filePath = node["directory"].as<std::string>() + "/config.yaml";
214 ierr = PetscOptionsGetString(
215 nullptr, nullptr, "-config", s, sizeof(s), &flag); CHKERRQ(ierr);
216 if (flag) filePath = s;
217 // Load the settings into the YAML node.
218 ierr = readYAMLFile(filePath, node); CHKERRQ(ierr);
219
220 // Load YAML configuration files provided through the command-line.
221 std::vector<const char *> cliOpts = {"-mesh", "-flow", "-parameters",
222 "-bodies", "-probes"};
223 for (auto cliOpt : cliOpts)
224 {
225 // Get the path of the YAML configuration file.
226 // TODO: if relative path, where should it be relative to?
227 ierr = PetscOptionsGetString(nullptr, nullptr, cliOpt, s, sizeof(s),
228 &flag); CHKERRQ(ierr);
229 if (flag)
230 {
231 // Load the YAML file and overwrite existing values into the node.
232 ierr = readYAMLFile(std::string(s), node); CHKERRQ(ierr);
233 }
234 }
235
236 PetscFunctionReturn(0);
237} // getSettings
238
239PetscErrorCode parseMesh(const YAML::Node &meshNode, PetscInt &dim,
241 type::IntVec1D &nTotal, type::RealVec2D &dL)
242{
243 using namespace type;
244
245 PetscFunctionBeginUser;
246
247 PetscErrorCode ierr;
248
249 // get the dimension of the mesh; no checking here
250 dim = meshNode.size();
251
252 // loop through all dimensions
253 for (auto ax : meshNode)
254 {
255 // note that the order of dimensions in the YAML file is not guaranteed,
256 // so we have to use some temporary variables
257 PetscInt dir, nTotalAx;
258 PetscReal bgAx, edAx;
259 type::RealVec1D dLAx;
260
261 // parse current dimension
262 ierr = parseOneAxis(ax, dir, bgAx, edAx, nTotalAx, dLAx);
263 CHKERRQ(ierr);
264
265 // assign results back
266 bg[dir] = bgAx;
267 ed[dir] = edAx;
268 nTotal[dir] = nTotalAx;
269 dL[dir] = dLAx;
270 }
271
272 PetscFunctionReturn(0);
273} // parseMesh
274
275PetscErrorCode parseOneAxis(const YAML::Node &axis, PetscInt &dir,
276 PetscReal &bg, PetscReal &ed, PetscInt &nTotal,
277 type::RealVec1D &dL)
278{
279 PetscFunctionBeginUser;
280
281 PetscErrorCode ierr;
282
283 // a map to transform a string to int
284
285 // get the direction
286 dir = PetscInt(axis["direction"].as<type::Dir>());
287
288 // get the far left boundary
289 bg = axis["start"].as<PetscReal>();
290
291 // parse sub-domains
292 ierr = parseSubDomains(axis["subDomains"], bg, nTotal, ed, dL);
293 CHKERRQ(ierr);
294
295 PetscFunctionReturn(0);
296} // parseOneAxis
297
298PetscErrorCode parseSubDomains(const YAML::Node &subs, const PetscReal bg,
299 PetscInt &nTotal, PetscReal &ed,
300 type::RealVec1D &dL)
301{
302 PetscFunctionBeginUser;
303
304 PetscErrorCode ierr;
305
306 // initialize nTotal
307 nTotal = 0;
308
309 // initialize max
310 ed = bg;
311
312 // initialize dL
313 dL = type::RealVec1D();
314
315 // loop through all sub-domains
316 for (auto sub : subs)
317 {
318 type::RealVec1D dLSub; // cell sizes of the sub-domains
319 PetscInt nSub; // number of the cells of the sub-domains
320
321 // the 1st ed is passed by value, while the 2nd one is by reference
322 ierr = parseOneSubDomain(sub, ed, nSub, ed, dLSub); CHKERRQ(ierr);
323
324 // add number of the sub-domain to total number of cells
325 nTotal += nSub;
326
327 // append the sub-domain dL to global dL
328 dL.insert(dL.end(), dLSub.begin(), dLSub.end());
329 }
330
331 PetscFunctionReturn(0);
332} // parseSubDomains
333
334PetscErrorCode parseOneSubDomain(const YAML::Node &sub, const PetscReal bg,
335 PetscInt &n, PetscReal &ed,
336 type::RealVec1D &dL)
337{
338 PetscFunctionBeginUser;
339
340 // get the number of the cells in this sub-domain
341 n = sub["cells"].as<PetscInt>();
342
343 // get the end of the sub-domain
344 ed = sub["end"].as<PetscReal>();
345
346 // get the stretching ratio
347 PetscReal r = sub["stretchRatio"].as<PetscReal>();
348
349 // obtain the cell sizes
350 if (std::abs(r - 1.0) <= 1e-12)
351 dL = type::RealVec1D(n, (ed - bg) / n); // uniform grid
352 else
353 misc::stretchGrid(bg, ed, n, r, dL); // stretch grid
354
355 PetscFunctionReturn(0);
356} // parseOneSubDomain
357
358// get information about if we have periodic BCs from YAML node
359PetscErrorCode parseBCs(const YAML::Node &node, type::IntVec2D &bcTypes,
360 type::RealVec2D &bcValues)
361{
362 PetscFunctionBeginUser;
363
364 if (!node["flow"].IsDefined())
365 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
366 "Could not find the key \"flow\" in the YAML "
367 "node passed to parseBCs.\n");
368
369 if (!node["flow"]["boundaryConditions"].IsDefined())
370 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
371 "Could not find the key \"boundaryConditions\" under the key "
372 "\"flow\" in the YAML node passed to parseBCs.\n");
373
374 bcTypes = type::IntVec2D(3, type::IntVec1D(6, int(type::BCType::NOBC)));
375 bcValues = type::RealVec2D(3, type::RealVec1D(6, 0.0));
376
377 for (auto sub : node["flow"]["boundaryConditions"])
378 {
379 int loc = int(sub["location"].as<type::BCLoc>());
380
381 for (auto ssub : sub)
382 {
383 if (ssub.first.as<std::string>() != "location")
384 {
385 int f = int(ssub.first.as<type::Field>());
386 bcTypes[f][loc] = int(ssub.second[0].as<type::BCType>());
387 bcValues[f][loc] = ssub.second[1].as<PetscReal>();
388 }
389 }
390 }
391
392 PetscFunctionReturn(0);
393} // parseBCs
394
395// get initial conditions
396PetscErrorCode parseICs(
397 const YAML::Node &node,
398 std::vector<SymEngine::LambdaRealDoubleVisitor> &lambdas)
399{
400 PetscFunctionBeginUser;
401
402 if (!node["flow"].IsDefined())
403 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
404 "Could not find the key \"flow\" in the YAML "
405 "node passed to parseICs.\n");
406
407 if (!node["flow"]["initialVelocity"].IsDefined())
408 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
409 "Could not find the key \"initialVelocity\" under the key "
410 "\"flow\" in the YAML node passed to parseICs.\n");
411
412 const YAML::Node &temp = node["flow"]["initialVelocity"];
413
414 // 0: u, 1: v, 2: w, 3: p
415 lambdas = std::vector<SymEngine::LambdaRealDoubleVisitor>(4);
416
417 // symbols for independent variables
418 auto x = SymEngine::symbol("x");
419 auto y = SymEngine::symbol("y");
420 auto z = SymEngine::symbol("z");
421 auto t = SymEngine::symbol("t");
422 auto nu = SymEngine::symbol("nu");
423
424 for (unsigned int i = 0; i < temp.size(); i++)
425 {
426 // get the pointer to the symbolic expression
427 auto expr = SymEngine::parse(temp[i].as<std::string>());
428
429 // assign the lambdified objects to the vector
430 lambdas[i].init({x, y, z, t, nu}, *expr);
431 }
432
433 // pressure; has default values if not provided
434 if (node["flow"]["initialPressure"].IsDefined()){
435 auto expr = SymEngine::parse(node["flow"]["initialPressure"].as<std::string>());
436 lambdas[3].init({x, y, z, t, nu}, *expr);
437 } else {
438 auto expr = SymEngine::parse("0");
439 lambdas[3].init({x, y, z, t, nu}, *expr);
440 }
441
442 PetscFunctionReturn(0);
443} // parseICs
444
445} // end of namespace parser
446} // end of namespace petibm
PetscErrorCode parseOneAxis(const YAML::Node &axis, PetscInt &dir, PetscReal &bg, PetscReal &ed, PetscInt &nTotal, type::RealVec1D &dL)
Parse the info of only one direction from YAML node.
Definition: parser.cpp:275
PetscErrorCode getSettings(YAML::Node &node)
Get configuration settings.
Definition: parser.cpp:175
PetscErrorCode parseSubDomains(const YAML::Node &subs, const PetscReal bg, PetscInt &nTotal, PetscReal &ed, type::RealVec1D &dL)
Parse all sub-domains in a direction.
Definition: parser.cpp:298
PetscErrorCode parseMesh(const YAML::Node &meshNode, PetscInt &dim, type::RealVec1D &bg, type::RealVec1D &ed, type::IntVec1D &nTotal, type::RealVec2D &dL)
Parse a YAML node of cartesianMesh.
Definition: parser.cpp:239
PetscErrorCode parseBCs(const YAML::Node &node, type::IntVec2D &bcTypes, type::RealVec2D &bcValues)
Parse boundary conditions from a YAML node.
Definition: parser.cpp:359
PetscErrorCode readYAMLFile(const std::string &filePath, YAML::Node &node)
Load the content of a YAML file into a YAML node.
Definition: parser.cpp:152
PetscErrorCode stretchGrid(const PetscReal &bg, const PetscReal &ed, const PetscInt &n, const PetscReal &r, type::RealVec1D &dL)
Calculate and return cell sizes of stretched grid in one direction.
Definition: misc.h:148
PetscErrorCode parseOneSubDomain(const YAML::Node &sub, const PetscReal bg, PetscInt &n, PetscReal &ed, type::RealVec1D &dL)
Parse only one sub-domain.
Definition: parser.cpp:334
PetscErrorCode parseICs(const YAML::Node &node, std::vector< SymEngine::LambdaRealDoubleVisitor > &ics)
Parse initial conditions from a YAML node.
Definition: parser.cpp:396
std::vector< IntVec1D > IntVec2D
2D std::vector holding PetscInt.
Definition: type.h:135
Field
Legal fields.
Definition: type.h:80
std::map< BCLoc, std::string > bl2str
Mapping between BCLoc and std::string.
Definition: type.cpp:48
BCType
Type of boundary conditions.
Definition: type.h:94
Dir
Legal physical directions.
Definition: type.h:68
std::map< Field, std::string > fd2str
Mapping between Field and std::string.
Definition: type.cpp:24
std::map< std::string, BCLoc > str2bl
Mapping between std::string and BCLoc.
Definition: type.cpp:41
std::map< std::string, BCType > str2bt
Mapping between std::string and BCType.
Definition: type.cpp:28
std::vector< RealVec1D > RealVec2D
2D std::vector holding PetscReal.
Definition: type.h:142
std::vector< PetscInt > IntVec1D
1D std::vector holding PetscInt.
Definition: type.h:133
BCLoc
Location of a boundary.
Definition: type.h:108
std::map< Dir, std::string > dir2str
Mapping between Dir and std::string.
Definition: type.cpp:18
std::map< BCType, std::string > bt2str
mapping between BCType and std::string.
Definition: type.cpp:34
std::map< std::string, Dir > str2dir
Mapping between std::string and Dir.
Definition: type.cpp:16
std::vector< PetscReal > RealVec1D
1D std::vector holding PetscReal.
Definition: type.h:140
std::map< std::string, Field > str2fd
Mapping between std::string and Field.
Definition: type.cpp:21
@ NOBC
Definition: type.h:95
Prototypes of some miscellaneous functions.
Definition: parser.cpp:45
A toolbox for building flow solvers.
Definition: bodypack.h:52
Prototypes of parser functions.