DNDSR 0.1.0.dev1+gcd065ad
Distributed Numeric Data Structure for CFV
Loading...
Searching...
No Matches
OpenFOAMMesh.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "Geometric.hpp"
4#include "Elements.hpp"
5#include "Quadrature.hpp"
6#include "Mesh.hpp"
7#include <map>
8
10{
17
18 inline int passOpenFOAMSpaces(std::istream &in)
19 {
20 int wsCount = 0;
21 while (!in.eof())
22 {
23 char c = in.peek();
24 if (std::isspace(c))
25 {
26 in.get();
27 wsCount++;
28 continue;
29 }
30 if (c == '/')
31 {
32 try
33 {
34 in.get();
35 c = in.peek();
36 if (c == '/') // line comment
37 {
38 std::string line;
39 std::getline(in, line);
40 }
41 else if (c == '*') // block comment
42 {
43 while (!in.eof())
44 {
45 c = in.get();
46 // std::cout << c << " : ";
47 if (c == '*')
48 {
49 c = in.get();
50 if (c == '/')
51 break;
52 }
53 }
54 }
55 }
56 catch (const std::exception &e)
57 {
58 std::cerr << "seems in a comment but failed to parse it: ";
59 std::cerr << e.what() << '\n';
60 }
61 wsCount++;
62 continue;
63 }
64 break;
65 }
66 return wsCount;
67 }
68
69 inline bool getUntil(std::istream &in, char v, std::string &buf)
70 {
71 // std::cout << "getUntil " << v << std::endl;
72 buf.clear();
73 while (!in.eof())
74 {
75 if (passOpenFOAMSpaces(in))
76 {
77 buf.push_back(' ');
78 continue;
79 }
80 char c = in.peek();
81 if (c == v)
82 break;
83 in.get();
84 buf.push_back(c);
85 }
86 // std::cout << "getUntil " << v << "is done" << std::endl;
87 return in.eof();
88 }
89
90 inline void readOpenFOAMList(std::istream &in, const std::function<void(std::istream &)> &readOneItem)
91 {
92 bool gotLeft = false;
93 std::string buf;
94 if (getUntil(in, '(', buf))
95 DNDS_assert(false);
96 in.get(); // omit the '('
97 while (!in.eof())
98 {
99
100 char c = in.peek();
101 if (c == ')')
102 {
103 in.get(); // omit the ')'
104 break;
105 }
106 readOneItem(in);
108 }
109 }
110
111 inline void readOpenFOAMObj(std::istream &in, const std::function<void(const std::string &)> &readOneItemLine)
112 {
113 bool gotLeft = false;
114 std::string buf;
115 if (getUntil(in, '{', buf))
116 DNDS_assert(false);
117 in.get(); // omit the '{'
119 while (!in.eof())
120 {
121 char c = in.peek();
122 if (c == '}')
123 {
124 in.get(); // omit the '}'
125 break;
126 }
127 std::string lineBuf;
128 if (getUntil(in, ';', lineBuf))
129 DNDS_assert(false);
130 in.get(); // omit the ';'
131 readOneItemLine(lineBuf);
133 }
134 }
135
136 inline std::vector<std::string> readOpenFOAMHeader(std::istream &in)
137 {
138 std::string buf;
139 if (getUntil(in, '{', buf))
140 DNDS_assert(false);
141 std::stringstream bufSS(buf);
142 std::string name;
143 bufSS >> name;
144 DNDS_assert(name == "FoamFile");
145 std::vector<std::string> ret;
146 readOpenFOAMObj(in, [&](const std::string &lineBuf)
147 { ret.push_back(lineBuf); });
148 return ret;
149 }
150
152 {
153 std::vector<tPoint> points;
154 std::vector<std::vector<index>> faces;
155 std::vector<index> owner;
156 std::vector<index> neighbour;
157 std::map<std::string, OpenFOAMBoundaryCondition> boundaryConditions;
158
159 void ReadPoints(std::istream &IFS)
160 {
161 DNDS_assert(IFS);
162 auto header = readOpenFOAMHeader(IFS);
163 // for (auto &i : header)
164 // std::cout << i << std::endl;
165
167 index nPoints;
168 IFS >> nPoints;
169 points.resize(nPoints);
170 index iPoint = 0;
171 readOpenFOAMList(IFS, [&](std::istream &in)
172 {
173 std::vector<real> readReals;
174 readReals.reserve(4);
175 readOpenFOAMList(in, [&](std::istream &iin)
176 {
177 real v{0};
178 iin >> v;
179 readReals.push_back(v);
180 });
181 DNDS_assert(readReals.size() == 3);
182 points.at(iPoint).x() = readReals.at(0);
183 points.at(iPoint).y() = readReals.at(1);
184 points.at(iPoint).z() = readReals.at(2);
185 iPoint++; });
186 // for (auto &i : points)
187 // std::cout << i.transpose() << std::endl;
188 }
189
190 void ReadFaces(std::istream &IFS)
191 {
192 DNDS_assert(IFS);
193 auto header = readOpenFOAMHeader(IFS);
194 // for (auto &i : header)
195 // std::cout << i << std::endl;
196
199 IFS >> nFaces;
200 faces.resize(nFaces);
201 index iFace = 0;
202 readOpenFOAMList(IFS, [&](std::istream &in)
203 {
204 int faceSiz{0};
205 in >> faceSiz;
206 faces.at(iFace).reserve(faceSiz);
207 readOpenFOAMList(in, [&](std::istream &iin)
208 {
209 index inode;
210 iin >> inode;
211 faces.at(iFace).push_back(inode);
212 });
213 iFace++; });
214 // for (auto &i : faces)
215 // {
216 // for(auto in : i)
217 // std::cout << in << " ";
218 // std::cout << std::endl;
219 // }
220 }
221
222 void ReadOwner(std::istream &IFS)
223 {
224 DNDS_assert(IFS);
225 auto header = readOpenFOAMHeader(IFS);
226 // for (auto &i : header)
227 // std::cout << i << std::endl;
228
231 IFS >> nFaces;
232 owner.resize(nFaces);
233 index iFace = 0;
234 readOpenFOAMList(IFS, [&](std::istream &in)
235 {
236 index iCell;
237 in >> iCell;
238 owner.at(iFace) = iCell;
239 iFace++; });
240
241 // for (auto i : owner)
242 // std::cout << i << std::endl;
243 }
244
245 void ReadNeighbour(std::istream &IFS)
246 {
247 DNDS_assert(IFS);
248 auto header = readOpenFOAMHeader(IFS);
249 // for (auto &i : header)
250 // std::cout << i << std::endl;
251
253 index nFaces; // smaller than faces.size()
254 IFS >> nFaces;
255 neighbour.resize(nFaces); // only internal
256 index iFace = 0;
257 readOpenFOAMList(IFS, [&](std::istream &in)
258 {
259 index iCell;
260 in >> iCell;
261 neighbour.at(iFace) = iCell;
262 iFace++; });
263
264 // for (auto i : neighbour)
265 // std::cout << i << std::endl;
266 }
267
268 void ReadBoundary(std::istream &IFS)
269 {
270 DNDS_assert(IFS);
271 auto header = readOpenFOAMHeader(IFS);
272 // for (auto &i : header)
273 // std::cout << i << std::endl;
274
276 index nBoundary;
277 IFS >> nBoundary;
278
280 IFS,
281 [&](std::istream &in)
282 {
283 std::string buf;
284 if (getUntil(in, '{', buf))
285 DNDS_assert(false);
286 std::stringstream bufSS(buf);
287 std::string name;
288 bufSS >> name;
290 in,
291 [&](const std::string &lineBuf)
292 {
293 std::stringstream lineBufSS(lineBuf);
294 std::string key;
295 lineBufSS >> key;
296 if (key == "type")
297 {
298 std::string type;
299 lineBufSS >> type;
300 boundaryConditions[name].type = type;
301 }
302 if (key == "nFaces")
303 {
305 lineBufSS >> nFaces;
306 boundaryConditions[name].nFaces = nFaces;
307 }
308 if (key == "startFace")
309 {
310 index startFace;
311 lineBufSS >> startFace;
312 boundaryConditions[name].startFace = startFace;
313 }
314 });
315 });
316
317 for (auto &bc : boundaryConditions)
318 {
319 std::cout << bc.first << " " << bc.second.type << " " << bc.second.nFaces << " " << bc.second.startFace << std::endl;
320 }
321 }
322 };
323
324 inline std::tuple<Elem::ElemType, std::vector<index>>
325 ExtractTopologicalElementFromPolyMeshCell(const std::vector<std::vector<index>> &facesIn,
326 const std::vector<int> &ownIn)
327 {
328 std::vector<std::vector<index>> faces = facesIn;
329 std::vector<int> own = ownIn;
330 // std::sort(faces.begin(), faces.end(), [](auto &&l, auto &&r)
331 // { return l.size() < r.size(); });
332 // for (auto &v : faces)
333 // std::sort(v.begin(), v.end());
334 std::vector<index> nodes;
336 if (faces.size() == 6)
337 {
338 for (auto &v : faces)
339 {
340 if (v.size() != 4)
341 return std::make_tuple(etype, nodes);
342 }
343 if (!own[0])
344 for (auto v : faces[0])
345 nodes.push_back(v);
346 else
347 for (int i = faces[0].size() - 1; i >= 0; i--)
348 nodes.push_back(faces[0][i]);
349 for (int iFoot = 0; iFoot < 4; iFoot++)
350 {
351 index foot = nodes.at(iFoot);
352 index head = -1;
353 for (int iFace = 1; iFace < faces.size(); iFace++)
354 {
355 int iFootC = -1;
356 index headL = -1;
357 index headR = -1;
358 for (int iF2N = 0; iF2N < faces[iFace].size(); iF2N++)
359 if (faces[iFace][iF2N] == foot)
360 iFootC = iF2N;
361 if (iFootC >= 0)
362 {
363 headL = faces[iFace][(iFootC - 1) % faces[iFace].size()];
364 headR = faces[iFace][(iFootC + 1) % faces[iFace].size()];
365 auto itFoundL = std::find(nodes.begin(), nodes.begin() + 4, headL);
366 if (itFoundL == nodes.begin() + 4)
367 head = headL;
368 else
369 head = headR;
370 }
371 }
372 if (!(head >= 0))
373 return std::make_tuple(etype, nodes);
374 nodes.push_back(head);
375 }
376 etype = Elem::ElemType::Hex8;
377 return std::make_tuple(etype, nodes);
378 }
379 else
380 {
381 DNDS_assert_info(false, fmt::format("faces size {} not supported", faces.size()));
382 return std::make_tuple(etype, nodes);
383 }
384 return std::make_tuple(etype, nodes);
385 }
386
388 {
389 std::vector<std::vector<index>> cell2face;
390 std::vector<std::vector<int>> cell2faceOwn;
391 std::vector<std::vector<index>> cell2node;
392 std::vector<ElemInfo> cellElemInfo;
393 std::vector<ElemInfo> faceElemInfo; // cannot decide bc zone id here
394
396 {
397 faceElemInfo.resize(reader.faces.size());
398 for (index iF = 0; iF < reader.faces.size(); iF++)
399 {
400 faceElemInfo.at(iF).zone = BC_ID_NULL;
401 if (reader.faces.at(iF).size() == 4)
403 else if (reader.faces.at(iF).size() == 3)
405 else
406 DNDS_assert_info(false, fmt::format("face {} has {} nodes, not supported", iF, reader.faces.at(iF).size()));
407 }
408 }
409
411 {
412 index nCell = 0;
413 for (auto v : reader.neighbour)
414 nCell = std::max(nCell, v);
415 for (auto v : reader.owner)
416 nCell = std::max(nCell, v);
417 nCell++;
418 cell2face.resize(nCell);
419 cell2faceOwn.resize(nCell);
420 std::vector<int> nFaces(nCell, 0);
421 for (auto v : reader.neighbour)
422 nFaces.at(v)++;
423 for (auto v : reader.owner)
424 nFaces.at(v)++;
425 for (index iCell = 0; iCell < nCell; iCell++)
426 {
427 cell2face.at(iCell).reserve(nFaces.at(iCell));
428 cell2faceOwn.at(iCell).reserve(nFaces.at(iCell));
429 }
430 for (index iFace = 0; iFace < reader.owner.size(); iFace++)
431 {
432 index iCell = reader.owner.at(iFace);
433 cell2face.at(iCell).push_back(iFace);
434 cell2faceOwn.at(iCell).push_back(1);
435 }
436 for (index iFace = 0; iFace < reader.neighbour.size(); iFace++)
437 {
438 index iCell = reader.neighbour.at(iFace);
439 cell2face.at(iCell).push_back(iFace);
440 cell2faceOwn.at(iCell).push_back(0);
441 }
442 std::cout << "OF Converter has nCell " << nCell << std::endl;
443 }
444
446 {
447 cell2node.resize(cell2face.size());
448 cellElemInfo.resize(cell2face.size());
449 for (index iCell = 0; iCell < cell2node.size(); iCell++)
450 {
451 std::vector<std::vector<index>> facesIn;
452 for (auto iFace : this->cell2face[iCell])
453 {
454 facesIn.push_back(reader.faces.at(iFace));
455 }
456 auto [etype, nodes] = ExtractTopologicalElementFromPolyMeshCell(facesIn, cell2faceOwn[iCell]);
458 fmt::format("elem reconstruction failed, iCell {}, nFaces {}", iCell, facesIn.size()));
459 cellElemInfo[iCell].setElemType(etype);
460 cell2node[iCell] = nodes;
461
462 /**********************************************************************/
463 // test code
464 // // std::cout << nodes.size() << std::endl;
465 // // std::cout << int(etype) << std::endl;
466 // // for (auto v : nodes)
467 // // std::cout << v << " ";
468 // // std::cout << std::endl;
469 // Geom::tSmallCoords coords;
470 // coords.resize(3, nodes.size());
471 // for (index iNode = 0; iNode < nodes.size(); iNode++)
472 // coords(EigenAll, iNode) = reader.points.at(nodes[iNode]);
473 // Elem::Element elem{Elem::Hex8};
474 // Elem::Quadrature quad(elem, 2);
475 // real vol = 0;
476 // quad.Integration(
477 // vol,
478 // [&](real &inc, int iG, const tPoint &pParam, auto &DiNj)
479 // {
480 // tJacobi J = Elem::ShapeJacobianCoordD01Nj(coords, DiNj);
481 // real JDet = J.determinant();
482 // DNDS_assert(JDet > 0);
483 // vol += JDet;
484 // });
485 // // std::cout << vol << std::endl;
486 }
487 }
488 };
489
490}
#define DNDS_assert_info(expr, info)
Debug-only assertion with an extra std::string info message.
Definition Errors.hpp:113
#define DNDS_assert(expr)
Debug-only assertion (compiled out when DNDS_NDEBUG is defined). Prints the expression + file/line + ...
Definition Errors.hpp:108
DNDS::index nFaces
Definition Mesh.cpp:1354
std::vector< std::string > readOpenFOAMHeader(std::istream &in)
void readOpenFOAMList(std::istream &in, const std::function< void(std::istream &)> &readOneItem)
std::tuple< Elem::ElemType, std::vector< index > > ExtractTopologicalElementFromPolyMeshCell(const std::vector< std::vector< index > > &facesIn, const std::vector< int > &ownIn)
int passOpenFOAMSpaces(std::istream &in)
bool getUntil(std::istream &in, char v, std::string &buf)
void readOpenFOAMObj(std::istream &in, const std::function< void(const std::string &)> &readOneItemLine)
int64_t index
Global row / DOF index type (signed 64-bit; handles multi-billion-cell meshes).
Definition Defines.hpp:107
double real
Canonical floating-point scalar used throughout DNDSR (double precision).
Definition Defines.hpp:105
std::vector< std::vector< index > > cell2face
std::vector< std::vector< index > > cell2node
void BuildCell2Face(OpenFOAMReader &reader)
void BuildFaceElemInfo(OpenFOAMReader &reader)
std::vector< std::vector< int > > cell2faceOwn
void BuildCell2Node(OpenFOAMReader &reader)
std::map< std::string, OpenFOAMBoundaryCondition > boundaryConditions
void ReadBoundary(std::istream &IFS)
void ReadNeighbour(std::istream &IFS)
std::vector< std::vector< index > > faces
Eigen::Matrix< real, 5, 1 > v