Line data Source code
1 : // Copyright (C) 2016 Technische Universitaet Muenchen
2 : // This file is part of the Mamico project. For conditions of distribution
3 : // and use, please see the copyright notice in Mamico's main folder, or at
4 : // www5.in.tum.de/mamico
5 : #ifndef _COUETTECONFIG_H_
6 : #define _COUETTECONFIG_H_
7 :
8 : #include "tarch/configuration/ParseConfiguration.h"
9 : #include "tarch/la/Vector.h"
10 :
11 : using tarch::configuration::ParseConfiguration;
12 :
13 : namespace coupling {
14 : namespace configurations {
15 :
16 : struct CouetteConfig;
17 : }
18 : } // namespace coupling
19 : /** Configuration parameters for Couette flow scenario
20 : * @brief Configuration parameters for Couette flow scenario
21 : *
22 : *
23 : * @author Niklas Wittmer
24 : */
25 4 : struct coupling::configurations::CouetteConfig {
26 :
27 : private:
28 : // CouetteConfig(){}
29 :
30 : public:
31 : /** Defines the type of continuum solver for the coupled simulation */
32 : enum MacroSolverType {
33 : COUETTE_ANALYTICAL = 0, ///< the analytical couette solver is used
34 : ///< (coupling::solvers::CouetteSolver)
35 : COUETTE_LB = 1, ///< the Lattice-Bolzmann solver is used
36 : ///< (coupling::solvers::LBCouetteSolver)
37 : COUETTE_FD = 2, ///< the 1d finite-difference solver is used
38 : ///< (coupling::solvers::FiniteDifferenceSolver)
39 : COUETTE_FOAM = 3 ///< the IcoFoam solver is used (coupling::solvers::IcoFoam)
40 : };
41 : /** Defines the type of md solver for the coupled simulation */
42 : enum MicroSolverType {
43 : SIMPLEMD = 0, ///< the SimpleMD solver is used
44 : SYNTHETIC = 1, ///< the synthetic solver is used
45 : LS1 = 2 ///< the LS1 solver is used
46 : };
47 :
48 : /** @brief creates CouetteConfig if all elements exist and can be read
49 : * @param filename
50 : */
51 4 : static CouetteConfig parseCouetteConfiguration(const std::string& filename) {
52 4 : CouetteConfig cfg;
53 :
54 4 : ParseConfiguration::XMLConfiguration xmlConfig = ParseConfiguration::XMLConfiguration::load(filename);
55 4 : tinyxml2::XMLElement* node = xmlConfig.root->FirstChildElement("couette-test");
56 :
57 4 : if (node == NULL) {
58 0 : std::cout << "Could not read input file " << filename
59 : << ": missing element "
60 0 : "<couette-test>"
61 0 : << std::endl;
62 0 : exit(EXIT_FAILURE);
63 : }
64 :
65 4 : tinyxml2::XMLElement* n_mamico = node->NextSiblingElement();
66 4 : if (n_mamico == NULL) {
67 0 : std::cout << "Could not read input file " << filename << ": missing element <mamico>" << std::endl;
68 0 : exit(EXIT_FAILURE);
69 : }
70 4 : tinyxml2::XMLElement* n_md = n_mamico->NextSiblingElement();
71 4 : if (n_md == NULL) {
72 0 : std::cout << "Could not read input file " << filename
73 : << ": missing element "
74 0 : "<molecular-dynamics>"
75 0 : << std::endl;
76 0 : exit(EXIT_FAILURE);
77 : }
78 4 : tinyxml2::XMLElement* n_fp = n_md->NextSiblingElement();
79 4 : if (n_fp == NULL) {
80 0 : std::cout << "Could not read input file " << filename
81 : << ": missing element "
82 0 : "<filter-pipeline>"
83 0 : << std::endl;
84 0 : exit(EXIT_FAILURE);
85 : }
86 4 : tinyxml2::XMLElement* n_unexpected = n_fp->NextSiblingElement();
87 4 : if (n_unexpected != NULL) {
88 0 : std::cout << "Could not read input file " << filename << ": unknown element " << n_unexpected->Name() << std::endl;
89 0 : exit(EXIT_FAILURE);
90 : }
91 :
92 4 : tinyxml2::XMLElement* subtag = node->FirstChildElement("domain");
93 4 : if (subtag == NULL) {
94 0 : std::cout << "Could not read input file " << filename << ": Missing subtag: domain" << std::endl;
95 0 : exit(EXIT_FAILURE);
96 : }
97 4 : tarch::configuration::ParseConfiguration::readDoubleMandatory(cfg.channelheight, subtag, "channelheight");
98 4 : tarch::configuration::ParseConfiguration::readVectorMandatory<3, double>(cfg.wallVelocity, subtag, "wall-velocity");
99 4 : cfg.wallInitCycles = 0;
100 4 : tarch::configuration::ParseConfiguration::readIntOptional(cfg.wallInitCycles, subtag, "wall-init-cycles");
101 4 : if (cfg.wallInitCycles > 0)
102 0 : tarch::configuration::ParseConfiguration::readVectorMandatory<3, double>(cfg.wallInitVelocity, subtag, "wall-init-velocity");
103 4 : cfg.wallOscillations = 0;
104 4 : tarch::configuration::ParseConfiguration::readDoubleOptional(cfg.wallOscillations, subtag, "wall-oscillations");
105 :
106 4 : subtag = node->FirstChildElement("coupling");
107 4 : if (subtag == NULL) {
108 0 : std::cout << "Could not read input file couette.xml: Missing subtag: coupling" << std::endl;
109 0 : exit(EXIT_FAILURE);
110 : }
111 4 : tarch::configuration::ParseConfiguration::readIntMandatory(cfg.couplingCycles, subtag, "coupling-cycles");
112 4 : tarch::configuration::ParseConfiguration::readBoolMandatory(cfg.twoWayCoupling, subtag, "two-way-coupling");
113 4 : tarch::configuration::ParseConfiguration::readBoolMandatory(cfg.md2Macro, subtag, "send-from-md-to-macro");
114 4 : tarch::configuration::ParseConfiguration::readBoolMandatory(cfg.macro2Md, subtag, "send-from-macro-to-md");
115 4 : tarch::configuration::ParseConfiguration::readIntMandatory(cfg.filterInitCycles, subtag, "filter-init-cycles");
116 4 : tarch::configuration::ParseConfiguration::readIntMandatory(cfg.csvEveryTimestep, subtag, "write-csv-every-timestep");
117 4 : tarch::configuration::ParseConfiguration::readBoolMandatory(cfg.computeSNR, subtag, "compute-snr");
118 :
119 4 : subtag = node->FirstChildElement("microscopic-solver");
120 4 : if (subtag == NULL) {
121 0 : std::cout << "Could not read input file " << filename
122 : << ": Missing subtag: "
123 0 : "microscopic-solver"
124 0 : << std::endl;
125 0 : exit(EXIT_FAILURE);
126 : }
127 4 : std::string type;
128 4 : tarch::configuration::ParseConfiguration::readStringMandatory(type, subtag, "type");
129 4 : if (type == "md") {
130 4 : cfg.miSolverType = SIMPLEMD;
131 4 : tarch::configuration::ParseConfiguration::readDoubleMandatory(cfg.temp, subtag, "temperature");
132 4 : tarch::configuration::ParseConfiguration::readIntMandatory(cfg.equSteps, subtag, "equilibration-steps");
133 :
134 4 : std::string num_MD;
135 4 : tarch::configuration::ParseConfiguration::readStringMandatory(num_MD, subtag, "number-md-simulations");
136 4 : if (num_MD == "dynamic") {
137 0 : cfg.totalNumberMDSimulations = -1;
138 0 : cfg.lowerBoundNumberMDSimulations = 1;
139 0 : tarch::configuration::ParseConfiguration::readIntOptional(cfg.lowerBoundNumberMDSimulations, subtag, "min-number-md");
140 0 : tarch::configuration::ParseConfiguration::readDoubleMandatory(cfg.absVelErrStart, subtag, "error-start");
141 0 : tarch::configuration::ParseConfiguration::readDoubleMandatory(cfg.absVelErrEnd, subtag, "error-end");
142 : } else {
143 4 : tarch::configuration::ParseConfiguration::readIntMandatory(cfg.totalNumberMDSimulations, subtag, "number-md-simulations");
144 4 : if (cfg.totalNumberMDSimulations < 1) {
145 0 : std::cout << "Could not read input file " << filename
146 : << ": "
147 0 : "number-md-simulations < 1"
148 0 : << std::endl;
149 0 : exit(EXIT_FAILURE);
150 : }
151 : }
152 4 : } else if (type == "synthetic") {
153 0 : cfg.miSolverType = SYNTHETIC;
154 0 : tarch::configuration::ParseConfiguration::readDoubleMandatory(cfg.noiseSigma, subtag, "noise-sigma");
155 0 : cfg.totalNumberMDSimulations = 1;
156 0 : tarch::configuration::ParseConfiguration::readIntOptional(cfg.totalNumberMDSimulations, subtag, "number-md-simulations");
157 0 : } else if (type == "ls1") {
158 0 : cfg.miSolverType = LS1;
159 :
160 0 : cfg.totalNumberMDSimulations = 1;
161 0 : tarch::configuration::ParseConfiguration::readDoubleMandatory(cfg.temp, subtag, "temperature");
162 0 : tarch::configuration::ParseConfiguration::readIntMandatory(cfg.equSteps, subtag, "equilibration-steps");
163 0 : tarch::configuration::ParseConfiguration::readIntOptional(cfg.totalNumberMDSimulations, subtag, "number-md-simulations");
164 : } else {
165 0 : std::cout << "Could not read input file " << filename
166 : << ": Unknown microscopic "
167 0 : "solver type!"
168 0 : << std::endl;
169 0 : exit(EXIT_FAILURE);
170 : }
171 4 : tarch::configuration::ParseConfiguration::readDoubleMandatory(cfg.density, subtag, "density");
172 :
173 4 : subtag = node->FirstChildElement("macroscopic-solver");
174 4 : if (subtag == NULL) {
175 0 : std::cout << "Could not read input file " << filename
176 : << ": Missing subtag: "
177 0 : "macroscopic-solver"
178 0 : << std::endl;
179 0 : exit(EXIT_FAILURE);
180 : }
181 20 : cfg.lbNumberProcesses = tarch::la::Vector<3, unsigned int>(1);
182 4 : tarch::configuration::ParseConfiguration::readStringMandatory(type, subtag, "type");
183 4 : if (type == "lb") {
184 0 : cfg.maSolverType = COUETTE_LB;
185 0 : tarch::configuration::ParseConfiguration::readVectorMandatory<3, unsigned int>(cfg.lbNumberProcesses, subtag, "number-of-processes");
186 0 : tarch::configuration::ParseConfiguration::readIntMandatory(cfg.plotEveryTimestep, subtag, "plot-every-timestep");
187 4 : } else if (type == "fd") {
188 4 : cfg.maSolverType = COUETTE_FD;
189 4 : tarch::configuration::ParseConfiguration::readVectorMandatory<3, unsigned int>(cfg.lbNumberProcesses, subtag, "number-of-processes");
190 8 : tarch::configuration::ParseConfiguration::readIntMandatory(cfg.plotEveryTimestep, subtag, "plot-every-timestep");
191 : }
192 : #if (BUILD_WITH_OPENFOAM)
193 : else if (type == "foam") {
194 : cfg.maSolverType = COUETTE_FOAM;
195 : tarch::configuration::ParseConfiguration::readIntMandatory(cfg.plotEveryTimestep, subtag, "plot-every-timestep");
196 : tarch::configuration::ParseConfiguration::readStringMandatory(cfg.foam.directory, subtag, "foam-setup-directory");
197 : tarch::configuration::ParseConfiguration::readStringMandatory(cfg.foam.folder, subtag, "foam-setup-folder");
198 : tarch::configuration::ParseConfiguration::readVectorMandatory<12, unsigned int>(cfg.foam.boundariesWithMD, subtag, "boundaries-with-MD");
199 : }
200 : #endif
201 0 : else if (type == "analytical") {
202 0 : cfg.maSolverType = COUETTE_ANALYTICAL;
203 0 : if (!(cfg.wallVelocity[1] == 0.0 && cfg.wallVelocity[2] == 0.0)) {
204 0 : std::cout << "analytic solver only supports flow in x-direction" << std::endl;
205 0 : exit(EXIT_FAILURE);
206 : }
207 : } else {
208 0 : std::cout << "Could not read input file " << filename
209 : << ": Unknown macroscopic "
210 0 : "solver type!"
211 0 : << std::endl;
212 0 : exit(EXIT_FAILURE);
213 : }
214 4 : double vis;
215 4 : tarch::configuration::ParseConfiguration::readDoubleMandatory(vis, subtag, "viscosity");
216 4 : cfg.kinVisc = vis / cfg.density;
217 4 : tarch::configuration::ParseConfiguration::readIntMandatory(cfg.initAdvanceCycles, subtag, "init-advance-cycles");
218 :
219 4 : subtag = node->FirstChildElement("tws-loop");
220 4 : if (subtag == NULL)
221 4 : cfg.twsLoop = false;
222 : else {
223 0 : cfg.twsLoop = true;
224 0 : tarch::configuration::ParseConfiguration::readIntMandatory(cfg.twsLoopMin, subtag, "min");
225 0 : tarch::configuration::ParseConfiguration::readIntMandatory(cfg.twsLoopMax, subtag, "max");
226 0 : cfg.twsLoopStep = 1;
227 0 : tarch::configuration::ParseConfiguration::readIntOptional(cfg.twsLoopStep, subtag, "step");
228 : }
229 :
230 4 : if (cfg.miSolverType == SYNTHETIC) {
231 0 : if (cfg.macro2Md || cfg.totalNumberMDSimulations > 1 || cfg.lbNumberProcesses[0] != 1 || cfg.lbNumberProcesses[1] != 1 || cfg.lbNumberProcesses[2] != 1) {
232 0 : std::cout << "Invalid configuration: Synthetic MD runs sequentially on "
233 : "rank 0 only. "
234 : << "It does neither support parallel communication nor "
235 0 : "multi-instance sampling"
236 0 : << std::endl;
237 0 : exit(EXIT_FAILURE);
238 : }
239 : }
240 4 : if (cfg.maSolverType == COUETTE_ANALYTICAL) {
241 0 : if (cfg.twoWayCoupling) {
242 0 : std::cout << "Invalid configuration: COUETTE_ANALYTICAL does not "
243 0 : "support twoWayCoupling"
244 0 : << std::endl;
245 0 : exit(EXIT_FAILURE);
246 : }
247 : }
248 :
249 8 : return cfg;
250 4 : }
251 :
252 : #if (BUILD_WITH_OPENFOAM)
253 : /** @brief holds the variables necessary for the interface to the IcoFoam
254 : * solver */
255 : struct FoamConfig {
256 : /** @brief the path to the directory, where the folder with the IcoFoam
257 : * OpenFOAM setup files are */
258 : std::string directory;
259 : /** @brief the name of the OpenFOAM folder */
260 : std::string folder;
261 : /** @brief the cubic mesh with a cubic hole has 12 boundaries, this vector
262 : * tells which of them
263 : * shall be coupled with the md; The order has to be the same as in
264 : * the blockMeshDict */
265 : tarch::la::Vector<12, unsigned int> boundariesWithMD;
266 : };
267 : #endif
268 :
269 : /** @brief channel is always expected to have origin at (0.0,0.0,0.0) and to
270 : * be cubic (MD 30: 50.0, MD 60: 100.0, MD 120: 200.0) */
271 : double channelheight;
272 : /** @brief velocity of moving wall (lower boundary moves) */
273 : tarch::la::Vector<3, double> wallVelocity;
274 : /** @brief number of coupling cycles that will be done, while the wall
275 : * velocity is the wallInitVelocity */
276 : int wallInitCycles;
277 : /** @brief the velocity at the moving wall (z=0) while the wallInitCycles*/
278 : tarch::la::Vector<3, double> wallInitVelocity;
279 : /** @brief total number of oscillation periods of the oscillating wall
280 : * velocity*/
281 : double wallOscillations;
282 : /** @brief number of coupling cycles, that is continuum time steps; MD/DPD:
283 : * 1000 */
284 : int couplingCycles;
285 : /** @brief true if data will be send & received from the md to the continuum
286 : * solver */
287 : bool md2Macro;
288 : /** @brief true if data will be send & received from the continuum to the md
289 : * solver */
290 : bool macro2Md;
291 : /** @brief true if the signal to noise ratio shall be evaluated */
292 : bool computeSNR;
293 : /** @brief true if from the md solver will be applied as boundary condition
294 : * for the continuum solver */
295 : bool twoWayCoupling;
296 : /** @brief number of coupling cycles before a filter is applied*/
297 : int filterInitCycles;
298 : /** @brief the time step interval for writing the md data to csv files */
299 : int csvEveryTimestep;
300 : /** @brief the type of continuum solver */
301 : MacroSolverType maSolverType;
302 : /** @brief the type of md solver */
303 : MicroSolverType miSolverType;
304 : /** @brief the general density of the fluid under consideration */
305 : double density;
306 : /** @brief the kinematic viscosity of the fluid under consideration */
307 : double kinVisc;
308 : /** @brief only for LB couette solver: number of processes */
309 : tarch::la::Vector<3, unsigned int> lbNumberProcesses;
310 : /** @brief only for LB couette solver: VTK plotting per time step */
311 : int plotEveryTimestep;
312 : /** @brief number of cycles the continuum solver is advanced before the
313 : * coupling is enabled */
314 : int initAdvanceCycles;
315 : /** @brief the start temperature for the fluid under consideration */
316 : double temp;
317 : /** @brief number of equilibartion time steps = number of time steps that
318 : * the md will run before the coupling is enabled */
319 : int equSteps;
320 : /** @brief the number of md simulation instances in a multi-instance
321 : * coupling, -1 = dynamic */
322 : int totalNumberMDSimulations;
323 : /** @brief the minimum number of md simulation instances in dynamic MD coupling */
324 : int lowerBoundNumberMDSimulations;
325 : /** @brief only for dynamic MD: target absolute velocity error at start of all coupling cycles */
326 : double absVelErrStart;
327 : /** @brief only for dynamic MD: target absolute velocity error at end of all coupling cycles */
328 : double absVelErrEnd;
329 : /** @brief the sigma for the random noise in the case of synthetic md solver
330 : */
331 : double noiseSigma;
332 : /** @todo piet */
333 : bool twsLoop;
334 : /** @todo piet*/
335 : int twsLoopMin;
336 : /** @todo piet */
337 : int twsLoopMax;
338 : /** @todo piet */
339 : int twsLoopStep;
340 :
341 : #if (BUILD_WITH_OPENFOAM)
342 : /** @brief the configurations for the OpenFoam solver */
343 : FoamConfig foam;
344 : #endif
345 : };
346 :
347 : #endif
|