edgeExtractor.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | cfMesh: A library for mesh generation
4  \\ / O peration |
5  \\ / A nd | Author: Franjo Juretic (franjo.juretic@c-fields.com)
6  \\/ M anipulation | Copyright (C) Creative Fields, Ltd.
7 -------------------------------------------------------------------------------
8 License
9  This file is part of cfMesh.
10 
11  cfMesh is free software; you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by the
13  Free Software Foundation; either version 3 of the License, or (at your
14  option) any later version.
15 
16  cfMesh 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 cfMesh. If not, see <http://www.gnu.org/licenses/>.
23 
24 Description
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "error.H"
29 #include "polyMeshGenModifier.H"
30 #include "edgeExtractor.H"
31 #include "meshSurfaceEngine.H"
33 #include "meshSurfaceOptimizer.H"
34 #include "meshOctree.H"
35 #include "triSurf.H"
36 #include "triSurfModifier.H"
37 #include "helperFunctions.H"
38 #include "DynList.H"
39 #include "labelPair.H"
40 #include "labelledScalar.H"
41 #include "labelledPoint.H"
42 #include "refLabelledPoint.H"
43 #include "HashSet.H"
44 #include "triSurfacePartitioner.H"
46 #include "meshSurfaceMapper.H"
49 
50 # ifdef USE_OMP
51 #include <omp.h>
52 # endif
53 
54 //#define DEBUGEdgeExtractor
55 
56 namespace Foam
57 {
58 
59 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
60 // Private member functions
61 
63 {
64  const meshSurfaceEngine& mse = this->surfaceEngine();
66  pointValence_ = 0;
67 
68  const faceList::subList& bFaces = mse.boundaryFaces();
69  const labelList& bp = mse.bp();
70 
71  forAll(bFaces, bfI)
72  {
73  const face& bf = bFaces[bfI];
74 
75  forAll(bf, pI)
76  ++pointValence_[bp[bf[pI]]];
77  }
78 
79  if( Pstream::parRun() )
80  {
81  const Map<label>& globalToLocal =
83  const VRWGraph& bpAtProcs = mse.bpAtProcs();
84  const DynList<label>& bpNeiProcs = mse.bpNeiProcs();
85 
86  std::map<label, LongList<labelPair> > exchangeData;
87  forAll(bpNeiProcs, i)
88  exchangeData.insert
89  (
90  std::make_pair(bpNeiProcs[i], LongList<labelPair>())
91  );
92 
93  forAllConstIter(Map<label>, globalToLocal, iter)
94  {
95  const label bpI = iter();
96 
97  forAllRow(bpAtProcs, bpI, i)
98  {
99  const label neiProc = bpAtProcs(bpI, i);
100 
101  if( neiProc == Pstream::myProcNo() )
102  continue;
103 
104  exchangeData[neiProc].append
105  (
106  labelPair(iter.key(), pointValence_[bpI])
107  );
108  }
109  }
110 
111  LongList<labelPair> receivedData;
112  help::exchangeMap(exchangeData, receivedData);
113 
114  forAll(receivedData, i)
115  {
116  const labelPair& lp = receivedData[i];
117 
118  pointValence_[globalToLocal[lp.first()]] += lp.second();
119  }
120  }
121 }
122 
124 {
125  const meshSurfaceEngine& mse = this->surfaceEngine();
126  const edgeList& edges = mse.edges();
127  const VRWGraph& bpEdges = mse.boundaryPointEdges();
128  const VRWGraph& edgeFaces = mse.edgeFaces();
129  const labelList& faceCells = mse.faceOwners();
130 
131  //- find the number of boundary faces for each cell in the mesh
132  edgeType_.setSize(edgeFaces.size());
133  edgeType_ = NONE;
134 
135  forAll(edgeFaces, eI)
136  {
137  if( edgeFaces.sizeOfRow(eI) == 2 )
138  {
139  const label c0 = faceCells[edgeFaces(eI, 0)];
140  const label c1 = faceCells[edgeFaces(eI, 1)];
141 
142  if( c0 == c1 )
143  edgeType_[eI] |= SINGLECELLEDGE;
144  }
145  }
146 
147  //- calculate the number of cells attache to a boundary edge
148  const labelList& bp = mse.bp();
149  const cellListPMG& cells = mse.mesh().cells();
150  const faceListPMG& faces = mse.faces();
151 
152  nCellsAtEdge_.setSize(edgeFaces.size());
153  nCellsAtEdge_ = 0;
154 
155  # ifdef USE_OMP
156  # pragma omp parallel for schedule(dynamic, 100)
157  # endif
158  forAll(cells, cellI)
159  {
160  const cell& c = cells[cellI];
161 
162  DynList<edge> foundEdge;
163 
164  forAll(c, fI)
165  {
166  const face& f = faces[c[fI]];
167 
168  forAll(f, eI)
169  {
170  const edge e = f.faceEdge(eI);
171 
172  const label bps = bp[e.start()];
173 
174  if( bps < 0 )
175  continue;
176 
177  forAllRow(bpEdges, bps, i)
178  {
179  const label beI = bpEdges(bps, i);
180  const edge& be = edges[beI];
181 
182  if( (e == be) && !foundEdge.contains(be) )
183  {
184  foundEdge.append(be);
185 
186  # ifdef USE_OMP
187  # pragma omp atomic
188  # endif
189  ++nCellsAtEdge_[beI];
190  }
191  }
192  }
193  }
194  }
195 }
196 
198 {
199  const meshSurfaceEngine& mse = this->surfaceEngine();
200  const pointFieldPMG& points = mse.points();
201  const faceList::subList& bFaces = mse.boundaryFaces();
202  const triSurf& surface = meshOctree_.surface();
203 
204  patchesNearFace_.setSize(bFaces.size());
205  labelLongList nPatchesAtFace(bFaces.size());
206 
207  # ifdef USE_OMP
208  # pragma omp parallel
209  # endif
210  {
211  labelLongList localData;
212  DynList<label> nearFacets;
213 
214  # ifdef USE_OMP
215  # pragma omp for schedule(dynamic, 40)
216  # endif
217  forAll(bFaces, bfI)
218  {
219  const face& bf = bFaces[bfI];
220 
221  const vector c = bf.centre(points);
222 
223  // find a reasonable searching distance comparable to face size
224  scalar d(0.0);
225  forAll(bf, pI)
226  d = Foam::max(d, Foam::mag(c - points[bf[pI]]));
227  d = 2.0 * d + VSMALL;
228 
229  const boundBox bb(c - vector(d, d, d), c + vector(d, d, d));
230 
231  //- get the patches near the current boundary face
232  meshOctree_.findTrianglesInBox(bb, nearFacets);
233  DynList<label> nearPatches;
234  forAll(nearFacets, i)
235  nearPatches.appendIfNotIn(surface[nearFacets[i]].region());
236 
237  localData.append(bfI);
238  nPatchesAtFace[bfI] = nearPatches.size();
239  forAll(nearPatches, i)
240  localData.append(nearPatches[i]);
241  }
242 
243  # ifdef USE_OMP
244  # pragma omp barrier
245 
246  # pragma omp master
247  patchesNearFace_.setSizeAndRowSize(nPatchesAtFace);
248 
249  # pragma omp barrier
250  # else
251  patchesNearFace_.setSizeAndRowSize(nPatchesAtFace);
252  # endif
253 
254  //- copy the data to the graph
255  label counter(0);
256  while( counter < localData.size() )
257  {
258  const label edgeI = localData[counter++];
259 
260  const label size = nPatchesAtFace[edgeI];
261 
262  for(label i=0;i<size;++i)
263  patchesNearFace_(edgeI, i) = localData[counter++];
264  }
265  }
266 }
267 
269 {
270  const meshSurfaceEngine& mse = this->surfaceEngine();
271  const pointFieldPMG& points = mse.points();
272  const edgeList& edges = mse.edges();
273 
275  labelLongList nFeatureEdgesAtEdge(edges.size());
276 
277  # ifdef USE_OMP
278  # pragma omp parallel
279  # endif
280  {
281  labelLongList localData;
282  DynList<label> nearEdges;
283 
284  # ifdef USE_OMP
285  # pragma omp for schedule(dynamic, 40)
286  # endif
287  forAll(edges, edgeI)
288  {
289  const edge& e = edges[edgeI];
290  const vector c = e.centre(points);
291  const scalar d = 1.5 * e.mag(points);
292 
293  const boundBox bb(c - vector(d, d, d), c + vector(d, d, d));
294 
295  //- get the edges near the current edge
296  meshOctree_.findEdgesInBox(bb, nearEdges);
297  forAllReverse(nearEdges, i)
298  {
299  const label pos = nearEdges.containsAtPosition(nearEdges[i]);
300 
301  if( pos < i )
302  nearEdges.removeElement(i);
303  }
304 
305  localData.append(edgeI);
306  nFeatureEdgesAtEdge[edgeI] = nearEdges.size();
307  forAll(nearEdges, i)
308  localData.append(nearEdges[i]);
309  }
310 
311  # ifdef USE_OMP
312  # pragma omp barrier
313 
314  # pragma omp master
315  featureEdgesNearEdge_.setSizeAndRowSize(nFeatureEdgesAtEdge);
316 
317  # pragma omp barrier
318  # else
319  featureEdgesNearEdge_.setSizeAndRowSize(nFeatureEdgesAtEdge);
320  # endif
321 
322  //- copy the data to the graph
323  label counter(0);
324  while( counter < localData.size() )
325  {
326  const label edgeI = localData[counter++];
327 
328  const label size = nFeatureEdgesAtEdge[edgeI];
329 
330  for(label i=0;i<size;++i)
331  featureEdgesNearEdge_(edgeI, i) = localData[counter++];
332  }
333  }
334 }
335 
337 {
338  const meshSurfaceEngine& mse = this->surfaceEngine();
339  const labelList& bPoints = mse.boundaryPoints();
340  const edgeList& edges = mse.edges();
341  const VRWGraph& edgeFaces = mse.edgeFaces();
342  const labelList& bp = mse.bp();
343 
344  patchPoint.setSize(bPoints.size());
345  patchPoint = true;
346 
347  std::map<label, label> otherProcPatch;
348  if( Pstream::parRun() )
349  {
350  const Map<label>& otherProc = mse.otherEdgeFaceAtProc();
351  const Map<label>& globalToLocal =
353 
354  //- create communication matrix
355  std::map<label, labelLongList> exchangeData;
356  const DynList<label>& neiProcs = mse.beNeiProcs();
357  forAll(neiProcs, procI)
358  exchangeData.insert
359  (
360  std::make_pair(neiProcs[procI], labelLongList())
361  );
362 
363  forAllConstIter(Map<label>, globalToLocal, it)
364  {
365  const label beI = it();
366 
367  if( edgeFaces.sizeOfRow(beI) == 1 )
368  {
369  labelLongList& dts = exchangeData[otherProc[beI]];
370  //- send data as follows:
371  //- 1. global edge label
372  //- 2. patch of the attached boundary face
373  dts.append(it.key());
374  dts.append(facePatch_[edgeFaces(beI, 0)]);
375  }
376  }
377 
378  labelLongList receivedData;
379  help::exchangeMap(exchangeData, receivedData);
380 
381  label counter(0);
382  while( counter < receivedData.size() )
383  {
384  const label beI = globalToLocal[receivedData[counter++]];
385  const label fPatch = receivedData[counter++];
386 
387  otherProcPatch[beI] = fPatch;
388  }
389  }
390 
391  //- set the patchPoint to false for all vertices at feature edges
392  # ifdef USE_OMP
393  # pragma omp parallel for schedule(dynamic, 40)
394  # endif
395  forAll(edgeFaces, beI)
396  {
397  if( edgeFaces.sizeOfRow(beI) == 2 )
398  {
399  //- an ordinary edge
400  if( facePatch_[edgeFaces(beI, 0)] != facePatch_[edgeFaces(beI, 1)] )
401  {
402  const edge& e = edges[beI];
403  patchPoint[bp[e.start()]] = false;
404  patchPoint[bp[e.end()]] = false;
405  }
406  }
407  else if( edgeFaces.sizeOfRow(beI) == 1 )
408  {
409  //- an edge at a parallel interface
410  const label otherPatch = otherProcPatch[beI];
411 
412  if( facePatch_[edgeFaces(beI, 0)] != otherPatch )
413  {
414  const edge& e = edges[beI];
415  patchPoint[bp[e.start()]] = false;
416  patchPoint[bp[e.end()]] = false;
417  }
418  }
419  else
420  {
421  //- this is a non-manifold edge
422  const edge& e = edges[beI];
423  patchPoint[bp[e.start()]] = false;
424  patchPoint[bp[e.end()]] = false;
425  }
426  }
427 
428  if( Pstream::parRun() )
429  {
430  //- make sure that the information is spread to all processors
431  const VRWGraph& bpAtProcs = mse.bpAtProcs();
432  const DynList<label>& neiProcs = mse.bpNeiProcs();
433  const labelList& globalPointLabel =
435  const Map<label>& globalToLocal =
437 
438 
439  std::map<label, labelLongList> sendData;
440  forAll(neiProcs, i)
441  sendData.insert(std::make_pair(neiProcs[i], labelLongList()));
442 
443  forAll(bpAtProcs, bpI)
444  {
445  forAllRow(bpAtProcs, bpI, i)
446  {
447  const label neiProc = bpAtProcs(bpI, i);
448 
449  if( neiProc != Pstream::myProcNo() )
450  sendData[neiProc].append(globalPointLabel[bpI]);
451  }
452  }
453 
454  labelLongList receivedData;
455  help::exchangeMap(sendData, receivedData);
456 
457  forAll(receivedData, i)
458  patchPoint[globalToLocal[receivedData[i]]] = false;
459  }
460 }
461 
463 {
464  if( !surfaceEnginePtr_ )
465  {
466  # ifdef USE_OMP
467  # pragma omp critical
468  # endif
469  {
470  if( !surfaceEnginePtr_ )
471  {
473  }
474  }
475  }
476 
477  return *surfaceEnginePtr_;
478 }
479 
481 {
482  if( !surfPartitionerPtr_ )
483  {
484  # ifdef USE_OMP
485  # pragma omp critical
486  # endif
487  {
488  if( !surfPartitionerPtr_ )
489  {
492  }
493  }
494  }
495 
496  return *surfPartitionerPtr_;
497 }
498 
500 {
502  {
505  }
506 
508 }
509 
511 (
512  labelLongList& faceCandidates,
513  const labelList* facePatchPtr,
514  const Map<label>* otherFacePatchPtr
515 ) const
516 {
517  faceCandidates.clear();
518  if( !facePatchPtr )
519  facePatchPtr = &facePatch_;
520 
521  const labelList& fPatches = *facePatchPtr;
522 
523  bool deleteOtherFacePatchPtr(false);
524  if( !otherFacePatchPtr )
525  {
526  Map<label>* helperPtr = new Map<label>();
527 
528  findOtherFacePatchesParallel(*helperPtr, facePatchPtr);
529 
530  otherFacePatchPtr = helperPtr;
531  deleteOtherFacePatchPtr = true;
532  }
533 
534  const Map<label>& otherFacePatch = *otherFacePatchPtr;
535 
536  const meshSurfaceEngine& mse = surfaceEngine();
537  const VRWGraph& faceEdges = mse.faceEdges();
538  const VRWGraph& edgeFaces = mse.edgeFaces();
539 
540  # ifdef USE_OMP
541  # pragma omp parallel if( faceEdges.size() > 1000 )
542  # endif
543  {
544  # ifdef USE_OMP
545  labelLongList procCandidates;
546  # pragma omp for schedule(dynamic, 40)
547  # endif
548  forAll(faceEdges, bfI)
549  {
550  DynList<label> allNeiPatches;
551  forAllRow(faceEdges, bfI, feI)
552  {
553  const label beI = faceEdges(bfI, feI);
554 
555  if( edgeFaces.sizeOfRow(beI) == 2 )
556  {
557  label fNei = edgeFaces(beI, 0);
558  if( fNei == bfI )
559  fNei = edgeFaces(beI, 1);
560 
561  allNeiPatches.appendIfNotIn(fPatches[fNei]);
562  }
563  else if( edgeFaces.sizeOfRow(beI) == 1 )
564  {
565  allNeiPatches.appendIfNotIn(otherFacePatch[beI]);
566  }
567  }
568 
569  if( allNeiPatches.size() > 1 )
570  {
571  //- this face is probably near some feature edge
572  # ifdef USE_OMP
573  procCandidates.append(bfI);
574  # else
575  faceCandidates.append(bfI);
576  # endif
577  }
578  }
579 
580  # ifdef USE_OMP
581  # pragma omp critical
582  {
583  forAll(procCandidates, i)
584  faceCandidates.append(procCandidates[i]);
585  }
586  # endif
587  }
588 
589  if( deleteOtherFacePatchPtr )
590  deleteDemandDrivenData(otherFacePatchPtr);
591 }
592 
594 (
595  Map<label>& otherFacePatch,
596  const labelList* facePatchPtr
597 ) const
598 {
599  otherFacePatch.clear();
600 
601  if( !facePatchPtr )
602  facePatchPtr = &facePatch_;
603 
604  const labelList& fPatches = *facePatchPtr;
605 
606  if( Pstream::parRun() )
607  {
608  const meshSurfaceEngine& mse = this->surfaceEngine();
609  const VRWGraph& edgeFaces = mse.edgeFaces();
610  const Map<label>& otherProc = mse.otherEdgeFaceAtProc();
611  const Map<label>& globalToLocal =
613 
614  //- create communication matrix
615  std::map<label, labelLongList> exchangeData;
616  const DynList<label>& neiProcs = mse.beNeiProcs();
617  forAll(neiProcs, procI)
618  exchangeData.insert
619  (
620  std::make_pair(neiProcs[procI], labelLongList())
621  );
622 
623  forAllConstIter(Map<label>, globalToLocal, it)
624  {
625  const label beI = it();
626 
627  if( edgeFaces.sizeOfRow(beI) == 1 )
628  {
629  labelLongList& dts = exchangeData[otherProc[beI]];
630  //- send data as follows:
631  //- 1. global edge label
632  //- 2. patch of the attached boundary face
633  dts.append(it.key());
634  dts.append(fPatches[edgeFaces(beI, 0)]);
635  }
636  }
637 
638  labelLongList receivedData;
639  help::exchangeMap(exchangeData, receivedData);
640 
641  label counter(0);
642  while( counter < receivedData.size() )
643  {
644  const label beI = globalToLocal[receivedData[counter++]];
645  const label fPatch = receivedData[counter++];
646 
647  otherFacePatch.insert(beI, fPatch);
648  }
649  }
650 }
651 
652 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
653 
655 (
656  polyMeshGen& mesh,
657  const meshOctree& octree
658 )
659 :
660  mesh_(mesh),
661  surfaceEnginePtr_(NULL),
662  meshOctree_(octree),
663  surfPartitionerPtr_(NULL),
664  surfEdgeClassificationPtr_(NULL),
665  pointValence_(),
666  pointPatch_(),
667  facePatch_(),
668  nCellsAtEdge_(),
669  edgeType_(),
670  patchesNearFace_(),
671  featureEdgesNearEdge_()
672 {
673  calculateValence();
674 
675  calculateSingleCellEdge();
676 
677  findPatchesNearSurfaceFace();
678 
679  findFeatureEdgesNearEdge();
680 }
681 
682 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
683 // Destructor
684 
686 {
690 }
691 
692 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
693 
695 {
696  Info << "Reducing Hausdorff distance:" << flush;
697 
698  const meshSurfaceEngine& mse = this->surfaceEngine();
699  const labelList& bPoints = mse.boundaryPoints();
700  const VRWGraph& pointFaces = mse.pointFaces();
701  const pointFieldPMG& points = mse.points();
702  const faceList::subList& bFaces = mse.boundaryFaces();
703 
704  meshSurfaceEngineModifier modifier(mse);
705 
706  vectorField faceCentreDisplacement(bFaces.size());
707  List<labelledPoint> pointDisplacements(bPoints.size());
708 
709  for(label iterI=0;iterI<nIterations;++iterI)
710  {
711  # ifdef USE_OMP
712  # pragma omp parallel
713  # endif
714  {
715  //- find displacements of face centres
716  # ifdef USE_OMP
717  # pragma omp for schedule(dynamic, 40)
718  # endif
719  forAll(bFaces, bfI)
720  {
721  const vector centre = bFaces[bfI].centre(points);
722 
723  point newP;
724  scalar distSq;
725  label patchI, nearestTri;
727  (
728  newP,
729  distSq,
730  nearestTri,
731  patchI,
732  centre
733  );
734 
735  faceCentreDisplacement[bfI] = newP - centre;
736  }
737 
738  //- initialise displacements
739  # ifdef USE_OMP
740  # pragma omp for schedule(dynamic, 40)
741  # endif
742  forAll(pointDisplacements, bpI)
743  pointDisplacements[bpI] = labelledPoint(0, vector::zero);
744 
745  # ifdef USE_OMP
746  # pragma omp barrier
747  # endif
748 
749  //- calculate displacements of boundary points as the average
750  //- of face centre displacements
751  # ifdef USE_OMP
752  # pragma omp for schedule(dynamic, 40)
753  # endif
754  forAll(pointFaces, bpI)
755  {
756  forAllRow(pointFaces, bpI, pfI)
757  {
758  pointDisplacements[bpI].coordinates() +=
759  faceCentreDisplacement[pointFaces(bpI, pfI)];
760  ++pointDisplacements[bpI].pointLabel();
761  }
762  }
763  }
764 
765  if( Pstream::parRun() )
766  {
767  const Map<label>& globalToLocal =
769  const DynList<label>& neiProcs = mse.bpNeiProcs();
770  const VRWGraph& bpAtProcs = mse.bpAtProcs();
771 
772  std::map<label, LongList<refLabelledPoint> > exchangeData;
773  forAll(neiProcs, i)
774  exchangeData[i] = LongList<refLabelledPoint>();
775 
776  forAllConstIter(Map<label>, globalToLocal, iter)
777  {
778  const label bpI = iter();
779 
780  forAllRow(bpAtProcs, bpI, i)
781  {
782  const label neiProc = bpAtProcs(bpI, i);
783 
784  if( neiProc == Pstream::myProcNo() )
785  continue;
786 
787  exchangeData[neiProc].append
788  (
789  refLabelledPoint(iter.key(), pointDisplacements[bpI])
790  );
791  }
792  }
793 
794  LongList<refLabelledPoint> receivedData;
795  help::exchangeMap(exchangeData, receivedData);
796 
797  forAll(receivedData, i)
798  {
799  const label globalLabel = receivedData[i].objectLabel();
800  const labelledPoint& lp = receivedData[i].lPoint();
801 
802  const label bpI = globalToLocal[globalLabel];
803 
804  pointDisplacements[bpI].coordinates() += lp.coordinates();
805  pointDisplacements[bpI].pointLabel() += lp.pointLabel();
806  }
807  }
808 
809  # ifdef USE_OMP
810  # pragma omp parallel for schedule(dynamic, 40)
811  # endif
812  forAll(pointDisplacements, bpI)
813  {
814  const labelledPoint& lp = pointDisplacements[bpI];
815  const point mp =
816  points[bPoints[bpI]] + lp.coordinates() / lp.pointLabel();
817 
818  //Info << "Original point " << bPoints[bpI] << " has coordinates "
819  // << points[bPoints[bpI]] << endl;
820  //Info << "Displacement vector " << lp.coordinates() / lp.pointLabel() << endl;
821  //Info << "Moved point " << mp << endl;
822 
823  point newPoint;
824  label patchI, nt;
825  scalar distSq;
826 
827  meshOctree_.findNearestSurfacePoint(newPoint, distSq, nt, patchI, mp);
828 
829  //Info << "Mapped point " << newPoint << nl << endl;
830 
831  modifier.moveBoundaryVertexNoUpdate(bpI, newPoint);
832  }
833 
834  //- update geometry
835  modifier.updateGeometry();
836 
837  Info << '.' << flush;
838  }
839 
840  Info << endl;
841 }
842 
844 {
845  const meshSurfaceEngine& mse = this->surfaceEngine();
846  const labelList& bPoints = mse.boundaryPoints();
847  const faceList::subList& bFaces = mse.boundaryFaces();
848  const pointFieldPMG& points = mse.points();
849 
850  //- set the size of the facePatch list
851  facePatch_.setSize(bFaces.size());
852 
853  //- check if the mesh already has patches
854  if( mesh_.boundaries().size() > 1 )
855  Warning << "Mesh patches are already assigned!" << endl;
856 
857  //- set size of patchNames, newBoundaryFaces_ and newBoundaryOwners_
858  const triSurf& surface = meshOctree_.surface();
859  const label nPatches = surface.patches().size();
860 
861  //- find patches to which the surface points are mapped to
862  pointPatch_.setSize(bPoints.size());
863 
864  # ifdef USE_OMP
865  # pragma omp parallel for schedule(dynamic, 40)
866  # endif
867  forAll(bPoints, bpI)
868  {
869  const point& bp = points[bPoints[bpI]];
870 
871  label fPatch, nTri;
872  point p;
873  scalar distSq;
874 
875  meshOctree_.findNearestSurfacePoint(p, distSq, nTri, fPatch, bp);
876 
877  if( (fPatch > -1) && (fPatch < nPatches) )
878  {
879  pointPatch_[bpI] = fPatch;
880  }
881  else
882  {
883  pointPatch_[bpI] = nPatches;
885  (
886  "void meshSurfaceEdgeExtractorNonTopo::"
887  "distributeBoundaryFaces()"
888  ) << "Cannot distribute a boundary points " << bPoints[bpI]
889  << " into any surface patch!. Exiting.." << exit(FatalError);
890  }
891  }
892 
893  //- find the patch for face by finding the patch nearest
894  //- to the face centre
895  # ifdef USE_OMP
896  # pragma omp parallel for schedule(dynamic, 40)
897  # endif
898  forAll(bFaces, bfI)
899  {
900  const face& bf = bFaces[bfI];
901 
902  const point c = bf.centre(points);
903 
904  //- find the nearest surface patch to face centre
905  label fPatch, nTri;
906  point p;
907  scalar distSq;
908 
909  meshOctree_.findNearestSurfacePoint(p, distSq, nTri, fPatch, c);
910 
911  if( (fPatch > -1) && (fPatch < nPatches) )
912  {
913  facePatch_[bfI] = fPatch;
914  }
915  else
916  {
917  facePatch_[bfI] = nPatches;
918 
920  (
921  "void meshSurfaceEdgeExtractorNonTopo::"
922  "distributeBoundaryFaces()"
923  ) << "Cannot distribute a face " << bFaces[bfI] << " into any "
924  << "surface patch!. Exiting.." << exit(FatalError);
925  }
926  }
927 }
928 
930 {
931  bool changed(false);
932 
933  const pointFieldPMG& points = mesh_.points();
934  const meshSurfaceEngine& mse = this->surfaceEngine();
935  const faceList::subList& bFaces = mse.boundaryFaces();
936  const VRWGraph& faceEdges = mse.faceEdges();
937  const VRWGraph& edgeFaces = mse.edgeFaces();
938 
939  const triSurf& surf = meshOctree_.surface();
940  const pointField& sPoints = surf.points();
941 
942  label nCorrected, nIterations(0);
943  Map<label> otherProcNewPatch;
944 
945  do
946  {
947  nCorrected = 0;
948 
949  //- allocate a copy of boundary patches
950  labelList newBoundaryPatches(facePatch_);
951 
952  //- check whether there exist situations where a boundary face
953  //- is surrounded by more faces in different patches than the
954  //- faces in the current patch
955  if( Pstream::parRun() )
956  {
958  (
959  otherProcNewPatch,
960  &facePatch_
961  );
962  }
963 
964  //- find the faces which have neighbouring faces in other patches
965  labelLongList candidates;
966  findFaceCandidates(candidates, &facePatch_, &otherProcNewPatch);
967 
968  //- go through the list of faces and check if they shall remain
969  //- in the current patch
970  # ifdef USE_OMP
971  # pragma omp parallel for schedule(dynamic, 40) \
972  reduction(+ : nCorrected)
973  # endif
974  forAll(candidates, i)
975  {
976  const label bfI = candidates[i];
977  const face& bf = bFaces[bfI];
978 
979  DynList<label> allNeiPatches;
980  DynList<label> neiPatches;
981  neiPatches.setSize(faceEdges.sizeOfRow(bfI));
982 
983  forAllRow(faceEdges, bfI, eI)
984  {
985  const label beI = faceEdges(bfI, eI);
986 
987  if( edgeFaces.sizeOfRow(beI) == 2 )
988  {
989  label fNei = edgeFaces(beI, 0);
990  if( fNei == bfI )
991  fNei = edgeFaces(faceEdges(bfI, eI), 1);
992 
993  allNeiPatches.appendIfNotIn(facePatch_[fNei]);
994  neiPatches[eI] = facePatch_[fNei];
995  }
996  else if( edgeFaces.sizeOfRow(beI) == 1 )
997  {
998  allNeiPatches.appendIfNotIn(otherProcNewPatch[beI]);
999  neiPatches[eI] = otherProcNewPatch[beI];
1000  }
1001  }
1002 
1003  //- do not modify faces with all neighbours in the same patch
1004  if
1005  (
1006  (allNeiPatches.size() == 1) &&
1007  (allNeiPatches[0] == facePatch_[bfI])
1008  )
1009  continue;
1010 
1011  //- check whether there exist edges which are more suitable for
1012  //- projection onto feature edges than the currently selected ones
1013  label newPatch(-1);
1014  DynList<scalar> normalAlignment(allNeiPatches.size());
1015  DynList<scalar> distanceSq(allNeiPatches.size());
1016  scalar maxDSq(0.0);
1017  forAll(allNeiPatches, i)
1018  {
1019  point pMap;
1020  scalar dSq(VGREAT);
1021  label nearestTriangle;
1022 
1023  point p = bf.centre(points);
1025  (
1026  pMap,
1027  dSq,
1028  nearestTriangle,
1029  allNeiPatches[i],
1030  p
1031  );
1032 
1033  maxDSq = Foam::max(dSq, maxDSq);
1034 
1035  //- calculate normal vectors
1036  vector tn = surf[nearestTriangle].normal(sPoints);
1037  tn /= (mag(tn) + VSMALL);
1038  vector fn = bf.normal(points);
1039  fn /= (mag(fn) + SMALL);
1040 
1041  //- calculate alignment
1042  normalAlignment[i] = mag(tn & fn);
1043  distanceSq[i] = dSq;
1044  }
1045 
1046  scalar maxAlignment(0.0);
1047  forAll(normalAlignment, i)
1048  {
1049  const scalar metric
1050  (
1051  sqrt(maxDSq / (distanceSq[i] + VSMALL)) * normalAlignment[i]
1052  );
1053 
1054  if( metric > maxAlignment )
1055  {
1056  maxAlignment = metric;
1057  newPatch = allNeiPatches[i];
1058  }
1059  }
1060 
1061  if( (newPatch >= 0) && (newPatch != facePatch_[bfI]) )
1062  {
1063  newBoundaryPatches[bfI] = newPatch;
1064  ++nCorrected;
1065  }
1066  }
1067 
1068  reduce(nCorrected, sumOp<label>());
1069 
1070  if( nCorrected )
1071  {
1072  changed = true;
1073 
1074  //- transfer the new patches back
1075  facePatch_.transfer(newBoundaryPatches);
1076  }
1077  } while( (nCorrected != 0) && (++nIterations < 5) );
1078 
1079  return changed;
1080 }
1081 
1083 {
1084  const triSurf& surface = meshOctree_.surface();
1085  const vectorField& sp = surface.points();
1086  const VRWGraph& facetEdges = surface.facetEdges();
1087  const VRWGraph& edgeFacets = surface.edgeFacets();
1088 
1090 
1091  const meshSurfaceEngine& mse = this->surfaceEngine();
1092  const pointFieldPMG& points = mse.points();
1093  const labelList& bPoints = mse.boundaryPoints();
1094  const labelList& bp = mse.bp();
1095  const VRWGraph& faceEdges = mse.faceEdges();
1096 
1097  Map<label> otherFacePatch;
1098  findOtherFacePatchesParallel(otherFacePatch, &facePatch_);
1099  labelLongList faceCandidates;
1100  findFaceCandidates(faceCandidates, &facePatch_, &otherFacePatch);
1101 
1102  # ifdef USE_OMP
1103  # pragma omp parallel for schedule(dynamic, 40) \
1104  if( faceCandidates.size() > 100 )
1105  # endif
1106  forAll(faceCandidates, fcI)
1107  {
1108  const label bfI = faceCandidates[fcI];
1109 
1110  forAllRow(faceEdges, bfI, i)
1111  {
1112  const label eI = faceEdges(bfI, i);
1113  edgeType_[eI] |= CANDIDATE;
1114  }
1115  }
1116 
1117  //- find distances of all vertices supporting CANDIDATE edges
1118  //- from feature edges separating various patches
1119  const VRWGraph& pEdges = mse.boundaryPointEdges();
1120  const edgeList& edges = mse.edges();
1121 
1122  List<List<labelledScalar> > featureEdgesNearPoint(bPoints.size());
1123 
1124  DynList<label> containedTriangles;
1125  # ifdef USE_OMP
1126  # pragma omp parallel for schedule(dynamic, 40) private(containedTriangles)
1127  # endif
1128  forAll(pEdges, bpI)
1129  {
1130  // TODO rewrite for execution on distributed machines
1131  bool check(false);
1132  forAllRow(pEdges, bpI, peI)
1133  {
1134  const label eI = pEdges(bpI, peI);
1135 
1136  if( edgeType_[eI] & CANDIDATE )
1137  {
1138  check = true;
1139  break;
1140  }
1141  }
1142 
1143  if( check )
1144  {
1145  //- check the squared distance from the nearest feature edge
1146  scalar rSq(0.0);
1147  forAllRow(pEdges, bpI, peI)
1148  {
1149  const label eI = pEdges(bpI, peI);
1150  const edge& e = edges[eI];
1151  const scalar dSq = magSqr(points[e.start()] - points[e.end()]);
1152 
1153  rSq = Foam::max(rSq, dSq);
1154  }
1155 
1156  rSq *= 2.0;
1157  const scalar r = Foam::sqrt(rSq);
1158 
1159  //- create a boundaing box used for searching neighbour edges
1160  const point& p = points[bPoints[bpI]];
1161  boundBox bb(p - point(r, r, r), p + point(r, r, r));
1162 
1163  //- find the surface triangles in the vicinity of the point
1164  //- check for potential feature edges
1165  containedTriangles.clear();
1166  meshOctree_.findTrianglesInBox(bb, containedTriangles);
1167 
1168  DynList<label> featureEdgeCandidates;
1169 
1170  forAll(containedTriangles, ctI)
1171  {
1172  const label tI = containedTriangles[ctI];
1173 
1174  forAllRow(facetEdges, tI, feI)
1175  {
1176  const label seI = facetEdges(tI, feI);
1177 
1178  if( edgeFacets.sizeOfRow(seI) == 2 )
1179  {
1180  const label p0 = surface[edgeFacets(seI, 0)].region();
1181  const label p1 = surface[edgeFacets(seI, 1)].region();
1182 
1183  if( p0 != p1 )
1184  {
1185  featureEdgeCandidates.appendIfNotIn(seI);
1186  }
1187  }
1188  else
1189  {
1190  featureEdgeCandidates.appendIfNotIn(seI);
1191  }
1192  }
1193  }
1194 
1195  //- check the distance of the vertex from the candidates
1196  List<labelledScalar>& featureEdgeDistances =
1197  featureEdgesNearPoint[bpI];
1198  featureEdgeDistances.setSize(featureEdgeCandidates.size());
1199  forAll(featureEdgeCandidates, i)
1200  {
1201  const label seI = featureEdgeCandidates[i];
1202 
1203  const point s = sp[edges[seI].start()];
1204  const point e = sp[edges[seI].end()];
1205  const point np = help::nearestPointOnTheEdgeExact(s, e, p);
1206 
1207  featureEdgeDistances[i] = labelledScalar(seI, magSqr(np - p));
1208  }
1209 
1210  //- find nearest edges
1211  sort(featureEdgeDistances);
1212  }
1213  }
1214 
1215  //- start post-processing gathered data
1216  const labelList& edgeGroup = partitioner.edgeGroups();
1217 
1218  List<List<labelledScalar> > edgeGroupAndWeights(edges.size());
1219 
1220  # ifdef USE_OMP
1221  # pragma omp parallel for schedule(dynamic, 40) \
1222  if( edges.size() > 1000 )
1223  # endif
1224  forAll(edgeType_, edgeI)
1225  {
1226  if( edgeType_[edgeI] & CANDIDATE )
1227  {
1228  const edge& e = edges[edgeI];
1229 
1230  const List<labelledScalar>& sc =
1231  featureEdgesNearPoint[bp[e.start()]];
1232  const List<labelledScalar>& ec =
1233  featureEdgesNearPoint[bp[e.end()]];
1234 
1235  //- find the feature-edge partition for which the sum of
1236  //- node weights is minimal.
1237  DynList<labelledScalar> weights;
1238  forAll(sc, i)
1239  {
1240  const label sPart = edgeGroup[sc[i].scalarLabel()];
1241 
1242  forAll(ec, j)
1243  {
1244  const label ePart = edgeGroup[ec[j].scalarLabel()];
1245 
1246  if( (sPart >= 0) && (sPart == ePart) )
1247  {
1248  weights.append
1249  (
1251  (
1252  sPart,
1253  sc[i].value() + ec[j].value()
1254  )
1255  );
1256  }
1257  }
1258  }
1259 
1260  //- store the data
1261  edgeGroupAndWeights[edgeI].setSize(weights.size());
1262  forAll(edgeGroupAndWeights[edgeI], epI)
1263  edgeGroupAndWeights[edgeI][epI] = weights[epI];
1264 
1265  //- sort the data according to the weights
1266  stableSort(edgeGroupAndWeights[edgeI]);
1267  }
1268  }
1269 
1270  Info << "Edge partitions and weights " << edgeGroupAndWeights << endl;
1271 }
1272 
1275  const label bfI,
1276  const Map<label>& otherProcPatch,
1277  DynList<label>& neiPatches
1278 ) const
1279 {
1280  const meshSurfaceEngine& mse = surfaceEngine();
1281 
1282  const VRWGraph& faceEdges = mse.faceEdges();
1283  const VRWGraph& edgeFaces = mse.edgeFaces();
1284 
1285  neiPatches.setSize(faceEdges.sizeOfRow(bfI));
1286 
1287  forAllRow(faceEdges, bfI, feI)
1288  {
1289  const label beI = faceEdges(bfI, feI);
1290 
1291  if( edgeFaces.sizeOfRow(beI) == 2 )
1292  {
1293  label nei = edgeFaces(beI, 0);
1294  if( nei == bfI )
1295  nei = edgeFaces(beI, 1);
1296 
1297  neiPatches[feI] = facePatch_[nei];
1298  }
1299  else if( edgeFaces.sizeOfRow(beI) == 1 )
1300  {
1301  neiPatches[feI] = otherProcPatch[beI];
1302  }
1303  }
1304 }
1305 
1308  const label beI,
1309  const label patch0,
1310  const label patch1
1311 ) const
1312 {
1313  scalar val(0.0);
1314 
1316  patches[0] = patch0;
1317  patches[1] = patch1;
1318 
1319  const pointFieldPMG& points = surfaceEnginePtr_->mesh().points();
1320 
1321  const edge& e = surfaceEnginePtr_->edges()[beI];
1322  const point& ps = points[e.start()];
1323  const point& pe = points[e.end()];
1324 
1325  vector ev = e.vec(points);
1326  const scalar magE = mag(ev) + VSMALL;
1327  ev /= magE;
1328 
1329  point mps, mpe;
1330  scalar dSqS, dSqE;
1331 
1332  meshOctree_.findNearestPointToPatches(mps, dSqS, ps, patches);
1333  meshOctree_.findNearestPointToPatches(mpe, dSqE, pe, patches);
1334 
1335  vector fv = mpe - mps;
1336  fv /= (mag(fv) + VSMALL);
1337 
1338  val = 0.5 * (1.0 + (ev & fv));
1339 
1340  val = min(val, 1.0);
1341  val = max(val, 0.0);
1342 
1343  return val;
1344 }
1345 
1348  const label beI,
1349  const label patch0,
1350  const label patch1
1351 ) const
1352 {
1353  scalar val(0.0);
1354 
1356  patches[0] = patch0;
1357  patches[1] = patch1;
1358 
1359  const pointFieldPMG& points = surfaceEnginePtr_->mesh().points();
1360 
1361  const edge& e = surfaceEnginePtr_->edges()[beI];
1362  const point& ps = points[e.start()];
1363  const point& pe = points[e.end()];
1364 
1365  vector ev = e.vec(points);
1366  const scalar magE = mag(ev) + VSMALL;
1367  ev /= magE;
1368 
1369  point mps, mpe;
1370  scalar dSqS, dSqE;
1371 
1372  meshOctree_.findNearestPointToPatches(mps, dSqS, ps, patches);
1373  meshOctree_.findNearestPointToPatches(mpe, dSqE, pe, patches);
1374 
1375  vector fv = mpe - mps;
1376  fv /= (mag(fv) + VSMALL);
1377 
1378  scalar c = min(fv & ev, 1.0);
1379  c = max(-1.0, c);
1380  const scalar angle = acos(c);
1381 
1382  val = 0.5 * (sqrt(dSqS) + sqrt(dSqE)) + magE * angle;
1383 
1384  return val;
1385 }
1386 
1389  const label bfI,
1390  const DynList<label>& neiPatches,
1391  const label facePatch
1392 ) const
1393 {
1394  scalar Enorm(0.0);
1395 
1396  const VRWGraph& faceEdges = surfaceEnginePtr_->faceEdges();
1397 
1398  if( neiPatches.size() != faceEdges.sizeOfRow(bfI) )
1399  {
1400  FatalErrorIn
1401  (
1402  "scalar edgeExtractor::calculateDeformationMetricForFace"
1403  "(const label, const DynList<label>&, const label) const"
1404  ) << "Number of neiPatches and faceEdge does not match for face "
1405  << bfI << abort(FatalError);
1406  }
1407 
1408  const label patch0 = facePatch == -1 ? facePatch_[bfI] : facePatch;
1409 
1410  forAllRow(faceEdges, bfI, i)
1411  {
1412  const label beI = faceEdges(bfI, i);
1413 
1414  if( neiPatches[i] == patch0 )
1415  continue;
1416 
1417  Enorm += calculateDeformationMetricForEdge(beI, patch0, neiPatches[i]);
1418  }
1419 
1420  return Enorm;
1421 }
1422 
1424 {
1425  bool changed(false);
1426 
1427  const triSurf& surf = meshOctree_.surface();
1428  const VRWGraph& edgeFacets = surf.edgeFacets();
1429 
1430  const pointFieldPMG& points = mesh_.points();
1431  const faceListPMG& faces = mesh_.faces();
1432  const cellListPMG& cells = mesh_.cells();
1433  const label bndStartFace = mesh_.boundaries()[0].patchStart();
1434 
1435  const meshSurfaceEngine& mse = this->surfaceEngine();
1436  const faceList::subList& bFaces = mse.boundaryFaces();
1437  const labelList& bp = mse.bp();
1438  const labelList& faceCells = mse.faceOwners();
1439  const VRWGraph& edgeFaces = mse.edgeFaces();
1440 
1441  //- analyse the surface mesh and find out which edges are concave or convex
1443  const List<direction>& edgeType = edgeClassifier.edgeTypes();
1444 
1445  //- create a copy of facePatch array for local modifications
1446  labelList newBoundaryPatches(facePatch_);
1447 
1448  //- start checking the surface of the mesh
1449  label nChanged;
1450 
1451  boolList patchPoint(mse.boundaryPoints().size(), false);
1452 
1453  do
1454  {
1455  nChanged = 0;
1456 
1457  //- check which surface points are surrounded by boundary faces
1458  //- in the same surface patch
1459  markPatchPoints(patchPoint);
1460 
1461  //- check whether exist edges of a single cell which shall be projected
1462  //- onto a concave edge
1463  # ifdef USE_OMP
1464  # pragma omp parallel for schedule(dynamic, 40) reduction(+ : nChanged)
1465  # endif
1466  forAll(edgeType_, beI)
1467  {
1468  if( !(edgeType_[beI] & SINGLECELLEDGE) )
1469  continue;
1470 
1471  //- check if all faces are assigned to the same patch
1472  const label firstPatch = newBoundaryPatches[edgeFaces(beI, 0)];
1473  const label secondPatch = newBoundaryPatches[edgeFaces(beI, 1)];
1474 
1475  if( firstPatch == secondPatch )
1476  continue;
1477 
1478  const cell& c = cells[faceCells[edgeFaces(beI, 0)]];
1479 
1480  //- find edges within the bounding box determined by the cell
1481  point pMin(VGREAT, VGREAT, VGREAT);
1482  point pMax(-VGREAT, -VGREAT, -VGREAT);
1483  forAll(c, fI)
1484  {
1485  const face& f = faces[c[fI]];
1486 
1487  forAll(f, pI)
1488  {
1489  pMin = Foam::min(pMin, points[f[pI]]);
1490  pMax = Foam::max(pMax, points[f[pI]]);
1491  }
1492  }
1493 
1494  const point cc = 0.5 * (pMin + pMax);
1495  const point diff = pMax - pMin;
1496  boundBox bb(cc-diff, cc+diff);
1497  DynList<label> containedEdges;
1498  meshOctree_.findEdgesInBox(bb, containedEdges);
1499 
1500  //- check if there exists concave edges boundaing patches
1501  //- assigned to boundary faces of the current cell
1502  forAll(containedEdges, ceI)
1503  {
1504  const label eI = containedEdges[ceI];
1505 
1506  if( edgeFacets.sizeOfRow(eI) != 2 )
1507  continue;
1508  if( !(edgeType[eI] & triSurfaceClassifyEdges::FEATUREEDGE) )
1509  continue;
1510 
1511  if( edgeType[eI] & triSurfaceClassifyEdges::CONCAVEEDGE )
1512  {
1513  const label patch0 = surf[edgeFacets(eI, 0)].region();
1514  const label patch1 = surf[edgeFacets(eI, 1)].region();
1515 
1516  if
1517  (
1518  ((firstPatch == patch0) && (secondPatch == patch1)) ||
1519  ((firstPatch == patch1) && (secondPatch == patch0))
1520  )
1521  {
1522  DynList<DynList<label>, 2> facesInPatch;
1523  facesInPatch.setSize(2);
1524 
1525  DynList<label, 2> nFacesInPatch;
1526  nFacesInPatch.setSize(2);
1527  nFacesInPatch = 0;
1528 
1529  DynList<bool, 2> hasPatchPoints;
1530  hasPatchPoints.setSize(2);
1531  hasPatchPoints = false;
1532 
1533  forAll(c, fI)
1534  {
1535  if( c[fI] < bndStartFace )
1536  continue;
1537 
1538  const label bfI = c[fI] - bndStartFace;
1539  const face& bf = bFaces[bfI];
1540 
1541  if( newBoundaryPatches[bfI] == patch1 )
1542  {
1543  facesInPatch[1].append(bfI);
1544  ++nFacesInPatch[1];
1545 
1546  forAll(bf, pI)
1547  {
1548  if( patchPoint[bp[bf[pI]]] )
1549  hasPatchPoints[1] = true;
1550  }
1551  }
1552  else if( newBoundaryPatches[bfI] == patch0 )
1553  {
1554  facesInPatch[0].append(bfI);
1555  ++nFacesInPatch[0];
1556 
1557  forAll(bf, pI)
1558  {
1559  if( patchPoint[bp[bf[pI]]] )
1560  hasPatchPoints[0] = true;
1561  }
1562  }
1563  }
1564 
1565  if( nFacesInPatch[1] > nFacesInPatch[0] )
1566  {
1567  //- there exist more faces in patch 1
1568  //- assign all boundary faces to the same patch
1569  forAll(facesInPatch[0], i)
1570  newBoundaryPatches[facesInPatch[0][i]] = patch1;
1571  ++nChanged;
1572  break;
1573  }
1574  else if( nFacesInPatch[0] > nFacesInPatch[1] )
1575  {
1576  //- there exist more faces in patch 0
1577  //- assign all boundary faces to the same patch
1578  forAll(facesInPatch[1], i)
1579  newBoundaryPatches[facesInPatch[1][i]] = patch0;
1580  ++nChanged;
1581  break;
1582  }
1583  else
1584  {
1585  if( hasPatchPoints[0] && !hasPatchPoints[1] )
1586  {
1587  //- transfer all faces to patch 1
1588  forAll(facesInPatch[0], i)
1589  newBoundaryPatches[facesInPatch[0][i]] =
1590  patch1;
1591  ++nChanged;
1592  break;
1593  }
1594  else if( !hasPatchPoints[0] && hasPatchPoints[1] )
1595  {
1596  //- transfer all faces to patch 0
1597  forAll(facesInPatch[1], i)
1598  newBoundaryPatches[facesInPatch[1][i]] =
1599  patch0;
1600  ++nChanged;
1601  break;
1602  }
1603  else
1604  {
1605  //- just transfer all faces to the same patch
1606  forAll(facesInPatch[1], i)
1607  newBoundaryPatches[facesInPatch[1][i]] =
1608  patch0;
1609  ++nChanged;
1610  break;
1611  }
1612  }
1613  }
1614  }
1615  }
1616  }
1617 
1618  if( Pstream::parRun() )
1619  reduce(nChanged, sumOp<label>());
1620 
1621  if( nChanged )
1622  changed = true;
1623 
1624  } while( nChanged != 0 );
1625 
1626  //- transfer the information back to facePatch
1627  facePatch_.transfer(newBoundaryPatches);
1628 
1629  return changed;
1630 }
1631 
1633 {
1634  bool changed(false);
1635 
1636  const meshSurfaceEngine& mse = this->surfaceEngine();
1637  const faceList::subList& bFaces = mse.boundaryFaces();
1638  const labelList& bp = mse.bp();
1639  const VRWGraph& faceEdges = mse.faceEdges();
1640  const VRWGraph& edgeFaces = mse.edgeFaces();
1641 
1642  label nCorrected;
1643  Map<label> otherProcNewPatch;
1644 
1645  label nIter(0);
1646  do
1647  {
1648  # ifdef DEBUGEdgeExtractor
1649  {
1650  const triSurf* surfPtr = surfaceWithPatches();
1651  surfPtr->writeSurface
1652  (
1653  "surfaceTopologyIter_"+help::scalarToText(nIter)+".stl"
1654  );
1655  delete surfPtr;
1656  }
1657  # endif
1658 
1659  nCorrected = 0;
1660 
1661  //- allocate a copy of boundary patches
1662  labelList newBoundaryPatches(facePatch_);
1663 
1664  //- check whether there exist situations where a boundary face
1665  //- is surrounded by more faces in different patches than the
1666  //- faces in the current patch
1667  if( Pstream::parRun() )
1668  {
1670  (
1671  otherProcNewPatch,
1672  &facePatch_
1673  );
1674  }
1675 
1676  //- find the faces which have neighbouring faces in other patches
1677  labelLongList candidates;
1678  findFaceCandidates(candidates, &facePatch_, &otherProcNewPatch);
1679 
1680  //- go through the list of faces and check if they shall remain
1681  //- in the current patch
1682  # ifdef USE_OMP
1683  # pragma omp parallel for schedule(dynamic, 40) \
1684  reduction(+ : nCorrected)
1685  # endif
1686  forAll(candidates, i)
1687  {
1688  const label bfI = candidates[i];
1689  const face& bf = bFaces[bfI];
1690 
1691  //- do not change patches of faces where all points are mapped
1692  //- onto the same patch
1693  bool allInSamePatch(true);
1694  forAll(bf, pI)
1695  if( pointPatch_[bp[bf[pI]]] != facePatch_[bfI] )
1696  {
1697  allInSamePatch = false;
1698  break;
1699  }
1700 
1701  if( allInSamePatch )
1702  continue;
1703 
1704  DynList<label> allNeiPatches;
1705  DynList<label> neiPatches;
1706  neiPatches.setSize(faceEdges.sizeOfRow(bfI));
1707 
1708  forAllRow(faceEdges, bfI, eI)
1709  {
1710  const label beI = faceEdges(bfI, eI);
1711 
1712  if( edgeFaces.sizeOfRow(beI) == 2 )
1713  {
1714  label fNei = edgeFaces(beI, 0);
1715  if( fNei == bfI )
1716  fNei = edgeFaces(faceEdges(bfI, eI), 1);
1717 
1718  allNeiPatches.appendIfNotIn(facePatch_[fNei]);
1719  neiPatches[eI] = facePatch_[fNei];
1720  }
1721  else if( edgeFaces.sizeOfRow(beI) == 1 )
1722  {
1723  allNeiPatches.appendIfNotIn(otherProcNewPatch[beI]);
1724  neiPatches[eI] = otherProcNewPatch[beI];
1725  }
1726  }
1727 
1728  //- do not modify faces with all neighbours in the same patch
1729  if
1730  (
1731  (allNeiPatches.size() == 1) &&
1732  (allNeiPatches[0] == facePatch_[bfI])
1733  )
1734  continue;
1735 
1736  //- check whether there exist edges which are more suitable for
1737  //- projection onto feature edges than the currently selected ones
1738  label newPatch(-1);
1739 
1740  //- check if some faces have to be distributed to another patch
1741  //- in order to reduce the number of feature edges
1742  Map<label> nNeiInPatch(allNeiPatches.size());
1743  forAll(allNeiPatches, i)
1744  nNeiInPatch.insert(allNeiPatches[i], 0);
1745  forAll(neiPatches, eI)
1746  ++nNeiInPatch[neiPatches[eI]];
1747 
1748  newPatch = -1;
1749  label nNeiEdges(0);
1750  forAllConstIter(Map<label>, nNeiInPatch, it)
1751  {
1752  if( it() > nNeiEdges )
1753  {
1754  newPatch = it.key();
1755  nNeiEdges = it();
1756  }
1757  else if
1758  (
1759  (it() == nNeiEdges) && (it.key() == facePatch_[bfI])
1760  )
1761  {
1762  newPatch = it.key();
1763  }
1764  }
1765 
1766  //- do not swap in case the
1767  if( (newPatch < 0) || (newPatch == facePatch_[bfI]) )
1768  continue;
1769 
1770  //- check whether the edges shared ith the neighbour patch form
1771  //- a singly linked chain
1773  sharedEdge.setSize(bFaces[bfI].size());
1774  sharedEdge = false;
1775 
1776  forAll(neiPatches, eI)
1777  if( neiPatches[eI] == newPatch )
1778  sharedEdge[eI] = true;
1779 
1781  {
1782  //- change the patch to the newPatch
1783  ++nCorrected;
1784  newBoundaryPatches[bfI] = newPatch;
1785  }
1786  }
1787 
1788  //- evaluate the new situation and ensure that no oscillation occur
1789  reduce(nCorrected, sumOp<label>());
1790  if( nCorrected )
1791  {
1793 
1794  faceEvaluator.setNewBoundaryPatches(newBoundaryPatches);
1795 
1796  # ifdef USE_OMP
1797  # pragma omp parallel for schedule(dynamic, 50)
1798  # endif
1799  forAll(candidates, i)
1800  {
1801  const label bfI = candidates[i];
1802 
1803  const label bestPatch =
1805 
1806  newBoundaryPatches[bfI] = bestPatch;
1807  }
1808  }
1809 
1810  if( nCorrected )
1811  {
1812  changed = true;
1813 
1814  //- transfer the new patches back
1815  facePatch_.transfer(newBoundaryPatches);
1816  }
1817 
1818  } while( nCorrected != 0 && (nIter++ < 3) );
1819 
1820  return changed;
1821 }
1822 
1823 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
1824 
1825 namespace featureEdgeHelpers
1826 {
1827 
1829 {
1830  // Private data
1831  //- reference to meshSurfaceEngine
1833 
1834  //- refence to a list holding information which edges are feature edges
1836 
1837  //- number of feature edges at a surface point
1839 
1840  // Private member functions
1841  //- calculate the number of feature edges connected to a surface vertex
1843  {
1844  const labelList& bp = mse_.bp();
1845  const edgeList& edges = mse_.edges();
1846 
1849 
1850  forAll(isFeatureEdge_, edgeI)
1851  {
1852  if( !isFeatureEdge_[edgeI] )
1853  continue;
1854 
1855  const edge& e = edges[edgeI];
1856  ++nFeatureEdgesAtPoint_[bp[e.start()]];
1857  ++nFeatureEdgesAtPoint_[bp[e.end()]];
1858  }
1859 
1860  if( Pstream::parRun() )
1861  {
1862  const Map<label>& globalToLocal =
1864  const DynList<label>& neiProcs = mse_.bpNeiProcs();
1865  const VRWGraph& bpAtProcs = mse_.bpAtProcs();
1866 
1867  std::map<label, DynList<labelPair> > exchangeData;
1868  forAll(neiProcs, i)
1869  exchangeData[neiProcs[i]].clear();
1870 
1871  //- fill the data from sending
1872  forAllConstIter(Map<label>, globalToLocal, it)
1873  {
1874  const label bpI = it();
1875 
1876  forAllRow(bpAtProcs, bpI, i)
1877  {
1878  const label neiProc = bpAtProcs(bpI, i);
1879 
1880  if( neiProc == Pstream::myProcNo() )
1881  continue;
1882 
1883  exchangeData[neiProc].append
1884  (
1885  labelPair(it.key(), nFeatureEdgesAtPoint_[bpI])
1886  );
1887  }
1888  }
1889 
1890  //- exchange the data between the procesors
1891  LongList<labelPair> receivedData;
1892  help::exchangeMap(exchangeData, receivedData);
1893 
1894  forAll(receivedData, i)
1895  {
1896  const labelPair& lp = receivedData[i];
1897 
1898  nFeatureEdgesAtPoint_[globalToLocal[lp.first()]] +=
1899  lp.second();
1900  }
1901  }
1902  }
1903 
1904 public:
1905 
1907  (
1908  const meshSurfaceEngine& mse,
1909  const boolList& isFeatureEdge
1910  )
1911  :
1912  mse_(mse),
1913  isFeatureEdge_(isFeatureEdge),
1915  {
1917  }
1918 
1919  label size() const
1920  {
1921  return isFeatureEdge_.size();
1922  }
1923 
1924  void operator()(const label beI, DynList<label>& neighbourEdges) const
1925  {
1926  neighbourEdges.clear();
1927 
1928  const VRWGraph& bpEdges = mse_.boundaryPointEdges();
1929  const labelList& bp = mse_.bp();
1930  const edgeList& edges = mse_.edges();
1931 
1932  const edge& e = edges[beI];
1933 
1934  const label bps = bp[e.start()];
1935  const label bpe = bp[e.end()];
1936 
1937  if( nFeatureEdgesAtPoint_[bps] == 2 )
1938  {
1939  forAllRow(bpEdges, bps, peI)
1940  {
1941  const label beJ = bpEdges(bps, peI);
1942 
1943  if( (beJ == beI) || !isFeatureEdge_[beJ] )
1944  continue;
1945 
1946  neighbourEdges.append(beJ);
1947  }
1948  }
1949 
1950  if( nFeatureEdgesAtPoint_[bpe] == 2 )
1951  {
1952  forAllRow(bpEdges, bpe, peI)
1953  {
1954  const label beJ = bpEdges(bpe, peI);
1955 
1956  if( (beJ == beI) || !isFeatureEdge_[beJ] )
1957  continue;
1958 
1959  neighbourEdges.append(beJ);
1960  }
1961  }
1962  }
1963 
1964  template<class labelListType>
1965  void collectGroups
1966  (
1967  std::map<label, DynList<label> >& neiGroups,
1968  const labelListType& elementInGroup,
1969  const DynList<label>& localGroupLabel
1970  ) const
1971  {
1972  const Map<label>& globalToLocal = mse_.globalToLocalBndPointAddressing();
1973  const VRWGraph& bpAtProcs = mse_.bpAtProcs();
1974  const VRWGraph& bpEdges = mse_.boundaryPointEdges();
1975 
1976  const DynList<label>& neiProcs = mse_.beNeiProcs();
1977 
1978  std::map<label, DynList<labelPair> > exchangeData;
1979  forAll(neiProcs, i)
1980  exchangeData[neiProcs[i]].clear();
1981 
1982  forAllConstIter(Map<label>, globalToLocal, it)
1983  {
1984  const label bpI = it();
1985 
1986  if( nFeatureEdgesAtPoint_[bpI] != 2 )
1987  continue;
1988 
1989  forAllRow(bpEdges, bpI, i)
1990  {
1991  const label beI = bpEdges(bpI, i);
1992 
1993  if( !isFeatureEdge_[beI] )
1994  continue;
1995 
1996  const label groupI = elementInGroup[beI];
1997 
1998  forAllRow(bpAtProcs, bpI, ppI)
1999  {
2000  const label neiProc = bpAtProcs(bpI, ppI);
2001 
2002  if( neiProc == Pstream::myProcNo() )
2003  continue;
2004 
2005  exchangeData[neiProc].append
2006  (
2007  labelPair(it.key(), localGroupLabel[groupI])
2008  );
2009  }
2010  }
2011  }
2012 
2013  LongList<labelPair> receivedData;
2014  help::exchangeMap(exchangeData, receivedData);
2015 
2016  forAll(receivedData, i)
2017  {
2018  const labelPair& lp = receivedData[i];
2019  const label groupI = elementInGroup[globalToLocal[lp.first()]];
2020 
2021  DynList<label>& ng = neiGroups[localGroupLabel[groupI]];
2022 
2023  //- store the connection over the inter-processor boundary
2024  ng.appendIfNotIn(lp.second());
2025  }
2026  }
2027 };
2028 
2030 {
2031  // Private data
2032  //- reference to a list holding information which edge is afeture edge
2034 
2035 public:
2036 
2037  featureEdgesSelOp(const boolList& isFeatureEdge)
2038  :
2039  isFeatureEdge_(isFeatureEdge)
2040  {}
2041 
2042  bool operator()(const label beI) const
2043  {
2044  return isFeatureEdge_[beI];
2045  }
2046 };
2047 
2048 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
2049 
2050 } // End namespace featureEdgeHelpers
2051 
2052 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
2053 
2055 {
2056  bool changed(false);
2057 
2058  const meshSurfaceEngine& mse = this->surfaceEngine();
2059  const labelList& bPoints = mse.boundaryPoints();
2060  const faceList::subList& bFaces = mse.boundaryFaces();
2061  const labelList& bp = mse.bp();
2062 
2063  //- allocate a copy of boundary patches
2064  labelList newBoundaryPatches(facePatch_.size());
2065 
2066  label nCorrected;
2067  Map<label> otherProcNewPatch;
2068 
2069  boolList activePoints(bPoints.size(), true);
2070  labelLongList activePointLabel(bPoints.size());
2071  forAll(bPoints, bpI)
2072  activePointLabel[bpI] = bpI;
2073 
2074  label iter(0);
2075 
2076  do
2077  {
2078  # ifdef DEBUGEdgeExtractor
2079  {
2080  const triSurf* surfPtr = surfaceWithPatches();
2081  surfPtr->writeSurface
2082  (
2083  "surfaceIter_"+help::scalarToText(iter)+".stl"
2084  );
2085  delete surfPtr;
2086  }
2087  # endif
2088 
2089  //- create feature edges and corners information
2090  meshSurfacePartitioner mPart(mse, facePatch_);
2091 
2092  //- project vertices onto the surface mesh
2094  (
2095  activePointLabel
2096  );
2097 
2098  //- stop after a certain number of iterations
2099  if( ++iter > 3 )
2100  break;
2101 
2102  //- update surface geometry data
2104 
2105  //- check if there exist any inverted faces
2106  meshSurfaceCheckInvertedVertices surfCheck(mPart, activePoints);
2107  const labelHashSet& invertedPoints = surfCheck.invertedVertices();
2108 
2109  if( returnReduce(invertedPoints.size(), sumOp<label>()) == 0 )
2110  return false;
2111 
2112  WarningIn
2113  (
2114  "void edgeExtractor::extractEdges()"
2115  ) << "Found " << invertedPoints.size()
2116  << " points with inverted surface normals. Getting rid of them..."
2117  << endl;
2118 
2119  //- untangle the surface
2120  activePointLabel.clear();
2121  activePoints = false;
2122  forAllConstIter(labelHashSet, invertedPoints, it)
2123  {
2124  activePointLabel.append(bp[it.key()]);
2125  activePoints[bp[it.key()]] = true;
2126  }
2127 
2128  //- untangle the surface
2129  meshSurfaceOptimizer mso(mPart, meshOctree_);
2130  mso.untangleSurface(activePointLabel, 1);
2131 
2132  nCorrected = 0;
2133  newBoundaryPatches = facePatch_;
2134 
2135  //- check whether there exist situations where a boundary face
2136  //- is surrounded by more faces in different patches than the
2137  //- faces in the current patch
2138  if( Pstream::parRun() )
2139  {
2141  (
2142  otherProcNewPatch,
2143  &facePatch_
2144  );
2145  }
2146 
2147  //- find the faces which have neighbouring faces in other patches
2148  labelLongList candidates;
2149  forAll(bFaces, bfI)
2150  {
2151  const face& bf = bFaces[bfI];
2152 
2153  forAll(bf, pI)
2154  if( invertedPoints.found(bf[pI]) )
2155  {
2156  candidates.append(bfI);
2157  break;
2158  }
2159  }
2160 
2161  # ifdef USE_OMP
2162  # pragma omp parallel for schedule(dynamic, 5) reduction(+ : nCorrected)
2163  # endif
2164  forAll(candidates, i)
2165  {
2166  const label bfI = candidates[i];
2167 
2168  DynList<label> neiPatches;
2169  findNeiPatches(bfI, otherProcNewPatch, neiPatches);
2170 
2171  DynList<label> allNeiPatches;
2172  forAll(neiPatches, i)
2173  allNeiPatches.appendIfNotIn(neiPatches[i]);
2174 
2175  //- check the deformation energy and find the minimum energy which
2176  //- can be achieved by switching face patch
2177  scalar minE(VGREAT);
2178  label minEPatch(-1);
2179  DynList<scalar> Enorm(allNeiPatches.size());
2180  forAll(allNeiPatches, i)
2181  {
2182  Enorm[i] =
2184  (
2185  bfI,
2186  neiPatches,
2187  allNeiPatches[i]
2188  );
2189 
2190  if( Enorm[i] < minE )
2191  {
2192  minE = Enorm[i];
2193  minEPatch = allNeiPatches[i];
2194  }
2195  }
2196 
2197  if( minEPatch != facePatch_[bfI] )
2198  {
2199  newBoundaryPatches[bfI] = minEPatch;
2200  ++nCorrected;
2201  }
2202  }
2203 
2204  //- check if any faces are re-assigned to some other patch
2205  reduce(nCorrected, sumOp<label>());
2206  if( nCorrected == 0 )
2207  break;
2208 
2209  //- update faceEvaluator with information after patches have been
2210  //- altered. It blocks chaning of patches if it causes oscillations
2211  faceEvaluator facePatchEvaluator(*this);
2212  facePatchEvaluator.setNewBoundaryPatches(newBoundaryPatches);
2213 
2214  //- compare face patches before and after
2215  //- disallow modification which may trigger oscillating behaviour
2216  labelLongList changedFaces;
2217  forAll(newBoundaryPatches, bfI)
2218  {
2219  if( newBoundaryPatches[bfI] != facePatch_[bfI] )
2220  {
2221  const label patchI =
2222  facePatchEvaluator.bestPatchAfterModification(bfI);
2223  newBoundaryPatches[bfI] = patchI;
2224 
2225  if( patchI != facePatch_[bfI] )
2226  changedFaces.append(bfI);
2227  }
2228  }
2229 
2230  nCorrected = changedFaces.size();
2231 
2232  reduce(nCorrected, sumOp<label>());
2233 
2234  if( nCorrected )
2235  {
2236  changed = true;
2237  facePatch_ = newBoundaryPatches;
2238  }
2239 
2240  } while( nCorrected != 0 );
2241 
2242  return changed;
2243 }
2244 
2246 {
2247  List<DynList<label, 5> > pointPatches;
2248  pointPatches.setSize(pointValence_.size());
2249 
2250  const meshSurfaceEngine& mse = surfaceEngine();
2251  const pointFieldPMG& points = mse.mesh().points();
2252  const labelList& bPoints = mse.boundaryPoints();
2253  const labelList& bp = mse.bp();
2254  const faceList::subList& bFaces = mse.boundaryFaces();
2256 
2257  //- calculate patches for each point
2258  forAll(bFaces, bfI)
2259  {
2260  const face& bf = bFaces[bfI];
2261 
2262  forAll(bf, pI)
2263  pointPatches[bp[bf[pI]]].appendIfNotIn(facePatch_[bfI]);
2264  }
2265 
2266  if( Pstream::parRun() )
2267  {
2268  const Map<label>& globalToLocal =
2270  const VRWGraph& bpAtProcs = mse.bpAtProcs();
2271  const DynList<label>& bpNeiProcs = mse.bpNeiProcs();
2272 
2273  std::map<label, LongList<labelPair> > exchangeData;
2274  forAll(bpNeiProcs, i)
2275  exchangeData.insert
2276  (
2277  std::make_pair(bpNeiProcs[i], LongList<labelPair>())
2278  );
2279 
2280  //- collect the data distributed to others
2281  forAllConstIter(Map<label>, globalToLocal, it)
2282  {
2283  const label bpI = it();
2284 
2285  const DynList<label, 5>& pPatches = pointPatches[bpI];
2286 
2287  forAllRow(bpAtProcs, bpI, i)
2288  {
2289  const label neiProc = bpAtProcs(bpI, i);
2290 
2291  if( neiProc == Pstream::myProcNo() )
2292  continue;
2293 
2294  LongList<labelPair>& data = exchangeData[neiProc];
2295 
2296  forAll(pPatches, ppI)
2297  data.append(labelPair(it.key(), pPatches[ppI]));
2298  }
2299  }
2300 
2301  //- exchange information
2302  LongList<labelPair> receivedData;
2303  help::exchangeMap(exchangeData, receivedData);
2304 
2305  //- unify the data
2306  forAll(receivedData, i)
2307  {
2308  const labelPair& lp = receivedData[i];
2309 
2310  pointPatches[globalToLocal[lp.first()]].appendIfNotIn(lp.second());
2311  }
2312  }
2313 
2314  meshSurfaceEngineModifier surfMod(mse);
2315 
2316  # ifdef USE_OMP
2317  # pragma omp parallel for schedule(dynamic, 10)
2318  # endif
2319  forAll(pointPatches, bpI)
2320  {
2321  if( pointPatches[bpI].size() < 2 )
2322  continue;
2323 
2324  const DynList<label> pPatches = pointPatches[bpI];
2325 
2326  const point& p = points[bPoints[bpI]];
2327 
2328  //- find the nearest object on the surface mesh
2329  point newP;
2330  scalar dSqExact;
2331  if( pPatches.size() == 2 )
2332  {
2333  label nse;
2334  meshOctree_.findNearestEdgePoint(newP, dSqExact, nse, p, pPatches);
2335  }
2336  else
2337  {
2338  label nsp;
2339  meshOctree_.findNearestCorner(newP, dSqExact, nsp, p, pPatches);
2340  }
2341 
2342  //- find the nearest object in an iterative procedure
2343  point pp(p);
2344  for(label iterI=0;iterI<20;++iterI)
2345  {
2346  point inp(vector::zero);
2347 
2348  forAll(pPatches, i)
2349  {
2350  point np;
2351  scalar dSq;
2352  label nt;
2353 
2355  (
2356  np,
2357  dSq,
2358  nt,
2359  pPatches[i],
2360  pp
2361  );
2362 
2363  inp += np;
2364  }
2365 
2366  inp /= pPatches.size();
2367  const scalar currDSq = magSqr(inp - pp);
2368  pp = inp;
2369 
2370  if( currDSq < 1e-2 * dSqExact )
2371  break;
2372  }
2373 
2374  //- check if the exact position of the corner is further away
2375  //- than the iteratively found object
2376  if( dSqExact > 1.1 * magSqr(pp - p) )
2377  newP = pp;
2378 
2379  surfMod.moveBoundaryVertexNoUpdate(bpI, newP);
2380  }
2381 
2383  surfMod.updateGeometry();
2384 }
2385 
2387 {
2388  bool changed(false);
2389 
2390  meshSurfaceEngine& mse =
2391  const_cast<meshSurfaceEngine&>(this->surfaceEngine());
2392  meshSurfaceOptimizer optimizer(mse, meshOctree_);
2393  changed = optimizer.untangleSurface();
2394 
2395  return changed;
2396 }
2397 
2399 {
2401 
2403 
2404  # ifdef DEBUGEdgeExtractor
2405  const triSurf* sPtr = surfaceWithPatches();
2406  sPtr->writeSurface("initialDistributionOfPatches.stl");
2407  deleteDemandDrivenData(sPtr);
2408  # endif
2409 
2410  Info << "Starting topological adjustment of patches" << endl;
2411  if( checkFacePatchesTopology() )
2412  {
2413  Info << "Finished topological adjustment of patches" << endl;
2414 
2415  # ifdef DEBUGEdgeExtractor
2416  Info << "Changes due to face patches" << endl;
2417  fileName sName("checkFacePatches"+help::scalarToText(nIter)+".stl");
2418  sPtr = surfaceWithPatches();
2419  sPtr->writeSurface(sName);
2420  deleteDemandDrivenData(sPtr);
2421  # endif
2422  }
2423  else
2424  {
2425  Info << "No topological adjustment was needed" << endl;
2426  }
2427 
2428  Info << "Starting geometrical adjustment of patches" << endl;
2429  if( checkFacePatchesGeometry() )
2430  {
2431  Info << "Finished geometrical adjustment of patches" << endl;
2432  }
2433  else
2434  {
2435  Info << "No geometrical adjustment was needed" << endl;
2436  }
2437 
2438  # ifdef DEBUGEdgeExtractor
2439  const triSurf* sPtr = surfaceWithPatches();
2440  sPtr->writeSurface("finalDistributionOfPatches.stl");
2441  deleteDemandDrivenData(sPtr);
2442  # endif
2443 }
2444 
2446 {
2447  //- allocate the memory for the surface mesh
2448  triSurf* surfPtr = new triSurf();
2449 
2450  //- surface of the volume mesh
2451  const meshSurfaceEngine& mse = surfaceEngine();
2452  const faceList::subList& bFaces = mse.boundaryFaces();
2453  const labelList& bp = mse.bp();
2454  const pointFieldPMG& points = mesh_.points();
2455 
2456  //- modifier of the new surface mesh
2457  triSurfModifier surfModifier(*surfPtr);
2458  surfModifier.patchesAccess() = meshOctree_.surface().patches();
2459  pointField& sPts = surfModifier.pointsAccess();
2460  sPts.setSize(mse.boundaryPoints().size());
2461 
2462  //- copy points
2463  forAll(bp, pointI)
2464  {
2465  if( bp[pointI] < 0 )
2466  continue;
2467 
2468  sPts[bp[pointI]] = points[pointI];
2469  }
2470 
2471  //- create the triangulation of the volume mesh surface
2472  forAll(bFaces, bfI)
2473  {
2474  const face& bf = bFaces[bfI];
2475 
2476  labelledTri tri;
2477  tri.region() = facePatch_[bfI];
2478  tri[0] = bp[bf[0]];
2479 
2480  for(label i=bf.size()-2;i>0;--i)
2481  {
2482  tri[1] = bp[bf[i]];
2483  tri[2] = bp[bf[i+1]];
2484 
2485  surfPtr->appendTriangle(tri);
2486  }
2487  }
2488 
2489  return surfPtr;
2490 }
2491 
2493 {
2494  //- allocate the memory for the surface mesh
2495  triSurf* surfPtr = new triSurf();
2496 
2497  //- surface of the volume mesh
2498  const meshSurfaceEngine& mse = surfaceEngine();
2499  const faceList::subList& bFaces = mse.boundaryFaces();
2500  const VRWGraph& pFaces = mse.pointFaces();
2501  const pointFieldPMG& points = mesh_.points();
2502 
2503  //- modifier of the new surface mesh
2504  triSurfModifier surfModifier(*surfPtr);
2505  surfModifier.patchesAccess() = meshOctree_.surface().patches();
2506  pointField& sPts = surfModifier.pointsAccess();
2507 
2508  //- create the triangulation of the volume mesh surface
2509  labelLongList newPointLabel(points.size(), -1);
2510  label nPoints(0);
2511  forAllRow(pFaces, bpI, pfI)
2512  {
2513  const label bfI = pFaces(bpI, pfI);
2514  const face& bf = bFaces[bfI];
2515 
2516  forAll(bf, pI)
2517  if( newPointLabel[bf[pI]] == -1 )
2518  newPointLabel[bf[pI]] = nPoints++;
2519 
2520  labelledTri tri;
2521  tri.region() = facePatch_[bfI];
2522  tri[0] = newPointLabel[bf[0]];
2523 
2524  for(label i=bf.size()-2;i>0;--i)
2525  {
2526  tri[1] = newPointLabel[bf[i]];
2527  tri[2] = newPointLabel[bf[i+1]];
2528 
2529  surfPtr->appendTriangle(tri);
2530  }
2531  }
2532 
2533  //- copy points
2534  sPts.setSize(nPoints);
2535  forAll(newPointLabel, pointI)
2536  if( newPointLabel[pointI] != -1 )
2537  {
2538  sPts[newPointLabel[pointI]] = points[pointI];
2539  }
2540 
2541  return surfPtr;
2542 }
2543 
2545 {
2546  const triSurf& surface = meshOctree_.surface();
2547  const geometricSurfacePatchList& surfPatches = surface.patches();
2548  const label nPatches = surfPatches.size();
2549 
2550  const meshSurfaceEngine& mse = this->surfaceEngine();
2551  const faceList::subList& bFaces = mse.boundaryFaces();
2552  const labelList& faceOwner = mse.faceOwners();
2553 
2555  VRWGraph newBoundaryFaces;
2556  labelLongList newBoundaryOwners(bFaces.size());
2557  labelLongList newBoundaryPatches(bFaces.size());
2558 
2559  //- set patchNames
2560  forAll(surface.patches(), patchI)
2561  patchNames[patchI] = surface.patches()[patchI].name();
2562 
2563  //- append boundary faces
2564  forAll(bFaces, bfI)
2565  {
2566  newBoundaryFaces.appendList(bFaces[bfI]);
2567  newBoundaryOwners[bfI] = faceOwner[bfI];
2568  newBoundaryPatches[bfI] = facePatch_[bfI];
2569  }
2570 
2571  //- replace the boundary with the new patches
2572  polyMeshGenModifier meshModifier(mesh_);
2573  meshModifier.replaceBoundary
2574  (
2575  patchNames,
2576  newBoundaryFaces,
2577  newBoundaryOwners,
2578  newBoundaryPatches
2579  );
2580 
2581  //- set the new patch types
2582  PtrList<boundaryPatch>& boundaries = meshModifier.boundariesAccess();
2583 
2584  forAll(surfPatches, patchI)
2585  boundaries[patchI].patchType() = surfPatches[patchI].geometricType();
2586 }
2587 
2588 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//
2589 
2590 } // End namespace Foam
2591 
2592 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Foam::meshSurfaceEngine::boundaryPointEdges
const VRWGraph & boundaryPointEdges() const
Definition: meshSurfaceEngineI.H:315
Foam::meshSurfaceEngine::bpAtProcs
const VRWGraph & bpAtProcs() const
processors which contain the vertex
Definition: meshSurfaceEngineI.H:451
Foam::face::normal
vector normal(const pointField &) const
Vector normal; magnitude is equal to area of face.
Definition: face.C:552
Foam::help::sharedEdge
edge sharedEdge(const faceType1 &f1, const faceType2 &f2)
return the edge shared by the faces
Definition: helperFunctionsTopologyManipulationI.H:343
Foam::constant::atomic::mp
const dimensionedScalar mp
Proton mass.
Foam::edgeExtractor::patchesNearFace_
VRWGraph patchesNearFace_
patches in the vicinity of a face on the surface of the volume mesh
Definition: edgeExtractor.H:99
Foam::edgeExtractor::featureEdgesNearEdge_
VRWGraph featureEdgesNearEdge_
Definition: edgeExtractor.H:103
Foam::meshSurfaceEngine::bp
const labelList & bp() const
Definition: meshSurfaceEngineI.H:64
Foam::featureEdgeHelpers::featureEdgesSelOp::isFeatureEdge_
const boolList & isFeatureEdge_
reference to a list holding information which edge is afeture edge
Definition: edgeExtractor.C:2033
Foam::featureEdgeHelpers::featureEdgesNeiOp::collectGroups
void collectGroups(std::map< label, DynList< label > > &neiGroups, const labelListType &elementInGroup, const DynList< label > &localGroupLabel) const
Definition: edgeExtractor.C:1966
Foam::triSurfacePartitioner
Definition: triSurfacePartitioner.H:53
Foam::meshSurfaceCheckInvertedVertices
Definition: meshSurfaceCheckInvertedVertices.H:54
Foam::LongList::append
void append(const T &e)
Append an element at the end of the list.
Definition: LongListI.H:265
Foam::edgeExtractor::checkConcaveEdgeCells
bool checkConcaveEdgeCells()
Definition: edgeExtractor.C:1423
triSurf.H
Foam::labelledPoint::coordinates
const point & coordinates() const
return point coordinates
Definition: labelledPoint.H:93
Foam::edgeExtractor::partitioner
const triSurfacePartitioner & partitioner() const
get the surface partitioner
Definition: edgeExtractor.C:480
Foam::Vector< scalar >::zero
static const Vector zero
Definition: Vector.H:80
p
p
Definition: pEqn.H:62
meshSurfaceMapper.H
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
Foam::edgeExtractor::surfaceWithPatches
const triSurf * surfaceWithPatches() const
Definition: edgeExtractor.C:2445
Foam::featureEdgeHelpers::featureEdgesNeiOp::calculateNumberOfEdgesAtPoint
void calculateNumberOfEdgesAtPoint()
calculate the number of feature edges connected to a surface vertex
Definition: edgeExtractor.C:1842
Foam::meshSurfaceEngine::globalToLocalBndEdgeAddressing
const Map< label > & globalToLocalBndEdgeAddressing() const
global boundary edge label to local label. Only for processor edges
Definition: meshSurfaceEngineI.H:510
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:86
nPatches
label nPatches
Definition: readKivaGrid.H:402
meshSurfaceCheckEdgeTypes.H
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::edgeExtractor::pointPatch_
labelLongList pointPatch_
patch to which a boundary point is mapped to
Definition: edgeExtractor.H:87
triSurfacePartitioner.H
Foam::edgeExtractor::edgeClassifier
const triSurfaceClassifyEdges & edgeClassifier() const
get the edge classifier
Definition: edgeExtractor.C:499
Foam::meshSurfaceCheckInvertedVertices::invertedVertices
const labelHashSet & invertedVertices() const
return the labels of inverted vertices
Definition: meshSurfaceCheckInvertedVertices.H:102
Foam::meshSurfaceEngine::globalBoundaryPointLabel
const labelList & globalBoundaryPointLabel() const
global boundary point label
Definition: meshSurfaceEngineI.H:410
Foam::DynList::removeElement
T removeElement(const label i)
Definition: DynListI.H:404
Foam::meshOctree::findNearestSurfacePoint
void findNearestSurfacePoint(point &nearest, scalar &distSq, label &nearestTriangle, label &region, const point &p) const
find nearest surface point for vertex and its region
Definition: meshOctreeFindNearestSurfacePoint.C:44
Foam::triSurfPoints::points
const pointField & points() const
access to points
Definition: triSurfPointsI.H:44
Foam::triSurfFacets::appendTriangle
void appendTriangle(const labelledTri &tria)
append a triangle to the end of the list
Definition: triSurfFacetsI.H:54
Foam::SubList
A List obtained as a section of another List.
Definition: SubList.H:53
meshSurfaceCheckInvertedVertices.H
Foam::edgeExtractor::nCellsAtEdge_
labelLongList nCellsAtEdge_
number of cells attached to a boundary edge
Definition: edgeExtractor.H:93
Foam::Warning
messageStream Warning
Foam::help::scalarToText
word scalarToText(const scalar s)
convert the scalar value into text
Definition: helperFunctionsStringConversion.C:61
Foam::LongList::clear
void clear()
Clear the list, i.e. set next free to zero.
Definition: LongListI.H:230
Foam::UPstream::parRun
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:377
Foam::meshSurfaceEngine::bpNeiProcs
const DynList< label > & bpNeiProcs() const
communication matrix for sending point data
Definition: meshSurfaceEngineI.H:470
Foam::face::centre
point centre(const pointField &) const
Centre point of face.
Definition: face.C:488
Foam::meshSurfaceEngine::pointFaces
const VRWGraph & pointFaces() const
Definition: meshSurfaceEngineI.H:162
polyMeshGenModifier.H
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:58
pMin
dimensionedScalar pMin("pMin", dimPressure, fluid)
Foam::featureEdgeHelpers::featureEdgesNeiOp::featureEdgesNeiOp
featureEdgesNeiOp(const meshSurfaceEngine &mse, const boolList &isFeatureEdge)
Definition: edgeExtractor.C:1907
Foam::List::transfer
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Foam::Pair::first
const Type & first() const
Return first.
Definition: Pair.H:87
Foam::edgeExtractor::NONE
@ NONE
Definition: edgeExtractor.H:328
Foam::meshSurfaceEngine::faceEdges
const VRWGraph & faceEdges() const
Definition: meshSurfaceEngineI.H:353
Foam::Map< label >
Foam::polyMeshGenModifier::replaceBoundary
void replaceBoundary(const wordList &patchNames, const VRWGraph &boundaryFaces, const labelLongList &faceOwners, const labelLongList &facePatches)
replace the boundary with new boundary faces
Definition: polyMeshGenModifierReplaceBoundary.C:42
triSurfModifier.H
Foam::edgeExtractor::findFeatureEdgesNearEdge
void findFeatureEdgesNearEdge()
Definition: edgeExtractor.C:268
Foam::polyMeshGen
Definition: polyMeshGen.H:46
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Foam::polyMeshGenPoints::points
const pointFieldPMG & points() const
access to points
Definition: polyMeshGenPointsI.H:44
Foam::triSurfaceClassifyEdges::edgeTypes
const List< direction > & edgeTypes() const
return the list of edge classification
Definition: triSurfaceClassifyEdges.C:59
Foam::featureEdgeHelpers::featureEdgesSelOp
Definition: edgeExtractor.C:2029
Foam::triSurfModifier
Definition: triSurfModifier.H:48
Foam::LongList::size
label size() const
Size of the active part of the list.
Definition: LongListI.H:203
Foam::meshOctree::findEdgesInBox
void findEdgesInBox(const boundBox &, DynList< label > &) const
Definition: meshOctreeInsideCalculations.C:60
Foam::edgeExtractor::surfaceEnginePtr_
meshSurfaceEngine * surfaceEnginePtr_
surface engine
Definition: edgeExtractor.H:72
Foam::mag
dimensioned< scalar > mag(const dimensioned< Type > &)
Foam::cellListPMG
Definition: cellListPMG.H:49
Foam::HashSet< label, Hash< label > >
Foam::triSurfaceClassifyEdges::CONCAVEEDGE
@ CONCAVEEDGE
Definition: triSurfaceClassifyEdges.H:88
Foam::DynList::contains
bool contains(const T &e) const
check if the element is in the list (takes linear time)
Definition: DynListI.H:339
Foam::triSurfModifier::patchesAccess
geometricSurfacePatchList & patchesAccess()
access to patches
Definition: triSurfModifierI.H:52
Foam::refLabelledPoint
Definition: refLabelledPoint.H:49
meshOctree.H
Foam::edgeExtractor::surfaceEngine
const meshSurfaceEngine & surfaceEngine() const
get the surface engine
Definition: edgeExtractor.C:462
Foam::polyMeshGenFaces::faces
const faceListPMG & faces() const
access to faces
Definition: polyMeshGenFacesI.H:43
forAllConstIter
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:39
Foam::edgeExtractor::pointValence_
labelLongList pointValence_
valence of surface points
Definition: edgeExtractor.H:84
Foam::LongList::setSize
void setSize(const label)
Reset size of List.
Definition: LongListI.H:223
pFaces
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
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Foam::polyMeshGenModifier::boundariesAccess
PtrList< boundaryPatch > & boundariesAccess()
access to boundary data
Definition: polyMeshGenModifier.H:131
Foam::diff
scalar diff(const triad &A, const triad &B)
Return a quantity of the difference between two triads.
Definition: triad.C:407
Foam::LongList
Definition: LongList.H:55
Foam::deleteDemandDrivenData
void deleteDemandDrivenData(DataPtr &dataPtr)
Definition: demandDrivenData.H:40
Foam::flush
Ostream & flush(Ostream &os)
Flush stream.
Definition: Ostream.H:243
Foam::edgeExtractor::moveVerticesTowardsDiscontinuities
void moveVerticesTowardsDiscontinuities(const label nIterations=2)
Definition: edgeExtractor.C:694
Foam::meshSurfaceEngineModifier
Definition: meshSurfaceEngineModifier.H:48
Foam::meshSurfaceOptimizer::untangleSurface
bool untangleSurface(const labelLongList &activeBoundaryPoints, const label nAdditionalLayers=0)
runs a surface smoother on the selected boundary points
Definition: meshSurfaceOptimizerOptimizeSurface.C:327
Foam::edgeExtractor::mesh_
polyMeshGen & mesh_
reference to the mesh
Definition: edgeExtractor.H:69
Foam::edgeExtractor::CANDIDATE
@ CANDIDATE
Definition: edgeExtractor.H:333
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:43
Foam::edgeExtractor::calculateDeformationMetricForFace
scalar calculateDeformationMetricForFace(const label bfI, const DynList< label > &neiPatches, const label facePatch=-1) const
calculates deformation energy metric for a face
Definition: edgeExtractor.C:1388
Foam::featureEdgeHelpers::featureEdgesNeiOp::nFeatureEdgesAtPoint_
labelList nFeatureEdgesAtPoint_
number of feature edges at a surface point
Definition: edgeExtractor.C:1838
Foam::stableSort
void stableSort(UList< T > &)
Definition: UList.C:121
Foam::meshSurfaceEngine::boundaryFaces
const faceList::subList & boundaryFaces() const
Definition: meshSurfaceEngineI.H:103
Foam::featureEdgeHelpers::featureEdgesNeiOp
Definition: edgeExtractor.C:1828
Foam::constant::physicoChemical::c1
const dimensionedScalar c1
First radiation constant: default SI units: [W/m2].
refLabelledPoint.H
Foam::featureEdgeHelpers::featureEdgesNeiOp::size
label size() const
Definition: edgeExtractor.C:1919
triSurfaceClassifyEdges.H
Foam::label
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
Foam::Field
Pre-declare SubField and related Field type.
Definition: Field.H:57
error.H
Foam::edgeExtractor::calculateSingleCellEdge
void calculateSingleCellEdge()
calculate the number of boundary faces for each cell
Definition: edgeExtractor.C:123
Foam::Info
messageStream Info
Foam::edgeExtractor::checkFacePatchesTopology
bool checkFacePatchesTopology()
Definition: edgeExtractor.C:1632
Foam::meshOctree::findNearestEdgePoint
bool findNearestEdgePoint(point &edgePoint, scalar &distSq, label &nearestEdge, const point &p, const DynList< label > &regions) const
find nearest feature-edges vertex to a given vertex
Definition: meshOctreeFindNearestSurfacePoint.C:215
Foam::edgeExtractor::calculateAlignmentForEdge
scalar calculateAlignmentForEdge(const label beI, const label patch0, const label patch1) const
Definition: edgeExtractor.C:1307
Foam::polyMeshGenCells::cells
const cellListPMG & cells() const
access to cells
Definition: polyMeshGenCellsI.H:39
Foam::triSurfModifier::pointsAccess
pointField & pointsAccess()
non-const access to points
Definition: triSurfModifierI.H:37
Foam::meshSurfaceEngineModifier::moveBoundaryVertexNoUpdate
void moveBoundaryVertexNoUpdate(const label bpI, const point &newP)
relocate the selected boundary vertex
Definition: meshSurfaceEngineModifier.C:68
Foam::edgeExtractor::markPatchPoints
void markPatchPoints(boolList &)
Definition: edgeExtractor.C:336
Foam::meshSurfaceEngine::otherEdgeFaceAtProc
const Map< label > & otherEdgeFaceAtProc() const
Definition: meshSurfaceEngineI.H:568
Foam::meshSurfaceEngine::beNeiProcs
const DynList< label > & beNeiProcs() const
communication matrix for sending edge data
Definition: meshSurfaceEngineI.H:549
Foam::triSurfFacets::patches
const geometricSurfacePatchList & patches() const
access to patches
Definition: triSurfFacetsI.H:49
Foam::VRWGraph::size
label size() const
Returns the number of rows.
Definition: VRWGraphI.H:122
Foam::DynList::appendIfNotIn
void appendIfNotIn(const T &e)
Definition: DynListI.H:324
Foam::Pair::second
const Type & second() const
Return second.
Definition: Pair.H:99
Foam::VRWGraph::setSize
void setSize(const label)
Reset the number of rows.
Definition: VRWGraphI.H:132
Foam::PtrList
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
Definition: List.H:61
forAllRow
#define forAllRow(graph, rowI, index)
Definition: VRWGraph.H:277
patchNames
wordList patchNames(nPatches)
Foam::meshSurfaceEngine::points
const pointFieldPMG & points() const
Definition: meshSurfaceEngineI.H:49
Foam::edgeExtractor::untangleSurface
bool untangleSurface()
check and untangle the surface of the volume mesh
Definition: edgeExtractor.C:2386
Foam::help::nearestPointOnTheEdgeExact
point nearestPointOnTheEdgeExact(const point &edgePoint0, const point &edgePoint1, const point &p)
find the vertex on the edge nearest to the point p
Definition: helperFunctionsGeometryQueriesI.H:1633
HashSet.H
Foam::VRWGraph::sizeOfRow
label sizeOfRow(const label rowI) const
Returns the number of elements in the given row.
Definition: VRWGraphI.H:127
Foam::FatalError
error FatalError
Foam::FixedList::setSize
void setSize(const label)
Dummy setSize function.
Definition: FixedListI.H:177
Foam::HashTable::size
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
labelledPoint.H
labelledScalar.H
Foam::featureEdgeHelpers::featureEdgesNeiOp::isFeatureEdge_
const boolList & isFeatureEdge_
refence to a list holding information which edges are feature edges
Definition: edgeExtractor.C:1835
forAllReverse
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: UList.H:418
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:18
Foam::edgeExtractor::distributeBoundaryFaces
void distributeBoundaryFaces()
Definition: edgeExtractor.C:843
Foam::HashTable::found
bool found(const Key &) const
Return true if hashedEntry is found in table.
Definition: HashTable.C:109
Foam::geometryBase::name
const word & name() const
Return the name.
Definition: geometryBase.C:124
Foam::meshSurfaceMapper::mapVerticesOntoSurfacePatches
void mapVerticesOntoSurfacePatches()
Definition: meshSurfaceMapperMapVertices.C:285
Foam::help::areElementsInChain
bool areElementsInChain(const boolListType &sel)
check if selected elements are in one singly-connected chain
Definition: helperFunctionsTopologyManipulationI.H:426
Foam::meshSurfaceEngine::edgeFaces
const VRWGraph & edgeFaces() const
Definition: meshSurfaceEngineI.H:334
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
Foam::meshSurfaceEngineModifier::updateGeometry
void updateGeometry(const labelLongList &)
Definition: meshSurfaceEngineModifier.C:234
Foam::edgeExtractor::~edgeExtractor
~edgeExtractor()
Definition: edgeExtractor.C:685
meshSurfaceEngine.H
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:131
Foam::meshOctree::findTrianglesInBox
void findTrianglesInBox(const boundBox &, DynList< label > &) const
Definition: meshOctreeInsideCalculations.C:98
Foam::e
const double e
Elementary charge.
Definition: doubleFloat.H:94
Foam::vector
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
s
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Foam::DynList< label >
Foam::edgeExtractor::updateMeshPatches
void updateMeshPatches()
update mesh with selected patches
Definition: edgeExtractor.C:2544
Foam::meshSurfacePartitioner
Definition: meshSurfacePartitioner.H:52
Foam::meshSurfaceEngine::edges
const edgeList & edges() const
Definition: meshSurfaceEngineI.H:296
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
Foam::labelledScalar
Definition: labelledScalar.H:50
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:405
Foam::max
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
fv
labelList fv(nPoints)
Foam::polyMeshGenModifier
Definition: polyMeshGenModifier.H:52
Foam::List::setSize
void setSize(const label)
Reset size of List.
Foam::featureEdgeHelpers::featureEdgesNeiOp::operator()
void operator()(const label beI, DynList< label > &neighbourEdges) const
Definition: edgeExtractor.C:1924
Foam::triSurfaceClassifyEdges
Definition: triSurfaceClassifyEdges.H:55
Foam::edgeExtractor::SINGLECELLEDGE
@ SINGLECELLEDGE
Definition: edgeExtractor.H:329
Foam::edgeExtractor::calculateDeformationMetricForEdge
scalar calculateDeformationMetricForEdge(const label beI, const label patch0, const label patch1) const
Definition: edgeExtractor.C:1347
Foam::DynList::containsAtPosition
label containsAtPosition(const T &e) const
Definition: DynListI.H:356
Foam::edgeExtractor::meshOctree_
const meshOctree & meshOctree_
reference to the octree
Definition: edgeExtractor.H:75
Foam::sumOp
Definition: ops.H:162
Foam::Pair
An ordered pair of two objects of type <T> with first() and second() elements.
Definition: contiguous.H:49
Foam::labelledTri::region
label region() const
Return region label.
Definition: labelledTriI.H:68
Foam::edgeExtractor::findNeiPatches
void findNeiPatches(const label, const Map< label > &, DynList< label > &) const
find neighbour patches over edges for a boundary face
Definition: edgeExtractor.C:1274
helperFunctions.H
edgeExtractor.H
Foam::edgeExtractor::projectDeterminedFeatureVertices
void projectDeterminedFeatureVertices()
project the estimated corners and edges onto the surface mesh
Definition: edgeExtractor.C:2245
Foam::edgeExtractor::calculateValence
void calculateValence()
calculate point valence
Definition: edgeExtractor.C:62
Foam::labelledPoint
Definition: labelledPoint.H:50
f
labelList f(nPoints)
Foam::VRWGraph::appendList
void appendList(const ListType &l)
Append a list as a row at the end of the graph.
Definition: VRWGraphI.H:286
Foam::Vector< scalar >
Foam::meshSurfaceOptimizer
Definition: meshSurfaceOptimizer.H:63
Foam::polyMeshGenFaces::boundaries
const PtrList< boundaryPatch > & boundaries() const
ordinary boundaries
Definition: polyMeshGenFacesI.H:111
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
Foam::featureEdgeHelpers::featureEdgesNeiOp::mse_
const meshSurfaceEngine & mse_
reference to meshSurfaceEngine
Definition: edgeExtractor.C:1832
Foam::sqrt
dimensionedScalar sqrt(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:142
Foam::meshSurfaceMapper
Definition: meshSurfaceMapper.H:59
Foam::DynList::setSize
void setSize(const label)
Reset size of List.
Definition: DynListI.H:263
Foam::acos
dimensionedScalar acos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:259
Foam::meshOctree
Definition: meshOctree.H:55
Foam::edgeExtractor::surfEdgeClassificationPtr_
const triSurfaceClassifyEdges * surfEdgeClassificationPtr_
classification of edges in the surface mesh
Definition: edgeExtractor.H:81
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::surface
Definition: surface.H:55
Foam::help::exchangeMap
void exchangeMap(const std::map< label, ListType > &m, LongList< T > &data, const Pstream::commsTypes commsType)
Definition: helperFunctionsPar.C:129
Foam::edgeExtractor::facePatch_
labelList facePatch_
boundary face patch
Definition: edgeExtractor.H:90
Foam::edgeExtractor::distributeBoundaryFacesNormalAlignment
bool distributeBoundaryFacesNormalAlignment()
move faces into the patch with the best alignment
Definition: edgeExtractor.C:929
Foam::labelledTri
Triangle with additional region number.
Definition: labelledTri.H:49
Foam::triSurfaceClassifyEdges::FEATUREEDGE
@ FEATUREEDGE
Definition: triSurfaceClassifyEdges.H:90
Foam::triSurf::writeSurface
void writeSurface(const fileName &) const
Definition: triSurf.C:430
meshSurfaceEngineModifier.H
Foam::boundBox
A bounding box defined in terms of the points at its extremities.
Definition: boundBox.H:55
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
Foam::meshSurfaceEngine::boundaryPoints
const labelList & boundaryPoints() const
Definition: meshSurfaceEngineI.H:84
Foam::edgeExtractor::findFaceCandidates
void findFaceCandidates(labelLongList &faceCandidates, const labelList *facePatchPtr=NULL, const Map< label > *otherFacePatchPtr=NULL) const
Definition: edgeExtractor.C:511
Foam::featureEdgeHelpers::featureEdgesSelOp::operator()
bool operator()(const label beI) const
Definition: edgeExtractor.C:2042
patches
patches[0]
Definition: createSingleCellMesh.H:36
Foam::edgeExtractor::checkFacePatchesGeometry
bool checkFacePatchesGeometry()
Definition: edgeExtractor.C:2054
FatalErrorIn
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:313
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
Foam::DynList::size
label size() const
Definition: DynListI.H:235
Foam::edgeExtractor::findEdgeCandidates
void findEdgeCandidates()
Definition: edgeExtractor.C:1082
Foam::edgeExtractor::edgeExtractor
edgeExtractor(const edgeExtractor &)
Disallow default bitwise copy construct.
Foam::featureEdgeHelpers::featureEdgesSelOp::featureEdgesSelOp
featureEdgesSelOp(const boolList &isFeatureEdge)
Definition: edgeExtractor.C:2037
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
WarningIn
#define WarningIn(functionName)
Report a warning using Foam::Warning.
Definition: messageStream.H:254
Foam::meshSurfaceEngine::globalToLocalBndPointAddressing
const Map< label > & globalToLocalBndPointAddressing() const
global point label to local label. Only for processors points
Definition: meshSurfaceEngineI.H:431
Foam::sort
void sort(UList< T > &)
Definition: UList.C:107
Foam::edgeExtractor::findOtherFacePatchesParallel
void findOtherFacePatchesParallel(Map< label > &otherFacePatch, const labelList *facePatchPtr=NULL) const
find patches over edges
Definition: edgeExtractor.C:594
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.
Foam::meshOctree::findNearestCorner
bool findNearestCorner(point &nearest, scalar &distSq, label &nearestPoint, const point &p, const DynList< label > &patches) const
find nearest corner point
Definition: meshOctreeFindNearestSurfacePoint.C:405
Foam::point
vector point
Point is a vector.
Definition: point.H:41
Foam::meshOctree::findNearestSurfacePointInRegion
void findNearestSurfacePointInRegion(point &nearest, scalar &distSq, label &nearestTriangle, const label region, const point &p) const
find nearest surface point for vertex in a given region
Definition: meshOctreeFindNearestSurfacePoint.C:131
Foam::meshOctree::surface
const triSurf & surface() const
return a reference to the surface
Definition: meshOctreeI.H:130
Foam::UList::size
label size() const
Return the number of elements in the UList.
Definition: UListI.H:299
Foam::edgeExtractor::faceEvaluator::bestPatchAfterModification
label bestPatchAfterModification(const label bfI) const
Definition: edgeExtractorCorners.C:394
Foam::triSurfacePartitioner::edgeGroups
const labelList & edgeGroups() const
Definition: triSurfacePartitioner.C:79
Foam::edgeExtractor::faceEvaluator
Definition: edgeExtractor.H:205
Foam::edgeExtractor::faceEvaluator::setNewBoundaryPatches
void setNewBoundaryPatches(const labelList &newBoudaryPatches)
set the values for new boundary patches
Definition: edgeExtractorCorners.C:353
Foam::faceListPMG
Definition: faceListPMG.H:50
Foam::edgeExtractor::surfPartitionerPtr_
const triSurfacePartitioner * surfPartitionerPtr_
surface mesh partitioner
Definition: edgeExtractor.H:78
Foam::pointFieldPMG
Definition: pointFieldPMG.H:50
Foam::VRWGraph
Definition: VRWGraph.H:101
Foam::triSurf
Definition: triSurf.H:59
Foam::labelLongList
LongList< label > labelLongList
Definition: labelLongList.H:46
Foam::min
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
Foam::cell
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:56
Foam::triSurfAddressing::edgeFacets
const VRWGraph & edgeFacets() const
return edge-facets addressing
Definition: triSurfAddressingI.H:97
Foam::triSurfAddressing::pointEdges
const VRWGraph & pointEdges() const
return point-edges addressing
Definition: triSurfAddressingI.H:115
meshSurfaceOptimizer.H
Foam::labelPair
Pair< label > labelPair
Label pair.
Definition: labelPair.H:48
Foam::meshSurfaceEngine::mesh
const polyMeshGen & mesh() const
Definition: meshSurfaceEngineI.H:44
Foam::data
Database for solution data, solver performance and other reduced data.
Definition: data.H:52
Foam::VRWGraph::setSizeAndRowSize
void setSizeAndRowSize(const ListType &)
Set the number of rows and the size of each row.
Definition: VRWGraphI.H:178
Foam::magSqr
dimensioned< scalar > magSqr(const dimensioned< Type > &)
Foam::edgeExtractor::extractEdges
void extractEdges()
assemble the above functionality into a workflow
Definition: edgeExtractor.C:2398
Foam::DynList::clear
void clear()
Clear the list, i.e. set next free to zero.
Definition: DynListI.H:279
Foam::meshSurfaceEngine
Definition: meshSurfaceEngine.H:54
Foam::edgeExtractor::edgeType_
LongList< direction > edgeType_
edge classification
Definition: edgeExtractor.H:96
DynList.H
labelPair.H
Foam::labelledPoint::pointLabel
label pointLabel() const
return point label
Definition: labelledPoint.H:82
Foam::edgeExtractor::findPatchesNearSurfaceFace
void findPatchesNearSurfaceFace()
Definition: edgeExtractor.C:197
Foam::DynList::append
void append(const T &e)
Append an element at the end of the list.
Definition: DynListI.H:304
Foam::meshSurfaceEngineModifier::syncVerticesAtParallelBoundaries
void syncVerticesAtParallelBoundaries()
Definition: meshSurfaceEngineModifier.C:160
Foam::meshSurfaceEngine::faceOwners
const labelList & faceOwners() const
Definition: meshSurfaceEngineI.H:143
Foam::pos
dimensionedScalar pos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:190
Foam::meshSurfaceEngine::faces
const faceListPMG & faces() const
Definition: meshSurfaceEngineI.H:54