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