22 #include <LbmLib/include/geometry/Connection.hpp>
23 #include <LbmLib/include/geometry/Geometry.hpp>
25 #include <LbmLib/include/Constants.hpp>
26 #include <LbmLib/include/GlobalSimulationParameters.hpp>
27 #include <UtilLib/include/Exception.hpp>
28 #include <UtilLib/include/Log.hpp>
41 #include <vtkSmartPointer.h>
42 #include <vtkPolygon.h>
43 #include <vtkCellArray.h>
44 #include <vtkPolyData.h>
45 #include <vtkDoubleArray.h>
46 #include <vtkStringArray.h>
47 #include <vtkPointData.h>
48 #include <vtkCellData.h>
49 #include <vtkMultiBlockDataSet.h>
50 #include <vtkXMLMultiBlockDataWriter.h>
51 #include <vtkXMLMultiBlockDataReader.h>
57 Parameters.getSizeY(),
58 (unsigned int)std::ceil(Parameters.getSizeX()/(double)MAXBINSIZE),
59 (unsigned int)std::ceil(Parameters.getSizeY()/(double)MAXBINSIZE)), isValidRangeQueryDataStructure_(0) {
61 int len = strlen(filename.c_str());
62 const char *last_four = &filename.c_str()[len-4];
64 if ( strcmp(last_four,
".vtm") == 0 )
66 this->loadGeometryVTK(filename);
68 else if ( strcmp(last_four,
".txt") == 0)
70 this->loadGeometryTXT(filename);
78 std::ofstream fileStream;
79 fileStream.open(fileName);
80 if (fileStream.is_open()) {
81 fileStream <<
"#Nodes (id\txPos\tyPos)\n";
83 node.second->writeNode(&fileStream);
86 "#Connection (nodeId1\tnodeId2\tdomainId\tbsolver\tcdesolver\t...)\n";
88 c->writeConnection(&fileStream);
91 lbm_fail(
"Cannot open the output file for the force solver.");
99 void Geometry::loadGeometryTXT(
const std::string& fileName) {
100 std::ifstream fileStream;
101 fileStream.open(fileName);
102 std::stringstream message;
104 this->cellTypeTrackerMap_[0] = 0;
105 message <<
"Loading geometry from txt file: cell type not supported; all cell types are set to 1.";
106 LOG(UtilLib::logINFO) << message.str().c_str();
108 if (this->connections_.size()!=0 ||
109 this->geometryNodes_.size()!=0) {
110 lbm_fail(
"Only load the geometry once.");
113 if (fileStream.is_open()) {
116 while (std::getline(fileStream, line)) {
117 std::stringstream lineStream(line);
118 if (line.find(
"#Connection") != std::string::npos) {
121 if (line.at(0) !=
'#') {
126 lineStream >>
id >> x >> y;
127 this->geometryNodes_[id] = std::make_shared<nodes::GeometryNode>(
131 this->fastneighborlist_.addElement(
132 this->geometryNodes_[
id]
136 unsigned int id1, id2, domainId;
137 std::map<std::string,
138 std::vector<std::string> > connectionType;
139 lineStream >> id1 >> id2 >> domainId;
140 this->cellTypeTrackerMap_[domainId] = 1;
141 std::string temp1, temp2;
142 while (lineStream >> temp1 >> temp2) {
143 connectionType[temp1].push_back(temp2);
145 this->connections_.push_back(std::make_shared<Connection>(
146 geometryNodes_[id1], geometryNodes_[id2],
147 connectionType, domainId));
150 this->geometryNodes_[id1]->setConnection<1>(this->connections_.back());
151 this->geometryNodes_[id2]->setConnection<0>(this->connections_.back());
156 lbm_fail(
"Cannot find the geometry.txt file.");
159 this->isValidRangeQueryDataStructure_ = 1;
162 void Geometry::loadGeometryVTK(
const std::string &fileName)
164 vtkSmartPointer<vtkMultiBlockDataSet> multiBDS_read =
165 vtkSmartPointer<vtkMultiBlockDataSet>::New ();
166 vtkSmartPointer<vtkXMLMultiBlockDataReader> reader =
167 vtkSmartPointer<vtkXMLMultiBlockDataReader>::New();
168 vtkSmartPointer<vtkPolyData> polygonPolyData_extract =
169 vtkSmartPointer<vtkPolyData>::New();
170 vtkSmartPointer<vtkPoints> points_extract =
171 vtkSmartPointer<vtkPoints>::New();
172 vtkSmartPointer<vtkCellArray> polygons_extract =
173 vtkSmartPointer<vtkCellArray>::New();
174 vtkSmartPointer<vtkDoubleArray> domainidentifierAttributeArray =
175 vtkSmartPointer<vtkDoubleArray>::New();
176 vtkSmartPointer<vtkDoubleArray> celltypeAttributeArray =
177 vtkSmartPointer<vtkDoubleArray>::New();
178 vtkSmartPointer<vtkDataArray> tempArray;
179 vtkSmartPointer<vtkAbstractArray> tempAbstractArray;
180 vtkSmartPointer<vtkStringArray> stringAttribute_extract =
181 vtkSmartPointer<vtkStringArray>::New();
183 unsigned int blockId_polygon;
184 unsigned int blockId_count = 0;
187 vtkIdType numPolygons;
188 vtkIdType cellLocation = 0;
192 std::map<std::string,
193 std::vector<std::string> > connectionType;
194 unsigned int id1,id2,domainId,cellType;
195 std::string temp1,temp2;
196 vtkStdString boundarystring;
198 this->cellTypeTrackerMap_[0] = 0;
200 reader->SetFileName(fileName.c_str());
202 if (stat (fileName.c_str(), &buffer) == 0) {
204 multiBDS_read->ShallowCopy(reader->GetOutput());
206 for (
unsigned int k=0; k<multiBDS_read->GetNumberOfBlocks(); ++k) {
207 polygonPolyData_extract->ShallowCopy(multiBDS_read->GetBlock(k));
208 if ( strcmp(multiBDS_read->GetBlock(k)->GetClassName(),
"vtkPolyData")==0 ) {
209 polygons_extract = polygonPolyData_extract->GetPolys();
210 if (polygons_extract->GetNumberOfCells() > 0) {
217 if (blockId_count != 1) {
218 lbm_fail(
"more or less than one vtk polygon block found in input geometry file found.");
221 polygonPolyData_extract->ShallowCopy(multiBDS_read->GetBlock(blockId_polygon));
222 points_extract = polygonPolyData_extract->GetPoints();
223 polygons_extract = polygonPolyData_extract->GetPolys();
224 numPolygons = polygons_extract->GetNumberOfCells();
227 for (
int k=0; k<points_extract->GetNumberOfPoints(); ++k) {
228 COORD = points_extract->GetPoint(k);
230 this->geometryNodes_[k] = std::make_shared<nodes::GeometryNode>(
234 this->fastneighborlist_.addElement(
235 this->geometryNodes_[k]
240 tempArray = polygonPolyData_extract->GetPointData()->GetArray(
"domain_identifier");
241 if (tempArray==NULL) {
242 lbm_fail(
"domain_identifier array not found in vtk input file.");
244 domainidentifierAttributeArray->DeepCopy(tempArray);
247 tempArray = polygonPolyData_extract->GetPointData()->GetArray(
"cell_type");
248 if (tempArray==NULL) {
249 lbm_fail(
"cell_type array not found in vtk input file.");
251 celltypeAttributeArray->DeepCopy(tempArray);
254 tempAbstractArray = polygonPolyData_extract->GetPointData()->GetAbstractArray(
"boundarydescriptors");
255 if (tempAbstractArray==NULL) {
256 lbm_fail(
"boundarydescriptor array not found in vtk input file");
258 stringAttribute_extract->DeepCopy(tempAbstractArray);
261 for (vtkIdType i = 0; i < numPolygons; i++)
263 polygons_extract->GetCell(cellLocation, numIds, pointIds) ;
264 cellLocation += 1 + numIds;
266 assert((
unsigned int)domainidentifierAttributeArray->GetSize() == (
unsigned int)this->geometryNodes_.size());
267 domainId = domainidentifierAttributeArray->GetValue(pointIds[0]);
269 assert((
unsigned int)domainidentifierAttributeArray->GetSize() == (
unsigned int)this->geometryNodes_.size());
270 cellType = celltypeAttributeArray->GetValue(pointIds[0]);
271 this->cellTypeTrackerMap_[domainId] = cellType;
273 for (
int k=0; k<numIds-1; ++k) {
277 boundarystring = stringAttribute_extract->GetValue(pointIds[k]);
278 std::stringstream stringattributestringstream(boundarystring);
280 connectionType.clear();
281 while (stringattributestringstream >> temp1 >> temp2) {
283 const std::map<std::string, double>& tempcdesolvers = Parameters.getCdeSolvers();
286 for (
auto it : tempcdesolvers) {
287 if (temp2 == it.first) {
293 connectionType[temp1].push_back(temp2);
296 LOG(UtilLib::logINFO) <<
"In the geometry file, you mention CDE solvers which do not exist in the configuration file. They're just ignored.";
300 this->connections_.push_back(std::make_shared<Connection>(
301 geometryNodes_[id1], geometryNodes_[id2],
302 connectionType, domainId));
305 this->geometryNodes_[id1]->setConnection<1>(this->connections_.back());
306 this->geometryNodes_[id2]->setConnection<0>(this->connections_.back());
309 this->connections_.push_back(std::make_shared<Connection>(
310 geometryNodes_[pointIds[numIds-1]], geometryNodes_[pointIds[0]],
311 connectionType, domainId));
314 this->geometryNodes_[pointIds[numIds-1]]->setConnection<1>(this->connections_.back());
315 this->geometryNodes_[pointIds[0]]->setConnection<0>(this->connections_.back());
319 lbm_fail(
"Cannot find the geometry.vtm file.");
323 const std::vector<std::shared_ptr<nodes::GeometryNode> >
326 const double radius)
const {
327 if (this->isValidRangeQueryDataStructure_ != 1) {
330 std::vector<std::shared_ptr<nodes::GeometryNode> > queryresult;
332 this->fastneighborlist_.getGeometryNodesWithinRadius(
340 const std::vector<std::shared_ptr<nodes::GeometryNode> >
344 const unsigned int avoidDomainID)
const
346 if (this->isValidRangeQueryDataStructure_ != 1) {
349 std::vector<std::shared_ptr<nodes::GeometryNode> > queryresult;
351 this->fastneighborlist_.getGeometryNodesWithinRadiusWithAvoidance(
359 std::vector<std::shared_ptr<nodes::GeometryNode> > temp =
365 std::shared_ptr<nodes::GeometryNode>
369 const unsigned int avoidDomainID)
const
371 if (this->isValidRangeQueryDataStructure_ != 1) {
375 std::vector<std::shared_ptr<nodes::GeometryNode> > queryresult;
376 this->fastneighborlist_.getGeometryNodesWithinRadiusWithAvoidanceClosest(
383 if (queryresult.size() == 1) {
384 return queryresult[0];
397 const unsigned int id = this->geometryNodes_.rbegin()->first+1;
398 this->geometryNodes_[id] =
399 std::make_shared<nodes::GeometryNode>(
403 this->fastneighborlist_.addElement(
404 this->geometryNodes_[
id]
406 if (this->geometryNodes_.rbegin()->first != id) {
407 lbm_fail(
"Could not create and add the GeometryNode.");
409 std::stringstream message;
410 message <<
"GeometryNode with nodeid=" <<
id
411 <<
" added at ("<< x <<
"," << y <<
")";
412 LOG(UtilLib::logINFO) << message.str().c_str();
419 std::shared_ptr<Connection> C1 = this->geometryNodes_[nodeid]->getConnection<0>();
420 std::shared_ptr<Connection> C2 = this->geometryNodes_[nodeid]->getConnection<1>();
421 std::shared_ptr<nodes::GeometryNode> N1 = C1->getGeometryNodes().first;
422 std::shared_ptr<nodes::GeometryNode> N2 = C2->getGeometryNodes().second;
423 std::map<std::string, std::vector<std::string> > descriptor = C1->getBoundaryConditionDescriptor();
424 unsigned int domainid = this->geometryNodes_[nodeid]->getDomainIdOfAdjacentConnections();
431 this->fastneighborlist_.removeElement(
432 this->geometryNodes_[nodeid]
434 this->geometryNodes_.erase(nodeid);
440 lbm_fail(
"Geometry::removeGeometryNode: Could not remove the GeometryNode");
449 std::shared_ptr<nodes::GeometryNode> p2,
450 const std::map<std::string, std::vector<std::string> > boundaryConditionDescriptor,
451 const unsigned int domainIdentifier) {
454 this->connections_.push_back(std::make_shared<Connection>(
457 boundaryConditionDescriptor,
460 p1->setConnection<1>(this->connections_.back());
461 p2->setConnection<0>(this->connections_.back());
464 assert(p1->getConnection<1>() !=
nullptr);
465 assert(p2->getConnection<0>() !=
nullptr);
466 LOG(UtilLib::logINFO) <<
"Connection added";
471 std::vector<std::shared_ptr<nodes::GeometryNode> > tempvector;
474 for (
auto it : this->geometryNodes_) {
475 tempvector.push_back(it.second);
479 #pragma omp parallel for schedule(dynamic)
480 for (
size_t it=0; it<tempvector.size(); ++it) {
481 tempvector[it]->move();
483 this->isValidRangeQueryDataStructure_ = 0;
492 if (toDelete->getGeometryNodes().first->getConnection<1>()
494 toDelete->getGeometryNodes().first->setConnection<1>(
nullptr);
496 if (toDelete->getGeometryNodes().second->getConnection<0>()
498 toDelete->getGeometryNodes().second->setConnection<0>(
nullptr);
500 this->connections_.erase(std::remove(this->connections_.begin(),
501 this->connections_.end(),
503 this->connections_.end());
504 LOG(UtilLib::logDEBUG1) <<
"Connection erased.";
511 for (
auto it : this->geometryNodes_) {
512 if (it.second != it.second->getConnection<0>()->getGeometryNodes().second) {
513 lbm_fail(
"Geometry::checkGeometryIntegrity");
516 if (it.second != it.second->getConnection<1>()->getGeometryNodes().first) {
517 lbm_fail(
"Geometry::checkGeometryIntegrity");
521 for (
auto it : this->connections_) {
522 if (it != it->getGeometryNodes().first->getConnection<1>()) {
523 lbm_fail(
"Geometry::checkGeometryIntegrity");
526 if (it != it->getGeometryNodes().second->getConnection<0>()) {
527 lbm_fail(
"Geometry::checkGeometryIntegrity");
531 if (this->connections_.size() != this->geometryNodes_.size()) {
532 lbm_fail(
"Geometry::checkGeometryIntegrity: #connections != #geometrynodes");
536 lbm_fail(
"Geometry::checkGeometryIntegrity: Couln't check geometry integrity.");
543 this->isValidRangeQueryDataStructure_ = 0;
548 this->fastneighborlist_.reset(this->geometryNodes_);
549 this->isValidRangeQueryDataStructure_ = 1;
554 return this->cellTypeTrackerMap_;
const std::vector< std::shared_ptr< nodes::GeometryNode > > getGeometryNodesWithinRadiusWithAvoidance(const double x, const double y, const double radius, const unsigned int avoidDomainID) const
getGeometryNodesWithinRadiusWithAvoidance Range query, but only nodes with domainID different from av...
unsigned int removeGeometryNode(const unsigned int nodeid)
removeGeometryNode Removes the GeometryNode with nodeid. One of the connections is removed...
const std::map< unsigned int, std::shared_ptr< nodes::GeometryNode > > & getGeometryNodes() const
Getter for the geometry nodes.
void moveGeometryNodes()
Geometry::moveGeometryNodes moves the *GeometryNode*s according to the local velocity field...
unsigned int addGeometryNode(const double x, const double y)
addGeometryNode Add a GeometryNode. The NodeID is bumped automatically.
Geometry(const std::string &filename)
Geometry constructs the geometry of the simulation.
void reconstructRangeQueryDataStructure() const
reconstructRangeQueryDataStructure
const std::vector< std::shared_ptr< Connection > > & getConnections() const
getConnections Getter for connections
bool checkGeometryIntegrity() const
checkGeometryIntegrity
~Geometry()
~Geometry Plain.
void addConnection(std::shared_ptr< nodes::GeometryNode > p1, std::shared_ptr< nodes::GeometryNode > p2, const std::map< std::string, std::vector< std::string > > boundaryConditionDescriptor, const unsigned int domainIdentifier)
addConnection Add a Connection.
void writeGeometry(const std::string &fileName) const
writeGeometry Writes the geometry to the file
void eraseConnection(std::shared_ptr< Connection > toDelete)
eraseConnection Erase the connection.
const std::vector< std::shared_ptr< nodes::GeometryNode > > getGeometryNodesWithinRadius(const double x, const double y, const double radius) const
getGeometryNodesWithinRadius Range query
std::shared_ptr< nodes::GeometryNode > getGeometryNodesWithinRadiusWithAvoidanceClosest(const double x, const double y, const double radius, const unsigned int avoidDomainID) const
getGeometryNodesWithinRadiusWithAvoidanceClosest Return closest GeometryNode, but only nodes with dom...
void invalidateRangeQueryDataStructure()
invalidateRangeQueryDataStructure Sets the internal flag to false.
std::map< unsigned int, unsigned int > getCellTypeTrackerMap(void) const
Returns a reference to the cellTypeTrackerMap.