22 #include <LbmLib/include/GlobalSimulationParameters.hpp>
23 #include <LbmLib/include/geometry/GeometryHandler.hpp>
24 #include <LbmLib/include/nodes/BoundaryNode.hpp>
25 #include <LbmLib/include/nodes/GeometryNode.hpp>
26 #include <LbmLib/include/nodes/PhysicalNode.hpp>
27 #include <LbmLib/include/solver/CDESolver/CDEAbstractSolver.hpp>
29 #include <LbmLib/include/Constants.hpp>
30 #include <LbmLib/include/Direction.hpp>
32 #include <UtilLib/include/Exception.hpp>
33 #include <UtilLib/include/Log.hpp>
35 #include <boost/geometry.hpp>
36 #include <boost/geometry/geometries/point_xy.hpp>
52 : geometry_(geometry) {
53 this->generatePhysicalGrid();
58 void GeometryHandler::updateDomainIdentifier() {
59 #pragma omp parallel for schedule(dynamic)
60 for (
size_t y = 0; y < physicalGrid_.size(); y++) {
61 for (
size_t x = 0; x < physicalGrid_[0].size(); x++) {
62 assert(physicalGrid_[y][x] !=
nullptr);
63 physicalGrid_[y][x]->updateDomainIdentifier();
68 void GeometryHandler::updateAllDomainIdentifiers()
70 #pragma omp parallel for schedule(dynamic)
71 for (
unsigned int y = 0; y < Parameters.getSizeY(); y++) {
72 unsigned int currentDomainId =
73 this->physicalGrid_[y][0]->getDomainIdentifier();
74 if (currentDomainId!=0) {
75 lbm_fail(
"domainID at the left boundary must be 0.");
77 for (
unsigned int x = 1; x < Parameters.getSizeX(); x++) {
78 if (this->physicalGrid_[y][x]->getBoundaryNeighbour(W) != nullptr ) {
80 this->physicalGrid_[y][x]->getBoundaryNeighbour(W)->getDomainIdentifier();
82 this->physicalGrid_[y][x]->setDomainIdentifier(currentDomainId);
88 for (
auto it : physicalGrid_) {
95 for (
auto b : boundaryNodes_) {
103 typedef boost::geometry::model::d2::point_xy<double> point;
104 typedef boost::geometry::model::polygon< point,false,false > Polygon;
105 std::map<unsigned int,std::vector<std::shared_ptr<LbmLib::geometry::Connection> > > celldefinition;
106 std::map<unsigned int, Polygon> polygonmap;
107 std::shared_ptr<LbmLib::geometry::Connection> startC =
nullptr;
108 std::shared_ptr<LbmLib::geometry::Connection> tempC =
nullptr;
109 std::map<unsigned int, double> arealist;
112 for (
auto it : this->
getGeometry().getConnections()) {
113 celldefinition[(*it).getDomainIdentifier()].push_back(it);
117 for (
auto it : celldefinition) {
118 startC = it.second[0];
121 boost::geometry::append(polygonmap[it.first], boost::geometry::make<point>(
122 tempC->getGeometryNodes().second->getXPos(),
123 tempC->getGeometryNodes().second->getYPos()));
124 tempC = tempC->getGeometryNodes().second->getConnection<1>();
125 }
while(tempC != startC);
129 for (
auto it : polygonmap) {
130 arealist[it.first] = boost::geometry::area(it.second);
138 std::map<unsigned int, double> accumulatedcellconcentration;
140 for (
unsigned int y = 0; y < Parameters.getSizeY(); y++) {
141 for (
unsigned int x = 1; x < Parameters.getSizeX(); x++) {
142 accumulatedcellconcentration[this->physicalGrid_[y][x]->getDomainIdentifier()] +=
143 this->physicalGrid_[y][x]->getCDESolverSlow(name).getC();;
146 return accumulatedcellconcentration;
152 this->perturbConnections();
155 this->connectGeometryNodesToPhysicalNodes();
158 for (
auto b : this->boundaryNodes_) {
159 b->getPhysicalNeighbour()->resetBoundaryNodes();
163 this->boundaryNodes_.clear();
166 this->generateBoundaryNodes();
169 this->updateAllDomainIdentifiers();
178 const std::shared_ptr<nodes::GeometryNode> p2,
179 const std::map<std::string, std::vector<std::string> > boundaryconditiondescriptor,
180 const unsigned int domainidentifier)
184 boundaryconditiondescriptor,
201 std::array<Direction, 4> dir {{N,S,E,W}};
203 for (
unsigned int y = 0; y < Parameters.getSizeY(); y++) {
204 for (
unsigned int x = 0; x < Parameters.getSizeX(); x++) {
205 myID = this->physicalGrid_[y][x]->getDomainIdentifier();
209 if (this->physicalGrid_[y][x]->getBoundaryNeighbour(d) ==
nullptr) {
210 if (myID != this->physicalGrid_[y][x]->getPhysicalNeighbour(d)->getDomainIdentifier()) {
211 std::stringstream message;
212 message <<
"Grid integrity not given (domainID jump to PhysicalNode neighbor): ";
213 message <<
"time=" << Parameters.getCurrentIteration() <<
"; ";
214 message <<
"position=(" << x <<
"," << y <<
"); ";
215 message <<
"my domainID=" << myID <<
"; ";
216 message <<
"neighbor domainID=" << this->physicalGrid_[y][x]->getPhysicalNeighbour(d)->getDomainIdentifier() <<
"; ";
217 message <<
"direction=" << d;
218 LOG(UtilLib::logINFO) << message.str().c_str();
219 lbm_fail(message.str().c_str());
226 if (this->physicalGrid_[y][x]->getBoundaryNeighbour(d) !=
nullptr) {
227 if (myID != this->physicalGrid_[y][x]->getBoundaryNeighbour(d)->getDomainIdentifier()) {
228 std::stringstream message;
229 message <<
"Grid integrity not given (domainID jump to BoundaryNode neighbor): ";
230 message <<
"time=" << Parameters.getCurrentIteration() <<
"; ";
231 message <<
"position=(" << x <<
"," << y <<
"); ";
232 message <<
"my domainID=" << myID <<
"; ";
233 message <<
"neighbor domainID=" << this->physicalGrid_[y][x]->getBoundaryNeighbour(d)->getDomainIdentifier() <<
"; ";
234 message <<
"direction=" << d;
235 LOG(UtilLib::logINFO) << message.str().c_str();
236 lbm_fail(message.str().c_str());
246 std::array<Direction, 4> dir {{N,S,E,W}};
248 for (
unsigned int y = 0; y < Parameters.getSizeY(); y++) {
249 for (
unsigned int x = 0; x < Parameters.getSizeX(); x++) {
251 if (this->physicalGrid_[y][x]->getBoundaryNeighbour(d) !=
nullptr) {
252 if (this->physicalGrid_[y][x]->getPhysicalNeighbour(d)->getBoundaryNeighbour(getInverseDirection(d)) ==
nullptr) {
253 std::stringstream message;
254 message <<
"BoundaryNode integrity not given: ";
255 message <<
"time=" << Parameters.getCurrentIteration() <<
"; ";
256 message <<
"PhysicalNode (" << x <<
"," << y <<
"); ";
257 message <<
"direction " << d <<
"; ";
258 LOG(UtilLib::logINFO) << message.str().c_str();
259 lbm_fail(message.str().c_str());
271 #pragma omp parallel for schedule(dynamic) private(id)
272 for (
size_t y = 0; y < physicalGrid_.size(); y++) {
273 for (
size_t x = 0; x < physicalGrid_[0].size(); x++) {
274 assert(physicalGrid_[y][x] !=
nullptr);
275 id = this->physicalGrid_[y][x]->getDomainIdentifier();
278 if (celltrackermap.find(
id) == celltrackermap.end() )
283 celltrackermap[id] = 1;
284 std::stringstream message;
285 message <<
"GeometryHandler::copyCellTypeToPhysicalNodes(): Could not find domainID="
286 <<
id <<
"; added it and set to cellType=1. " ;
288 message <<
"The celltrackermap reads: [domainID/cellType]: ";
289 for (
auto it : celltrackermap) {
290 message <<
"[" << it.first <<
"/" << it.second <<
"] ";
292 LOG(UtilLib::logINFO) << message.str().c_str();
296 this->physicalGrid_[y][x]->setCellType(
305 #pragma omp parallel for schedule(dynamic)
306 for (
size_t y = 0; y < physicalGrid_.size(); y++) {
307 for (
size_t x = 0; x < physicalGrid_[0].size(); x++) {
308 assert(physicalGrid_[y][x] !=
nullptr);
309 if (this->physicalGrid_[y][x]->getDomainIdentifier() == domainidentifier) {
310 this->physicalGrid_[y][x]->setCellType(celltype);
318 return this->cellTypeTrackerMap_;
326 void GeometryHandler::perturbConnections() {
327 std::map<unsigned int,std::shared_ptr<LbmLib::geometry::Connection> > celldefinitionmap;
328 std::vector<std::shared_ptr<LbmLib::geometry::Connection> > celldefinitionvector;
329 std::shared_ptr<LbmLib::geometry::Connection> startC =
nullptr;
330 std::shared_ptr<LbmLib::geometry::Connection> tempC =
nullptr;
333 for (
auto it : this->
getGeometry().getConnections()) {
334 if (celldefinitionmap.find((*it).getDomainIdentifier()) == celldefinitionmap.end()) {
335 celldefinitionmap[(*it).getDomainIdentifier()] = it;
340 for (
auto it : celldefinitionmap) {
341 celldefinitionvector.push_back(it.second);
345 #pragma omp parallel for schedule(dynamic) private(startC,tempC)
347 it<celldefinitionvector.size();
349 startC = celldefinitionvector[it];
352 tempC->perturbConnection();
353 tempC = tempC->getGeometryNodes().second->getConnection<1>();
354 }
while(tempC != startC);
361 this->perturbConnections();
364 for (
auto b : this->boundaryNodes_) {
365 b->getPhysicalNeighbour()->resetBoundaryNodes();
369 this->boundaryNodes_.clear();
372 this->generateBoundaryNodes();
375 this->connectGeometryNodesToPhysicalNodes();
378 this->updateDomainIdentifier();
379 this->updateAllDomainIdentifiers();
387 std::vector<std::shared_ptr<Connection> > concopy(this->geometry_.
getConnections());
388 unsigned int counter = 0;
390 for (
auto c = concopy.begin();
393 if ((*c)->getLength()>MAXLENGTH) {
395 const double x1 = (*c)->getGeometryNodes().first->getXPos();
396 const double y1 = (*c)->getGeometryNodes().first->getYPos();
397 const double x2 = (*c)->getGeometryNodes().second->getXPos();
398 const double y2 = (*c)->getGeometryNodes().second->getYPos();
399 const unsigned int newnodeID =
402 const std::shared_ptr<nodes::GeometryNode> newnode =
406 std::pair<std::shared_ptr<nodes::GeometryNode>
const,
407 std::shared_ptr<nodes::GeometryNode>
const> adjacentnodes = (*c)->getGeometryNodes();
408 std::map<std::string, std::vector<std::string> > descriptor = (*c)->getBoundaryConditionDescriptor();
409 const unsigned int domainID = (*c)->getDomainIdentifier();
420 adjacentnodes.second,
428 this->connectGeometryNodesToPhysicalNodes();
440 for (
auto it = this->
getGeometry().getGeometryNodes().begin();
445 P1 = (*it).second->getConnection<0>()->getGeometryNodes().first->getPos();
446 P2 = (*it).second->getConnection<1>()->getGeometryNodes().second->getPos();
447 length = std::sqrt( (P2.
x-P1.
x)*(P2.
x-P1.
x) + (P2.
y-P1.
y)*(P2.
y-P1.
y) );
449 if (length < MAXLENGTH) {
450 std::stringstream message;
451 message <<
"GeometryHandler::coarsenBoundary(): "
452 <<
"removed GeometryNode=" << (*it).first <<
"; "
453 <<
"length=" << length;
455 LOG(UtilLib::logINFO) << message.str().c_str();
463 void GeometryHandler::generatePhysicalGrid() {
464 for (
unsigned int y = 0; y < Parameters.getSizeY(); y++) {
465 std::vector<nodes::PhysicalNode*> temp;
466 for (
unsigned int x = 0; x < Parameters.getSizeX(); x++) {
469 physicalGrid_.push_back(temp);
472 this->makePhysicalGridConnections();
473 this->makePeriodicBoundary();
476 void GeometryHandler::makePhysicalGridConnections() {
479 for (
auto it : physicalGrid_) {
481 unsigned int x = i->getXPos();
482 unsigned int y = i->getYPos();
484 if (x != Parameters.getSizeX() - 1) {
485 i->setPhysicalNeighbour(physicalGrid_[y][x + 1], E);
488 if ((x != Parameters.getSizeX() - 1) &&
489 (y != Parameters.getSizeY() - 1) ) {
490 i->setPhysicalNeighbour(physicalGrid_[y + 1][x + 1], NE);
493 if (y != Parameters.getSizeY() - 1) {
494 i->setPhysicalNeighbour(physicalGrid_[y + 1][x], N);
497 if ((x != 0) && (y != Parameters.getSizeY() - 1)) {
498 i->setPhysicalNeighbour(physicalGrid_[y + 1][x - 1], NW);
502 i->setPhysicalNeighbour(physicalGrid_[y][x - 1], W);
505 if ((x != 0) && (y != 0)) {
506 i->setPhysicalNeighbour(physicalGrid_[y - 1][x - 1], SW);
510 i->setPhysicalNeighbour(physicalGrid_[y - 1][x], S);
513 if ((x != Parameters.getSizeX() - 1) && (y != 0)) {
514 i->setPhysicalNeighbour(physicalGrid_[y - 1][x + 1], SE);
520 void GeometryHandler::makePeriodicBoundary() {
522 for (
auto it : physicalGrid_) {
524 unsigned int x = i->getXPos();
525 unsigned int y = i->getYPos();
527 if (x == Parameters.getSizeX() - 1) {
528 i->setPhysicalNeighbour(physicalGrid_[y][0], E);
530 i->setPhysicalNeighbour(physicalGrid_[y - 1][0], SE);
532 i->setPhysicalNeighbour(physicalGrid_[Parameters.getSizeY()
535 if (y != Parameters.getSizeY() - 1) {
536 i->setPhysicalNeighbour(physicalGrid_[y + 1][0], NE);
538 i->setPhysicalNeighbour(physicalGrid_[0][0], NE);
542 if (y == Parameters.getSizeY() - 1) {
543 i->setPhysicalNeighbour(physicalGrid_[0][x], N);
544 if (x != Parameters.getSizeX() - 1) {
545 i->setPhysicalNeighbour(physicalGrid_[0][x + 1], NE);
548 i->setPhysicalNeighbour(physicalGrid_[0][x - 1], NW);
554 i->setPhysicalNeighbour(physicalGrid_[y -
555 1][Parameters.getSizeX()
558 i->setPhysicalNeighbour(physicalGrid_[Parameters.getSizeY()
563 if (y != Parameters.getSizeY() - 1) {
564 i->setPhysicalNeighbour(physicalGrid_[y + 1][Parameters.
568 i->setPhysicalNeighbour(physicalGrid_[0][Parameters.
572 i->setPhysicalNeighbour(physicalGrid_[y][Parameters.getSizeX()
577 i->setPhysicalNeighbour(physicalGrid_[Parameters.getSizeY()
580 if (x != Parameters.getSizeX() - 1) {
581 i->setPhysicalNeighbour(physicalGrid_[Parameters.getSizeY()
584 i->setPhysicalNeighbour(physicalGrid_[Parameters.getSizeY() -
591 void GeometryHandler::connectGeometryNodesToPhysicalNodes() {
592 typedef std::map<unsigned int,std::shared_ptr<nodes::GeometryNode> >::const_iterator MapIterator;
593 std::vector<MapIterator> helper_vector;
599 helper_vector.push_back(it);
602 #pragma omp parallel for schedule(static)
603 for (
size_t it=0; it<helper_vector.size(); ++it) {
604 this->connectGeometryNodesToPhysicalNodes(helper_vector[it]->second);
608 void GeometryHandler::connectGeometryNodesToPhysicalNodes(
609 std::shared_ptr<nodes::GeometryNode> pt) {
610 if (!pt->isUpdateNeeded())
613 double minX = pt->getXPos() - 2.0;
614 double maxX = pt->getXPos() + 2.0;
615 double minY = pt->getYPos() - 2.0;
616 double maxY = pt->getYPos() + 2.0;
620 "geometry point moved too close to the west boundary");
625 "geometry point moved too close to the south boundary");
628 if (maxX > Parameters.getSizeX()) {
630 "geometry point moved too close to the east boundary");
633 if (maxY > Parameters.getSizeY()) {
635 "geometry point moved too close to the north boundary");
639 for (
int x = std::ceil(minX); x <= std::floor(maxX); x++) {
640 for (
int y = std::ceil(minY); y <= std::floor(maxY); y++) {
641 pt->addPhysicalNode(this->physicalGrid_[y][x], (x * 4 + y) % 16);
646 void GeometryHandler::generateBoundaryNodes() {
647 std::vector<std::shared_ptr<Connection> > helper_vector =
655 it<helper_vector.size();
657 helper_vector[it]->generateBoundaryNodes(this->physicalGrid_, this->boundaryNodes_);
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 checkLatticeIntegrity()
Check lattice integrity.
const std::shared_ptr< nodes::GeometryNode > returnGeometryNode(const unsigned int nodeID) const
returnGeometryNode
const std::map< unsigned int, std::shared_ptr< nodes::GeometryNode > > & getGeometryNodes() const
Getter for the geometry nodes.
~GeometryHandler()
~GeometryHandler Destroyes all nodes.
std::map< unsigned int, double > computeAccumulatedDomainConcentrations(const std::string &name) const
Compute the accumulated concentrations of species name in all domains.
bool checkGeometryIntegrity(void) const
checkGeometryIntegrity
class representing a physical node
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.
T x
x the value in x direction
void coarsenBoundary()
If *Connection*s are too short, a GeometryNode is remove.
void moveLattice()
moveLattcie Updates the Lattice after the Geometric Points have been moved
const Geometry & getGeometry() const
getter for the geometry
void cureLattice()
Cure the Lattice: update *BoundaryNode*s, DomainIdentifier, and IB connections.
const std::vector< std::shared_ptr< Connection > > & getConnections() const
getConnections Getter for connections
bool checkGeometryIntegrity() const
checkGeometryIntegrity
const std::map< unsigned int, double > computeAreas() const
Compute the areas of the domains by using the domainIdentifiers.
unsigned int remeshBoundary()
If a Connection is too long, a GeometryNode is added and linked.
void checkBoundaryNodeIntegrity()
checkBoundaryNodeIntegrity Checks the integrity of the boundary node pairs.
unsigned int createGeometryNode(const double xpos, const double ypos)
Add a new GeometryNode.
GeometryHandler(const Geometry &geometry)
GeometryHandler Constructs the simulation grid.
class representing the external geometry
std::map< unsigned int, unsigned int > & getCellTypeTrackerMap(void)
Returns a reference to the cellTypeTrackerMap.
T y
y the value in y direction
std::map< unsigned int, unsigned int > getCellTypeTrackerMap(void) const
Returns a reference to the cellTypeTrackerMap.