LBIBCell
 All Classes Functions Variables Friends Pages
SimulationRunner.cpp
1 /* Copyright (c) 2013 David Sichau <mail"at"sichau"dot"eu>
2  * 2013-2015 Simon Tanaka <tanakas"at"gmx"dot"ch>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  * THE SOFTWARE.
21  */
22 #include <LbmLib/include/geometry/GeometryHandler.hpp>
23 #include <LbmLib/include/nodes/BoundaryNode.hpp>
24 #include <LbmLib/include/nodes/PhysicalNode.hpp>
25 
26 #include <LbmLib/include/SimulationRunner.hpp>
27 
28 #include <LbmLib/include/reportHandler/ReportHandler.hpp>
29 #include <LbmLib/include/solver/MassSolver/MassSolverFactory.hpp>
30 
31 #include <LbmLib/include/GlobalSimulationParameters.hpp>
32 #include <LbmLib/include/solver/BoundaryAbstractSolver.hpp>
33 #include <LbmLib/include/solver/CDESolver/CDEAbstractSolver.hpp>
34 #include <LbmLib/include/solver/FluidSolver/FluidSolver.hpp>
35 #include <UtilLib/include/ProgressBar.hpp>
36 #include <omp.h>
37 #include <cassert>
38 #include <fstream>
39 #include <iomanip>
40 #include <iostream>
41 #include <sstream>
42 #include <string>
43 #include <limits.h>
44 
45 namespace {
46 unsigned int t;
47 }
48 
49 namespace LbmLib {
51  const geometry::GeometryHandler& geometry,
52  const reportHandler::ReportHandler& reportHandler)
53  :
54  geometryHandler_(geometry),
55  reportHandler_(reportHandler)
56 {
57  this->setTau(Parameters.getTauFluid());
58  const auto& cdeSolvers = Parameters.getCdeSolvers();
59  for (const auto& cdeSolver : cdeSolvers)
60  {
61  this->addCDESolver(cdeSolver.first);
62  this->setTau(cdeSolver.second, cdeSolver.first);
63  }
64 }
65 
67 {}
68 
70  UtilLib::ProgressBar progress(Parameters.getIterations() - 1);
71  try {
72  for (t = 1; t < Parameters.getIterations()+1; t++) {
73  this->calculateForce();
74  this->distributeForce();
75  this->preAdvect();
76  this->advect();
77  this->postAdvect();
78  this->collide();
79  this->collectVelocity();
80 
81  this->moveGeometry();
82 
83  this->remeshBoundary();
84  if (Parameters.getCurrentIteration()%10 == 0) {
85  this->forceSolver_.deleteAllForces();
86  this->coarsenBoundary();
87  }
88 
89  this->applyMassSolvers();
90  this->applyBioSolvers();
91 
92 #ifndef NDEBUG
93  this->checkLatticeIntegrity();
94  this->checkBoundaryIntegrity();
95 #endif
96 
97  progress++;
98  Parameters++;
99  this->reportHandler_.writeReport(t);
100  }
101  } catch(const std::exception& exp) {
102  Parameters.setReportSteps(1);
103  this->reportHandler_.writeCrashReport(t);
104  this->writeSimulation("output/CRASH_forceOut_" + std::to_string(t) + ".txt",
105  "output/CRASH_geoOut_" + std::to_string(t) + ".txt",
106  "output/CRASH_parameterOut_" + std::to_string(t) + ".txt",
107  "output/CRASH_solverOut_" + std::to_string(t) + ".txt");
108  std::cout << exp.what() << std::endl;
109  }
110 }
111 
113  const std::string& forceFileName,
114  const std::string& geometryFileName,
115  const std::string& parameterFileName,
116  const std::string& solverFileName) const {
117  this->forceSolver_.writeForceSolver(forceFileName);
118  this->geometryHandler_.getGeometry().writeGeometry(geometryFileName);
119  Parameters.writeGlobalSimulationParameters(parameterFileName);
120 
121  //loadable fulldump of the solvers:
122  std::ofstream fileStream;
123  fileStream.open(solverFileName);
124  if (fileStream.is_open()) {
125  fileStream << "#Solvers (xPos\tyPos\tDistributions...)\n";
126  fileStream << "#BEGIN FluidSolver\n";
127  for (auto it : geometryHandler_.getPhysicalNodes()) {
128  for (auto i : it) {
129  i->getFluidSolver().writeSolver(&fileStream);
130  }
131  }
132  fileStream << "#END FluidSolver\n";
133  for (auto cde : geometryHandler_.getPhysicalNodes()[0][0]->
134  getCDESolvers()) {
135  fileStream << "#BEGIN " << cde->getName() << "\n";
136  for (auto it : geometryHandler_.getPhysicalNodes()) {
137  for (auto i : it) {
138  i->getCDESolver(cde->getId()).writeSolver(&fileStream);
139  }
140  }
141  fileStream << "#END " << cde->getName() << "\n";
142  }
143  } else {
144  lbm_fail(
145  "Cannot open the output file for the force solver.");
146  }
147 
148  fileStream.close();
149 }
150 
151 void SimulationRunner::initSolvers(const std::string& filename) {
152  std::ifstream fileStream;
153  fileStream.open(filename);
154  if (fileStream.is_open()) {
155  std::string line;
156  std::string solverName("");
157  while (std::getline(fileStream, line)) {
158  std::stringstream lineStream(line);
159  if (line.at(0) != '#') {
160  int x, y;
161  lineStream >> x >> y;
162  if (solverName == "FluidSolver") {
163  geometryHandler_.getPhysicalNodes()[y][x]->getFluidSolver()
164  .loadSolver(&lineStream);
165  } else {
166  // reset of the stringstream
167  lineStream.seekg(0);
168  geometryHandler_.getPhysicalNodes()[y][x]->getCDESolverSlow(
169  solverName).loadSolver(&lineStream);
170  }
171  } else if (line.find("#BEGIN") != std::string::npos) {
172  std::string temp;
173  lineStream >> temp >> solverName;
174  } else if (line.find("#END") != std::string::npos) {
175  solverName = "";
176  }
177  }
178  } else {
179  lbm_fail("Cannot find the force file.");
180  }
181  fileStream.close();
182 }
183 
184 void SimulationRunner::moveGeometry() {
185  // We cast away constness to allow this function call where the Lattice might be changed.
186  // As this should not happens frequently we assume this as OK
187  const_cast<geometry::GeometryHandler&>(this->geometryHandler_).moveLattice();
188 }
189 
190 void SimulationRunner::remeshBoundary() {
191  while ( // remesh as long as there is nothing to remesh any more
192  // We cast away constness to allow this function call where the Lattice might be changed.
193  // As this should not happens frequently we assume this as OK
194  const_cast<geometry::GeometryHandler&>(this->geometryHandler_).remeshBoundary()
195  )
196  {
197  assert(this->geometryHandler_.checkGeometryIntegrity());
198  }
199 }
200 
201 void SimulationRunner::coarsenBoundary()
202 {
203  // We cast away constness to allow this function call where the Lattice might be changed.
204  // As this should not happens frequently we assume this as OK
205  const_cast<geometry::GeometryHandler&>(this->geometryHandler_).coarsenBoundary();
206  assert(this->geometryHandler_.checkGeometryIntegrity());
207 }
208 
209 void SimulationRunner::checkLatticeIntegrity()
210 {
211  const_cast<geometry::GeometryHandler&>(this->geometryHandler_).checkLatticeIntegrity();
212 }
213 
214 void SimulationRunner::checkBoundaryIntegrity()
215 {
216  const_cast<geometry::GeometryHandler&>(this->geometryHandler_).checkBoundaryNodeIntegrity();
217 }
218 
219 
220 void SimulationRunner::collectVelocity() {
221  typedef std::map<unsigned int,std::shared_ptr<nodes::GeometryNode> >::const_iterator MapIterator;
222  std::vector<MapIterator> helper_vector;
223 
224  // create helper_vector for parallelzation:
225  for (MapIterator it = this->geometryHandler_.getGeometry().getGeometryNodes().begin();
226  it != this->geometryHandler_.getGeometry().getGeometryNodes().end();
227  it++)
228  {
229  helper_vector.push_back(it);
230  }
231 
232  // collect velocity:
233 #pragma omp parallel for schedule(static)
234  for (size_t it=0; it<helper_vector.size(); ++it) {
235  helper_vector[it]->second->collectVelocity();
236  }
237 }
238 
239 void SimulationRunner::calculateForce() {
240  // the parallelisation is done in the force solver
241  this->forceSolver_.calculateForce(geometryHandler_.getGeometry().getGeometryNodes());
242 }
243 
244 void SimulationRunner::collide() {
245 #pragma omp parallel for schedule(dynamic)
246  for (unsigned int it = 0; it < geometryHandler_.getPhysicalNodes().size();
247  it++) {
248  for (unsigned int i = 0;
249  i < geometryHandler_.getPhysicalNodes()[0].size();
250  i++) {
251  nodes::PhysicalNode* node =
252  geometryHandler_.getPhysicalNodes()[it][i];
253  node->getFluidSolver().collide();
254  for (auto j = node->getCDESolvers().begin();
255  j != node->getCDESolvers().end();
256  j++) {
257  (*j)->collide();
258  }
259  }
260  }
261 }
262 
263 void SimulationRunner::advect() {
264 #pragma omp parallel for schedule(dynamic)
265  for (size_t it = 0; it < this->geometryHandler_.getPhysicalNodes().size();
266  it++)
267  { // loop x direction of the grid
268  for (unsigned int i = 0;
269  i < this->geometryHandler_.getPhysicalNodes()[0].size();
270  i++)
271  { // loop y direction of the grid
272  nodes::PhysicalNode* node =
273  this->geometryHandler_.getPhysicalNodes()[it][i];
274  node->getFluidSolver().advect();
275  for (auto j = node->getCDESolvers().begin();
276  j != node->getCDESolvers().end();
277  j++)
278  { // loop solvers
279  (*j)->advect();
280  }
281  }
282  }
283  for (const auto& it : this->geometryHandler_.getBoundaryNodes()) {
284  for (const auto bd : it->getBoundarySolvers()) {
285  bd.second->advect();
286  }
287  }
288 }
289 
291 
292  for (size_t it = 0; it < geometryHandler_.getPhysicalNodes().size();
293  it++) {
294 
295  for (const auto& i : geometryHandler_.getPhysicalNodes()[it]) {
296 
297  i->getFluidSolver().initSolver();
298  for (const auto& cde : i->getCDESolvers()) {
299  cde->initSolver();
300  }
301 
302  }
303 
304  }
305  reportHandler_.writeReport(0);
306 }
307 
309  for (size_t it = 0; it < geometryHandler_.getPhysicalNodes().size();
310  it++) {
311  for (const auto& i : geometryHandler_.getPhysicalNodes()[it]) {
312  i->getFluidSolver().setVelocity(fluidVelocity);
313  i->getFluidSolver().initSolver();
314  for (const auto& cde : i->getCDESolvers()) {
315  cde->initSolver();
316  }
317  }
318  }
319  // reportHandler_.writeReport(0);
320 }
321 
322 void SimulationRunner::preAdvect() {
323  typedef std::unordered_set<nodes::BoundaryNode*>::const_iterator ListIterator;
324  std::vector<ListIterator> helper_vector;
325 
326  // create helper vector for parallelization:
327  std::unordered_set<nodes::BoundaryNode*> tempBoundaryNodes = this->geometryHandler_.getBoundaryNodes();
328  for (ListIterator it=tempBoundaryNodes.begin();
329  it != tempBoundaryNodes.end();
330  ++it) {
331  helper_vector.push_back(it);
332  }
333 
334 #pragma omp parallel for schedule(dynamic)
335  for (size_t it=0;
336  it<helper_vector.size();
337  ++it) {
338  for (const auto bd : (*helper_vector[it])->getBoundarySolvers()) {
339  bd.second->preAdvect();
340  }
341  }
342 }
343 
344 void SimulationRunner::postAdvect() {
345  typedef std::unordered_set<nodes::BoundaryNode*>::const_iterator ListIterator;
346  std::vector<ListIterator> helper_vector;
347 
348  // create helper vector for parallelization:
349  std::unordered_set<nodes::BoundaryNode*> tempBoundaryNodes = this->geometryHandler_.getBoundaryNodes();
350  for (ListIterator it=tempBoundaryNodes.begin();
351  it != tempBoundaryNodes.end();
352  ++it) {
353  helper_vector.push_back(it);
354  }
355 
356 #pragma omp parallel for schedule(dynamic)
357  for (size_t it=0;
358  it<helper_vector.size();
359  ++it) {
360  for (const auto bd : (*helper_vector[it])->getBoundarySolvers()) {
361  bd.second->postAdvect();
362  }
363  }
364 }
365 
366 void SimulationRunner::applyMassSolvers()
367 {
368  for (auto it : this->massSolvers_) {
369  it->calculateMass(this->geometryHandler_.getPhysicalNodes());
370  }
371 }
372 
373 void SimulationRunner::applyBioSolvers()
374 {
375  for (auto it : this->bioSolvers_) {
376  (*it).applyBioProcess(const_cast<geometry::GeometryHandler&>(this->geometryHandler_),
377  this->forceSolver_
378  );
379  assert(this->geometryHandler_.checkGeometryIntegrity());
380  }
381 }
382 
383 void SimulationRunner::addCDESolver(const std::string& name) {
384  for (size_t it = 0; it < geometryHandler_.getPhysicalNodes().size();
385  it++) {
386  for (const auto& i : geometryHandler_.getPhysicalNodes()[it]) {
387  i->addCDESolver(name);
388  }
389  }
390 }
391 
392 void SimulationRunner::initForceSolver(const std::string& filename) {
393  this->forceSolver_.loadForceFile(filename);
394 }
395 
397 {
398  return this->forceSolver_;
399 }
400 
401 void SimulationRunner::addMassSolver(const std::string& name) {
402  this->massSolvers_.push_back(solver::MassSolverFactory::instance().createObject(name));
403 }
404 
405 void SimulationRunner::addBioSolver(const std::string &name)
406 {
407  this->bioSolvers_.push_back(solver::BioSolverFactory::instance().createObject(name));
408 }
409 
410 void SimulationRunner::setTau(
411  double tau,
412  const std::string& name) {
413  for (size_t it = 0; it < geometryHandler_.getPhysicalNodes().size();
414  it++) {
415  for (const auto& i : geometryHandler_.getPhysicalNodes()[it]) {
416  if (name.empty()) {
417  i->getFluidSolver().setTau(tau);
418  } else {
419  i->getCDESolverSlow(name).setTau(tau);
420  }
421  }
422  }
423 }
424 
425 void SimulationRunner::distributeForce() {
426  typedef std::map<unsigned int,std::shared_ptr<nodes::GeometryNode> >::const_iterator MapIterator;
427 
428  // first reset the forces:
429 #pragma omp parallel for collapse(1) schedule(dynamic)
430  for (size_t it = 0; it < geometryHandler_.getPhysicalNodes().size();
431  it++) {
432  for (size_t i = 0; i < geometryHandler_.getPhysicalNodes()[0].size();
433  i++ )
434  {
435  geometryHandler_.getPhysicalNodes()[it][i]->getFluidSolver().resetForce();
436  }
437  }
438 
439  // build helper vector with iterators for parallelization:
440  std::vector<MapIterator> helper_vector;
441  for (MapIterator it = this->geometryHandler_.getGeometry().getGeometryNodes().begin();
442  it != this->geometryHandler_.getGeometry().getGeometryNodes().end();
443  it++) {
444  helper_vector.push_back(it);
445 
446  }
447 
448  // distribute forces:
449 #pragma omp parallel for schedule(static)
450  for (size_t it=0; it< helper_vector.size(); ++it) {
451  helper_vector[it]->second->distributeForce();
452  }
453 }
454 } // end namespace
void addMassSolver(const std::string &name)
adds a mass solver to the simulation
SimulationRunner(const geometry::GeometryHandler &geometry, const reportHandler::ReportHandler &reportHandler)
constructor
void initSolvers()
initSolvers Initialises the solvers
The actual force solver.
Definition: ForceSolver.hpp:43
const std::map< unsigned int, std::shared_ptr< nodes::GeometryNode > > & getGeometryNodes() const
Getter for the geometry nodes.
Definition: Geometry.hpp:92
void runSimulation()
runSimulation Runs the main Simulation loop
void addBioSolver(const std::string &name)
Adds a BioSolver.
bool checkGeometryIntegrity(void) const
checkGeometryIntegrity
static T & instance()
Definition: Singleton.hpp:90
a class for reporting the current simulation status. Usage: construct an object of this class with th...
Definition: ProgressBar.hpp:36
const Geometry & getGeometry() const
getter for the geometry
const solver::ForceSolver & getForceSolver(void)
getForceSolver Returns a reference to the solver::ForceSolver
void writeSimulation(const std::string &forceFileName, const std::string &geometryFileName, const std::string &parameterFileName, const std::string &solverFileName) const
writes the simulation to the files
void writeForceSolver(const std::string &filename) const
writes the forces to the file
void initForceSolver(const std::string &fileName)
Inits the Force solver to calculate the forces on the geometry nodes.
void writeCrashReport(unsigned int time) const
writeCrashReport Dumps the reporters when crashed.
const std::unordered_set< nodes::BoundaryNode * > & getBoundaryNodes() const
Getter for the Boundary nodes.
void writeReport(unsigned int time) const
writeReport Writes the report if the time step fits to the reportStep
void writeGeometry(const std::string &fileName) const
writeGeometry Writes the geometry to the file
Definition: Geometry.cpp:77
void loadForceFile(const std::string &filename)
loading of the force solver
Definition: ForceSolver.cpp:89
const std::vector< std::vector< nodes::PhysicalNode * > > & getPhysicalNodes() const
getPhysicalNodes Getter method for the physical node grid
the report handler which stores the reporters
class responsible for generating the internal geometry representation
void deleteAllForces()
reset all forces
void calculateForce(const std::map< unsigned int, std::shared_ptr< nodes::GeometryNode > > &nodes)
calculates the Force
Definition: ForceSolver.cpp:42