readKivaGrid.H
Go to the documentation of this file.
1 std::ifstream kivaFile(kivaFileName);
2 
3 if (!kivaFile.good())
4 {
6  << "Cannot open file " << kivaFileName
7  << exit(FatalError);
8 }
9 
10 Info << "Reading kiva grid from file " << kivaFileName << endl;
11 
12 
13 char title[120];
14 kivaFile.getline(title, 120, '\n');
15 
16 label nPoints, nCells, nRegs;
17 kivaFile >> nCells >> nPoints >> nRegs;
18 
20 label i4;
22 
23 for (label i=0; i<nPoints; i++)
24 {
25  scalar ffv;
26  kivaFile
27  >> i4
28  >> points[i].x() >> points[i].y() >> points[i].z()
29  >> ffv;
30 
31  if (kivaVersion == kiva3v)
32  {
33  kivaFile >> idface[i];
34  }
35 
36  // Convert from KIVA cgs units to SI
37  points[i] *= 0.01;
38 
39  fv[i] = label(ffv);
40 }
41 
44 
45 // label nBfaces = 0;
46 
47 for (label i=0; i<nPoints; i++)
48 {
49  label i1, i3, i8;
50  scalar ff, fbcl, fbcf, fbcb;
51 
52  kivaFile
53  >> i1 >> i3 >> i4 >> i8
54  >> ff >> fbcl >> fbcf >> fbcb
55  >> idreg[i];
56 
57  // Correct indices to start from 0
58  i1tab[i] = i1 - 1;
59  i3tab[i] = i3 - 1;
60  i8tab[i] = i8 - 1;
61 
62  // Convert scalar indices into hexLabels
63  f[i] = label(ff);
64  bcl[i] = label(fbcl);
65  bcf[i] = label(fbcf);
66  bcb[i] = label(fbcb);
67 
68  // if (bcl[i] > 0 && bcl[i] != 4) ++nBfaces;
69  // if (bcf[i] > 0 && bcf[i] != 4) ++nBfaces;
70  // if (bcb[i] > 0 && bcb[i] != 4) ++nBfaces;
71 }
72 
73 
74 label mTable;
75 kivaFile >> mTable;
76 
77 if (mTable == 0)
78 {
80  << "mTable == 0. This is not supported."
81  " kivaToFoam needs complete neighbour information"
82  << exit(FatalError);
83 }
84 
85 
87 
88 for (label i=0; i<nPoints; i++)
89 {
90  label im, jm, km;
91  kivaFile >> i4 >> im >> jm >> km;
92 
93  // Correct indices to start from 0
94  imtab[i] = im - 1;
95  jmtab[i] = jm - 1;
96  kmtab[i] = km - 1;
97 }
98 
99 Info << "Finished reading KIVA file" << endl;
100 
102 
103 labelList cellZoning(nPoints, -1);
104 
105 const cellModel& hex = cellModel::ref(cellModel::HEX);
106 labelList hexLabels(8);
107 label activeCells = 0;
108 
109 // Create and set the collocated point collapse map
110 labelList pointMap(nPoints);
111 
112 forAll(pointMap, i)
113 {
114  pointMap[i] = i;
115 }
116 
117 // Initialise all cells to hex and search and set map for collocated points
118 for (label i=0; i<nPoints; i++)
119 {
120  if (f[i] > 0.0)
121  {
122  hexLabels[0] = i;
123  hexLabels[1] = i1tab[i];
124  hexLabels[2] = i3tab[i1tab[i]];
125  hexLabels[3] = i3tab[i];
126  hexLabels[4] = i8tab[i];
127  hexLabels[5] = i1tab[i8tab[i]];
128  hexLabels[6] = i3tab[i1tab[i8tab[i]]];
129  hexLabels[7] = i3tab[i8tab[i]];
130 
131  cellShapes[activeCells].reset(hex, hexLabels);
132 
133  edgeList edges = cellShapes[activeCells].edges();
134 
135  forAll(edges, ei)
136  {
137  if (edges[ei].mag(points) < SMALL)
138  {
139  label start = pointMap[edges[ei].start()];
140  while (start != pointMap[start])
141  {
142  start = pointMap[start];
143  }
144 
145  label end = pointMap[edges[ei].end()];
146  while (end != pointMap[end])
147  {
148  end = pointMap[end];
149  }
150 
151  pointMap[start] = pointMap[end] = Foam::min(start, end);
152  }
153  }
154 
155  // Grab the cell zoning info
156  cellZoning[activeCells] = idreg[i];
157 
158  activeCells++;
159  }
160 }
161 
162 // Contract list of cells to the active ones
163 cellShapes.setSize(activeCells);
164 cellZoning.setSize(activeCells);
165 
166 // Map collocated points to refer to the same point and collapse cell shape
167 // to the corresponding hex-degenerate.
168 forAll(cellShapes, celli)
169 {
170  cellShape& cs = cellShapes[celli];
171 
172  forAll(cs, i)
173  {
174  cs[i] = pointMap[cs[i]];
175  }
176 
177  cs.collapse();
178 }
179 
180 label bcIDs[11] = {-1, 0, 2, 4, -1, 5, -1, 6, 7, 8, 9};
181 
182 constexpr label nBCs = 12;
183 
184 const word* kivaPatchTypes[nBCs] =
185 {
186  &wallPolyPatch::typeName,
187  &wallPolyPatch::typeName,
188  &wallPolyPatch::typeName,
189  &wallPolyPatch::typeName,
190  &symmetryPolyPatch::typeName,
191  &wedgePolyPatch::typeName,
192  &polyPatch::typeName,
193  &polyPatch::typeName,
194  &polyPatch::typeName,
195  &polyPatch::typeName,
196  &symmetryPolyPatch::typeName,
197  &oldCyclicPolyPatch::typeName
198 };
199 
200 enum patchTypeNames
201 {
202  PISTON,
203  VALVE,
204  LINER,
205  CYLINDERHEAD,
206  AXIS,
207  WEDGE,
208  INFLOW,
209  OUTFLOW,
210  PRESIN,
211  PRESOUT,
212  SYMMETRYPLANE,
213  CYCLIC
214 };
215 
216 const char* kivaPatchNames[nBCs] =
217 {
218  "piston",
219  "valve",
220  "liner",
221  "cylinderHead",
222  "axis",
223  "wedge",
224  "inflow",
225  "outflow",
226  "presin",
227  "presout",
228  "symmetryPlane",
229  "cyclic"
230 };
231 
232 
233 List<DynamicList<face>> pFaces[nBCs];
234 
235 face quadFace(4);
236 face triFace(3);
237 
238 for (label i=0; i<nPoints; i++)
239 {
240  if (f[i] > 0)
241  {
242  // left
243  label bci = bcl[i];
244  if (bci != 4)
245  {
246  quadFace[0] = i3tab[i];
247  quadFace[1] = i;
248  quadFace[2] = i8tab[i];
249  quadFace[3] = i3tab[i8tab[i]];
250 
251  #include "checkPatch.H"
252  }
253 
254  // right
255  bci = bcl[i1tab[i]];
256  if (bci != 4)
257  {
258  quadFace[0] = i1tab[i];
259  quadFace[1] = i3tab[i1tab[i]];
260  quadFace[2] = i8tab[i3tab[i1tab[i]]];
261  quadFace[3] = i8tab[i1tab[i]];
262 
263  #include "checkPatch.H"
264  }
265 
266  // front
267  bci = bcf[i];
268  if (bci != 4)
269  {
270  quadFace[0] = i;
271  quadFace[1] = i1tab[i];
272  quadFace[2] = i8tab[i1tab[i]];
273  quadFace[3] = i8tab[i];
274 
275  #include "checkPatch.H"
276  }
277 
278  // derriere (back)
279  bci = bcf[i3tab[i]];
280  if (bci != 4)
281  {
282  quadFace[0] = i3tab[i];
283  quadFace[1] = i8tab[i3tab[i]];
284  quadFace[2] = i8tab[i1tab[i3tab[i]]];
285  quadFace[3] = i1tab[i3tab[i]];
286 
287  #include "checkPatch.H"
288  }
289 
290  // bottom
291  bci = bcb[i];
292  if (bci != 4)
293  {
294  quadFace[0] = i;
295  quadFace[1] = i3tab[i];
296  quadFace[2] = i1tab[i3tab[i]];
297  quadFace[3] = i1tab[i];
298 
299  #include "checkPatch.H"
300  }
301 
302  // top
303  bci = bcb[i8tab[i]];
304  if (bci != 4)
305  {
306  quadFace[0] = i8tab[i];
307  quadFace[1] = i1tab[i8tab[i]];
308  quadFace[2] = i3tab[i1tab[i8tab[i]]];
309  quadFace[3] = i3tab[i8tab[i]];
310 
311  #include "checkPatch.H"
312  }
313  }
314 }
315 
316 // Transfer liner faces that are above the minimum cylinder-head z height
317 // into the cylinder-head region
318 if
319 (
320  pFaces[LINER].size()
321  && pFaces[LINER][0].size()
322  && pFaces[CYLINDERHEAD].size()
323  && pFaces[CYLINDERHEAD][0].size()
324 )
325 {
326  scalar minz = GREAT;
327 
328  for (const face& pf : pFaces[CYLINDERHEAD][0])
329  {
330  forAll(pf, pfi)
331  {
332  minz = Foam::min(minz, points[pf[pfi]].z());
333  }
334  }
335 
336  minz += SMALL;
337 
338  DynamicList<face> newLinerFaces;
339 
340  for (const face& pf : pFaces[LINER][0])
341  {
342  scalar minfz = GREAT;
343  for (const label pointi : pf)
344  {
345  minfz = Foam::min(minfz, points[pointi].z());
346  }
347 
348  if (minfz > minz)
349  {
350  pFaces[CYLINDERHEAD][0].push_back(pf);
351  }
352  else
353  {
354  newLinerFaces.push_back(pf);
355  }
356  }
357 
358  if (pFaces[LINER][0].size() != newLinerFaces.size())
359  {
360  Info<< "Transferred " << pFaces[LINER][0].size() - newLinerFaces.size()
361  << " faces from liner region to cylinder head" << endl;
362  pFaces[LINER][0] = std::move(newLinerFaces);
363  }
364 
365  DynamicList<face> newCylinderHeadFaces;
366 
367  for (const face& pf : pFaces[CYLINDERHEAD][0])
368  {
369  scalar minfz = GREAT;
370  for (const label pointi : pf)
371  {
372  minfz = Foam::min(minfz, points[pointi].z());
373  }
374 
375  if (minfz < zHeadMin)
376  {
377  pFaces[LINER][0].push_back(pf);
378  }
379  else
380  {
381  newCylinderHeadFaces.push_back(pf);
382  }
383  }
384 
385  if (pFaces[CYLINDERHEAD][0].size() != newCylinderHeadFaces.size())
386  {
387  Info<< "Transferred faces from cylinder-head region to linder" << endl;
388  pFaces[CYLINDERHEAD][0] = std::move(newCylinderHeadFaces);
389  }
390 }
391 
392 
393 // Count the number of non-zero sized patches
394 label nPatches = 0;
395 for (int bci=0; bci<nBCs; bci++)
396 {
397  for (const auto& faces : pFaces[bci])
398  {
399  if (faces.size())
400  {
401  nPatches++;
402  }
403  }
404 }
405 
406 
407 // Sort-out the 2D/3D wedge geometry
408 if (pFaces[WEDGE].size() && pFaces[WEDGE][0].size())
409 {
410  if (pFaces[WEDGE][0].size() == cellShapes.size())
411  {
412  // Distribute the points to be +/- 2.5deg from the x-z plane
413 
414  const scalar tanTheta = Foam::tan(degToRad(2.5));
415 
416  auto iterf = pFaces[WEDGE][0].cbegin();
417  auto iterb = pFaces[WEDGE][1].cbegin();
418 
419  const auto end_iterf = pFaces[WEDGE][0].cend();
420  const auto end_iterb = pFaces[WEDGE][1].cend();
421 
422  for
423  (
424  ;
425  (iterf != end_iterf) && (iterb != end_iterb);
426  ++iterf, ++iterb
427  )
428  {
429  const auto& facef = *iterf;
430  const auto& faceb = *iterb;
431 
432  for (direction d=0; d<4; d++)
433  {
434  points[facef[d]].y() = -tanTheta*points[facef[d]].x();
435  points[faceb[d]].y() = tanTheta*points[faceb[d]].x();
436  }
437  }
438  }
439  else
440  {
441  pFaces[CYCLIC].resize(1);
442  pFaces[CYCLIC][0] = pFaces[WEDGE][0];
443  pFaces[CYCLIC][0].push_back(pFaces[WEDGE][1]);
444 
445  pFaces[WEDGE].clear();
446  nPatches--;
447  }
448 }
449 
450 
451 // Build the patches
452 
456 word defaultFacesName = "defaultFaces";
457 word defaultFacesType = emptyPolyPatch::typeName;
458 
459 label nAddedPatches = 0;
460 
461 for (int bci=0; bci<nBCs; bci++)
462 {
463  forAll(pFaces[bci], rgi)
464  {
465  if (pFaces[bci][rgi].size())
466  {
467  patchTypes[nAddedPatches] = *kivaPatchTypes[bci];
468 
469  patchNames[nAddedPatches] = kivaPatchNames[bci];
470 
471  if (pFaces[bci].size() > 1)
472  {
473  patchNames[nAddedPatches] += name(rgi+1);
474  }
475 
476  boundary[nAddedPatches] = pFaces[bci][rgi];
477  nAddedPatches++;
478  }
479  }
480 }
481 
482 
483 // Remove unused points and update cell and face labels accordingly
484 
486 
487 // Scan cells for used points
489 {
490  forAll(cellShapes[celli], i)
491  {
492  pointLabels[cellShapes[celli][i]] = 1;
493  }
494 }
495 
496 // Create addressing for used points and pack points array
497 label newPointi = 0;
499 {
500  if (pointLabels[pointi] != -1)
501  {
502  pointLabels[pointi] = newPointi;
503  points[newPointi++] = points[pointi];
504  }
505 }
506 points.setSize(newPointi);
507 
508 // Reset cell point labels
509 forAll(cellShapes, celli)
510 {
511  cellShape& cs = cellShapes[celli];
512 
513  forAll(cs, i)
514  {
515  cs[i] = pointLabels[cs[i]];
516  }
517 }
518 
519 // Reset boundary-face point labels
520 forAll(boundary, patchi)
521 {
522  forAll(boundary[patchi], facei)
523  {
524  face& f = boundary[patchi][facei];
525 
526  forAll(f, i)
527  {
528  f[i] = pointLabels[f[i]];
529  }
530  }
531 }
532 
533 PtrList<dictionary> patchDicts;
535 (
536  runTime,
537  runTime.constant(),
538  polyMesh::meshSubDir,
539  patchNames,
540  patchDicts,
543 );
544 // Add information to dictionary
546 {
547  if (!patchDicts.set(patchi))
548  {
549  patchDicts.set(patchi, new dictionary());
550  }
551  // Add but not overwrite
552  patchDicts[patchi].add("type", patchTypes[patchi], false);
553 }
554 
555 // Build the mesh and write it out
556 polyMesh pShapeMesh
557 (
558  IOobject
559  (
560  polyMesh::defaultRegion,
561  runTime.constant(),
562  runTime
563  ),
564  std::move(points),
565  cellShapes,
566  boundary,
567  patchNames,
568  patchDicts,
571 );
572 
573 // More precision (for points data)
574 IOstream::minPrecision(10);
575 
576 Info << "Writing polyMesh" << endl;
577 pShapeMesh.removeFiles();
578 pShapeMesh.write();
579 
580 fileName czPath
581 (
582  runTime.path()/runTime.constant()/polyMesh::defaultRegion/"cellZoning"
583 );
584 Info << "Writing cell zoning info to file: " << czPath << endl;
585 OFstream cz(czPath);
586 
587 cz << cellZoning << endl;
label nPatches
Definition: readKivaGrid.H:394
word defaultFacesType
Definition: readKivaGrid.H:457
labelList imtab(nPoints)
List< faceList > faceListList
List of faceList.
Definition: faceListFwd.H:44
uint8_t direction
Definition: direction.H:46
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
labelList pointLabels(nPoints, -1)
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
IOstream & hex(IOstream &io)
Definition: IOstream.H:560
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:600
List< edge > edgeList
List of edge.
Definition: edgeList.H:32
wordList patchTypes(nPatches)
labelList idface(nPoints)
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:529
List< cellShape > cellShapeList
List of cellShape.
Definition: cellShapeList.H:32
preservePatchTypes(runTime, runTime.constant(), polyMesh::meshSubDir, patchNames, patchDicts, defaultFacesName, defaultFacesType)
polyMesh pShapeMesh(IOobject(polyMesh::defaultRegion, runTime.constant(), runTime), std::move(points), cellShapes, boundary, patchNames, patchDicts, defaultFacesName, defaultFacesType)
std::ifstream kivaFile(kivaFileName)
labelList kmtab(nPoints)
labelList jmtab(nPoints)
labelList i8tab(nPoints)
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
label nAddedPatches
Definition: readKivaGrid.H:459
labelList bcb(nPoints)
labelList i3tab(nPoints)
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
label nPoints
labelList fv(nPoints)
face triFace(3)
wordList patchNames(nPatches)
label mTable
Definition: readKivaGrid.H:74
label i4
Definition: readKivaGrid.H:20
cellShapeList cellShapes
labelList idreg(nPoints)
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=cellModel::ref(cellModel::HEX);labelList hexLabels(8);label activeCells=0;labelList pointMap(nPoints);forAll(pointMap, i){ pointMap[i]=i;}for(label i=0;i< nPoints;i++){ if(f[i] > 0.0) { hexLabels[0]=i;hexLabels[1]=i1tab[i];hexLabels[2]=i3tab[i1tab[i]];hexLabels[3]=i3tab[i];hexLabels[4]=i8tab[i];hexLabels[5]=i1tab[i8tab[i]];hexLabels[6]=i3tab[i1tab[i8tab[i]]];hexLabels[7]=i3tab[i8tab[i]];cellShapes[activeCells].reset(hex, hexLabels);edgeList edges=cellShapes[activeCells].edges();forAll(edges, ei) { if(edges[ei].mag(points)< SMALL) { label start=pointMap[edges[ei].start()];while(start !=pointMap[start]) { start=pointMap[start];} label end=pointMap[edges[ei].end()];while(end !=pointMap[end]) { end=pointMap[end];} pointMap[start]=pointMap[end]=Foam::min(start, end);} } cellZoning[activeCells]=idreg[i];activeCells++;}}cellShapes.setSize(activeCells);cellZoning.setSize(activeCells);forAll(cellShapes, celli){ cellShape &cs=cellShapes[celli];forAll(cs, i) { cs[i]=pointMap[cs[i]];} cs.collapse();}label bcIDs[11]={-1, 0, 2, 4, -1, 5, -1, 6, 7, 8, 9};constexpr label nBCs=12;const word *kivaPatchTypes[nBCs]={ &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &symmetryPolyPatch::typeName, &wedgePolyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &symmetryPolyPatch::typeName, &oldCyclicPolyPatch::typeName};enum patchTypeNames{ PISTON, VALVE, LINER, CYLINDERHEAD, AXIS, WEDGE, INFLOW, OUTFLOW, PRESIN, PRESOUT, SYMMETRYPLANE, CYCLIC};const char *kivaPatchNames[nBCs]={ "piston", "valve", "liner", "cylinderHead", "axis", "wedge", "inflow", "outflow", "presin", "presout", "symmetryPlane", "cyclic"};List< DynamicList< face > > pFaces[nBCs]
Definition: readKivaGrid.H:233
faceListList boundary(nPatches)
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
forAll(cellShapes, celli)
Definition: readKivaGrid.H:488
rDeltaT ref()
labelList bcl(nPoints)
labelList f(nPoints)
word defaultFacesName
Definition: readKivaGrid.H:456
face quadFace(4)
List< word > wordList
List of word.
Definition: fileName.H:59
label newPointi
Definition: readKivaGrid.H:497
pointField points(nPoints)
const char * end
Definition: SVGTools.H:223
Info<< "Reading kiva grid from file "<< kivaFileName<< endl;char title[120];kivaFile.getline(title, 120, '\n');label nPoints, nCells, nRegs;kivaFile > nCells nPoints nRegs
Definition: readKivaGrid.H:17
messageStream Info
Information stream (stdout output on master, null elsewhere)
labelList bcf(nPoints)
PtrList< dictionary > patchDicts
Definition: readKivaGrid.H:533
List< label > labelList
A List of labels.
Definition: List.H:61
dimensionedScalar tan(const dimensionedScalar &ds)
constexpr scalar degToRad(const scalar deg) noexcept
Conversion from degrees to radians.
labelList i1tab(nPoints)
const FieldField< fvPatchField, Type > & ff(const FieldField< fvPatchField, Type > &bf)