LBIBCell
 All Classes Functions Variables Friends Pages
BioSolverAreaRegulator.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/solver/BioSolver/BioSolverAreaRegulator.hpp>
23 #include <LbmLib/include/GlobalSimulationParameters.hpp>
24 #include <LbmLib/include/geometry/GeometryHandler.hpp>
25 #include <LbmLib/include/nodes/PhysicalNode.hpp>
26 #include <vector>
27 #include <string>
28 #include <iostream>
29 #include <omp.h>
30 
31 namespace LbmLib {
32 namespace solver {
33 namespace {
34  const unsigned int FREQUENCY = 1;
35  const double TARGETAREA = 200.0;
36  const double TARGETAREA2 = 1000;
37  const double KP = 0.00001;
38  const double KI = 0.0;
39  const double MAXSOURCE = 0.004;
40 }
41 
42 BioSolverAreaRegulator::BioSolverAreaRegulator() : BioBaseSolver()
43 {}
44 
46  geometry::GeometryHandler& geometryhandler,
47  solver::ForceSolver& forcesolver
48  ) {
49  std::map<unsigned int,double> areas;
50  std::map<unsigned int,double> temperror;
51  std::map<unsigned int,double> sourcemap;
52  std::map<unsigned int,double> uncutsourcemap;
53  unsigned int domainid;
54  double source;
55 
56  if (Parameters.getCurrentIteration()%FREQUENCY != 0) {
57  return;
58  }
59 
60  // step 0: initialize
61  if (Parameters.getCurrentIteration()<5000) { // switch off after 5000
62  this->targetareamap_[1] = TARGETAREA2; // only cell 1 shall grow and divide
63  this->integratormap_[1] = 0.0; // initialize integrator with 0
64  }
65  else {
66  this->targetareamap_[1] = TARGETAREA; // only cell 1 shall grow and divide
67  }
68 
69  // step 1: compute areas
70  areas = geometryhandler.computeAreas();
71  //areas.erase(0); // remove fluid
72 
73  // step 2: update targetareamap
74  for (auto it : areas) {
75  if ( this->targetareamap_.find(it.first) == this->targetareamap_.end() ) { // not existing yet
76  this->targetareamap_[it.first] = TARGETAREA; // default
77  this->integratormap_[it.first] = 0.0; // initialize integrator with 0
78  }
79  }
80 
81  // step 3: update error map
82  for (auto it : areas) {
83  temperror[it.first] = this->targetareamap_[it.first] - areas[it.first];
84  }
85 
86  // step 4: update integral
87  for (auto it : areas) {
88  this->integratormap_[it.first] += temperror[it.first];
89  }
90 
91  // step 5: compute source
92  for (auto it : areas) {
93  uncutsourcemap[it.first] = KP*temperror[it.first] + KI*this->integratormap_[it.first];
94  }
95 
96  // step 6: cut the sources
97  for (auto it : uncutsourcemap)
98  {
99  if (uncutsourcemap[it.first] > MAXSOURCE) {
100  sourcemap[it.first] = MAXSOURCE;
101  }
102  else if (uncutsourcemap[it.first] < 0.0) {
103  sourcemap[it.first] = 0.0; // no negative source
104  }
105  else {
106  sourcemap[it.first] = uncutsourcemap[it.first];
107  }
108  }
109 
110  // step 5: add mass to the cells:
111 #pragma omp parallel for schedule(dynamic) private(domainid,source)
112  for (unsigned int ity = 0;
113  ity < geometryhandler.getPhysicalNodes().size();
114  ity++) { // loop y direction
115  for (unsigned int itx = 0;
116  itx < geometryhandler.getPhysicalNodes()[0].size();
117  itx++) { // loop x direction
118  domainid = geometryhandler.getPhysicalNodes()[ity][itx]->getDomainIdentifier();
119  if (domainid != 0) {
120  if (geometryhandler.getPhysicalNodes()[ity][itx]->getCellType()==1) {
121  geometryhandler.getPhysicalNodes()[ity][itx]->getFluidSolver().addMass(MAXSOURCE);
122  }
123  else {
124  source = sourcemap[domainid];
125  geometryhandler.getPhysicalNodes()[ity][itx]->getFluidSolver().addMass(source);
126  }
127  }
128  }
129  }
130 }
131 
132 const std::string BioSolverAreaRegulator::name = "BioSolverAreaRegulator";
133 }
134 } // end namespace
The actual force solver.
Definition: ForceSolver.hpp:43
virtual void applyBioProcess(geometry::GeometryHandler &geometryhandler, solver::ForceSolver &forcesolver)
Applies biological processes.
const std::map< unsigned int, double > computeAreas() const
Compute the areas of the domains by using the domainIdentifiers.
const std::vector< std::vector< nodes::PhysicalNode * > > & getPhysicalNodes() const
getPhysicalNodes Getter method for the physical node grid
class responsible for generating the internal geometry representation