boundaryLayerOptimisationNormals.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 "demandDrivenData.H"
30 #include "meshSurfacePartitioner.H"
31 #include "meshSurfaceEngine.H"
32 #include "helperFunctions.H"
33 #include "labelledScalar.H"
34 #include "refLabelledPoint.H"
35 #include "refLabelledPointScalar.H"
36 #include "polyMeshGenAddressing.H"
37 #include "partTriMesh.H"
38 #include "partTetMeshSimplex.H"
39 #include "volumeOptimizer.H"
40 
41 //#define DEBUGLayer
42 
43 # ifdef USE_OMP
44 #include <omp.h>
45 # endif
46 
47 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
48 
49 namespace Foam
50 {
51 
52 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
53 
55 (
56  const direction eType,
57  pointNormalsType& pointPatchNormal
58 ) const
59 {
60  const meshSurfaceEngine& mse = meshSurface();
61  const labelList& facePatch = mse.boundaryFacePatches();
62  const labelList& bp = mse.bp();
63  const VRWGraph& pointFaces = mse.pointFaces();
64  const vectorField& fNormals = mse.faceNormals();
65 
66  //- calculate point normals with respect to all patches at a point
67  pointPatchNormal.clear();
68 
69  # ifdef USE_OMP
70  # pragma omp parallel for schedule(dynamic, 20)
71  # endif
72  forAll(hairEdges_, hairEdgeI)
73  {
74  if( !(hairEdgeType_[hairEdgeI] & eType) )
75  continue;
76 
77  const label bpI = bp[hairEdges_[hairEdgeI][0]];
78 
79  //- create an entry in a map
80  patchNormalType* patchNormalPtr(NULL);
81  # ifdef USE_OMP
82  # pragma omp critical
83  patchNormalPtr = &pointPatchNormal[bpI];
84  # else
85  patchNormalPtr = &pointPatchNormal[bpI];
86  # endif
87  patchNormalType& patchNormal = *patchNormalPtr;
88 
89  //- sum normals of faces attached to a point
90  forAllRow(pointFaces, bpI, pfI)
91  {
92  const label bfI = pointFaces(bpI, pfI);
93  const label patchI = facePatch[bfI];
94 
95  if( patchNormal.find(patchI) == patchNormal.end() )
96  {
97  patchNormal[patchI].first = fNormals[bfI];
98  patchNormal[patchI].second = mag(fNormals[bfI]);
99  }
100  else
101  {
102  patchNormal[patchI].first += fNormals[bfI];
103  patchNormal[patchI].second += mag(fNormals[bfI]);
104  }
105  }
106  }
107 
108  if( Pstream::parRun() )
109  {
110  //- gather information about face normals on other processors
111  const Map<label>& globalToLocal =
113  const DynList<label>& neiProcs = mse.bpNeiProcs();
114  const VRWGraph& bpAtProcs = mse.bpAtProcs();
115 
116  std::map<label, LongList<refLabelledPointScalar> > exchangeData;
117  forAll(neiProcs, i)
118  exchangeData[neiProcs[i]].clear();
119 
120  forAllConstIter(Map<label>, globalToLocal, it)
121  {
122  const label bpI = it();
123 
124  if( pointPatchNormal.find(bpI) != pointPatchNormal.end() )
125  {
126  const patchNormalType& patchNormal = pointPatchNormal[bpI];
127 
128  forAllRow(bpAtProcs, bpI, i)
129  {
130  const label neiProc = bpAtProcs(bpI, i);
131 
132  if( neiProc == Pstream::myProcNo() )
133  continue;
134 
135  forAllConstIter(patchNormalType, patchNormal, pIt)
136  exchangeData[neiProc].append
137  (
139  (
140  it.key(),
142  (
143  pIt->first,
144  pIt->second.first,
145  pIt->second.second
146  )
147  )
148  );
149  }
150  }
151  }
152 
154  help::exchangeMap(exchangeData, receivedData);
155 
156  forAll(receivedData, i)
157  {
158  const refLabelledPointScalar& rlps = receivedData[i];
159  const label bpI = globalToLocal[rlps.objectLabel()];
160 
161  patchNormalType& patchNormal = pointPatchNormal[bpI];
162 
163  const labelledPointScalar& lps = rlps.lps();
164  patchNormal[lps.pointLabel()].first += lps.coordinates();
165  patchNormal[lps.pointLabel()].second += lps.scalarValue();
166  }
167  }
168 
169  //- finally, calculate normal vectors
170  # ifdef USE_OMP
171  # pragma omp parallel
172  # pragma omp single nowait
173  # endif
174  forAllIter(pointNormalsType, pointPatchNormal, it)
175  {
176  # ifdef USE_OMP
177  # pragma omp task firstprivate(it)
178  {
179  # endif
180 
181  patchNormalType& patchNormal = it->second;
182 
183  forAllIter(patchNormalType, patchNormal, pIt)
184  {
185  pIt->second.first /= pIt->second.second;
186  //pIt->second.first /= (mag(pIt->second.first) + VSMALL);
187  }
188 
189  # ifdef USE_OMP
190  }
191  # endif
192  }
193 }
194 
196 (
197  const direction eType,
198  pointNormalsType& pointPatchNormal
199 )
200 {
201  const meshSurfacePartitioner& mPart = surfacePartitioner();
202  const meshSurfaceEngine& mse = mPart.surfaceEngine();
203  const pointFieldPMG& points = mse.points();
204  const labelList& bp = mse.bp();
205 
206  partTriMesh triMesh(mPart);
207 
208  const pointField& triMeshPoints = triMesh.points();
209  const VRWGraph& pTriangles = triMesh.pointTriangles();
210  const LongList<labelledTri>& triangles = triMesh.triangles();
211  const labelList& triPointLabel = triMesh.meshSurfacePointLabelInTriMesh();
212  const labelLongList& surfPointLabel = triMesh.pointLabelInMeshSurface();
213 
214  Info << "Calculating normals using smoother " << endl;
215 
216  # ifdef USE_OMP
217  # pragma omp parallel for schedule(dynamic, 50)
218  # endif
219  forAll(hairEdgeType_, heI)
220  {
221  if( !(hairEdgeType_[heI] & eType) )
222  continue;
223 
224  const edge& he = hairEdges_[heI];
225  const label bpI = bp[he.start()];
226 
227  const label triPointI = triPointLabel[bpI];
228 
229  //- create an entry in a map
230  patchNormalType* patchNormalPtr(NULL);
231  # ifdef USE_OMP
232  # pragma omp critical
233  patchNormalPtr = &pointPatchNormal[bpI];
234  # else
235  patchNormalPtr = &pointPatchNormal[bpI];
236  # endif
237 
238  patchNormalType& patchNormal = *patchNormalPtr;
239 
240  //- find patches at this point
241  DynList<label> patchesAtPoint;
242  forAllRow(pTriangles, triPointI, ptI)
243  {
244  patchesAtPoint.appendIfNotIn
245  (
246  triangles[pTriangles(triPointI, ptI)].region()
247  );
248  }
249 
250  forAll(patchesAtPoint, ptchI)
251  {
252  const label patchI = patchesAtPoint[ptchI];
253 
254  DynList<point, 128> pts(2);
256 
257  //- create points
258  pts[0] = points[he.start()];
259  pts[1] = points[he.end()];
260 
261  Map<label> bpToSimplex;
262  bpToSimplex.insert(bpI, 0);
263 
264  forAllRow(pTriangles, triPointI, ptI)
265  {
266  const labelledTri& tri = triangles[pTriangles(triPointI, ptI)];
267 
268  if( tri.region() == patchI )
269  {
270  //- create points originating from triangles
271  FixedList<label, 3> triLabels;
272  forAll(tri, pI)
273  {
274  const label spLabel = tri[pI];
275  const label bpLabel = surfPointLabel[spLabel];
276 
277  if( bpLabel < 0 )
278  {
279  triLabels[pI] = pts.size();
280  pts.append(triMeshPoints[spLabel]);
281  continue;
282  }
283 
284  if( !bpToSimplex.found(bpLabel) )
285  {
286  bpToSimplex.insert(bpLabel, pts.size());
287  pts.append(triMeshPoints[spLabel]);
288  }
289 
290  triLabels[pI] = bpToSimplex[bpLabel];
291  }
292 
293  //- create a new tetrahedron
294  tets.append
295  (
296  partTet(triLabels[2], triLabels[1], triLabels[0], 1)
297  );
298  }
299  }
300 
301  //- create partTeMeshSimplex
302  partTetMeshSimplex simplex(pts, tets, 1);
303 
304  //- activate volume optimizer
305  volumeOptimizer vOpt(simplex);
306 
307  vOpt.optimizeNodePosition();
308 
309  const point newP = simplex.centrePoint();
310 
311  vector n = -1.0 * (newP - pts[0]);
312  const scalar magN = (mag(n) + VSMALL);
313 
314  patchNormal[patchI].first = (n / magN);
315  patchNormal[patchI].second = magN;
316  }
317  }
318 
319  Info << "Finished calculating normals using smoother " << endl;
320 }
321 
323 (
324  vectorField& hairVecs
325 )
326 {
327  //- set the size of hairVecs
328  hairVecs.setSize(hairEdges_.size());
329 
330  const pointFieldPMG& points = mesh_.points();
331 
332  const meshSurfaceEngine& mse = meshSurface();
333  const faceList::subList& bFaces = mse.boundaryFaces();
334  const labelList& bp = mse.bp();
335  const VRWGraph& bpEdges = mse.boundaryPointEdges();
336  const edgeList& edges = mse.edges();
337  const VRWGraph& edgeFaces = mse.edgeFaces();
338 
339  # ifdef USE_OMP
340  # pragma omp parallel for schedule(dynamic, 50)
341  # endif
342  forAll(hairEdges_, hairEdgeI)
343  {
344  const direction hairType = hairEdgeType_[hairEdgeI];
345 
346  if( hairType & BOUNDARY )
347  {
348  const edge& he = hairEdges_[hairEdgeI];
349  vector& hv = hairVecs[hairEdgeI];
350  hv = vector::zero;
351 
352  if( hairType & FEATUREEDGE )
353  {
354  //- do not modify hair vectors at feature edges
355  hv = he.vec(points);
356  }
357  else if( hairType & (ATEDGE|ATCORNER) )
358  {
359  //- this is a case of O-layer at a corner or feature edge
360 
361  //- find the surface edges corresponding to the hair edge
362  label beI(-1);
363 
364  const label bps = bp[he.start()];
365  forAllRow(bpEdges, bps, bpeI)
366  {
367  const label beJ = bpEdges(bps, bpeI);
368 
369  if( edges[beJ] == he )
370  {
371  beI = beJ;
372  continue;
373  }
374  }
375 
376  if( beI < 0 )
378  (
379  "boundaryLayerOptimisation::"
380  "calculateHairVectorsAtTheBoundary(vectorField&)"
381  ) << "Cannot find hair edge "
382  << hairEdgeI << abort(FatalError);
383 
384  //- find the vector at the same angle from both feature edges
385  forAllRow(edgeFaces, beI, befI)
386  {
387  const face& bf = bFaces[edgeFaces(beI, befI)];
388  const vector fNormal = bf.normal(points);
389 
390  const label pos = bf.which(he.start());
391 
392  if( pos < 0 )
394  (
395  "boundaryLayerOptimisation::"
396  "calculateHairVectorsAtTheBoundary(vectorField&)"
397  ) << "Cannot find hair edge "
398  << hairEdgeI << " in face " << bf
399  << abort(FatalError);
400 
401  if( he.end() == bf.prevLabel(pos) )
402  {
403  const edge fe = bf.faceEdge(pos);
404  const vector ev = fe.vec(points);
405 
406  vector hev = fNormal ^ ev;
407  hev /= (mag(hev) + VSMALL);
408 
409  hv += hev;
410  }
411  else
412  {
413  const edge fe = bf.faceEdge(bf.rcIndex(pos));
414  const vector ev = fe.vec(points);
415 
416  vector hev = fNormal ^ ev;
417  hev /= (mag(hev) + VSMALL);
418 
419  hv += hev;
420  }
421  }
422  }
423  else
424  {
426  (
427  "boundaryLayerOptimisation::"
428  "calculateHairVectorsAtTheBoundary(vectorField&)"
429  ) << "Invalid hair type " << label(hairType)
430  << abort(FatalError);
431  }
432  }
433  }
434 
435  if( Pstream::parRun() )
436  {
437  //- collect data at inter-processor boundaries
438  const Map<label>& globalToLocal =
440 
441  const edgeList& edges = mesh_.addressingData().edges();
442  const VRWGraph& pointEdges = mesh_.addressingData().pointEdges();
443  const VRWGraph& edgesAtProcs =
444  mesh_.addressingData().edgeAtProcs();
445  const labelLongList& globalEdgeLabel =
446  mesh_.addressingData().globalEdgeLabel();
447  const Map<label>& globalToLocalEdge =
448  mesh_.addressingData().globalToLocalEdgeAddressing();
449  const DynList<label>& eNeiProcs =
450  mesh_.addressingData().edgeNeiProcs();
451 
452  std::map<label, LongList<labelledPoint> > exchangeData;
453  forAll(eNeiProcs, i)
454  exchangeData[eNeiProcs[i]].clear();
455 
456  forAllConstIter(Map<label>, globalToLocal, it)
457  {
458  const label bpI = it();
459 
460  forAllRow(hairEdgesAtBndPoint_, bpI, i)
461  {
462  const label hairEdgeI = hairEdgesAtBndPoint_(bpI, i);
463  const edge& he = hairEdges_[hairEdgeI];
464 
465  const direction eType = hairEdgeType_[hairEdgeI];
466 
467  //- filte out edges which are not relevant
468  if( !(eType & BOUNDARY) )
469  continue;
470 
471  forAllRow(pointEdges, he.start(), peI)
472  {
473  const label edgeI = pointEdges(he.start(), peI);
474 
475  if( he == edges[edgeI] )
476  {
477  labelledPoint lp
478  (
479  globalEdgeLabel[edgeI],
480  hairVecs[hairEdgeI]
481  );
482 
483  forAllRow(edgesAtProcs, edgeI, j)
484  {
485  const label neiProc = edgesAtProcs(edgeI, j);
486 
487  if( neiProc == Pstream::myProcNo() )
488  continue;
489 
491  exchangeData[neiProc];
492 
493  dts.append(lp);
494  }
495  }
496  }
497  }
498  }
499 
500  LongList<labelledPoint> receivedData;
501  help::exchangeMap(exchangeData, receivedData);
502 
503  forAll(receivedData, i)
504  {
505  const labelledPoint& lp = receivedData[i];
506  const label edgeI = globalToLocalEdge[lp.pointLabel()];
507  const edge& e = edges[edgeI];
508 
509  bool found(false);
510  for(label pI=0;pI<2;++pI)
511  {
512  const label bpI = bp[e[pI]];
513 
514  if( bpI < 0 )
515  continue;
516 
517  forAllRow(hairEdgesAtBndPoint_, bpI, i)
518  {
519  const label hairEdgeI = hairEdgesAtBndPoint_(bpI, i);
520 
521  if( hairEdges_[hairEdgeI] == e )
522  {
523  hairVecs[hairEdgeI] += lp.coordinates();
524 
525  found = true;
526  break;
527  }
528  }
529 
530  if( found )
531  break;
532  }
533  }
534  }
535 
536  //- calculate new normal vectors
537  # ifdef USE_OMP
538  # pragma omp parallel for schedule(dynamic, 100)
539  # endif
540  forAll(hairVecs, hairEdgeI)
541  {
542  if( hairEdgeType_[hairEdgeI] & BOUNDARY )
543  hairVecs[hairEdgeI] /= (mag(hairVecs[hairEdgeI]) + VSMALL);
544  }
545 
546  # ifdef DEBUGLayer
547  Info << "Saving bnd hair vectors" << endl;
548  writeHairEdges("bndHairVectors.vtk", (BOUNDARY | ATEDGE), hairVecs);
549  # endif
550 }
551 
553 {
555 
556  //- calculate direction of hair vector based on the surface normal
557  const meshSurfaceEngine& mse = meshSurface();
558  const labelList& bp = mse.bp();
559  const VRWGraph& pFaces = mse.pointFaces();
560  const faceList::subList& bFaces = mse.boundaryFaces();
561 
562  //- calculate hair vectors
563  //- they point in the normal direction to the surface
564  vectorField hairVecs(hairEdges_.size());
565 
566  if( reCalculateNormals_ )
567  {
568  //- calulate new normal vectors
570  }
571  else
572  {
573  if( nSmoothNormals_ == 0 )
574  return;
575 
576  //- keep existing hair vectors
577  # ifdef USE_OMP
578  # pragma omp parallel for schedule(dynamic, 50)
579  # endif
580  forAll(hairEdges_, heI)
581  hairVecs[heI] = hairEdges_[heI].vec(points);
582  }
583 
584  Info << "Smoothing boundary hair vectors" << endl;
585 
586  //- smooth the variation of normals to reduce the twisting of faces
587  label nIter(0);
588 
589  while( nIter++ < nSmoothNormals_ )
590  {
591  vectorField newNormals(hairVecs.size());
592 
593  # ifdef USE_OMP
594  # pragma omp parallel for schedule(dynamic, 50)
595  # endif
596  forAll(hairEdgesNearHairEdge_, hairEdgeI)
597  {
598  vector& newNormal = newNormals[hairEdgeI];
599  newNormal = vector::zero;
600 
601  const direction eType = hairEdgeType_[hairEdgeI];
602 
603  if( eType & BOUNDARY )
604  {
605  if( eType & (FEATUREEDGE | ATCORNER) )
606  {
607  //- hair vectors at feature edges must not be modified
608  newNormal += hairVecs[hairEdgeI];
609  }
610  else if( eType & ATEDGE )
611  {
612  const edge& he = hairEdges_[hairEdgeI];
613 
614  DynList<label, 2> edgeFaces;
615  const label bps = bp[he.start()];
616  forAllRow(pFaces, bps, pfI)
617  {
618  const label bfI = pFaces(bps, pfI);
619  const face& bf = bFaces[bfI];
620 
621  forAll(bf, eI)
622  {
623  if( bf.faceEdge(eI) == he )
624  {
625  edgeFaces.append(bfI);
626  }
627  }
628  }
629 
630  //- find the best fitting vector
631  //- at the surface of the mesh
632  forAllRow(hairEdgesNearHairEdge_, hairEdgeI, nheI)
633  {
634  const label hairEdgeJ =
635  hairEdgesNearHairEdge_(hairEdgeI, nheI);
636 
637  //- check if the neighbour hair edge shares a boundary
638  //- face with the current hair edge
639  bool useNeighbour(false);
640  const edge& nhe = hairEdges_[hairEdgeJ];
641  forAll(edgeFaces, efI)
642  {
643  const face& bf = bFaces[edgeFaces[efI]];
644 
645  forAll(bf, eI)
646  {
647  if( bf.faceEdge(eI) == nhe )
648  {
649  useNeighbour = true;
650  break;
651  }
652  }
653  }
654 
655  if( useNeighbour )
656  newNormal += hairVecs[hairEdgeJ];
657  }
658  }
659  else
660  {
662  (
663  "void boundaryLayerOptimisation::"
664  "optimiseHairNormalsAtTheBoundary(const label)"
665  ) << "Cannot smooth hair with type " << label(eType)
666  << abort(FatalError);
667  }
668  }
669  }
670 
671  if( Pstream::parRun() )
672  {
673  //- collect data at inter-processor boundaries
674  const Map<label>& globalToLocal =
676 
677  const edgeList& edges = mesh_.addressingData().edges();
678  const VRWGraph& pointEdges = mesh_.addressingData().pointEdges();
679  const VRWGraph& edgesAtProcs =
681  const labelLongList& globalEdgeLabel =
683  const Map<label>& globalToLocalEdge =
685  const DynList<label>& eNeiProcs =
687 
688  std::map<label, LongList<labelledPoint> > exchangeData;
689  forAll(eNeiProcs, i)
690  exchangeData[eNeiProcs[i]].clear();
691 
692  forAllConstIter(Map<label>, globalToLocal, it)
693  {
694  const label bpI = it();
695 
697  {
698  const label hairEdgeI = hairEdgesAtBndPoint_(bpI, i);
699  const edge& he = hairEdges_[hairEdgeI];
700 
701  const direction eType = hairEdgeType_[hairEdgeI];
702 
703  //- filte out edges which are not relevant
704  if( !(eType & BOUNDARY) )
705  continue;
706  if( !(eType & ATEDGE) )
707  continue;
708  if( eType & (FEATUREEDGE|ATCORNER) )
709  continue;
710 
711  forAllRow(pointEdges, he.start(), peI)
712  {
713  const label edgeI = pointEdges(he.start(), peI);
714 
715  if( he == edges[edgeI] )
716  {
717  labelledPoint lp
718  (
719  globalEdgeLabel[edgeI],
720  hairVecs[hairEdgeI]
721  );
722 
723  forAllRow(edgesAtProcs, edgeI, j)
724  {
725  const label neiProc = edgesAtProcs(edgeI, j);
726 
727  if( neiProc == Pstream::myProcNo() )
728  continue;
729 
731  exchangeData[neiProc];
732 
733  dts.append(lp);
734  }
735  }
736  }
737  }
738  }
739 
740  LongList<labelledPoint> receivedData;
741  help::exchangeMap(exchangeData, receivedData);
742 
743  forAll(receivedData, i)
744  {
745  const labelledPoint& lp = receivedData[i];
746  const label edgeI = globalToLocalEdge[lp.pointLabel()];
747  const edge& e = edges[edgeI];
748 
749  bool found(false);
750  for(label pI=0;pI<2;++pI)
751  {
752  const label bpI = bp[e[pI]];
753 
754  if( bpI < 0 )
755  continue;
756 
758  {
759  const label hairEdgeI = hairEdgesAtBndPoint_(bpI, i);
760 
761  if( hairEdges_[hairEdgeI] == e )
762  {
763  hairVecs[hairEdgeI] += lp.coordinates();
764 
765  found = true;
766  break;
767  }
768  }
769 
770  if( found )
771  break;
772  }
773  }
774  }
775 
776  //- calculate new normal vectors
777  # ifdef USE_OMP
778  # pragma omp parallel for schedule(dynamic, 100)
779  # endif
780  forAll(newNormals, heI)
781  {
782  if( hairEdgeType_[heI] & BOUNDARY )
783  {
784  newNormals[heI] /= (mag(newNormals[heI]) + VSMALL);
785  newNormals[heI] = 0.5 * (newNormals[heI] + hairVecs[heI]);
786  newNormals[heI] /= (mag(newNormals[heI]) + VSMALL);
787  }
788  }
789 
790  //- transfer new hair vectors to the hairVecs list
791  hairVecs.transfer(newNormals);
792 
793  # ifdef DEBUGLayer
794  if( true )
795  {
797  (
798  "bndHairVectors_"+help::scalarToText(nIter)+".vtk",
799  (BOUNDARY | ATEDGE),
800  hairVecs
801  );
802  }
803  # endif
804  }
805 
806  //- move vertices to the new locations
807  # ifdef USE_OMP
808  # pragma omp parallel for schedule(dynamic, 100)
809  # endif
810  forAll(hairEdges_, hairEdgeI)
811  {
812  if( hairEdgeType_[hairEdgeI] & BOUNDARY )
813  {
814  const edge& he = hairEdges_[hairEdgeI];
815 
816  const vector& hv = hairVecs[hairEdgeI];
817 
818  points[he.end()] = points[he.start()] + hv * he.mag(points);
819  }
820  }
821 
822  Info << "Finished smoothing boundary hair vectors" << endl;
823 }
824 
826 {
828 
829  //- calculate direction of hair vector based on the surface normal
830  const meshSurfaceEngine& mse = meshSurface();
831  const labelList& bp = mse.bp();
832  const VRWGraph& bpEdges = mse.boundaryPointEdges();
833  const edgeList& edges = mse.edges();
834 
835  //- they point in the normal direction to the surface
836  vectorField hairVecs(hairEdges_.size());
837 
838  if( reCalculateNormals_ )
839  {
840  //- calculate point normals with respect to all patches at a point
841  pointNormalsType pointPatchNormal;
842  calculateNormalVectors(INSIDE, pointPatchNormal);
843  //calculateNormalVectorsSmother(INSIDE, pointPatchNormal);
844 
845  # ifdef USE_OMP
846  # pragma omp parallel for schedule(dynamic, 50)
847  # endif
848  forAll(hairEdges_, hairEdgeI)
849  {
850  const direction hairType = hairEdgeType_[hairEdgeI];
851 
852  if( hairType & INSIDE )
853  {
854  vector& hv = hairVecs[hairEdgeI];
855  hv = vector::zero;
856 
857  const label bpI = bp[hairEdges_[hairEdgeI].start()];
858 
859  label counter(0);
860  const patchNormalType& patchNormals = pointPatchNormal[bpI];
861  forAllConstIter(patchNormalType, patchNormals, pIt)
862  {
863  hv -= pIt->second.first;
864  ++counter;
865  }
866 
867  if( counter == 0 )
868  {
870  (
871  "void boundaryLayerOptimisation::"
872  "optimiseHairNormalsInside()"
873  ) << "No valid patches for boundary point "
874  << bp[hairEdges_[hairEdgeI].start()] << abort(FatalError);
875  }
876 
877  hv /= (mag(hv) + VSMALL);
878  }
879  else
880  {
881  //- initialise boundary hair vectors. They influence internal
882  //- hairs connected to them
883  vector hvec = hairEdges_[hairEdgeI].vec(points);
884  hvec /= (mag(hvec) + VSMALL);
885  hairVecs[hairEdgeI] = hvec;
886  }
887  }
888  }
889  else
890  {
891  if( nSmoothNormals_ == 0 )
892  return;
893 
894  Info << "Using existing hair vectors" << endl;
895 
896  # ifdef USE_OMP
897  # pragma omp parallel for schedule(dynamic, 50)
898  # endif
899  forAll(hairEdges_, hairEdgeI)
900  {
901  //- initialise boundary hair vectors.
902  vector hvec = hairEdges_[hairEdgeI].vec(points);
903  hvec /= (mag(hvec) + VSMALL);
904  hairVecs[hairEdgeI] = hvec;
905  }
906  }
907 
908  # ifdef DEBUGLayer
909  writeHairEdges("insideHairVectors.vtk", (INSIDE|BOUNDARY), hairVecs);
910  # endif
911 
912  Info << "Smoothing internal hair vectors" << endl;
913 
914  //- smooth the variation of normals to reduce twisting of faces
915  label nIter(0);
916 
917  while( nIter++ < nSmoothNormals_ )
918  {
919  vectorField newNormals(hairVecs.size());
920 
921  # ifdef USE_OMP
922  # pragma omp parallel for schedule(dynamic, 50)
923  # endif
924  forAll(hairEdgesNearHairEdge_, hairEdgeI)
925  {
926  vector& newNormal = newNormals[hairEdgeI];
927  newNormal = vector::zero;
928 
929  const direction eType = hairEdgeType_[hairEdgeI];
930 
931  const edge& he = hairEdges_[hairEdgeI];
932  const vector& heVec = hairVecs[hairEdgeI];
933 
934  if( eType & INSIDE )
935  {
936  if( eType & ATCORNER )
937  {
938  //- hair vectors at feature edges must not be modified
939  newNormal = hairVecs[hairEdgeI];
940  }
941  else if( eType & ATEDGE )
942  {
943  forAllRow(hairEdgesNearHairEdge_, hairEdgeI, nheI)
944  {
945  const label hairEdgeJ =
946  hairEdgesNearHairEdge_(hairEdgeI, nheI);
947 
948  const edge& nhe = hairEdges_[hairEdgeJ];
949  const vector& nhVec = hairVecs[hairEdgeJ];
950 
951  vector n = nhVec ^ (points[nhe[0]] - points[he[0]]);
952  n /= (mag(n) + VSMALL);
953 
954  vector newVec = heVec - (heVec & n) * n;
955  newVec /= (mag(newVec) + VSMALL);
956 
957  scalar weight = 1.0;
958 
959  if( Pstream::parRun() )
960  {
961  //- edges at inter-processor boundaries contribute
962  //- at two sides are given weight 0.5
963  const edge be(he[0], nhe[0]);
964  const label bpI = bp[he[0]];
965 
966  forAllRow(bpEdges, bpI, bpeI)
967  {
968  const edge& bndEdge = edges[bpEdges(bpI, bpeI)];
969 
970  if( bndEdge == be )
971  {
972  weight = 0.5;
973  break;
974  }
975  }
976  }
977 
978  newNormal += weight * newVec;
979  }
980  }
981  else
982  {
983  //- find the best fitting vector
984  //- at the surface of the mesh
985  forAllRow(hairEdgesNearHairEdge_, hairEdgeI, nheI)
986  {
987  const label hairEdgeJ =
988  hairEdgesNearHairEdge_(hairEdgeI, nheI);
989 
990  scalar weight = 1.0;
991 
992  if( Pstream::parRun() )
993  {
994  //- edges at inter-processor boundaries contribute
995  //- at two sides are given weight 0.5
996  const edge& nhe = hairEdges_[hairEdgeJ];
997  const edge be(he[0], nhe[0]);
998  const label bpI = bp[he[0]];
999 
1000  forAllRow(bpEdges, bpI, bpeI)
1001  {
1002  const edge& bndEdge = edges[bpEdges(bpI, bpeI)];
1003 
1004  if( bndEdge == be )
1005  {
1006  weight = 0.5;
1007  break;
1008  }
1009  }
1010  }
1011 
1012  newNormal += weight * hairVecs[hairEdgeJ];
1013  }
1014  }
1015  }
1016  else
1017  {
1018  //- copy the existing hair vector
1019  newNormal = hairVecs[hairEdgeI];
1020  }
1021  }
1022 
1023  if( Pstream::parRun() )
1024  {
1025  //- collect data at inter-processor boundaries
1026  const Map<label>& globalToLocal =
1028 
1029  const edgeList& edges = mesh_.addressingData().edges();
1030  const VRWGraph& pointEdges = mesh_.addressingData().pointEdges();
1031  const VRWGraph& edgesAtProcs =
1033  const labelLongList& globalEdgeLabel =
1035  const Map<label>& globalToLocalEdge =
1037  const DynList<label>& eNeiProcs =
1039 
1040  std::map<label, LongList<labelledPoint> > exchangeData;
1041  forAll(eNeiProcs, i)
1042  exchangeData[eNeiProcs[i]].clear();
1043 
1044  forAllConstIter(Map<label>, globalToLocal, it)
1045  {
1046  const label bpI = it();
1047 
1049  {
1050  const label hairEdgeI = hairEdgesAtBndPoint_(bpI, i);
1051  const edge& he = hairEdges_[hairEdgeI];
1052 
1053  const direction eType = hairEdgeType_[hairEdgeI];
1054 
1055  //- handle boundary points, only
1056  if( !(eType & INSIDE) || (eType & ATCORNER) )
1057  continue;
1058 
1059  forAllRow(pointEdges, he.start(), peI)
1060  {
1061  const label edgeI = pointEdges(he.start(), peI);
1062 
1063  if( he == edges[edgeI] )
1064  {
1065  labelledPoint lp
1066  (
1067  globalEdgeLabel[edgeI],
1068  hairVecs[hairEdgeI]
1069  );
1070 
1071  forAllRow(edgesAtProcs, edgeI, j)
1072  {
1073  const label neiProc = edgesAtProcs(edgeI, j);
1074 
1075  if( neiProc == Pstream::myProcNo() )
1076  continue;
1077 
1079  exchangeData[neiProc];
1080 
1081  dts.append(lp);
1082  }
1083  }
1084  }
1085  }
1086  }
1087 
1088  LongList<labelledPoint> receivedData;
1089  help::exchangeMap(exchangeData, receivedData);
1090 
1091  forAll(receivedData, i)
1092  {
1093  const labelledPoint& lp = receivedData[i];
1094  const label edgeI = globalToLocalEdge[lp.pointLabel()];
1095  const edge& e = edges[edgeI];
1096 
1097  bool found(false);
1098  for(label pI=0;pI<2;++pI)
1099  {
1100  const label bpI = bp[e[pI]];
1101 
1102  if( bpI < 0 )
1103  continue;
1104 
1106  {
1107  const label hairEdgeI = hairEdgesAtBndPoint_(bpI, i);
1108 
1109  if( hairEdges_[hairEdgeI] == e )
1110  {
1111  hairVecs[hairEdgeI] += lp.coordinates();
1112 
1113  found = true;
1114  break;
1115  }
1116  }
1117 
1118  if( found )
1119  break;
1120  }
1121  }
1122  }
1123 
1124  //- calculate new normal vectors
1125  # ifdef USE_OMP
1126  # pragma omp parallel for schedule(dynamic, 100)
1127  # endif
1128  forAll(newNormals, hairEdgeI)
1129  {
1130  if( hairEdgeType_[hairEdgeI] & INSIDE )
1131  newNormals[hairEdgeI] /= (mag(newNormals[hairEdgeI]) + VSMALL);
1132  }
1133 
1134  //- transfer new hair vectors to the hairVecs list
1135  hairVecs.transfer(newNormals);
1136 
1137  # ifdef DEBUGLayer
1138  if( true )
1139  {
1141  (
1142  "insideHairVectors_"+help::scalarToText(nIter)+".vtk",
1143  INSIDE,
1144  hairVecs
1145  );
1146  }
1147  # endif
1148  }
1149 
1150  //- move vertices to the new locations
1151  # ifdef USE_OMP
1152  # pragma omp parallel for schedule(dynamic, 100)
1153  # endif
1154  forAll(hairEdges_, hairEdgeI)
1155  {
1156  if( hairEdgeType_[hairEdgeI] & INSIDE )
1157  {
1158  const edge& he = hairEdges_[hairEdgeI];
1159 
1160  const vector& hv = hairVecs[hairEdgeI];
1161 
1162  points[he.end()] = points[he.start()] + hv * he.mag(points);
1163  }
1164  }
1165 
1166  Info << "Finished smoothing internal hair vectors" << endl;
1167 }
1168 
1169 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1170 
1171 } // End namespace Foam
1172 
1173 // ************************************************************************* //
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::meshSurfaceEngine::bp
const labelList & bp() const
Definition: meshSurfaceEngineI.H:64
Foam::boundaryLayerOptimisation::ATEDGE
@ ATEDGE
Definition: boundaryLayerOptimisation.H:213
Foam::boundaryLayerOptimisation::ATCORNER
@ ATCORNER
Definition: boundaryLayerOptimisation.H:214
Foam::refLabelledPointScalar
Definition: refLabelledPointScalar.H:48
Foam::polyMeshGenCells::addressingData
const polyMeshGenAddressing & addressingData() const
addressing which may be needed
Definition: polyMeshGenCells.C:327
Foam::LongList::append
void append(const T &e)
Append an element at the end of the list.
Definition: LongListI.H:265
Foam::labelledPointScalar::scalarValue
const scalar & scalarValue() const
return scalar value
Definition: labelledPointScalar.H:109
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
Foam::partTetMeshSimplex
Definition: partTetMeshSimplex.H:52
forAllIter
#define forAllIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:431
Foam::polyMeshGenAddressing::pointEdges
const VRWGraph & pointEdges() const
Definition: polyMeshGenAddressingPointEdges.C:59
Foam::boundaryLayerOptimisation::reCalculateNormals_
bool reCalculateNormals_
activate calculation of normals
Definition: boundaryLayerOptimisation.H:109
Foam::boundaryLayerOptimisation::FEATUREEDGE
@ FEATUREEDGE
Definition: boundaryLayerOptimisation.H:217
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::boundaryLayerOptimisation::optimiseHairNormalsInside
void optimiseHairNormalsInside()
optimise hair normals inside the mesh
Definition: boundaryLayerOptimisationNormals.C:825
Foam::partTriMesh::points
const pointField & points() const
access to points, tets and other data
Definition: partTriMesh.H:153
Foam::boundaryLayerOptimisation::nSmoothNormals_
label nSmoothNormals_
number of iterations for smoothing of hairs
Definition: boundaryLayerOptimisation.H:100
Foam::edge::vec
vector vec(const pointField &) const
Return the vector (end - start)
Definition: edgeI.H:157
demandDrivenData.H
Template functions to aid in the implementation of demand driven data.
Foam::boundaryLayerOptimisation::optimiseHairNormalsAtTheBoundary
void optimiseHairNormalsAtTheBoundary()
Definition: boundaryLayerOptimisationNormals.C:552
Foam::SubList
A List obtained as a section of another List.
Definition: SubList.H:53
Foam::face::faceEdge
edge faceEdge(const label n) const
Return n-th face edge.
Definition: faceI.H:110
Foam::partTriMesh::meshSurfacePointLabelInTriMesh
const labelList & meshSurfacePointLabelInTriMesh() const
Definition: partTriMesh.H:180
Foam::help::scalarToText
word scalarToText(const scalar s)
convert the scalar value into text
Definition: helperFunctionsStringConversion.C:61
Foam::UPstream::parRun
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:377
Foam::labelledPointScalar::coordinates
const point & coordinates() const
return point coordinates
Definition: labelledPointScalar.H:98
Foam::meshSurfaceEngine::bpNeiProcs
const DynList< label > & bpNeiProcs() const
communication matrix for sending point data
Definition: meshSurfaceEngineI.H:470
Foam::meshSurfaceEngine::pointFaces
const VRWGraph & pointFaces() const
Definition: meshSurfaceEngineI.H:162
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:58
Foam::meshSurfaceEngine::boundaryFacePatches
const labelList & boundaryFacePatches() const
patch label for each boundary face
Definition: meshSurfaceEngineI.H:123
Foam::partTet
Definition: partTet.H:53
Foam::polyMeshGenAddressing::globalEdgeLabel
const labelLongList & globalEdgeLabel() const
Definition: polyMeshGenAddressingParallelAddressing.C:755
Foam::polyMeshGenAddressing::globalToLocalEdgeAddressing
const Map< label > & globalToLocalEdgeAddressing() const
Definition: polyMeshGenAddressingParallelAddressing.C:872
Foam::Map< label >
Foam::boundaryLayerOptimisation::pointNormalsType
std::map< label, patchNormalType > pointNormalsType
Definition: boundaryLayerOptimisation.H:121
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::boundaryLayerOptimisation::BOUNDARY
@ BOUNDARY
Definition: boundaryLayerOptimisation.H:215
Foam::meshSurfacePartitioner::surfaceEngine
const meshSurfaceEngine & surfaceEngine() const
return const reference to meshSurfaceEngine
Definition: meshSurfacePartitioner.H:109
Foam::boundaryLayerOptimisation::calculateNormalVectorsSmother
void calculateNormalVectorsSmother(const direction eType, pointNormalsType &)
calculate normal vectors
Definition: boundaryLayerOptimisationNormals.C:196
Foam::face::which
label which(const label globalIndex) const
Navigation through face vertices.
Definition: face.C:630
forAllConstIter
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:39
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
Definition: LongList.H:55
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::boundaryLayerOptimisation::patchNormalType
std::map< label, std::pair< point, scalar > > patchNormalType
Definition: boundaryLayerOptimisation.H:120
Foam::boundaryLayerOptimisation::hairEdgesNearHairEdge_
VRWGraph hairEdgesNearHairEdge_
hair edge to other hair edges
Definition: boundaryLayerOptimisation.H:82
Foam::boundaryLayerOptimisation::hairEdgesAtBndPoint_
VRWGraph hairEdgesAtBndPoint_
hair edges attached to a boundary point
Definition: boundaryLayerOptimisation.H:79
Foam::meshSurfaceEngine::boundaryFaces
const faceList::subList & boundaryFaces() const
Definition: meshSurfaceEngineI.H:103
refLabelledPoint.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
Foam::Info
messageStream Info
partTetMeshSimplex.H
volumeOptimizer.H
boundaryLayerOptimisation.H
Foam::DynList::appendIfNotIn
void appendIfNotIn(const T &e)
Definition: DynListI.H:324
Foam::volumeOptimizer
class for volume optimizer
Definition: volumeOptimizer.H:53
forAllRow
#define forAllRow(graph, rowI, index)
Definition: VRWGraph.H:277
Foam::partTriMesh::pointLabelInMeshSurface
const labelLongList & pointLabelInMeshSurface() const
Definition: partTriMesh.H:173
Foam::meshSurfaceEngine::points
const pointFieldPMG & points() const
Definition: meshSurfaceEngineI.H:49
Foam::partTetMeshSimplex::centrePoint
const point & centrePoint() const
return centre point coordinates
Definition: partTetMeshSimplex.H:106
Foam::polyMeshGenAddressing::edgeNeiProcs
const DynList< label > & edgeNeiProcs() const
Definition: polyMeshGenAddressingParallelAddressing.C:853
Foam::labelledPointScalar
Definition: labelledPointScalar.H:50
Foam::refLabelledPointScalar::objectLabel
label objectLabel() const
return object label
Definition: refLabelledPointScalar.H:80
Foam::FatalError
error FatalError
Foam::volumeOptimizer::optimizeNodePosition
void optimizeNodePosition(const scalar tol=0.001)
find the best position for the node
Definition: volumeOptimizer.C:67
labelledScalar.H
Foam::meshSurfaceEngine::edgeFaces
const VRWGraph & edgeFaces() const
Definition: meshSurfaceEngineI.H:334
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
meshSurfaceEngine.H
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:131
Foam::e
const double e
Elementary charge.
Definition: doubleFloat.H:94
Foam::polyMeshGenAddressing::edges
const edgeList & edges() const
Return mesh edges.
Definition: polyMeshGenAddressingEdges.C:157
Foam::DynList< label >
Foam::boundaryLayerOptimisation::meshSurface
const meshSurfaceEngine & meshSurface() const
access to mesh surface
Definition: boundaryLayerOptimisationFunctions.C:187
Foam::meshSurfacePartitioner
Definition: meshSurfacePartitioner.H:52
Foam::meshSurfaceEngine::edges
const edgeList & edges() const
Definition: meshSurfaceEngineI.H:296
Foam::partTriMesh
Definition: partTriMesh.H:59
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:405
Foam::boundaryLayerOptimisation::mesh_
polyMeshGen & mesh_
reference to polyMeshGen
Definition: boundaryLayerOptimisation.H:66
found
bool found
Definition: TABSMDCalcMethod2.H:32
Foam::face::prevLabel
label prevLabel(const label i) const
Previous vertex on face.
Definition: faceI.H:124
Foam::boundaryLayerOptimisation::hairEdges_
edgeLongList hairEdges_
boundary layer hairs
Definition: boundaryLayerOptimisation.H:76
he
volScalarField & he
Definition: YEEqn.H:56
Foam::labelledTri::region
label region() const
Return region label.
Definition: labelledTriI.H:68
helperFunctions.H
Foam::labelledPoint
Definition: labelledPoint.H:50
Foam::Vector< scalar >
Foam::refLabelledPointScalar::lps
const labelledPointScalar & lps() const
return labelledPointScalar
Definition: refLabelledPointScalar.H:86
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::labelledPointScalar::pointLabel
label pointLabel() const
return point label
Definition: labelledPointScalar.H:87
Foam::FixedList< label, 3 >
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::polyMeshGenAddressing::edgeAtProcs
const VRWGraph & edgeAtProcs() const
Definition: polyMeshGenAddressingParallelAddressing.C:834
Foam::direction
unsigned char direction
Definition: direction.H:43
Foam::labelledTri
Triangle with additional region number.
Definition: labelledTri.H:49
Foam::boundaryLayerOptimisation::INSIDE
@ INSIDE
Definition: boundaryLayerOptimisation.H:216
Foam::boundaryLayerOptimisation::writeHairEdges
void writeHairEdges(const fileName &fName, const direction eType, const vectorField &vecs) const
write vector correcposing to hair edges. Helper for debugging
Definition: boundaryLayerOptimisationFunctions.C:104
Foam::boundaryLayerOptimisation::calculateHairVectorsAtTheBoundary
void calculateHairVectorsAtTheBoundary(vectorField &)
calculate hair vectors at the boundary
Definition: boundaryLayerOptimisationNormals.C:323
refLabelledPointScalar.H
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::boundaryLayerOptimisation::hairEdgeType_
List< direction > hairEdgeType_
classification of hair edges
Definition: boundaryLayerOptimisation.H:91
Foam::pointFieldPMG
Definition: pointFieldPMG.H:50
Foam::VRWGraph
Definition: VRWGraph.H:101
polyMeshGenAddressing.H
Foam::meshSurfaceEngine::faceNormals
const vectorField & faceNormals() const
Definition: meshSurfaceEngineI.H:258
partTriMesh.H
Foam::meshSurfaceEngine
Definition: meshSurfaceEngine.H:54
Foam::partTriMesh::triangles
const LongList< labelledTri > & triangles() const
Definition: partTriMesh.H:158
Foam::partTriMesh::pointTriangles
const VRWGraph & pointTriangles() const
Definition: partTriMesh.H:163
Foam::boundaryLayerOptimisation::calculateNormalVectors
void calculateNormalVectors(const direction eType, pointNormalsType &) const
Definition: boundaryLayerOptimisationNormals.C:55
meshSurfacePartitioner.H
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