22 #include <LbmLib/include/solver/BioSolver/tutorial_01_BioSolverCellDivision.hpp>
23 #include <LbmLib/include/geometry/Connection.hpp>
24 #include <LbmLib/include/geometry/GeometryHandler.hpp>
25 #include <LbmLib/include/nodes/PhysicalNode.hpp>
26 #include <LbmLib/include/GlobalSimulationParameters.hpp>
34 const unsigned int FREQUENCY = 100;
35 const double MAXCELLSIZE = 380;
37 namespace bg = boost::geometry;
39 tutorial_01_BioSolverCellDivision::tutorial_01_BioSolverCellDivision() : BioBaseSolver()
45 std::map<unsigned int,double> areas;
47 if (Parameters.getCurrentIteration()%FREQUENCY != 0) {
52 this->updateCellDefinition(geometryhandler);
58 for (
auto it : this->cellDefinition_) {
68 for (
auto it = ++areas.begin();
71 if (it->second > MAXCELLSIZE) {
74 this->divideCell(geometryhandler,it->first);
77 this->updateCellDefinition(geometryhandler);
94 void tutorial_01_BioSolverCellDivision::divideCell(
geometry::GeometryHandler& geometryhandler,
unsigned int domainidentifier)
96 const unsigned int newCellID = this->cellDefinition_.rbegin()->first + 1;
97 std::vector<std::shared_ptr<LbmLib::geometry::Connection> > affectedConnections;
100 affectedConnections = this->getTwoConnectionsLongestAxis(domainidentifier);
104 affectedConnections[0]->getGeometryNodes().first->setConnection<1>(
nullptr);
105 affectedConnections[0]->getGeometryNodes().second->setConnection<0>(
nullptr);
106 affectedConnections[1]->getGeometryNodes().first->setConnection<1>(
nullptr);
107 affectedConnections[1]->getGeometryNodes().second->setConnection<0>(
nullptr);
110 const std::map<std::string, std::vector<std::string> > descriptor1 =
111 affectedConnections[0]->getBoundaryConditionDescriptor();
112 const std::map<std::string, std::vector<std::string> > descriptor2 =
113 affectedConnections[1]->getBoundaryConditionDescriptor();
114 if (descriptor1 != descriptor2) {
115 lbm_fail(
"The method cannot handle cell division cases with heterogeneous boundary conditions.");
119 (*affectedConnections[0]).getGeometryNodes().first,
120 (*affectedConnections[1]).getGeometryNodes().second,
125 (*affectedConnections[1]).getGeometryNodes().first,
126 (*affectedConnections[0]).getGeometryNodes().second,
131 for (
auto it : affectedConnections) {
136 std::shared_ptr<LbmLib::geometry::Connection> CSTART = (*affectedConnections[1]).getGeometryNodes().second->getConnection<1>();
137 std::shared_ptr<LbmLib::geometry::Connection> C1 = CSTART;
138 std::shared_ptr<LbmLib::geometry::Connection> C2 =
nullptr;
139 CSTART->setDomainIdentifier(newCellID);
140 while (C2 != CSTART) {
141 C2 = (*C1).getGeometryNodes().second->getConnection<1>();
142 C2->setDomainIdentifier(newCellID);
146 LOG(UtilLib::logINFO) <<
"Cell with domainIdentifier=" <<
147 domainidentifier <<
" divided" <<
148 " at time " << Parameters.getCurrentIteration();
151 const std::vector<std::shared_ptr<LbmLib::geometry::Connection> >
152 tutorial_01_BioSolverCellDivision::getTwoConnectionsLongestAxis(
unsigned int domainidentifier)
154 typedef bg::model::point<double, 2, bg::cs::cartesian> point;
155 std::vector<std::shared_ptr<LbmLib::geometry::Connection> > affectedconnections;
157 double tempdist = 0.0;
158 double invslope = 0.0;
159 double intercept = 0.0;
160 std::shared_ptr<nodes::GeometryNode> N1 =
nullptr;
161 std::shared_ptr<nodes::GeometryNode> N2 =
nullptr;
167 for (
auto it1 : this->cellDefinition_[domainidentifier]) {
168 for (
auto it2 : this->cellDefinition_[domainidentifier]) {
169 tempdist = boost::geometry::distance(*((*it1).getGeometryNodes().first),
170 *((*it2).getGeometryNodes().first)
172 if (tempdist > dist) {
174 N1 = (*it1).getGeometryNodes().first;
175 N2 = (*it2).getGeometryNodes().first;
181 MIDPOINT.set<0>(0.5*(N1->getXPos()+N2->getXPos()));
182 MIDPOINT.set<1>(0.5*(N1->getYPos()+N2->getYPos()));
183 invslope = -(N2->getXPos()-N1->getXPos()) / (N2->getYPos()-N1->getYPos());
184 intercept = MIDPOINT.get<1>() - invslope*MIDPOINT.get<0>();
185 assert(std::isfinite(invslope));
186 assert(std::isfinite(intercept));
189 for (
auto it : this->cellDefinition_[domainidentifier]) {
190 C1 = (*it).getGeometryNodes().first->getYPos() > invslope*(*it).getGeometryNodes().first->getXPos() + intercept;
191 C2 = (*it).getGeometryNodes().second->getYPos() < invslope*(*it).getGeometryNodes().second->getXPos() + intercept;
192 if ( (C1 && C2) || (!C1 && !C2)) {
193 affectedconnections.push_back(it);
196 assert(affectedconnections.size()==2 &&
"More or less than 2 connections found in BioSolver::getTwoConnectionsLongestAxis().");
197 return affectedconnections;
200 const std::vector<std::shared_ptr<LbmLib::geometry::Connection> >
201 tutorial_01_BioSolverCellDivision::getTwoConnectionsRandomDirection(
unsigned int domainidentifier)
203 typedef bg::model::point<double, 2, bg::cs::cartesian> point;
204 std::vector<std::shared_ptr<LbmLib::geometry::Connection> > affectedconnections;
205 double invslope = 0.0;
206 double intercept = 0.0;
208 static std::mt19937 gen(seed);
211 std::uniform_real_distribution<> dis(0.0,2.0*M_PI);
214 Field<double> cm(0,0);
217 for (
auto it : this->cellDefinition_[domainidentifier]) {
218 cm += (*it).getGeometryNodes().first->getPos();
220 cm /= this->cellDefinition_[domainidentifier].size();
222 unsigned int counter = 0;
223 while (affectedconnections.size()!=2) {
225 invslope = std::tan(dis(gen));
226 intercept = cm.y - invslope*cm.x;
227 assert(std::isfinite(invslope));
228 assert(std::isfinite(intercept));
229 affectedconnections.clear();
232 for (
auto it : this->cellDefinition_[domainidentifier]) {
233 C1 = (*it).getGeometryNodes().first->getYPos() > invslope*(*it).getGeometryNodes().first->getXPos() + intercept;
234 C2 = (*it).getGeometryNodes().second->getYPos() < invslope*(*it).getGeometryNodes().second->getXPos() + intercept;
235 if ( (C1 && C2) || (!C1 && !C2)) {
236 affectedconnections.push_back(it);
242 lbm_fail(
"could not find cell division plane");
246 assert(affectedconnections.size()==2 &&
"More or less than 2 connections found in BioSolver::getTwoConnectionsLongestAxis().");
247 return affectedconnections;
250 void tutorial_01_BioSolverCellDivision::updateCellDefinition(geometry::GeometryHandler& geometryhandler)
252 this->cellDefinition_.clear();
253 for (
auto it : geometryhandler.getGeometry().getConnections()) {
254 this->cellDefinition_[(*it).getDomainIdentifier()].push_back(it);
258 const std::string tutorial_01_BioSolverCellDivision::name =
"tutorial_01_BioSolverCellDivision";
void copyCellTypeToPhysicalNodes(std::map< unsigned int, unsigned int > &celltrackermap)
update the celltypes of all *PhysicalNode*s with domainid
void eraseConnection(std::shared_ptr< Connection > toErase)
Erases the Connection.
void createConnection(std::shared_ptr< nodes::GeometryNode > const p1, std::shared_ptr< nodes::GeometryNode > const p2, const std::map< std::string, std::vector< std::string > > boundaryconditiondescriptor, const unsigned int domainidentifier)
Create a new connection.
void cureLattice()
Cure the Lattice: update *BoundaryNode*s, DomainIdentifier, and IB connections.
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.
std::map< unsigned int, unsigned int > & getCellTypeTrackerMap(void)
Returns a reference to the cellTypeTrackerMap.
class responsible for generating the internal geometry representation