triSurface.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "triSurface.H"
27 #include "demandDrivenData.H"
28 #include "IFstream.H"
29 #include "OFstream.H"
30 #include "Time.H"
31 #include "boundBox.H"
32 #include "SortableList.H"
33 #include "PackedBoolList.H"
34 #include "plane.H"
35 #include "tensor2D.H"
36 #include "symmTensor2D.H"
37 #include "transform.H"
38 
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 
41 namespace Foam
42 {
43  defineTypeNameAndDebug(triSurface, 0);
44 }
45 
46 
47 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
48 
50 {
51  fileName foamName(d.caseName() + ".ftr");
52 
53  // Search back through the time directories list to find the time
54  // closest to and lower than current time
55 
56  instantList ts = d.times();
57  label i;
58 
59  for (i=ts.size()-1; i>=0; i--)
60  {
61  if (ts[i].value() <= d.timeOutputValue())
62  {
63  break;
64  }
65  }
66 
67  // Noting that the current directory has already been searched
68  // for mesh data, start searching from the previously stored time directory
69 
70  if (i>=0)
71  {
72  for (label j=i; j>=0; j--)
73  {
74  if (isFile(d.path()/ts[j].name()/typeName/foamName))
75  {
76  if (debug)
77  {
78  Pout<< " triSurface::triSurfInstance(const Time& d)"
79  << "reading " << foamName
80  << " from " << ts[j].name()/typeName
81  << endl;
82  }
83 
84  return ts[j].name();
85  }
86  }
87  }
88 
89  if (debug)
90  {
91  Pout<< " triSurface::triSurfInstance(const Time& d)"
92  << "reading " << foamName
93  << " from constant/" << endl;
94  }
95  return d.constant();
96 }
97 
98 
99 Foam::List<Foam::labelledTri> Foam::triSurface::convertToTri
100 (
101  const faceList& faces,
102  const label defaultRegion
103 )
104 {
105  List<labelledTri> triFaces(faces.size());
106 
107  forAll(triFaces, facei)
108  {
109  const face& f = faces[facei];
110 
111  if (f.size() != 3)
112  {
114  << "Face at position " << facei
115  << " does not have three vertices:" << f
116  << abort(FatalError);
117  }
118 
119  labelledTri& tri = triFaces[facei];
120 
121  tri[0] = f[0];
122  tri[1] = f[1];
123  tri[2] = f[2];
124  tri.region() = defaultRegion;
125  }
126 
127  return triFaces;
128 }
129 
130 
131 Foam::List<Foam::labelledTri> Foam::triSurface::convertToTri
132 (
133  const triFaceList& faces,
134  const label defaultRegion
135 )
136 {
137  List<labelledTri> triFaces(faces.size());
138 
139  forAll(triFaces, facei)
140  {
141  const triFace& f = faces[facei];
142 
143  labelledTri& tri = triFaces[facei];
144 
145  tri[0] = f[0];
146  tri[1] = f[1];
147  tri[2] = f[2];
148  tri.region() = defaultRegion;
149  }
150 
151  return triFaces;
152 }
153 
154 
155 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
156 
157 void Foam::triSurface::printTriangle
158 (
159  Ostream& os,
160  const string& pre,
161  const labelledTri& f,
162  const pointField& points
163 )
164 {
165  os
166  << pre.c_str() << "vertex numbers:"
167  << f[0] << ' ' << f[1] << ' ' << f[2] << endl
168  << pre.c_str() << "vertex coords :"
169  << points[f[0]] << ' ' << points[f[1]] << ' ' << points[f[2]]
170  << pre.c_str() << "region :" << f.region() << endl
171  << endl;
172 }
173 
174 
175 Foam::string Foam::triSurface::getLineNoComment(IFstream& is)
176 {
177  string line;
178  do
179  {
180  is.getLine(line);
181  }
182  while ((line.empty() || line[0] == '#') && is.good());
183 
184  return line;
185 }
186 
187 
188 Foam::scalar Foam::triSurface::pointNormalWeight
189 (
190  const triFace& f,
191  const label pi,
192  const vector& fa,
193  const pointField& points
194 ) const
195 {
196  const label index = findIndex(f, pi);
197 
198  if (index == -1)
199  {
201  << "Point not in face" << abort(FatalError);
202  }
203 
204  const vector e1 = points[f[index]] - points[f[f.fcIndex(index)]];
205  const vector e2 = points[f[index]] - points[f[f.rcIndex(index)]];
206 
207  return mag(fa)/(magSqr(e1)*magSqr(e2) + vSmall);
208 }
209 
210 
211 Foam::tmp<Foam::vectorField> Foam::triSurface::weightedPointNormals() const
212 {
213  // Weighted average of normals of faces attached to the vertex
214  // Weight = fA / (mag(e0)^2 * mag(e1)^2);
215 
216  tmp<vectorField> tpointNormals
217  (
218  new vectorField(nPoints(), Zero)
219  );
220  vectorField& pointNormals = tpointNormals.ref();
221 
222  const pointField& points = this->points();
223  const labelListList& pointFaces = this->pointFaces();
224  const labelList& meshPoints = this->meshPoints();
225 
226  forAll(pointFaces, pi)
227  {
228  const labelList& pFaces = pointFaces[pi];
229 
230  forAll(pFaces, fi)
231  {
232  const label facei = pFaces[fi];
233  const triFace& f = operator[](facei);
234 
235  const vector fa = f.area(points);
236  const scalar weight =
237  pointNormalWeight(f, meshPoints[pi], fa, points);
238 
239  pointNormals[pi] += weight*fa;
240  }
241 
242  pointNormals[pi] /= mag(pointNormals[pi]) + vSmall;
243  }
244 
245  return tpointNormals;
246 }
247 
248 
249 Foam::tmp<Foam::triadField> Foam::triSurface::pointCoordSys
250 (
251  const vectorField& pointNormals
252 ) const
253 {
254  tmp<triadField> tpointCoordSys(new triadField(nPoints()));
255  triadField& pointCoordSys = tpointCoordSys.ref();
256 
257  const pointField& points = this->points();
258  const labelList& meshPoints = this->meshPoints();
259 
260  forAll(meshPoints, pi)
261  {
262  const point& pt = points[meshPoints[pi]];
263  const vector& normal = pointNormals[pi];
264 
265  if (mag(normal) < small)
266  {
267  pointCoordSys[pi] = triad::unset;
268  continue;
269  }
270 
271  plane p(pt, normal);
272 
273  // Pick a point in plane
274  vector dir1 = pt - p.aPoint();
275  dir1 /= mag(dir1);
276 
277  vector dir2 = dir1 ^ normal;
278  dir2 /= mag(dir2);
279 
280  pointCoordSys[pi] = triad(dir1, dir2, normal);
281  }
282 
283  return pointCoordSys;
284 }
285 
286 
287 bool Foam::triSurface::read(Istream& is)
288 {
289  is >> patches_ >> storedPoints() >> storedFaces();
290 
291  return true;
292 }
293 
294 
295 bool Foam::triSurface::read
296 (
297  const fileName& name,
298  const word& ext,
299  const bool check
300 )
301 {
302  if (check && !exists(name))
303  {
305  << "Cannot read " << name << exit(FatalError);
306  }
307 
308  if (ext == "gz")
309  {
310  fileName unzipName = name.lessExt();
311 
312  // Do not check for existence. Let IFstream do the unzipping.
313  return read(unzipName, unzipName.ext(), false);
314  }
315  else if (ext == "ftr")
316  {
317  return read(IFstream(name)());
318  }
319  else if (ext == "stl")
320  {
321  return readSTL(name);
322  }
323  else if (ext == "stlb")
324  {
325  return readSTLBINARY(name);
326  }
327  else if (ext == "gts")
328  {
329  return readGTS(name);
330  }
331  else if (ext == "obj")
332  {
333  return readOBJ(name);
334  }
335  else if (ext == "off")
336  {
337  return readOFF(name);
338  }
339  else if (ext == "tri")
340  {
341  return readTRI(name);
342  }
343  else if (ext == "ac")
344  {
345  return readAC(name);
346  }
347  else if (ext == "nas")
348  {
349  return readNAS(name);
350  }
351  else if (ext == "vtk")
352  {
353  return readVTK(name);
354  }
355  else
356  {
358  << "unknown file extension " << ext
359  << ". Supported extensions are '.ftr', '.stl', '.stlb', '.gts'"
360  << ", '.obj', '.ac', '.off', '.nas', '.tri' and '.vtk'"
361  << exit(FatalError);
362 
363  return false;
364  }
365 }
366 
367 
368 void Foam::triSurface::write
369 (
370  const fileName& name,
371  const word& ext,
372  const bool sort
373 ) const
374 {
375  if (ext == "ftr")
376  {
377  return write(OFstream(name)());
378  }
379  else if (ext == "stl")
380  {
381  return writeSTLASCII(sort, OFstream(name)());
382  }
383  else if (ext == "stlb")
384  {
385  ofstream outFile(name.c_str(), std::ios::binary);
386 
387  writeSTLBINARY(outFile);
388  }
389  else if (ext == "gts")
390  {
391  return writeGTS(sort, OFstream(name)());
392  }
393  else if (ext == "obj")
394  {
395  writeOBJ(sort, OFstream(name)());
396  }
397  else if (ext == "off")
398  {
399  writeOFF(sort, OFstream(name)());
400  }
401  else if (ext == "vtk")
402  {
403  writeVTK(sort, OFstream(name)());
404  }
405  else if (ext == "tri")
406  {
407  writeTRI(sort, OFstream(name)());
408  }
409  else if (ext == "ac")
410  {
411  writeAC(OFstream(name)());
412  }
413  else if (ext == "smesh")
414  {
415  writeSMESH(sort, OFstream(name)());
416  }
417  else
418  {
420  << "unknown file extension " << ext
421  << " for file " << name
422  << ". Supported extensions are '.ftr', '.stl', '.stlb', "
423  << "'.gts', '.obj', '.vtk'"
424  << ", '.off', '.dx', '.smesh', '.ac' and '.tri'"
425  << exit(FatalError);
426  }
427 }
428 
429 
430 Foam::surfacePatchList Foam::triSurface::calcPatches(labelList& faceMap) const
431 {
432  // Sort according to region numbers of labelledTri
433  SortableList<label> sortedRegion(size());
434 
435  forAll(sortedRegion, facei)
436  {
437  sortedRegion[facei] = operator[](facei).region();
438  }
439  sortedRegion.sort();
440 
441  faceMap = sortedRegion.indices();
442 
443  // Extend regions
444  label maxRegion = patches_.size()-1; // for non-compacted regions
445 
446  if (faceMap.size())
447  {
448  maxRegion = max
449  (
450  maxRegion,
451  operator[](faceMap.last()).region()
452  );
453  }
454 
455  // Get new region list
456  surfacePatchList newPatches(maxRegion + 1);
457 
458  // Fill patch sizes
459  forAll(*this, facei)
460  {
461  label region = operator[](facei).region();
462 
463  newPatches[region].size()++;
464  }
465 
466 
467  // Fill rest of patch info
468 
469  label startFacei = 0;
470  forAll(newPatches, newPatchi)
471  {
472  surfacePatch& newPatch = newPatches[newPatchi];
473 
474  newPatch.index() = newPatchi;
475 
476  label oldPatchi = newPatchi;
477 
478  // start of patch
479  newPatch.start() = startFacei;
480 
481 
482  // Take over any information from existing patches
483  if ((oldPatchi < patches_.size()) && (patches_[oldPatchi].name() != ""))
484  {
485  newPatch.name() = patches_[oldPatchi].name();
486  }
487  else
488  {
489  newPatch.name() = word("patch") + name(newPatchi);
490  }
491 
492  if
493  (
494  (oldPatchi < patches_.size())
495  && (patches_[oldPatchi].geometricType() != "")
496  )
497  {
498  newPatch.geometricType() = patches_[oldPatchi].geometricType();
499  }
500  else
501  {
502  newPatch.geometricType() = "empty";
503  }
504 
505  startFacei += newPatch.size();
506  }
507 
508  return newPatches;
509 }
510 
511 
512 void Foam::triSurface::setDefaultPatches()
513 {
515 
516  // Get names, types and sizes
517  surfacePatchList newPatches(calcPatches(faceMap));
518 
519  // Take over names and types (but not size)
520  patches_.setSize(newPatches.size());
521 
522  forAll(newPatches, patchi)
523  {
524  patches_[patchi].index() = patchi;
525  patches_[patchi].name() = newPatches[patchi].name();
526  patches_[patchi].geometricType() = newPatches[patchi].geometricType();
527  }
528 }
529 
530 
531 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
532 
534 :
536  patches_(0),
537  sortedEdgeFacesPtr_(nullptr),
538  edgeOwnerPtr_(nullptr)
539 {}
540 
541 
542 
544 (
545  const List<labelledTri>& triangles,
546  const geometricSurfacePatchList& patches,
547  const pointField& points
548 )
549 :
550  ParentType(triangles, points),
551  patches_(patches),
552  sortedEdgeFacesPtr_(nullptr),
553  edgeOwnerPtr_(nullptr)
554 {}
555 
556 
558 (
559  List<labelledTri>& triangles,
560  const geometricSurfacePatchList& patches,
561  pointField& points,
562  const bool reuse
563 )
564 :
565  ParentType(triangles, points, reuse),
566  patches_(patches),
567  sortedEdgeFacesPtr_(nullptr),
568  edgeOwnerPtr_(nullptr)
569 {}
570 
571 
573 (
574  const Xfer<List<labelledTri>>& triangles,
575  const geometricSurfacePatchList& patches,
576  const Xfer<List<point>>& points
577 )
578 :
579  ParentType(triangles, points),
580  patches_(patches),
581  sortedEdgeFacesPtr_(nullptr),
582  edgeOwnerPtr_(nullptr)
583 {}
584 
585 
587 (
588  const List<labelledTri>& triangles,
589  const pointField& points
590 )
591 :
592  ParentType(triangles, points),
593  patches_(),
594  sortedEdgeFacesPtr_(nullptr),
595  edgeOwnerPtr_(nullptr)
596 {
597  setDefaultPatches();
598 }
599 
600 
602 (
603  const triFaceList& triangles,
604  const pointField& points
605 )
606 :
607  ParentType(convertToTri(triangles, 0), points),
608  patches_(),
609  sortedEdgeFacesPtr_(nullptr),
610  edgeOwnerPtr_(nullptr)
611 {
612  setDefaultPatches();
613 }
614 
615 
617 :
619  patches_(),
620  sortedEdgeFacesPtr_(nullptr),
621  edgeOwnerPtr_(nullptr)
622 {
623  word ext = name.ext();
624 
625  read(name, ext);
626 
627  setDefaultPatches();
628 }
629 
630 
632 :
634  patches_(),
635  sortedEdgeFacesPtr_(nullptr),
636  edgeOwnerPtr_(nullptr)
637 {
638  read(is);
639 
640  setDefaultPatches();
641 }
642 
643 
645 :
647  patches_(),
648  sortedEdgeFacesPtr_(nullptr),
649  edgeOwnerPtr_(nullptr)
650 {
651  fileName foamFile(d.caseName() + ".ftr");
652 
653  fileName foamPath(d.path()/triSurfInstance(d)/typeName/foamFile);
654 
655  IFstream foamStream(foamPath);
656 
657  read(foamStream);
658 
659  setDefaultPatches();
660 }
661 
662 
664 :
665  ParentType(ts, ts.points()),
666  patches_(ts.patches()),
667  sortedEdgeFacesPtr_(nullptr),
668  edgeOwnerPtr_(nullptr)
669 {}
670 
671 
672 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
673 
675 {
676  clearOut();
677 }
678 
679 
680 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
681 
683 {
685  deleteDemandDrivenData(sortedEdgeFacesPtr_);
686  deleteDemandDrivenData(edgeOwnerPtr_);
687 }
688 
689 
691 {
693 }
694 
695 
697 {
699 
700  clearTopology();
702 }
703 
704 
706 {
707  if (!sortedEdgeFacesPtr_)
708  {
709  calcSortedEdgeFaces();
710  }
711 
712  return *sortedEdgeFacesPtr_;
713 }
714 
715 
717 {
718  if (!edgeOwnerPtr_)
719  {
720  calcEdgeOwner();
721  }
722 
723  return *edgeOwnerPtr_;
724 }
725 
726 
728 {
729  // Remove all geometry dependent data
730  deleteDemandDrivenData(sortedEdgeFacesPtr_);
731 
732  // Adapt for new point position
733  ParentType::movePoints(newPoints);
734 
735  // Copy new points
736  storedPoints() = newPoints;
737 }
738 
739 
740 void Foam::triSurface::scalePoints(const scalar scaleFactor)
741 {
742  // avoid bad scaling
743  if (scaleFactor > 0 && scaleFactor != 1.0)
744  {
745  // Remove all geometry dependent data
746  clearTopology();
747 
748  // Adapt for new point position
750 
751  storedPoints() *= scaleFactor;
752  }
753 }
754 
755 
756 void Foam::triSurface::checkTriangles(const bool verbose)
757 {
758  // Simple check on indices ok.
759  const label maxPointi = points().size() - 1;
760 
761  forAll(*this, facei)
762  {
763  const triSurface::FaceType& f = (*this)[facei];
764 
765  forAll(f, fp)
766  {
767  if (f[fp] < 0 || f[fp] > maxPointi)
768  {
770  << "triangle " << f
771  << " uses point indices outside point range 0.."
772  << maxPointi
773  << exit(FatalError);
774  }
775  }
776  }
777 
778  // Two phase process
779  // 1. mark invalid faces
780  // 2. pack
781  // Done to keep numbering constant in phase 1
782 
783  // List of valid triangles
784  boolList valid(size(), true);
785  bool hasInvalid = false;
786 
787  forAll(*this, facei)
788  {
789  const labelledTri& f = (*this)[facei];
790 
791  if ((f[0] == f[1]) || (f[0] == f[2]) || (f[1] == f[2]))
792  {
793  // 'degenerate' triangle check
794  valid[facei] = false;
795  hasInvalid = true;
796 
797  if (verbose)
798  {
800  << "triangle " << facei
801  << " does not have three unique vertices:\n";
802  printTriangle(Warning, " ", f, points());
803  }
804  }
805  else
806  {
807  // duplicate triangle check
808  const labelList& fEdges = faceEdges()[facei];
809 
810  // Check if faceNeighbours use same points as this face.
811  // Note: discards normal information - sides of baffle are merged.
812 
813  forAll(fEdges, fp)
814  {
815  const labelList& eFaces = edgeFaces()[fEdges[fp]];
816 
817  forAll(eFaces, i)
818  {
819  label neighbour = eFaces[i];
820 
821  if (neighbour > facei)
822  {
823  // lower numbered faces already checked
824  const labelledTri& n = (*this)[neighbour];
825 
826  if
827  (
828  ((f[0] == n[0]) || (f[0] == n[1]) || (f[0] == n[2]))
829  && ((f[1] == n[0]) || (f[1] == n[1]) || (f[1] == n[2]))
830  && ((f[2] == n[0]) || (f[2] == n[1]) || (f[2] == n[2]))
831  )
832  {
833  valid[facei] = false;
834  hasInvalid = true;
835 
836  if (verbose)
837  {
839  << "triangles share the same vertices:\n"
840  << " face 1 :" << facei << endl;
841  printTriangle(Warning, " ", f, points());
842 
843  Warning
844  << endl
845  << " face 2 :"
846  << neighbour << endl;
847  printTriangle(Warning, " ", n, points());
848  }
849 
850  break;
851  }
852  }
853  }
854  }
855  }
856  }
857 
858  if (hasInvalid)
859  {
860  // Pack
861  label newFacei = 0;
862  forAll(*this, facei)
863  {
864  if (valid[facei])
865  {
866  const labelledTri& f = (*this)[facei];
867  (*this)[newFacei++] = f;
868  }
869  }
870 
871  if (verbose)
872  {
874  << "Removing " << size() - newFacei
875  << " illegal faces." << endl;
876  }
877  (*this).setSize(newFacei);
878 
879  // Topology can change because of renumbering
880  clearOut();
881  }
882 }
883 
884 
885 void Foam::triSurface::checkEdges(const bool verbose)
886 {
887  const labelListList& eFaces = edgeFaces();
888 
889  forAll(eFaces, edgeI)
890  {
891  const labelList& myFaces = eFaces[edgeI];
892 
893  if (myFaces.empty())
894  {
896  << "Edge " << edgeI << " with vertices " << edges()[edgeI]
897  << " has no edgeFaces"
898  << exit(FatalError);
899  }
900  else if (myFaces.size() > 2 && verbose)
901  {
903  << "Edge " << edgeI << " with vertices " << edges()[edgeI]
904  << " has more than 2 faces connected to it : " << myFaces
905  << endl;
906  }
907  }
908 }
909 
910 
911 void Foam::triSurface::cleanup(const bool verbose)
912 {
913  // Merge points (already done for STL, TRI)
914  stitchTriangles(small, verbose);
915 
916  // Merging points might have changed geometric factors
917  clearOut();
918 
919  checkTriangles(verbose);
920 
921  checkEdges(verbose);
922 }
923 
924 
926 (
927  const boolList& borderEdge,
928  const label facei,
929  const label currentZone,
930  labelList& faceZone
931 ) const
932 {
933  // List of faces whose faceZone has been set.
934  labelList changedFaces(1, facei);
935 
936  while (true)
937  {
938  // Pick up neighbours of changedFaces
939  DynamicList<label> newChangedFaces(2*changedFaces.size());
940 
941  forAll(changedFaces, i)
942  {
943  label facei = changedFaces[i];
944 
945  const labelList& fEdges = faceEdges()[facei];
946 
947  forAll(fEdges, i)
948  {
949  label edgeI = fEdges[i];
950 
951  if (!borderEdge[edgeI])
952  {
953  const labelList& eFaces = edgeFaces()[edgeI];
954 
955  forAll(eFaces, j)
956  {
957  label nbrFacei = eFaces[j];
958 
959  if (faceZone[nbrFacei] == -1)
960  {
961  faceZone[nbrFacei] = currentZone;
962  newChangedFaces.append(nbrFacei);
963  }
964  else if (faceZone[nbrFacei] != currentZone)
965  {
967  << "Zones " << faceZone[nbrFacei]
968  << " at face " << nbrFacei
969  << " connects to zone " << currentZone
970  << " at face " << facei
971  << abort(FatalError);
972  }
973  }
974  }
975  }
976  }
977 
978  if (newChangedFaces.empty())
979  {
980  break;
981  }
982 
983  changedFaces.transfer(newChangedFaces);
984  }
985 }
986 
987 
989 (
990  const boolList& borderEdge,
991  labelList& faceZone
992 ) const
993 {
994  faceZone.setSize(size());
995  faceZone = -1;
996 
997  if (borderEdge.size() != nEdges())
998  {
1000  << "borderEdge boolList not same size as number of edges" << endl
1001  << "borderEdge:" << borderEdge.size() << endl
1002  << "nEdges :" << nEdges()
1003  << exit(FatalError);
1004  }
1005 
1006  label zoneI = 0;
1007 
1008  for (label startFacei = 0;; zoneI++)
1009  {
1010  // Find first non-coloured face
1011  for (; startFacei < size(); startFacei++)
1012  {
1013  if (faceZone[startFacei] == -1)
1014  {
1015  break;
1016  }
1017  }
1018 
1019  if (startFacei >= size())
1020  {
1021  break;
1022  }
1023 
1024  faceZone[startFacei] = zoneI;
1025 
1026  markZone(borderEdge, startFacei, zoneI, faceZone);
1027  }
1028 
1029  return zoneI;
1030 }
1031 
1032 
1035  const boolList& include,
1036  labelList& pointMap,
1037  labelList& faceMap
1038 ) const
1039 {
1040  const List<labelledTri>& locFaces = localFaces();
1041 
1042  label facei = 0;
1043  label pointi = 0;
1044 
1045  faceMap.setSize(locFaces.size());
1046 
1047  pointMap.setSize(nPoints());
1048 
1049  boolList pointHad(nPoints(), false);
1050 
1051  forAll(include, oldFacei)
1052  {
1053  if (include[oldFacei])
1054  {
1055  // Store new faces compact
1056  faceMap[facei++] = oldFacei;
1057 
1058  // Renumber labels for face
1059  const triSurface::FaceType& f = locFaces[oldFacei];
1060 
1061  forAll(f, fp)
1062  {
1063  label labI = f[fp];
1064  if (!pointHad[labI])
1065  {
1066  pointHad[labI] = true;
1067  pointMap[pointi++] = labI;
1068  }
1069  }
1070  }
1071  }
1072 
1073  // Trim
1074  faceMap.setSize(facei);
1075  pointMap.setSize(pointi);
1076 }
1077 
1078 
1081  const boolList& include,
1082  labelList& pointMap,
1083  labelList& faceMap
1084 ) const
1085 {
1086  const pointField& locPoints = localPoints();
1087  const List<labelledTri>& locFaces = localFaces();
1088 
1089  // Fill pointMap, faceMap
1090  subsetMeshMap(include, pointMap, faceMap);
1091 
1092 
1093  // Create compact coordinate list and forward mapping array
1094  pointField newPoints(pointMap.size());
1095  labelList oldToNew(locPoints.size());
1096  forAll(pointMap, pointi)
1097  {
1098  newPoints[pointi] = locPoints[pointMap[pointi]];
1099  oldToNew[pointMap[pointi]] = pointi;
1100  }
1101 
1102  // Renumber triangle node labels and compact
1103  List<labelledTri> newTriangles(faceMap.size());
1104 
1105  forAll(faceMap, facei)
1106  {
1107  // Get old vertex labels
1108  const labelledTri& tri = locFaces[faceMap[facei]];
1109 
1110  newTriangles[facei][0] = oldToNew[tri[0]];
1111  newTriangles[facei][1] = oldToNew[tri[1]];
1112  newTriangles[facei][2] = oldToNew[tri[2]];
1113  newTriangles[facei].region() = tri.region();
1114  }
1115 
1116  // Construct subsurface
1117  return triSurface(newTriangles, patches(), newPoints, true);
1118 }
1119 
1120 
1122 {
1123  faceList faces(size());
1124 
1125  forAll(*this, facei)
1126  {
1127  faces[facei] = operator[](facei).triFaceFace();
1128  }
1129 
1130  return faces;
1131 }
1132 
1133 
1135 {
1136  // Curvature calculation is an implementation of the algorithm from:
1137  // "Estimating Curvatures and their Derivatives on Triangle Meshes"
1138  // by S. Rusinkiewicz
1139 
1140  const pointField& points = this->points();
1141  const labelList& meshPoints = this->meshPoints();
1142  const Map<label>& meshPointMap = this->meshPointMap();
1143 
1145  (
1146  this->weightedPointNormals()
1147  );
1148 
1149  const triadField pointCoordSys
1150  (
1151  this->pointCoordSys(pointNormals)
1152  );
1153 
1154  tmp<scalarField> tcurvaturePointField(new scalarField(nPoints(), 0.0));
1155  scalarField& curvaturePointField = tcurvaturePointField.ref();
1156 
1157  List<symmTensor2D> pointFundamentalTensors(nPoints(), Zero);
1158  scalarList accumulatedWeights(nPoints(), 0.0);
1159 
1160  forAll(*this, fi)
1161  {
1162  const triFace& f = operator[](fi);
1163  const edgeList fEdges = f.edges();
1164 
1165  // Calculate the edge vectors and the normal differences
1166  vectorField edgeVectors(f.size(), Zero);
1167  vectorField normalDifferences(f.size(), Zero);
1168 
1169  forAll(fEdges, feI)
1170  {
1171  const edge& e = fEdges[feI];
1172 
1173  edgeVectors[feI] = e.vec(points);
1174  normalDifferences[feI] =
1175  pointNormals[meshPointMap[e[0]]]
1176  - pointNormals[meshPointMap[e[1]]];
1177  }
1178 
1179  // Set up a local coordinate system for the face
1180  const vector& e0 = edgeVectors[0];
1181  const vector eN = f.area(points);
1182  const vector e1 = (e0 ^ eN);
1183 
1184  if (magSqr(eN) < rootVSmall)
1185  {
1186  continue;
1187  }
1188 
1189  triad faceCoordSys(e0, e1, eN);
1190  faceCoordSys.normalize();
1191 
1192  // Construct the matrix to solve
1194  scalarDiagonalMatrix Z(3, 0);
1195 
1196  // Least Squares
1197  for (label i = 0; i < 3; ++i)
1198  {
1199  const scalar x = edgeVectors[i] & faceCoordSys[0];
1200  const scalar y = edgeVectors[i] & faceCoordSys[1];
1201 
1202  T(0, 0) += sqr(x);
1203  T(1, 0) += x*y;
1204  T(1, 1) += sqr(x) + sqr(y);
1205  T(2, 1) += x*y;
1206  T(2, 2) += sqr(y);
1207 
1208  const scalar dndx = normalDifferences[i] & faceCoordSys[0];
1209  const scalar dndy = normalDifferences[i] & faceCoordSys[1];
1210 
1211  Z[0] += dndx*x;
1212  Z[1] += dndx*y + dndy*x;
1213  Z[2] += dndy*y;
1214  }
1215 
1216  // Perform Cholesky decomposition and back substitution.
1217  // Decomposed matrix is in T and solution is in Z.
1218  LUsolve(T, Z);
1219  const symmTensor2D secondFundamentalTensor(Z[0], Z[1], Z[2]);
1220 
1221  // Loop over the face points adding the contribution of the face
1222  // curvature to the points.
1223  forAll(f, fpi)
1224  {
1225  const label patchPointIndex = meshPointMap[f[fpi]];
1226 
1227  const triad& ptCoordSys = pointCoordSys[patchPointIndex];
1228 
1229  if (!ptCoordSys.set())
1230  {
1231  continue;
1232  }
1233 
1234  // Rotate faceCoordSys to ptCoordSys
1235  const tensor rotTensor = rotationTensor
1236  (
1237  ptCoordSys[2],
1238  faceCoordSys[2]
1239  );
1240  const triad rotatedFaceCoordSys = rotTensor & tensor(faceCoordSys);
1241 
1242  // Project the face curvature onto the point plane
1243 
1244  const vector2D cmp1
1245  (
1246  ptCoordSys[0] & rotatedFaceCoordSys[0],
1247  ptCoordSys[0] & rotatedFaceCoordSys[1]
1248  );
1249  const vector2D cmp2
1250  (
1251  ptCoordSys[1] & rotatedFaceCoordSys[0],
1252  ptCoordSys[1] & rotatedFaceCoordSys[1]
1253  );
1254 
1255  const tensor2D projTensor
1256  (
1257  cmp1,
1258  cmp2
1259  );
1260 
1261  const symmTensor2D projectedFundamentalTensor
1262  (
1263  projTensor.x() & (secondFundamentalTensor & projTensor.x()),
1264  projTensor.x() & (secondFundamentalTensor & projTensor.y()),
1265  projTensor.y() & (secondFundamentalTensor & projTensor.y())
1266  );
1267 
1268  // Calculate weight
1269  const scalar weight = pointNormalWeight
1270  (
1271  f,
1272  meshPoints[patchPointIndex],
1273  f.area(points),
1274  points
1275  );
1276 
1277  // Sum contribution of face to this point
1278  pointFundamentalTensors[patchPointIndex] +=
1279  weight*projectedFundamentalTensor;
1280 
1281  accumulatedWeights[patchPointIndex] += weight;
1282  }
1283  }
1284 
1285  forAll(curvaturePointField, pi)
1286  {
1287  pointFundamentalTensors[pi] /= (accumulatedWeights[pi] + small);
1288 
1289  const vector2D principalCurvatures =
1290  eigenValues(pointFundamentalTensors[pi]);
1291 
1292  // scalar curvature =
1293  // (principalCurvatures[0] + principalCurvatures[1])/2;
1294  const scalar curvature = max
1295  (
1296  mag(principalCurvatures[0]),
1297  mag(principalCurvatures[1])
1298  );
1299  // scalar curvature = principalCurvatures[0]*principalCurvatures[1];
1300 
1301  curvaturePointField[meshPoints[pi]] = curvature;
1302  }
1303 
1304  return tcurvaturePointField;
1305 }
1306 
1307 
1308 void Foam::triSurface::write
1310  const fileName& name,
1311  const bool sortByRegion
1312 ) const
1313 {
1314  write(name, name.ext(), sortByRegion);
1315 }
1316 
1317 
1318 void Foam::triSurface::write(Ostream& os) const
1319 {
1320  os << patches() << endl;
1321 
1322  // Note: Write with global point numbering
1323  os << points() << nl
1324  << static_cast<const List<labelledTri>&>(*this) << endl;
1325 
1326  // Check state of Ostream
1327  os.check("triSurface::write(Ostream&)");
1328 }
1329 
1330 
1331 void Foam::triSurface::write(const Time& d) const
1332 {
1333  fileName foamFile(d.caseName() + ".ftr");
1334 
1335  fileName foamPath(d.path()/triSurfInstance(d)/typeName/foamFile);
1336 
1337  OFstream foamStream(foamPath);
1338 
1339  write(foamStream);
1340 }
1341 
1342 
1344 {
1345  // Unfortunately nPoints constructs meshPoints() so do compact version
1346  // ourselves.
1347  PackedBoolList pointIsUsed(points().size());
1348 
1349  label nPoints = 0;
1351 
1352  forAll(*this, facei)
1353  {
1354  const triSurface::FaceType& f = operator[](facei);
1355 
1356  forAll(f, fp)
1357  {
1358  label pointi = f[fp];
1359  if (pointIsUsed.set(pointi, 1))
1360  {
1361  bb.min() = ::Foam::min(bb.min(), points()[pointi]);
1362  bb.max() = ::Foam::max(bb.max(), points()[pointi]);
1363  nPoints++;
1364  }
1365  }
1366  }
1367 
1368  os << "Triangles : " << size() << endl
1369  << "Vertices : " << nPoints << endl
1370  << "Bounding Box : " << bb << endl;
1371 }
1372 
1373 
1374 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
1375 
1377 {
1379  clearOut();
1380  storedPoints() = ts.points();
1381  patches_ = ts.patches();
1382 }
1383 
1384 
1385 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
1386 
1388 {
1389  sm.write(os);
1390  return os;
1391 }
1392 
1393 
1394 // ************************************************************************* //
virtual const fileName & name() const
Return the name of the stream.
Definition: OSstream.H:88
A simple container for copying or transferring objects of type <T>.
Definition: Xfer.H:85
label nPoints() const
Return number of points supporting patch faces.
void cleanup(const bool verbose)
Remove non-valid triangles.
Definition: triSurface.C:911
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
bool empty() const
Return true if the UList is empty (ie, size() is zero)
Definition: UListI.H:313
fileName path() const
Return path.
Definition: Time.H:266
label start() const
Return start label of this patch in the polyMesh face list.
Definition: surfacePatch.H:109
virtual void movePoints(const Field< point > &)
Correct patch after moving points.
void sort()
(stable) sort the list (if changed after construction time)
Definition: SortableList.C:104
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
A line primitive.
Definition: line.H:56
A class for handling file names.
Definition: fileName.H:69
const word & name() const
Return name.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
error FatalError
void operator=(const triSurface &)
Definition: triSurface.C:1376
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
T & operator[](const label)
Return element of UList.
Definition: UListI.H:167
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
virtual bool check(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:92
const Field< point > & pointNormals() const
Return point normals for patch.
A list that is sorted upon construction or when explicitly requested with the sort() method...
Definition: List.H:73
T & ref() const
Return non-const reference or generate a fatal error.
Definition: tmpI.H:174
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Vector2D< Cmpt > x() const
Definition: Tensor2DI.H:100
Output to file stream.
Definition: OFstream.H:82
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:163
const word & geometricType() const
Return the type of the patch.
dimensionedVector eigenValues(const dimensionedTensor &dt)
tmp< scalarField > curvature() const
Return the curvature of surface at the points.
Definition: triSurface.C:1134
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:256
A bounding box defined in terms of the points at its extremities.
Definition: boundBox.H:58
void writeOBJ(Ostream &os, const point &pt)
Write obj representation of point.
Definition: meshTools.C:203
edgeList edges() const
Return edges in face point ordering,.
Definition: triFaceI.H:325
virtual void scalePoints(const scalar)
Scale points. A non-positive factor is ignored.
Definition: triSurface.C:740
Geometric class that creates a 2D plane and can return the intersection point between a line and the ...
Definition: plane.H:60
tensor rotationTensor(const vector &n1, const vector &n2)
Rotational transformation tensor from vector n1 to n2.
Definition: transform.H:47
void clearPatchMeshAddr()
Definition: triSurface.C:690
vector area(const pointField &) const
Return vector area.
Definition: triFaceI.H:174
Vector2D< Cmpt > y() const
Definition: Tensor2DI.H:106
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:68
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:333
word ext() const
Return file name extension (part after last .)
Definition: fileName.C:283
Templated 2D tensor derived from VectorSpace adding construction from 4 components, element access using xx(), xy(), yx() and yy() member functions and the iner-product (dot-product) and outer-product of two Vector2Ds (tensor-product) operators.
Definition: Tensor2D.H:56
const labelList & meshPoints() const
Return labelList of mesh points in patch. They are constructed.
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
bool set(const direction d) const
Is the vector in the direction d set.
Definition: triadI.H:61
const List< labelledTri > & localFaces() const
Return patch faces addressing into local point list.
virtual void movePoints(const pointField &)
Move points.
Definition: triSurface.C:727
void write(Ostream &, const label, const dictionary &)
Write with dictionary lookup.
void normalize()
Normalize each set axis vector to have a unit magnitude.
Definition: triadI.H:111
scalar y
label region() const
Return region label.
Definition: labelledTriI.H:68
bool read(const char *, int32_t &)
Definition: int32IO.C:85
static fileName triSurfInstance(const Time &)
Name of triSurface directory to use.
Definition: triSurface.C:49
const Map< label > & meshPointMap() const
Mesh point map. Given the global point index find its.
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
const labelListList & sortedEdgeFaces() const
Return edge-face addressing sorted (for edges with more than.
Definition: triSurface.C:705
&#39;Patch&#39; on surface as subset of triSurface.
Definition: surfacePatch.H:58
void set(const PackedList< 1 > &)
Set specified bits.
const pointField & points
static const triad unset
Definition: triad.H:99
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:58
void writeStats(Ostream &) const
Write some statistics.
Definition: triSurface.C:1343
point aPoint() const
Return a point on the plane.
Definition: plane.C:292
A class for handling words, derived from string.
Definition: word.H:59
label nPoints
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
A triangular face using a FixedList of labels corresponding to mesh vertices.
Definition: triFace.H:68
virtual const fileName & name() const
Return the name of the stream.
Definition: IOstream.H:297
3D tensor transformation operations.
const fileName & caseName() const
Return case name.
Definition: Time.H:260
void checkTriangles(const bool verbose)
Check/remove duplicate/degenerate triangles.
Definition: triSurface.C:756
void sort(UList< T > &)
Definition: UList.C:115
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:184
const word & constant() const
Return constant name.
Definition: TimePaths.H:124
void checkEdges(const bool verbose)
Check triply (or more) connected edges.
Definition: triSurface.C:885
word name() const
Return file name (part beyond last /)
Definition: fileName.C:179
const Field< point > & points() const
Return reference to global points.
const labelListList & edgeFaces() const
Return edge-face addressing.
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
static const zero Zero
Definition: zero.H:97
Triangle with additional region number.
Definition: labelledTri.H:57
errorManip< error > abort(error &err)
Definition: errorManip.H:131
label fcIndex(const label i) const
Return the forward circular index, i.e. the next index.
Definition: FixedListI.H:135
const labelList & indices() const
Return the list of sorted indices. Updated every sort.
Definition: SortableList.H:93
pointField & storedPoints()
Non-const access to global points.
Definition: triSurface.H:231
bool isFile(const fileName &, const bool checkGzip=true, const bool followLink=true)
Does the name exist as a FILE in the file system?
Definition: POSIX.C:543
Field< triad > triadField
Specialisation of Field<T> for triad.
Definition: triadField.H:49
dimensioned< scalar > magSqr(const dimensioned< Type > &)
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:53
const Field< point > & localPoints() const
Return pointField of points in patch.
vector vec(const pointField &) const
Return the vector (end - start)
Definition: edgeI.H:175
label nEdges() const
Return number of edges in patch.
static const char nl
Definition: Ostream.H:265
label size() const
Return the number of elements in the FixedList.
Definition: FixedListI.H:429
void markZone(const boolList &borderEdge, const label facei, const label currentZone, labelList &faceZone) const
Fill faceZone with currentZone for every face reachable.
Definition: triSurface.C:926
defineTypeNameAndDebug(combustionModel, 0)
Input from file stream.
Definition: IFstream.H:81
labelList f(nPoints)
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
messageStream Warning
A templated 2D square symmetric matrix of objects of <T>, where the n x n matrix dimension is known a...
Representation of a 3D Cartesian coordinate system as a Vector of vectors.
Definition: triad.H:65
void operator=(const UList< T > &)
Assignment to UList operator. Takes linear time.
Definition: List.C:376
void setSize(const label)
Reset size of List.
Definition: List.C:281
Template functions to aid in the implementation of demand driven data.
const point & max() const
Maximum describing the bounding box.
Definition: boundBoxI.H:60
const geometricSurfacePatchList & patches() const
Definition: triSurface.H:325
A bit-packed bool list.
static const boundBox invertedBox
A very large inverted boundBox: min/max == +/- vGreat.
Definition: boundBox.H:82
triSurface()
Construct null.
Definition: triSurface.C:533
label patchi
scalar timeOutputValue() const
Return current time value.
Definition: TimeStateI.H:29
label size() const
Return size of this patch in the polyMesh face list.
Definition: surfacePatch.H:121
#define WarningInFunction
Report a warning using Foam::Warning.
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
void subsetMeshMap(const boolList &include, labelList &pointMap, labelList &faceMap) const
&#39;Create&#39; sub mesh, including only faces for which
Definition: triSurface.C:1034
instantList times() const
Search the case for valid time directories.
Definition: Time.C:642
Ostream & operator<<(Ostream &, const ensightPart &)
fileName lessExt() const
Return file name without extension (part before last .)
Definition: fileName.C:268
Templated 2D symmetric tensor derived from VectorSpace adding construction from 4 components...
Definition: SymmTensor2D.H:53
const labelListList & faceEdges() const
Return face-edge addressing.
dimensioned< scalar > mag(const dimensioned< Type > &)
label n
Field< vector > vectorField
Specialisation of Field<T> for vector.
faceList faces() const
Return the list of triangles as a faceList.
Definition: triSurface.C:1121
const doubleScalar e
Elementary charge.
Definition: doubleScalar.H:98
label index() const
Return the index of this patch in the boundaryMesh.
const point & min() const
Minimum describing the bounding box.
Definition: boundBoxI.H:54
label markZones(const boolList &borderEdge, labelList &faceZone) const
(size and) fills faceZone with zone of face. Zone is area
Definition: triSurface.C:989
~triSurface()
Destructor.
Definition: triSurface.C:674
void writeVTK(OFstream &os, const Type &value)
void clearTopology()
Definition: triSurface.C:682
volScalarField & p
A class for managing temporary objects.
Definition: PtrList.H:53
triSurface subsetMesh(const boolList &include, labelList &pointMap, labelList &faceMap) const
Return new surface. Returns pointMap, faceMap from.
Definition: triSurface.C:1080
T & last()
Return the last element of the list.
Definition: UListI.H:128
Triangulated surface description with patch information.
Definition: triSurface.H:66
void deleteDemandDrivenData(DataPtr &dataPtr)
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=*(cellModeller::lookup("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]=cellShape(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];} label minLabel=min(start, end);pointMap[start]=pointMap[end]=minLabel;} } 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};const 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< SLList< face > > pFaces[nBCs]
Definition: readKivaGrid.H:235
const labelList & edgeOwner() const
If 2 face neighbours: label of face where ordering of edge.
Definition: triSurface.C:716
A class for handling character strings derived from std::string.
Definition: string.H:74
label size() const
Return the number of elements in the UList.
Definition: ListI.H:170
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Definition: List.C:342
Tensor< scalar > tensor
Tensor of scalars.
Definition: tensor.H:51
bool exists(const fileName &, const bool checkGzip=true, const bool followLink=true)
Does the name exist (as DIRECTORY or FILE) in the file system?
Definition: POSIX.C:509
Namespace for OpenFOAM.
void LUsolve(scalarSquareMatrix &matrix, List< Type > &source)
Solve the matrix using LU decomposition with pivoting.
ISstream & getLine(string &)
Raw, low-level getline into a string function.
Definition: ISstreamI.H:77