boundaryLayersCreateVertices.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 "boundaryLayers.H"
29 #include "meshSurfaceEngine.H"
30 #include "helperFunctions.H"
31 #include "helperFunctionsPar.H"
32 #include "demandDrivenData.H"
33 
34 #include "labelledPoint.H"
35 #include "labelledScalar.H"
36 
37 #include <map>
38 
39 # ifdef USE_OMP
40 #include <omp.h>
41 # endif
42 
43 //#define DEBUGLayer
44 
45 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
46 
47 namespace Foam
48 {
49 
50 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
51 
53 (
54  const boolList& treatPatches,
55  List<direction>& pVertices
56 ) const
57 {
58  const meshSurfaceEngine& mse = surfaceEngine();
59  const meshSurfacePartitioner& mPart = surfacePartitioner();
60  const VRWGraph& pPatches = mPart.pointPatches();
61 
62  pVertices.setSize(pPatches.size());
63  pVertices = NONE;
64 
65  # ifdef USE_OMP
66  # pragma omp parallel for if( pPatches.size() > 1000 ) \
67  schedule(dynamic, Foam::max(10, pPatches.size()/(2*omp_get_num_threads())))
68  # endif
69  forAll(pPatches, bpI)
70  {
71  bool hasTreated(false);
72  bool hasNotTreated(false);
73 
74  forAllRow(pPatches, bpI, patchI)
75  {
76  const label patch = pPatches(bpI, patchI);
77  if( treatPatches[patch] )
78  {
79  hasTreated = true;
80  }
81  else
82  {
83  hasNotTreated = true;
84  }
85  }
86 
87  if( hasTreated )
88  {
89  pVertices[bpI] |= PATCHNODE;
90 
91  if( hasNotTreated )
92  pVertices[bpI] |= EDGENODE;
93  }
94  }
95 
96  if( Pstream::parRun() )
97  {
98  const VRWGraph& bpAtProcs = mse.bpAtProcs();
99  forAll(pVertices, bpI)
100  if( pVertices[bpI] && (bpAtProcs.sizeOfRow(bpI) != 0) )
101  pVertices[bpI] |= PARALLELBOUNDARY;
102  }
103 }
104 
106 (
107  const label bpI,
108  const boolList& treatPatches,
109  const List<direction>& patchVertex
110 ) const
111 {
112  const meshSurfaceEngine& mse = surfaceEngine();
113  const labelList& bPoints = mse.boundaryPoints();
114  const faceList::subList& bFaces = mse.boundaryFaces();
115  const vectorField& pNormals = mse.pointNormals();
116  const VRWGraph& pFaces = mse.pointFaces();
117  const labelList& boundaryFacePatches = mse.boundaryFacePatches();
118  const VRWGraph& pointPoints = mse.pointPoints();
119 
120  const meshSurfacePartitioner& mPart = surfacePartitioner();
121  const VRWGraph& pPatches = mPart.pointPatches();
122 
123  const pointFieldPMG& points = mesh_.points();
124 
125  # ifdef DEBUGLayer
126  Info << "Creating new vertex for boundary vertex " << bpI << endl;
127  Info << "Global vertex label " << bPoints[bpI] << endl;
128  # endif
129 
131  scalar dist(VGREAT);
132  const point& p = points[bPoints[bpI]];
133  if( patchVertex[bpI] & EDGENODE )
134  {
135  # ifdef DEBUGLayer
136  Info << "Vertex is on the border" << endl;
137  # endif
138 
139  DynList<label> otherPatches;
140  forAllRow(pPatches, bpI, patchI)
141  if( !treatPatches[pPatches(bpI, patchI)] )
142  otherPatches.appendIfNotIn
143  (
144  pPatches(bpI, patchI)
145  );
146 
147  if( otherPatches.size() == 1 )
148  {
149  //- vertex is on an edge
150  # ifdef DEBUGLayer
151  Info << "Vertex is on an edge" << endl;
152  # endif
153  vector v(vector::zero);
154 
155  forAllRow(pFaces, bpI, pfI)
156  {
157  const face& f = bFaces[pFaces(bpI, pfI)];
158  const label patchLabel =
159  boundaryFacePatches[pFaces(bpI, pfI)];
160 
161  if( treatPatches[patchLabel] )
162  {
163  normal += f.normal(points);
164  }
165  else
166  {
167  v += f.normal(points);
168  }
169  }
170 
171  const scalar magV = mag(v) + VSMALL;
172  v /= magV;
173 
174  normal -= (normal & v) * v;
175 
176  const scalar magN = mag(normal) + VSMALL;
177  normal /= magN;
178 
179  forAllRow(pointPoints, bpI, ppI)
180  {
181  if( patchVertex[pointPoints(bpI, ppI)] )
182  continue;
183 
184  const vector vec = points[bPoints[pointPoints(bpI, ppI)]] - p;
185  const scalar prod = 0.5 * mag(vec & normal);
186 
187  if( prod < dist )
188  dist = prod;
189  }
190  }
191  else if( otherPatches.size() == 2 )
192  {
193  # ifdef DEBUGLayer
194  Info << "Vertex is a corner" << endl;
195  # endif
196 
197  label otherVertex(-1);
198  forAllRow(pointPoints, bpI, ppI)
199  {
200  const label bpJ = pointPoints(bpI, ppI);
201 
202  bool found(true);
203  forAll(otherPatches, opI)
204  if( !pPatches.contains(bpJ, otherPatches[opI]) )
205  {
206  found = false;
207  break;
208  }
209 
210  if( found )
211  {
212  otherVertex = bpJ;
213  break;
214  }
215  }
216 
217  if( otherVertex == -1 )
218  {
220  (
221  "void boundaryLayers::createNewVertices"
222  "("
223  "const boolList& treatPatches,"
224  "labelList& newLabelForVertex"
225  ")"
226  ) << "Cannot find moving vertex!" << exit(FatalError);
227  }
228 
229  //- normal vector is co-linear with that edge
230  normal = p - points[bPoints[otherVertex]];
231  dist = 0.5 * mag(normal) + VSMALL;
232 
233  normal /= 2.0 * dist;
234  }
235  else
236  {
238  (
239  "void boundaryLayers::createNewVertices"
240  "("
241  "const boolList& treatPatches,"
242  "labelList& newLabelForVertex"
243  ") const"
244  ) << "There are more than 3 patches meeting at this vertex!"
245  << pPatches[bpI] << abort(FatalError);
246  }
247 
248  //- limit distances
249  forAllRow(pFaces, bpI, pfI)
250  {
251  const label faceLabel = pFaces(bpI, pfI);
252  if( otherPatches.contains(boundaryFacePatches[faceLabel]) )
253  {
254  const face& f = bFaces[faceLabel];
255  const label pos = f.which(bPoints[bpI]);
256 
257  if( pos != -1 )
258  {
259  const point& ep1 = points[f.prevLabel(pos)];
260  const point& ep2 = points[f.nextLabel(pos)];
261 
262  const scalar dst =
264 
265  if( dst < dist )
266  dist = 0.9 * dst;
267  }
268  else
269  {
271  (
272  "void boundaryLayers::createNewVertices"
273  "("
274  "const boolList& treatPatches,"
275  "labelList& newLabelForVertex"
276  ") const"
277  ) << "Face does not contains this vertex!"
278  << abort(FatalError);
279  }
280  }
281  }
282  }
283  else
284  {
285  normal = pNormals[bpI];
286 
287  forAllRow(pointPoints, bpI, ppI)
288  {
289  const scalar d =
290  0.5 * mag
291  (
292  points[bPoints[pointPoints(bpI, ppI)]] -
293  p
294  );
295 
296  if( d < dist )
297  dist = d;
298  }
299  }
300 
301  //- create new vertex
302  # ifdef DEBUGLayer
303  Info << "Normal for vertex " << bpI << " is " << normal << endl;
304  Info << "Distance is " << dist << endl;
305  # endif
306 
307  dist = Foam::max(dist, VSMALL);
308 
309  const point newP = p - dist * normal;
310 
311  if( help::isnan(newP) || help::isinf(newP) )
312  return p;
313 
314  return newP;
315 }
316 
318 {
319  Info << "Creating vertices for layer cells" << endl;
320 
321  List<direction> patchVertex;
322  findPatchVertices(treatPatches, patchVertex);
323 
324  const meshSurfaceEngine& mse = surfaceEngine();
325  const labelList& bPoints = mse.boundaryPoints();
326 
327  //- the following is needed for parallel runs
328  //- it is ugly, but must stay for now :(
329  if( Pstream::parRun() )
330  {
331  mse.pointNormals();
332  mse.pointPoints();
333  }
334 
336 
337  label nExtrudedVertices(0);
338  forAll(patchVertex, bpI)
339  if( patchVertex[bpI] )
340  ++nExtrudedVertices;
341 
342  points.setSize(points.size() + nExtrudedVertices);
343 
344  labelLongList procPoints;
345  forAll(bPoints, bpI)
346  if( patchVertex[bpI] )
347  {
348  if( patchVertex[bpI] & PARALLELBOUNDARY )
349  {
350  procPoints.append(bpI);
351  continue;
352  }
353 
354  points[nPoints_] = createNewVertex(bpI, treatPatches, patchVertex);
355  newLabelForVertex_[bPoints[bpI]] = nPoints_;
356  ++nPoints_;
357  }
358 
359  if( Pstream::parRun() )
360  {
362  (
363  procPoints,
364  patchVertex,
365  treatPatches
366  );
367 
369  (
370  procPoints,
371  patchVertex,
372  treatPatches
373  );
374  }
375 
376  //- swap coordinates of new and old points
377  forAll(bPoints, bpI)
378  {
379  const label pLabel = newLabelForVertex_[bPoints[bpI]];
380  if( pLabel != -1 )
381  {
382  const point p = points[pLabel];
383  points[pLabel] = points[bPoints[bpI]];
384  points[bPoints[bpI]] = p;
385  }
386  }
387 
388  if( nPoints_ != points.size() )
390  (
391  "void boundaryLayers::createNewVertices("
392  "const meshSurfaceEngine& mse,"
393  "const boolList& treatPatches,"
394  "labelList& newLabelForVertex)"
395  ) << "Number of vertices " << nPoints_
396  << " does not match the list size "
397  << abort(FatalError);
398 
399  Info << "Finished creating layer vertices" << endl;
400 }
401 
403 {
404  otherVrts_.clear();
405 
406  patchKey_.setSize(mesh_.boundaries().size());
407  patchKey_ = -1;
408 
409  const meshSurfaceEngine& mse = surfaceEngine();
410  const labelList& bPoints = mse.boundaryPoints();
411 
413  const VRWGraph& pPatches = mPart.pointPatches();
414 
415  //- the following is needed for parallel runs
416  //- it is ugly, but must stay for now :(
417  mse.boundaryFaces();
418  mse.pointNormals();
419  mse.pointFaces();
420  mse.pointPoints();
421 
423  boolList treatPatches(mesh_.boundaries().size());
424  List<direction> patchVertex(bPoints.size());
425 
426  //- make sure than the points are never re-allocated during the process
427  points.reserve(points.size() + 2 * bPoints.size());
428 
429  //- generate new layer vertices for each patch
430  forAll(patchLabels, patchI)
431  {
432  const label pLabel = patchLabels[patchI];
433  treatPatches = false;
434 
435  bool treat(true);
436  forAll(treatPatchesWithPatch_[pLabel], pI)
437  {
438  const label otherPatch = treatPatchesWithPatch_[pLabel][pI];
439  treatPatches[otherPatch] = true;
440 
441  if( patchKey_[otherPatch] == -1 )
442  {
443  patchKey_[otherPatch] = patchI;
444  }
445  else
446  {
447  treat = false;
448  }
449  }
450 
451  if( !treat )
452  continue;
453 
454  const label pKey = patchKey_[pLabel];
455 
456  //- classify vertices belonging to this patch
457  findPatchVertices(treatPatches, patchVertex);
458 
459  //- create indices and allocate maps for new points
460  labelLongList procPoints, patchPoints;
461  forAll(bPoints, bpI)
462  {
463  if( !patchVertex[bpI] )
464  continue;
465 
466  //- skip vertices at parallel boundaries
467  if( patchVertex[bpI] & PARALLELBOUNDARY )
468  {
469  procPoints.append(bpI);
470 
471  continue;
472  }
473 
474  patchPoints.append(bpI);
475  const label pointI = bPoints[bpI];
476 
477  if( patchVertex[bpI] & EDGENODE )
478  {
479  if( otherVrts_.find(pointI) == otherVrts_.end() )
480  {
481  std::map<std::pair<label, label>, label> m;
482 
483  otherVrts_.insert(std::make_pair(pointI, m));
484  }
485 
486  std::pair<label, label> pr(pKey, pKey);
487  otherVrts_[pointI].insert(std::make_pair(pr, nPoints_++));
488  }
489  else
490  {
491  //- this the only new point
492  newLabelForVertex_[pointI] = nPoints_++;
493  }
494  }
495 
496  //- set the size of points
497  points.setSize(nPoints_);
498 
499  //- calculate coordinates of new points
500  # ifdef USE_OMP
501  # pragma omp parallel for schedule(dynamic, 50)
502  # endif
503  forAll(patchPoints, i)
504  {
505  const label bpI = patchPoints[i];
506 
507  const label pointI = bPoints[bpI];
508 
509  //- create new point
510  const point p = createNewVertex(bpI, treatPatches, patchVertex);
511 
512  if( patchVertex[bpI] & EDGENODE )
513  {
514  //- set the new point or an edge point
515  if( otherVrts_.find(pointI) == otherVrts_.end() )
516  {
517  std::map<std::pair<label, label>, label> m;
518 
519  otherVrts_.insert(std::make_pair(pointI, m));
520  }
521 
522  std::pair<label, label> pr(pKey, pKey);
523  const label npI = otherVrts_[pointI][pr];
524  points[npI] = p;
525  }
526  else
527  {
528  //- set the new point
529  points[newLabelForVertex_[pointI]] = p;
530  }
531  }
532 
533  if( Pstream::parRun() )
534  {
535  points.setSize(nPoints_+procPoints.size());
536 
538  (
539  procPoints,
540  patchVertex,
541  treatPatches
542  );
543 
545  (
546  procPoints,
547  patchVertex,
548  treatPatches
549  );
550  }
551  }
552 
553  //- create missing vertices for edge and corner vertices
554  //- they should be stored in the otherNodes map
555  forAll(bPoints, bpI)
556  {
557  const label pointI = bPoints[bpI];
558 
559  if( otherVrts_.find(pointI) == otherVrts_.end() )
560  continue;
561 
562  const point& p = points[pointI];
563 
564  std::map<std::pair<label, label>, label>& m = otherVrts_[pointI];
565  DynList<label> usedPatches;
566  DynList<label> newNodeLabel;
567  DynList<vector> newPatchPenetrationVector;
568  forAllRow(pPatches, bpI, patchI)
569  {
570  const label pKey = patchKey_[pPatches(bpI, patchI)];
571  const std::pair<label, label> pr(pKey, pKey);
572  const std::map<std::pair<label, label>, label>::const_iterator it =
573  m.find(pr);
574  if( (it != m.end()) && !usedPatches.contains(pKey) )
575  {
576  usedPatches.append(pKey);
577  newNodeLabel.append(it->second);
578  newPatchPenetrationVector.append(points[it->second] - p);
579  }
580  }
581 
582  if( newNodeLabel.size() == 1 )
583  {
584  //- only one patch is treated
585  newLabelForVertex_[pointI] = newNodeLabel[0];
586  otherVrts_.erase(pointI);
587  }
588  else if( newNodeLabel.size() == 2 )
589  {
590  //- point is located at an extrusion edge
591  //- create the new position for the existing point
592  point newP(p);
593  newP += newPatchPenetrationVector[0];
594  newP += newPatchPenetrationVector[1];
595 
596  if( !help::isnan(newP) && !help::isinf(newP) )
597  {
598  points.append(newP);
599  }
600  else
601  {
602  points.append(p);
603  }
604  newLabelForVertex_[pointI] = nPoints_;
605  ++nPoints_;
606  }
607  else if( newNodeLabel.size() == 3 )
608  {
609  //- point is located at an extrusion corner
610  //- create 3 points and the new position for the existing point
611  point newP(p);
612  for(label i=0;i<3;++i)
613  {
614  newP += newPatchPenetrationVector[i];
615  for(label j=i+1;j<3;++j)
616  {
617  const point np =
618  p + newPatchPenetrationVector[i] +
619  newPatchPenetrationVector[j];
620 
621  if( !help::isnan(np) && !help::isinf(np) )
622  {
623  points.append(np);
624  }
625  else
626  {
627  points.append(p);
628  }
629 
630  m.insert
631  (
632  std::make_pair
633  (
634  std::make_pair(usedPatches[i], usedPatches[j]),
635  nPoints_
636  )
637  );
638  ++nPoints_;
639  }
640  }
641 
642  //- create new position for the existing point
643  if( !help::isnan(newP) && !help::isinf(newP) )
644  {
645  points.append(newP);
646  }
647  else
648  {
649  points.append(p);
650  }
651 
652  newLabelForVertex_[pointI] = nPoints_;
653  ++nPoints_;
654  }
655  else
656  {
658  (
659  "void boundaryLayers::createNewVertices("
660  "const labelList& patchLabels, labelLongList& newLabelForVertex,"
661  "std::map<label, std::map<std::pair<label, label>, label> >&)"
662  ) << "Boundary node " << bpI << " is not at an edge!"
663  << abort(FatalError);
664  }
665  }
666 
667  //- swap coordinates of new and old points
668  # ifdef USE_OMP
669  # pragma omp parallel for if( bPoints.size() > 1000 ) \
670  schedule(dynamic, 100)
671  # endif
672  forAll(bPoints, bpI)
673  {
674  const label pLabel = newLabelForVertex_[bPoints[bpI]];
675 
676  if( pLabel != -1 )
677  {
678  const point p = points[pLabel];
679  points[pLabel] = points[bPoints[bpI]];
680  points[bPoints[bpI]] = p;
681  }
682  }
683 }
684 
686 (
687  const labelLongList& procPoints,
688  const List<direction>& pVertices,
689  const boolList& /*treatPatches*/
690 )
691 {
692  if( !Pstream::parRun() )
693  return;
694 
695  if( returnReduce(procPoints.size(), sumOp<label>()) == 0 )
696  return;
697 
698  const meshSurfaceEngine& mse = surfaceEngine();
699  pointFieldPMG& points = mesh_.points();
700  const labelList& bPoints = mse.boundaryPoints();
701  const VRWGraph& pointPoints = mse.pointPoints();
702  const VRWGraph& bpAtProcs = mse.bpAtProcs();
703  const labelList& globalPointLabel = mse.globalBoundaryPointLabel();
704  const Map<label>& globalToLocal = mse.globalToLocalBndPointAddressing();
705 
706  scalarField penetrationDistances(bPoints.size(), VGREAT);
707 
708  std::map<label, LongList<labelledScalar> > exchangeDistances;
709 
710  forAll(procPoints, pointI)
711  {
712  const label bpI = procPoints[pointI];
713  forAllRow(bpAtProcs, bpI, procI)
714  {
715  const label neiProc = bpAtProcs(bpI, procI);
716  if( neiProc == Pstream::myProcNo() )
717  continue;
718 
719  if( exchangeDistances.find(neiProc) == exchangeDistances.end() )
720  {
721  exchangeDistances.insert
722  (
723  std::make_pair(neiProc, LongList<labelledScalar>())
724  );
725  }
726  }
727 
728  if( pVertices[bpI] & EDGENODE )
729  continue;
730 
731  scalar dist(VGREAT);
732  const point& p = points[bPoints[bpI]];
733  forAllRow(pointPoints, bpI, ppI)
734  {
735  const scalar d =
736  0.5 * mag(points[bPoints[pointPoints(bpI, ppI)]] - p);
737 
738  if( d < dist )
739  dist = d;
740  }
741 
742  penetrationDistances[bpI] = dist;
743 
744  forAllRow(bpAtProcs, bpI, procI)
745  {
746  const label neiProc = bpAtProcs(bpI, procI);
747  if( neiProc == Pstream::myProcNo() )
748  continue;
749 
750  exchangeDistances[neiProc].append
751  (
752  labelledScalar(globalPointLabel[bpI], dist)
753  );
754  }
755  }
756 
757  //- exchange distances with other processors
758  LongList<labelledScalar> receivedData;
759  help::exchangeMap(exchangeDistances, receivedData);
760  forAll(receivedData, i)
761  {
762  const label bpI = globalToLocal[receivedData[i].scalarLabel()];
763 
764  if( penetrationDistances[bpI] > receivedData[i].value() )
765  penetrationDistances[bpI] = receivedData[i].value();
766  }
767 
768  //- Finally, create the points
769  const vectorField& pNormals = mse.pointNormals();
770  forAll(procPoints, pointI)
771  {
772  const label bpI = procPoints[pointI];
773 
774  if( pVertices[bpI] & EDGENODE )
775  continue;
776 
777  const point& p = points[bPoints[bpI]];
778  const point np = p - pNormals[bpI] * penetrationDistances[bpI];
779  if( !help::isnan(np) && !help::isinf(np) )
780  {
781  points[nPoints_] = np;
782  }
783  else
784  {
785  points[nPoints_] = p;
786  }
787  newLabelForVertex_[bPoints[bpI]] = nPoints_;
788  ++nPoints_;
789  }
790 }
791 
793 (
794  const labelLongList& procPoints,
795  const List<direction>& pVertices,
796  const boolList& treatPatches
797 )
798 {
799  if( !Pstream::parRun() )
800  return;
801 
802  if( returnReduce(procPoints.size(), sumOp<label>()) == 0 )
803  return;
804 
805  const meshSurfaceEngine& mse = surfaceEngine();
806  pointFieldPMG& points = mesh_.points();
807  const labelList& bPoints = mse.boundaryPoints();
808  const VRWGraph& pointPoints = mse.pointPoints();
809  const VRWGraph& bpAtProcs = mse.bpAtProcs();
810  const labelList& globalPointLabel = mse.globalBoundaryPointLabel();
811  const Map<label>& globalToLocal = mse.globalToLocalBndPointAddressing();
812 
813  DynList<label> neiProcs;
814  labelLongList edgePoints;
815  Map<label> bpToEdgePoint;
816  forAll(procPoints, pointI)
817  {
818  const label bpI = procPoints[pointI];
819  forAllRow(bpAtProcs, bpI, procI)
820  {
821  const label neiProc = bpAtProcs(bpI, procI);
822  if( neiProc == Pstream::myProcNo() )
823  continue;
824 
825  neiProcs.appendIfNotIn(neiProc);
826  }
827 
828  if( pVertices[bpI] & EDGENODE )
829  {
830  bpToEdgePoint.insert(bpI, edgePoints.size());
831  edgePoints.append(bpI);
832  }
833  }
834 
835  if( returnReduce(edgePoints.size(), sumOp<label>()) == 0 )
836  return;
837 
838  const meshSurfacePartitioner& mPart = surfacePartitioner();
839  const VRWGraph& pPatches = mPart.pointPatches();
840 
841  const VRWGraph& pFaces = mse.pointFaces();
842  const faceList::subList& bFaces = mse.boundaryFaces();
843  const labelList& boundaryFacePatches = mse.boundaryFacePatches();
844 
845  scalarField dist(edgePoints.size(), VGREAT);
846  vectorField normal(edgePoints.size(), vector::zero);
847  vectorField v(edgePoints.size(), vector::zero);
848 
849  label pKey(-1);
850  if( patchKey_.size() )
851  {
852  forAll(treatPatches, patchI)
853  if( treatPatches[patchI] )
854  {
855  pKey = patchKey_[patchI];
856  break;
857  }
858  }
859 
860  forAll(edgePoints, epI)
861  {
862  const label bpI = edgePoints[epI];
863  const point& p = points[bPoints[bpI]];
864 
865  //- find patches for the given point
866  DynList<label> otherPatches;
867  forAllRow(pPatches, bpI, patchI)
868  if( !treatPatches[pPatches(bpI, patchI)] )
869  otherPatches.appendIfNotIn(pPatches(bpI, patchI));
870 
871  //- find local values of normals and v
872  if( otherPatches.size() == 1 )
873  {
874  forAllRow(pFaces, bpI, pfI)
875  {
876  const face& f = bFaces[pFaces(bpI, pfI)];
877  const label patchLabel =
878  boundaryFacePatches[pFaces(bpI, pfI)];
879 
880  if( treatPatches[patchLabel] )
881  {
882  normal[epI] += f.normal(points);
883  }
884  else
885  {
886  v[epI] += f.normal(points);
887  }
888  }
889  }
890  else if( otherPatches.size() == 2 )
891  {
892  label otherVertex(-1);
893  forAllRow(pointPoints, bpI, ppI)
894  {
895  const label bpJ = pointPoints(bpI, ppI);
896 
897  bool found(true);
898  forAll(otherPatches, opI)
899  if( !pPatches.contains(bpJ, otherPatches[opI]) )
900  {
901  found = false;
902  break;
903  }
904 
905  if( found )
906  {
907  otherVertex = bpJ;
908  break;
909  }
910  }
911 
912  if( otherVertex == -1 )
913  continue;
914 
915  //- normal vector is co-linear with that edge
916  normal[epI] = p - points[bPoints[otherVertex]];
917  dist[epI] = mag(normal[epI]);
918  }
919  else
920  {
922  (
923  "void boundaryLayers::createNewEdgeVerticesParallel("
924  "const labelLongList& procPoints,"
925  "const List<direction>& pVertices,"
926  "const boolList& treatPatches,"
927  "labelList& newLabelForVertex"
928  ") const"
929  ) << "There are more than 3 patches meeting at this vertex!"
930  << abort(FatalError);
931  }
932  }
933 
934  //- prepare normals and v for sending to other procs
935  std::map<label, LongList<labelledPoint> > exchangeNormals;
936  forAll(neiProcs, procI)
937  exchangeNormals.insert
938  (
939  std::make_pair(neiProcs[procI], LongList<labelledPoint>())
940  );
941 
942  forAll(edgePoints, epI)
943  {
944  const label bpI = edgePoints[epI];
945 
946  forAllRow(bpAtProcs, bpI, procI)
947  {
948  const label neiProc = bpAtProcs(bpI, procI);
949  if( neiProc == Pstream::myProcNo() )
950  continue;
951 
952  //- store values in the list for sending
953  LongList<labelledPoint>& dataToSend = exchangeNormals[neiProc];
954  dataToSend.append
955  (
956  labelledPoint(globalPointLabel[bpI], normal[epI])
957  );
958  dataToSend.append(labelledPoint(globalPointLabel[bpI], v[epI]));
959  }
960  }
961 
962  //- exchange data with other processors
963  LongList<labelledPoint> receivedData;
964  help::exchangeMap(exchangeNormals, receivedData);
965  exchangeNormals.clear();
966 
967  label counter(0);
968  while( counter < receivedData.size() )
969  {
970  const labelledPoint& otherNormal = receivedData[counter++];
971  const labelledPoint& otherV = receivedData[counter++];
972 
973  const label bpI = globalToLocal[otherNormal.pointLabel()];
974  normal[bpToEdgePoint[bpI]] += otherNormal.coordinates();
975  v[bpToEdgePoint[bpI]] += otherV.coordinates();
976  }
977 
978  //- calculate normals
979  forAll(normal, epI)
980  {
981  const label bpI = edgePoints[epI];
982 
983  //- find patches for the given point
984  DynList<label> otherPatches;
985  forAllRow(pPatches, bpI, patchI)
986  if( !treatPatches[pPatches(bpI, patchI)] )
987  otherPatches.appendIfNotIn(pPatches(bpI, patchI));
988 
989  if( otherPatches.size() == 1 )
990  {
991  const scalar magV = mag(v[epI]) + VSMALL;
992  v[epI] /= magV;
993  normal[epI] -= (normal[epI] & v[epI]) * v[epI];
994  }
995 
996  const scalar magN = mag(normal[epI]) + VSMALL;
997  normal[epI] /= magN;
998  }
999 
1000  //- calculate distances
1001  forAll(edgePoints, epI)
1002  {
1003  const label bpI = edgePoints[epI];
1004  const point& p = points[bPoints[bpI]];
1005 
1006  //- find patches for the given point
1007  DynList<label> otherPatches;
1008  forAllRow(pPatches, bpI, patchI)
1009  if( !treatPatches[pPatches(bpI, patchI)] )
1010  otherPatches.appendIfNotIn(pPatches(bpI, patchI));
1011 
1012  if( otherPatches.size() == 1 )
1013  {
1014  forAllRow(pointPoints, bpI, ppI)
1015  {
1016  if( pVertices[pointPoints(bpI, ppI)] )
1017  continue;
1018 
1019  const vector vec = points[bPoints[pointPoints(bpI, ppI)]] - p;
1020  const scalar prod = 0.5 * mag(vec & normal[epI]);
1021 
1022  if( prod < dist[epI] )
1023  dist[epI] = prod;
1024  }
1025  }
1026 
1027  //- limit distances
1028  forAllRow(pFaces, bpI, pfI)
1029  {
1030  const label faceLabel = pFaces(bpI, pfI);
1031  if( otherPatches.contains(boundaryFacePatches[faceLabel]) )
1032  {
1033  const face& f = bFaces[faceLabel];
1034  const label pos = f.which(bPoints[bpI]);
1035 
1036  if( pos != -1 )
1037  {
1038  const point& ep1 = points[f.prevLabel(pos)];
1039  const point& ep2 = points[f.nextLabel(pos)];
1040 
1041  const scalar dst =
1043 
1044  if( dst < dist[epI] )
1045  dist[epI] = 0.9 * dst;
1046  }
1047  else
1048  {
1049  FatalErrorIn
1050  (
1051  "void boundaryLayers::createNewEdgeVerticesParallel"
1052  "("
1053  "const labelLongList& procPoints,"
1054  "const List<direction>& pVertices,"
1055  "const boolList& treatPatches,"
1056  "labelList& newLabelForVertex"
1057  ") const"
1058  ) << "Face does not contains this vertex!"
1059  << abort(FatalError);
1060  }
1061  }
1062  }
1063  }
1064 
1065  //- exchange distances with other processors
1066  std::map<label, LongList<labelledScalar> > exchangeDistances;
1067  forAll(neiProcs, procI)
1068  exchangeDistances.insert
1069  (
1070  std::make_pair(neiProcs[procI], LongList<labelledScalar>())
1071  );
1072 
1073  forAll(edgePoints, epI)
1074  {
1075  const label bpI = edgePoints[epI];
1076  forAllRow(bpAtProcs, bpI, procI)
1077  {
1078  const label neiProc = bpAtProcs(bpI, procI);
1079  if( neiProc == Pstream::myProcNo() )
1080  continue;
1081 
1082  LongList<labelledScalar>& ls = exchangeDistances[neiProc];
1083  ls.append(labelledScalar(globalPointLabel[bpI], dist[epI]));
1084  }
1085  }
1086 
1087  //- exchange distances with other processors
1088  LongList<labelledScalar> receivedDistances;
1089  help::exchangeMap(exchangeDistances, receivedDistances);
1090  exchangeDistances.clear();
1091 
1092  forAll(receivedDistances, i)
1093  {
1094  const label bpI = globalToLocal[receivedDistances[i].scalarLabel()];
1095  const label epI = bpToEdgePoint[bpI];
1096  if( dist[epI] > receivedDistances[i].value() )
1097  dist[epI] = receivedDistances[i].value();
1098  }
1099 
1100  //- Finally, create new points
1101  forAll(edgePoints, epI)
1102  {
1103  const label bpI = edgePoints[epI];
1104 
1105  const point& p = points[bPoints[bpI]];
1106  const point np = p - normal[epI] * dist[epI];
1107  if( !help::isnan(np) && !help::isinf(np) )
1108  {
1109  points[nPoints_] = np;
1110  }
1111  else
1112  {
1113  points[nPoints_] = p;
1114  }
1115 
1116  if( pKey == -1 )
1117  {
1118  //- extrusion for one patch in a single go
1119  newLabelForVertex_[bPoints[bpI]] = nPoints_;
1120  }
1121  else
1122  {
1123  const label pointI = bPoints[bpI];
1124 
1125  if( otherVrts_.find(pointI) == otherVrts_.end() )
1126  {
1127  std::map<std::pair<label, label>, label> m;
1128  otherVrts_.insert(std::make_pair(pointI, m));
1129  }
1130 
1131  std::pair<label, label> pr(pKey, pKey);
1132  otherVrts_[pointI].insert(std::make_pair(pr, nPoints_));
1133  }
1134  ++nPoints_;
1135  }
1136 }
1137 
1138 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1139 
1140 } // End namespace Foam
1141 
1142 // ************************************************************************* //
Foam::meshSurfaceEngine::bpAtProcs
const VRWGraph & bpAtProcs() const
processors which contain the vertex
Definition: meshSurfaceEngineI.H:451
Foam::LongList::append
void append(const T &e)
Append an element at the end of the list.
Definition: LongListI.H:265
Foam::labelledPoint::coordinates
const point & coordinates() const
return point coordinates
Definition: labelledPoint.H:93
Foam::Vector< scalar >::zero
static const Vector zero
Definition: Vector.H:80
p
p
Definition: pEqn.H:62
Foam::boundaryLayers::surfaceEngine
const meshSurfaceEngine & surfaceEngine() const
Return const reference to meshSurfaceEngine.
Definition: boundaryLayers.C:54
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:86
helperFunctionsPar.H
Foam::boundaryLayers::createNewPartitionVerticesParallel
void createNewPartitionVerticesParallel(const labelLongList &procPoints, const List< direction > &pVertices, const boolList &treatPatches)
creates new vertices for vertices at parallel boundaries
Definition: boundaryLayersCreateVertices.C:686
Foam::boundaryLayers::nPoints_
label nPoints_
number of vertices in the mesh
Definition: boundaryLayers.H:105
Foam::help::isnan
bool isnan(const ListType &)
check if a list has nan entries
Definition: helperFunctionsGeometryQueriesI.H:53
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::meshSurfaceEngine::globalBoundaryPointLabel
const labelList & globalBoundaryPointLabel() const
global boundary point label
Definition: meshSurfaceEngineI.H:410
Foam::boundaryLayers::mesh_
polyMeshGen & mesh_
Reference to the mesh.
Definition: boundaryLayers.H:63
Foam::help::distanceOfPointFromTheEdge
scalar distanceOfPointFromTheEdge(const point &edgePoint0, const point &edgePoint1, const point &p)
find and return the distance between the edge and the point p
Definition: helperFunctionsGeometryQueriesI.H:1660
demandDrivenData.H
Template functions to aid in the implementation of demand driven data.
Foam::SubList
A List obtained as a section of another List.
Definition: SubList.H:53
Foam::UPstream::parRun
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:377
Foam::meshSurfaceEngine::pointFaces
const VRWGraph & pointFaces() const
Definition: meshSurfaceEngineI.H:162
Foam::meshSurfaceEngine::boundaryFacePatches
const labelList & boundaryFacePatches() const
patch label for each boundary face
Definition: meshSurfaceEngineI.H:123
Foam::Map< label >
Foam::boundaryLayers::newLabelForVertex_
labelLongList newLabelForVertex_
label of a new node (helper)
Definition: boundaryLayers.H:95
Foam::boundaryLayers::otherVrts_
std::map< label, std::map< std::pair< label, label >, label > > otherVrts_
Definition: boundaryLayers.H:99
Foam::boundaryLayers::PARALLELBOUNDARY
@ PARALLELBOUNDARY
Definition: boundaryLayers.H:238
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::LongList::size
label size() const
Size of the active part of the list.
Definition: LongListI.H:203
Foam::mag
dimensioned< scalar > mag(const dimensioned< Type > &)
Foam::boundaryLayers::EDGENODE
@ EDGENODE
Definition: boundaryLayers.H:236
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::VRWGraph::contains
bool contains(const label rowI, const label e) const
check if the element is in the given row (takes linear time)
Definition: VRWGraphI.H:511
Foam::meshSurfacePartitioner::pointPatches
const VRWGraph & pointPatches() const
Definition: meshSurfacePartitioner.H:123
Foam::help::isinf
bool isinf(const ListType &)
check if a list has inf entries
Definition: helperFunctionsGeometryQueriesI.H:63
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
Foam::LongList< label >
Foam::meshSurfaceEngine::boundaryFaces
const faceList::subList & boundaryFaces() const
Definition: meshSurfaceEngineI.H:103
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
Foam::Info
messageStream Info
Foam::meshSurfaceEngine::pointNormals
const vectorField & pointNormals() const
Definition: meshSurfaceEngineI.H:239
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
forAllRow
#define forAllRow(graph, rowI, index)
Definition: VRWGraph.H:277
Foam::boundaryLayers::createNewEdgeVerticesParallel
void createNewEdgeVerticesParallel(const labelLongList &procPoints, const List< direction > &pVertices, const boolList &treatPatches)
Definition: boundaryLayersCreateVertices.C:793
Foam::VRWGraph::sizeOfRow
label sizeOfRow(const label rowI) const
Returns the number of elements in the given row.
Definition: VRWGraphI.H:127
Foam::boundaryLayers::patchKey_
labelList patchKey_
a key assigned to each patch. It is needed to search in otherVrts_
Definition: boundaryLayers.H:102
Foam::FatalError
error FatalError
labelledPoint.H
Foam::meshSurfaceEngine::pointPoints
const VRWGraph & pointPoints() const
Definition: meshSurfaceEngineI.H:220
labelledScalar.H
Foam::boundaryLayers::findPatchVertices
void findPatchVertices(const boolList &treatPatches, List< direction > &patchVertex) const
find vertices of the selected patches
Definition: boundaryLayersCreateVertices.C:53
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
meshSurfaceEngine.H
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:131
Foam::DynList< label >
Foam::meshSurfacePartitioner
Definition: meshSurfacePartitioner.H:52
Foam::boundaryLayers::createNewVertex
point createNewVertex(const label bpI, const boolList &treatPatches, const List< direction > &pVertices) const
create new vertex
Definition: boundaryLayersCreateVertices.C:106
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 > &)
found
bool found
Definition: TABSMDCalcMethod2.H:32
Foam::List::setSize
void setSize(const label)
Reset size of List.
Foam::sumOp
Definition: ops.H:162
Foam::boundaryLayers::treatPatchesWithPatch_
List< DynList< label > > treatPatchesWithPatch_
extrude patches with patch
Definition: boundaryLayers.H:92
helperFunctions.H
Foam::labelledPoint
Definition: labelledPoint.H:50
f
labelList f(nPoints)
Foam::Vector< scalar >
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
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::help::exchangeMap
void exchangeMap(const std::map< label, ListType > &m, LongList< T > &data, const Pstream::commsTypes commsType)
Definition: helperFunctionsPar.C:129
Foam::meshSurfaceEngine::boundaryPoints
const labelList & boundaryPoints() const
Definition: meshSurfaceEngineI.H:84
Foam::boundaryLayers::createNewVertices
void createNewVertices(const boolList &treatPatches)
create new vertices for the selected patches
Definition: boundaryLayersCreateVertices.C:317
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::meshSurfaceEngine::globalToLocalBndPointAddressing
const Map< label > & globalToLocalBndPointAddressing() const
global point label to local label. Only for processors points
Definition: meshSurfaceEngineI.H:431
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.
Foam::pointFieldPMG
Definition: pointFieldPMG.H:50
Foam::VRWGraph
Definition: VRWGraph.H:101
Foam::boundaryLayers::surfacePartitioner
const meshSurfacePartitioner & surfacePartitioner() const
return const reference to meshSurfacePartitioner
Definition: boundaryLayers.C:62
boundaryLayers.H
Foam::meshSurfaceEngine
Definition: meshSurfaceEngine.H:54
normal
A normal distribution model.
Foam::labelledPoint::pointLabel
label pointLabel() const
return point label
Definition: labelledPoint.H:82
Foam::DynList::append
void append(const T &e)
Append an element at the end of the list.
Definition: DynListI.H:304
Foam::pos
dimensionedScalar pos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:190