addPatchCellLayer.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2015-2017 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "addPatchCellLayer.H"
30 #include "polyMesh.H"
31 #include "polyTopoChange.H"
32 #include "meshTools.H"
33 #include "mapPolyMesh.H"
34 #include "syncTools.H"
35 #include "polyAddPoint.H"
36 #include "polyAddFace.H"
37 #include "polyModifyFace.H"
38 #include "polyAddCell.H"
39 #include "globalIndex.H"
40 #include "PatchTools.H"
41 #include "dummyTransform.H"
42 
43 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
44 
45 namespace Foam
46 {
47  defineTypeNameAndDebug(addPatchCellLayer, 0);
48 }
49 
50 
51 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
52 
53 Foam::label Foam::addPatchCellLayer::nbrFace
54 (
55  const labelListList& edgeFaces,
56  const label edgei,
57  const label facei
58 )
59 {
60  const labelList& eFaces = edgeFaces[edgei];
61 
62  if (eFaces.size() == 2)
63  {
64  return (eFaces[0] != facei ? eFaces[0] : eFaces[1]);
65  }
66  else
67  {
68  return -1;
69  }
70 }
71 
72 
73 void Foam::addPatchCellLayer::addVertex
74 (
75  const label pointi,
76  face& f,
77  label& fp
78 )
79 {
80  if (fp == 0)
81  {
82  f[fp++] = pointi;
83  }
84  else
85  {
86  if (f[fp-1] != pointi && f[0] != pointi)
87  {
88  f[fp++] = pointi;
89  }
90  }
91 }
92 
93 
94 // Is edge to the same neighbour? (and needs extrusion and has not been
95 // dealt with already)
96 bool Foam::addPatchCellLayer::sameEdgeNeighbour
97 (
98  const indirectPrimitivePatch& pp,
99  const labelListList& globalEdgeFaces,
100  const boolList& doneEdge,
101  const label thisGlobalFacei,
102  const label nbrGlobalFacei,
103  const label edgei
104 ) const
105 {
106  const edge& e = pp.edges()[edgei];
107 
108  return
109  !doneEdge[edgei] // not yet handled
110  && (
111  addedPoints_[e[0]].size() // is extruded
112  || addedPoints_[e[1]].size()
113  )
114  && (
115  nbrFace(globalEdgeFaces, edgei, thisGlobalFacei)
116  == nbrGlobalFacei // is to same neighbour
117  );
118 }
119 
120 
121 // Collect consecutive string of edges that connects the same two
122 // (possibly coupled) faces. Returns -1 if no unvisited edge can be found.
123 // Otherwise returns start and end index in face.
124 Foam::labelPair Foam::addPatchCellLayer::getEdgeString
125 (
126  const indirectPrimitivePatch& pp,
127  const labelListList& globalEdgeFaces,
128  const boolList& doneEdge,
129  const label patchFacei,
130  const label globalFacei
131 ) const
132 {
133  const labelList& fEdges = pp.faceEdges()[patchFacei];
134 
135  label startFp = -1;
136  label endFp = -1;
137 
138  // Get edge that hasn't been done yet but needs extrusion
139  forAll(fEdges, fp)
140  {
141  label edgei = fEdges[fp];
142  const edge& e = pp.edges()[edgei];
143 
144  if
145  (
146  !doneEdge[edgei]
147  && ( addedPoints_[e[0]].size() || addedPoints_[e[1]].size() )
148  )
149  {
150  startFp = fp;
151  break;
152  }
153  }
154 
155  if (startFp != -1)
156  {
157  // We found an edge that needs extruding but hasn't been done yet.
158  // Now find the face on the other side
159  label nbrGlobalFacei = nbrFace
160  (
161  globalEdgeFaces,
162  fEdges[startFp],
163  globalFacei
164  );
165 
166  if (nbrGlobalFacei == -1)
167  {
168  // Proper boundary edge. Only extrude single edge.
169  endFp = startFp;
170  }
171  else
172  {
173  // Search back for edge
174  // - which hasn't been handled yet
175  // - with same neighbour
176  // - that needs extrusion
177 
178  const label initFp = startFp;
179  while (true)
180  {
181  label prevFp = fEdges.rcIndex(startFp);
182 
183  if (prevFp == initFp)
184  {
185  const edge& e = pp.edges()[fEdges[initFp]];
186  const face& localF = pp.localFaces()[patchFacei];
187 
189  << "On face:" << patchFacei
190  << " fc:" << pp.faceCentres()[patchFacei]
191  << " vertices:" << localF
192  << " points:"
193  << UIndirectList<point>(pp.points(), pp[patchFacei])
194  << " edges:" << fEdges
195  << " All edges of face seem to have same neighbour "
196  << nbrGlobalFacei
197  << " starting walking from edge " << e
198  << exit(FatalError);
199  }
200 
201  if
202  (
203  !sameEdgeNeighbour
204  (
205  pp,
206  globalEdgeFaces,
207  doneEdge,
208  globalFacei,
209  nbrGlobalFacei,
210  fEdges[prevFp]
211  )
212  )
213  {
214  break;
215  }
216  startFp = prevFp;
217  }
218 
219  // Search forward for end of string
220  endFp = startFp;
221  while (true)
222  {
223  label nextFp = fEdges.fcIndex(endFp);
224 
225  if
226  (
227  !sameEdgeNeighbour
228  (
229  pp,
230  globalEdgeFaces,
231  doneEdge,
232  globalFacei,
233  nbrGlobalFacei,
234  fEdges[nextFp]
235  )
236  )
237  {
238  break;
239  }
240  endFp = nextFp;
241  }
242  }
243  }
244 
245  return labelPair(startFp, endFp);
246 }
247 
248 
249 Foam::label Foam::addPatchCellLayer::addSideFace
250 (
251  const indirectPrimitivePatch& pp,
252  const labelListList& addedCells, // per pp face the new extruded cell
253  const face& newFace,
254  const label newPatchID,
255  const label zonei,
256  const bool edgeFlip,
257  const label inflateFacei,
258 
259  const label ownFacei, // pp face that provides owner
260  const label nbrFacei,
261  const label meshEdgei, // corresponding mesh edge
262  const label layeri, // layer
263  const label numEdgeFaces, // number of layers for edge
264  const labelList& meshFaces, // precalculated edgeFaces
265  polyTopoChange& meshMod
266 ) const
267 {
268  // Adds a side face i.e. extrudes a patch edge.
269 
270  label addedFacei = -1;
271 
272 
273  // Is patch edge external edge of indirectPrimitivePatch?
274  if (nbrFacei == -1)
275  {
276  // External edge so external face.
277 
278  // Determine if different number of layer on owner and neighbour side
279  // (relevant only for coupled faces). See section for internal edge
280  // below.
281 
282  label layerOwn;
283 
284  if (addedCells[ownFacei].size() < numEdgeFaces)
285  {
286  label offset = numEdgeFaces - addedCells[ownFacei].size();
287  if (layeri <= offset)
288  {
289  layerOwn = 0;
290  }
291  else
292  {
293  layerOwn = layeri - offset;
294  }
295  }
296  else
297  {
298  layerOwn = layeri;
299  }
300 
301 
302  //Pout<< "Added boundary face:" << newFace
303  // << " own:" << addedCells[ownFacei][layerOwn]
304  // << " patch:" << newPatchID
305  // << endl;
306 
307  addedFacei = meshMod.setAction
308  (
309  polyAddFace
310  (
311  newFace, // face
312  addedCells[ownFacei][layerOwn], // owner
313  -1, // neighbour
314  -1, // master point
315  -1, // master edge
316  inflateFacei, // master face
317  false, // flux flip
318  newPatchID, // patch for face
319  zonei, // zone for face
320  edgeFlip // face zone flip
321  )
322  );
323  }
324  else
325  {
326  // When adding side faces we need to modify neighbour and owners
327  // in region where layer mesh is stopped. Determine which side
328  // has max number of faces and make sure layers match closest to
329  // original pp if there are different number of layers.
330 
331  label layerNbr;
332  label layerOwn;
333 
334  if (addedCells[ownFacei].size() > addedCells[nbrFacei].size())
335  {
336  label offset =
337  addedCells[ownFacei].size() - addedCells[nbrFacei].size();
338 
339  layerOwn = layeri;
340 
341  if (layeri <= offset)
342  {
343  layerNbr = 0;
344  }
345  else
346  {
347  layerNbr = layeri - offset;
348  }
349  }
350  else if (addedCells[nbrFacei].size() > addedCells[ownFacei].size())
351  {
352  label offset =
353  addedCells[nbrFacei].size() - addedCells[ownFacei].size();
354 
355  layerNbr = layeri;
356 
357  if (layeri <= offset)
358  {
359  layerOwn = 0;
360  }
361  else
362  {
363  layerOwn = layeri - offset;
364  }
365  }
366  else
367  {
368  // Same number of layers on both sides.
369  layerNbr = layeri;
370  layerOwn = layeri;
371  }
372 
373 
374  // Check mesh internal faces using edge to initialise
375  label inflateEdgei = -1;
376  if (addToMesh_)
377  {
378  forAll(meshFaces, i)
379  {
380  if (mesh_.isInternalFace(meshFaces[i]))
381  {
382  // meshEdge uses internal faces so ok to inflate from it
383  inflateEdgei = meshEdgei;
384  break;
385  }
386  }
387  }
388 
389 
390  addedFacei = meshMod.setAction
391  (
392  polyAddFace
393  (
394  newFace, // face
395  addedCells[ownFacei][layerOwn], // owner
396  addedCells[nbrFacei][layerNbr], // neighbour
397  -1, // master point
398  inflateEdgei, // master edge
399  -1, // master face
400  false, // flux flip
401  -1, // patch for face
402  zonei, // zone for face
403  edgeFlip // face zone flip
404  )
405  );
406 
407  //Pout<< "Added internal face:" << newFace
408  // << " own:" << addedCells[ownFacei][layerOwn]
409  // << " nei:" << addedCells[nbrFacei][layerNbr]
410  // << endl;
411  }
412 
413  return addedFacei;
414 }
415 
416 
417 Foam::label Foam::addPatchCellLayer::findProcPatch
418 (
419  const polyMesh& mesh,
420  const label nbrProcID
421 )
422 {
423  const polyBoundaryMesh& patches = mesh.boundaryMesh();
424 
426  {
427  label patchi = mesh.globalData().processorPatches()[i];
428 
429  if
430  (
431  refCast<const processorPolyPatch>(patches[patchi]).neighbProcNo()
432  == nbrProcID
433  )
434  {
435  return patchi;
436  }
437  }
438  return -1;
439 }
440 
441 
442 void Foam::addPatchCellLayer::setFaceProps
443 (
444  const polyMesh& mesh,
445  const label facei,
446 
447  label& patchi,
448  label& zonei,
449  bool& zoneFlip
450 )
451 {
452  patchi = mesh.boundaryMesh().whichPatch(facei);
453  zonei = mesh.faceZones().whichZone(facei);
454  if (zonei != -1)
455  {
456  label index = mesh.faceZones()[zonei].whichFace(facei);
457  zoneFlip = mesh.faceZones()[zonei].flipMap()[index];
458  }
459 }
460 
461 
462 void Foam::addPatchCellLayer::setFaceProps
463 (
464  const polyMesh& mesh,
465  const indirectPrimitivePatch& pp,
466  const label ppEdgeI,
467  const label faceI,
468 
469  label& patchI,
470  label& zoneI,
471  bool& zoneFlip,
472  label& inflateFaceI
473 )
474 {
475  setFaceProps
476  (
477  mesh,
478  faceI,
479 
480  patchI,
481  zoneI,
482  zoneFlip
483  );
484 
485  if (patchI != -1 || zoneI != -1)
486  {
487  inflateFaceI = faceI;
488  }
489 
490  if (zoneI != -1)
491  {
492  // Correct flip for patch edge ordering
493  const edge& ppEdge = pp.edges()[ppEdgeI];
494  const edge patchEdge
495  (
496  pp.meshPoints()[ppEdge[0]],
497  pp.meshPoints()[ppEdge[1]]
498  );
499 
500  const face& f = mesh.faces()[faceI];
501  bool found = false;
502  forAll(f, fp)
503  {
504  const edge e(f[fp], f.nextLabel(fp));
505  int stat = edge::compare(e, patchEdge);
506  if (stat == 1)
507  {
508  found = true;
509  break;
510  }
511  else if (stat == -1)
512  {
513  found = true;
514  zoneFlip = !zoneFlip;
515  break;
516  }
517  }
518 
519  if (!found)
520  {
521  //FatalErrorInFunction
523  << "Problem: cannot find patch edge " << ppEdgeI
524  << " with mesh vertices " << patchEdge
525  << " at " << patchEdge.line(mesh.points())
526  << " in face " << faceI << " with mesh vertices "
527  << f
528  << " at " << pointField(mesh.points(), f)
529  << endl
530  << "Continuing with potentially incorrect faceZone orientation"
531  //<< exit(FatalError);
532  << endl;
533  }
534  }
535 }
536 
537 
538 void Foam::addPatchCellLayer::findZoneFace
539 (
540  const bool useInternalFaces,
541  const bool useBoundaryFaces,
542 
543  const polyMesh& mesh,
544  const indirectPrimitivePatch& pp,
545  const label ppEdgeI,
546  const labelUIndList& excludeFaces,
547  const labelList& meshFaces,
548 
549  label& inflateFaceI,
550  label& patchI,
551  label& zoneI,
552  bool& zoneFlip
553 )
554 {
555  inflateFaceI = -1;
556  patchI = -1;
557  zoneI = -1;
558  zoneFlip = false;
559 
560  forAll(meshFaces, k)
561  {
562  label faceI = meshFaces[k];
563 
564  if
565  (
566  !excludeFaces.found(faceI)
567  && (
568  (mesh.isInternalFace(faceI) && useInternalFaces)
569  || (!mesh.isInternalFace(faceI) && useBoundaryFaces)
570  )
571  )
572  {
573  setFaceProps
574  (
575  mesh,
576  pp,
577  ppEdgeI,
578  faceI,
579 
580  patchI,
581  zoneI,
582  zoneFlip,
583  inflateFaceI
584  );
585 
586  if (zoneI != -1 || patchI != -1)
587  {
588  break;
589  }
590  }
591  }
592 }
593 
594 
595 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
596 
597 // Construct from mesh
598 Foam::addPatchCellLayer::addPatchCellLayer
599 (
600  const polyMesh& mesh,
601  const bool addToMesh
602 )
603 :
604  mesh_(mesh),
605  addToMesh_(addToMesh),
606  addedPoints_(0),
607  layerFaces_(0)
608 {}
609 
610 
611 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
612 
614 (
615  const polyMesh& mesh,
616  const labelListList& layerFaces
617 )
618 {
619  labelListList layerCells(layerFaces.size());
620 
621  forAll(layerFaces, patchFacei)
622  {
623  const labelList& faceLabels = layerFaces[patchFacei];
624 
625  if (faceLabels.size())
626  {
627  labelList& added = layerCells[patchFacei];
628  added.setSize(faceLabels.size()-1);
629 
630  for (label i = 0; i < faceLabels.size()-1; i++)
631  {
632  added[i] = mesh.faceNeighbour()[faceLabels[i]];
633  }
634  }
635  }
636  return layerCells;
637 }
638 
639 
641 {
642  return addedCells(mesh_, layerFaces_);
643 }
644 
645 
646 // Calculate global faces per pp edge.
648 (
649  const polyMesh& mesh,
650  const globalIndex& globalFaces,
651  const indirectPrimitivePatch& pp
652 )
653 {
654  // Precalculate mesh edges for pp.edges.
655  const labelList meshEdges(pp.meshEdges(mesh.edges(), mesh.pointEdges()));
656 
657  // From mesh edge to global face labels. Non-empty sublists only for
658  // pp edges.
659  labelListList globalEdgeFaces(mesh.nEdges());
660 
661  const labelListList& edgeFaces = pp.edgeFaces();
662 
663  forAll(edgeFaces, edgeI)
664  {
665  label meshEdgeI = meshEdges[edgeI];
666 
667  const labelList& eFaces = edgeFaces[edgeI];
668 
669  // Store face and processor as unique tag.
670  labelList& globalEFaces = globalEdgeFaces[meshEdgeI];
671  globalEFaces.setSize(eFaces.size());
672  forAll(eFaces, i)
673  {
674  globalEFaces[i] = globalFaces.toGlobal(pp.addressing()[eFaces[i]]);
675  }
676  }
677 
678  // Synchronise across coupled edges.
680  (
681  mesh,
682  globalEdgeFaces,
684  labelList() // null value
685  );
686 
687  // Extract pp part
688  return labelListList(UIndirectList<labelList>(globalEdgeFaces, meshEdges));
689 }
690 
691 
693 (
694  const bool zoneFromAnyFace,
695 
696  const polyMesh& mesh,
697  const globalIndex& globalFaces,
698  const labelListList& globalEdgeFaces,
699  const indirectPrimitivePatch& pp,
700 
701  labelList& edgePatchID,
702  label& nPatches,
703  Map<label>& nbrProcToPatch,
704  Map<label>& patchToNbrProc,
705  labelList& edgeZoneID,
706  boolList& edgeFlip,
707  labelList& inflateFaceID
708 )
709 {
711  const globalMeshData& gd = mesh.globalData();
712 
713  // Precalculate mesh edges for pp.edges.
714  const labelList meshEdges(pp.meshEdges(mesh.edges(), mesh.pointEdges()));
715 
716  edgePatchID.setSize(pp.nEdges());
717  edgePatchID = -1;
718  edgeZoneID.setSize(pp.nEdges());
719  edgeZoneID = -1;
720  edgeFlip.setSize(pp.nEdges());
721  edgeFlip = false;
722 
723 
724  // Determine properties for faces extruded from edges
725  // - edge inbetween two different processors:
726  // - extrude as patch face on correct processor
727  // - edge at end of patch (so edgeFaces.size() == 1):
728  // - use mesh face that is a boundary face
729  // - edge internal to patch (so edgeFaces.size() == 2):
730 
731 
732 
733  // These also get determined but not (yet) exported:
734  // - whether face is created from other face or edge
735 
736  inflateFaceID.setSize(pp.nEdges(), -1);
737 
738  nPatches = patches.size();
739 
740 
741 
742  // Pass1:
743  // For all edges inbetween two processors: see if matches to existing
744  // processor patch or create interprocessor-patch if necessary.
745  // Sets edgePatchID[edgeI] but none of the other quantities
746 
747  forAll(globalEdgeFaces, edgei)
748  {
749  const labelList& eGlobalFaces = globalEdgeFaces[edgei];
750  if
751  (
752  eGlobalFaces.size() == 2
753  && pp.edgeFaces()[edgei].size() == 1
754  )
755  {
756  // Locally but not globally a boundary edge. Hence a coupled
757  // edge. Find the patch to use if on different processors.
758 
759  label f0 = eGlobalFaces[0];
760  label f1 = eGlobalFaces[1];
761 
762  label otherProci = -1;
763  if (globalFaces.isLocal(f0) && !globalFaces.isLocal(f1))
764  {
765  otherProci = globalFaces.whichProcID(f1);
766  }
767  else if (!globalFaces.isLocal(f0) && globalFaces.isLocal(f1))
768  {
769  otherProci = globalFaces.whichProcID(f0);
770  }
771 
772 
773  if (otherProci != -1)
774  {
775  if (gd[Pstream::myProcNo()].found(otherProci))
776  {
777  // There is already a processorPolyPatch to otherProci.
778  // Use it. Note that we can only index procPatchMap
779  // if the processor actually is a neighbour processor
780  // so that is why we first check.
781  edgePatchID[edgei] = gd.procPatchMap()[otherProci];
782  }
783  else
784  {
785  // Cannot find a patch to processor. See if already
786  // marked for addition
787  if (nbrProcToPatch.found(otherProci))
788  {
789  edgePatchID[edgei] = nbrProcToPatch[otherProci];
790  }
791  else
792  {
793  edgePatchID[edgei] = nPatches;
794  nbrProcToPatch.insert(otherProci, nPatches);
795  patchToNbrProc.insert(nPatches, otherProci);
796  nPatches++;
797  }
798  }
799  }
800  }
801  }
802 
803 
804  // Pass2: determine face properties for all other edges
805  // ----------------------------------------------------
806 
807  const labelListList& edgeFaces = pp.edgeFaces();
808 
809  DynamicList<label> dynMeshEdgeFaces;
810 
811  forAll(edgeFaces, edgei)
812  {
813  if (edgePatchID[edgei] == -1)
814  {
815  labelUIndList ppFaces(pp.addressing(), edgeFaces[edgei]);
816 
817  label meshEdgei = meshEdges[edgei];
818  const labelList& meshFaces = mesh.edgeFaces
819  (
820  meshEdgei,
821  dynMeshEdgeFaces
822  );
823 
824  if (edgeFaces[edgei].size() == 2)
825  {
826  // Internal edge. Look at any face (internal or boundary) to
827  // determine extrusion properties. First one that has zone
828  // info wins
829 
830  label dummyPatchi = -1;
831  findZoneFace
832  (
833  true, // useInternalFaces,
834  zoneFromAnyFace, // useBoundaryFaces,
835 
836  mesh,
837  pp,
838  edgei,
839 
840 
841  ppFaces, // excludeFaces,
842  meshFaces, // meshFaces,
843 
844  inflateFaceID[edgei],
845  dummyPatchi, // do not use patch info
846  edgeZoneID[edgei],
847  edgeFlip[edgei]
848  );
849  }
850  else
851  {
852  // Proper, uncoupled patch edge
853 
854  findZoneFace
855  (
856  false, // useInternalFaces,
857  true, // useBoundaryFaces,
858 
859  mesh,
860  pp,
861  edgei,
862 
863 
864  ppFaces, // excludeFaces,
865  meshFaces, // meshFaces,
866 
867  inflateFaceID[edgei],
868  edgePatchID[edgei],
869  edgeZoneID[edgei],
870  edgeFlip[edgei]
871  );
872  }
873  }
874  }
875 
876 
877 
878  // Now hopefully every boundary edge has a edge patch. Check
879  if (debug)
880  {
881  forAll(edgeFaces, edgei)
882  {
883  if (edgeFaces[edgei].size() == 1 && edgePatchID[edgei] == -1)
884  {
885  const edge& e = pp.edges()[edgei];
887  << "Have no sidePatchID for edge " << edgei << " points "
888  << pp.points()[pp.meshPoints()[e[0]]]
889  << pp.points()[pp.meshPoints()[e[1]]]
890  << endl;
891  }
892  }
893  }
894 
895 
896 
897  // Pass3: for any faces set in pass1 see if we can find a processor face
898  // to inherit from (we only have a patch, not a patch face)
899  forAll(edgeFaces, edgei)
900  {
901  if
902  (
903  edgeFaces[edgei].size() == 1
904  && edgePatchID[edgei] != -1
905  && inflateFaceID[edgei] == -1
906  )
907  {
908  // 1. Do we have a boundary face to inflate from
909 
910  label myFaceI = pp.addressing()[edgeFaces[edgei][0]];
911 
912  // Pick up any boundary face on this edge and use its properties
913  label meshEdgei = meshEdges[edgei];
914  const labelList& meshFaces = mesh.edgeFaces
915  (
916  meshEdgei,
917  dynMeshEdgeFaces
918  );
919 
920  forAll(meshFaces, k)
921  {
922  label facei = meshFaces[k];
923 
924  if (facei != myFaceI && !mesh.isInternalFace(facei))
925  {
926  if (patches.whichPatch(facei) == edgePatchID[edgei])
927  {
928  setFaceProps
929  (
930  mesh,
931  pp,
932  edgei,
933  facei,
934 
935  edgePatchID[edgei],
936  edgeZoneID[edgei],
937  edgeFlip[edgei],
938  inflateFaceID[edgei]
939  );
940  break;
941  }
942  }
943  }
944  }
945  }
946 
947 
948 
949  // Sync all data:
950  // - edgePatchID : might be local in case of processor patch. Do not
951  // sync for now
952  // - inflateFaceID: local. Do not sync
953  // - edgeZoneID : global. sync.
954  // - edgeFlip : global. sync.
955 
956  if (Pstream::parRun())
957  {
958  const globalMeshData& gd = mesh.globalData();
959  const indirectPrimitivePatch& cpp = gd.coupledPatch();
960 
961  labelList patchEdges;
962  labelList coupledEdges;
963  bitSet sameEdgeOrientation;
965  (
966  pp,
967  cpp,
968  patchEdges,
969  coupledEdges,
970  sameEdgeOrientation
971  );
972 
973  // Convert data on pp edges to data on coupled patch
974  labelList cppEdgeZoneID(cpp.nEdges(), -1);
975  boolList cppEdgeFlip(cpp.nEdges(), false);
976  forAll(coupledEdges, i)
977  {
978  label cppEdgei = coupledEdges[i];
979  label ppEdgei = patchEdges[i];
980 
981  cppEdgeZoneID[cppEdgei] = edgeZoneID[ppEdgei];
982  if (sameEdgeOrientation[i])
983  {
984  cppEdgeFlip[cppEdgei] = edgeFlip[ppEdgei];
985  }
986  else
987  {
988  cppEdgeFlip[cppEdgei] = !edgeFlip[ppEdgei];
989  }
990  }
991 
992  // Sync
993  const globalIndexAndTransform& git = gd.globalTransforms();
994  const mapDistribute& edgeMap = gd.globalEdgeSlavesMap();
995 
997  (
998  cppEdgeZoneID,
999  gd.globalEdgeSlaves(),
1001  edgeMap,
1002  git,
1003  maxEqOp<label>(),
1004  dummyTransform()
1005  );
1007  (
1008  cppEdgeFlip,
1009  gd.globalEdgeSlaves(),
1011  edgeMap,
1012  git,
1013  andEqOp<bool>(),
1014  dummyTransform()
1015  );
1016 
1017  // Convert data on coupled edges to pp edges
1018  forAll(coupledEdges, i)
1019  {
1020  label cppEdgei = coupledEdges[i];
1021  label ppEdgei = patchEdges[i];
1022 
1023  edgeZoneID[ppEdgei] = cppEdgeZoneID[cppEdgei];
1024  if (sameEdgeOrientation[i])
1025  {
1026  edgeFlip[ppEdgei] = cppEdgeFlip[cppEdgei];
1027  }
1028  else
1029  {
1030  edgeFlip[ppEdgei] = !cppEdgeFlip[cppEdgei];
1031  }
1032  }
1033  }
1034 }
1035 
1036 
1039  const globalIndex& globalFaces,
1040  const labelListList& globalEdgeFaces,
1041  const scalarField& expansionRatio,
1042  const indirectPrimitivePatch& pp,
1043 
1044  const labelList& edgePatchID,
1045  const labelList& edgeZoneID,
1046  const boolList& edgeFlip,
1047  const labelList& inflateFaceID,
1048 
1049  const labelList& exposedPatchID,
1050  const labelList& nFaceLayers,
1051  const labelList& nPointLayers,
1052  const vectorField& firstLayerDisp,
1053  polyTopoChange& meshMod
1054 )
1055 {
1056  if (debug)
1057  {
1058  Pout<< "addPatchCellLayer::setRefinement : Adding up to "
1059  << gMax(nPointLayers)
1060  << " layers of cells to indirectPrimitivePatch with "
1061  << pp.nPoints() << " points" << endl;
1062  }
1063 
1064  if
1065  (
1066  pp.nPoints() != firstLayerDisp.size()
1067  || pp.nPoints() != nPointLayers.size()
1068  || pp.size() != nFaceLayers.size()
1069  )
1070  {
1072  << "Size of new points is not same as number of points used by"
1073  << " the face subset" << endl
1074  << " patch.nPoints:" << pp.nPoints()
1075  << " displacement:" << firstLayerDisp.size()
1076  << " nPointLayers:" << nPointLayers.size() << nl
1077  << " patch.nFaces:" << pp.size()
1078  << " nFaceLayers:" << nFaceLayers.size()
1079  << abort(FatalError);
1080  }
1081 
1082  forAll(nPointLayers, i)
1083  {
1084  if (nPointLayers[i] < 0)
1085  {
1087  << "Illegal number of layers " << nPointLayers[i]
1088  << " at patch point " << i << abort(FatalError);
1089  }
1090  }
1091  forAll(nFaceLayers, i)
1092  {
1093  if (nFaceLayers[i] < 0)
1094  {
1096  << "Illegal number of layers " << nFaceLayers[i]
1097  << " at patch face " << i << abort(FatalError);
1098  }
1099  }
1100 
1101  forAll(globalEdgeFaces, edgei)
1102  {
1103  if (globalEdgeFaces[edgei].size() > 2)
1104  {
1105  const edge& e = pp.edges()[edgei];
1106 
1107  if (nPointLayers[e[0]] > 0 || nPointLayers[e[1]] > 0)
1108  {
1110  << "Trying to extrude edge "
1111  << e.line(pp.localPoints())
1112  << " which is non-manifold (has "
1113  << globalEdgeFaces[edgei].size()
1114  << " local or coupled faces using it)"
1115  << " of which "
1116  << pp.edgeFaces()[edgei].size()
1117  << " local"
1118  << abort(FatalError);
1119  }
1120  }
1121  }
1122 
1123 
1124  const labelList& meshPoints = pp.meshPoints();
1125 
1126  // Some storage for edge-face-addressing.
1127  DynamicList<label> ef;
1128 
1129  // Precalculate mesh edges for pp.edges.
1130  const labelList meshEdges(pp.meshEdges(mesh_.edges(), mesh_.pointEdges()));
1131 
1132  if (debug)
1133  {
1134  // Check synchronisation
1135  // ~~~~~~~~~~~~~~~~~~~~~
1136 
1137  {
1138  labelList n(mesh_.nPoints(), Zero);
1139  labelUIndList(n, meshPoints) = nPointLayers;
1141 
1142  // Non-synced
1143  forAll(meshPoints, i)
1144  {
1145  label meshPointi = meshPoints[i];
1146 
1147  if (n[meshPointi] != nPointLayers[i])
1148  {
1150  << "At mesh point:" << meshPointi
1151  << " coordinate:" << mesh_.points()[meshPointi]
1152  << " specified nLayers:" << nPointLayers[i] << endl
1153  << "On coupled point a different nLayers:"
1154  << n[meshPointi] << " was specified."
1155  << abort(FatalError);
1156  }
1157  }
1158 
1159 
1160  // Check that nPointLayers equals the max layers of connected faces
1161  // (or 0). Anything else makes no sense.
1162  labelList nFromFace(mesh_.nPoints(), Zero);
1163  forAll(nFaceLayers, i)
1164  {
1165  const face& f = pp[i];
1166 
1167  forAll(f, fp)
1168  {
1169  label pointi = f[fp];
1170 
1171  nFromFace[pointi] = max(nFromFace[pointi], nFaceLayers[i]);
1172  }
1173  }
1175  (
1176  mesh_,
1177  nFromFace,
1178  maxEqOp<label>(),
1179  label(0)
1180  );
1181 
1182  forAll(nPointLayers, i)
1183  {
1184  label meshPointi = meshPoints[i];
1185 
1186  if
1187  (
1188  nPointLayers[i] > 0
1189  && nPointLayers[i] != nFromFace[meshPointi]
1190  )
1191  {
1193  << "At mesh point:" << meshPointi
1194  << " coordinate:" << mesh_.points()[meshPointi]
1195  << " specified nLayers:" << nPointLayers[i] << endl
1196  << "but the max nLayers of surrounding faces is:"
1197  << nFromFace[meshPointi]
1198  << abort(FatalError);
1199  }
1200  }
1201  }
1202 
1203  {
1204  pointField d(mesh_.nPoints(), vector::max);
1205  UIndirectList<point>(d, meshPoints) = firstLayerDisp;
1207  (
1208  mesh_,
1209  d,
1210  minEqOp<vector>(),
1211  vector::max
1212  );
1213 
1214  forAll(meshPoints, i)
1215  {
1216  label meshPointi = meshPoints[i];
1217 
1218  if (mag(d[meshPointi] - firstLayerDisp[i]) > SMALL)
1219  {
1221  << "At mesh point:" << meshPointi
1222  << " coordinate:" << mesh_.points()[meshPointi]
1223  << " specified displacement:" << firstLayerDisp[i]
1224  << endl
1225  << "On coupled point a different displacement:"
1226  << d[meshPointi] << " was specified."
1227  << abort(FatalError);
1228  }
1229  }
1230  }
1231 
1232  // Check that edges of pp (so ones that become boundary faces)
1233  // connect to only one boundary face. Guarantees uniqueness of
1234  // patch that they go into so if this is a coupled patch both
1235  // sides decide the same.
1236  // ~~~~~~~~~~~~~~~~~~~~~~
1237 
1238  for (label edgei = pp.nInternalEdges(); edgei < pp.nEdges(); edgei++)
1239  {
1240  const edge& e = pp.edges()[edgei];
1241 
1242  if (nPointLayers[e[0]] > 0 || nPointLayers[e[1]] > 0)
1243  {
1244  // Edge is to become a face
1245 
1246  const labelList& eFaces = pp.edgeFaces()[edgei];
1247 
1248  // First check: pp should be single connected.
1249  if (eFaces.size() != 1)
1250  {
1252  << "boundary-edge-to-be-extruded:"
1253  << pp.points()[meshPoints[e[0]]]
1254  << pp.points()[meshPoints[e[1]]]
1255  << " has more than two faces using it:" << eFaces
1256  << abort(FatalError);
1257  }
1258 
1259  label myFacei = pp.addressing()[eFaces[0]];
1260 
1261  label meshEdgei = meshEdges[edgei];
1262 
1263  // Mesh faces using edge
1264  const labelList& meshFaces = mesh_.edgeFaces(meshEdgei, ef);
1265 
1266  // Check that there is only one patchface using edge.
1267  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
1268 
1269  label bFacei = -1;
1270 
1271  forAll(meshFaces, i)
1272  {
1273  label facei = meshFaces[i];
1274 
1275  if (facei != myFacei)
1276  {
1277  if (!mesh_.isInternalFace(facei))
1278  {
1279  if (bFacei == -1)
1280  {
1281  bFacei = facei;
1282  }
1283  else
1284  {
1286  << "boundary-edge-to-be-extruded:"
1287  << pp.points()[meshPoints[e[0]]]
1288  << pp.points()[meshPoints[e[1]]]
1289  << " has more than two boundary faces"
1290  << " using it:"
1291  << bFacei << " fc:"
1292  << mesh_.faceCentres()[bFacei]
1293  << " patch:" << patches.whichPatch(bFacei)
1294  << " and " << facei << " fc:"
1295  << mesh_.faceCentres()[facei]
1296  << " patch:" << patches.whichPatch(facei)
1297  << abort(FatalError);
1298  }
1299  }
1300  }
1301  }
1302  }
1303  }
1304  }
1305 
1306 
1307  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
1308 
1309  // Precalculated patchID for each patch face
1310  labelList patchID(pp.size());
1311 
1312  forAll(pp, patchFacei)
1313  {
1314  label meshFacei = pp.addressing()[patchFacei];
1315 
1316  patchID[patchFacei] = patches.whichPatch(meshFacei);
1317  }
1318 
1319 
1320  // From master point (in patch point label) to added points (in mesh point
1321  // label)
1322  addedPoints_.setSize(pp.nPoints());
1323 
1324  // Mark points that do not get extruded by setting size of addedPoints_ to 0
1325  label nTruncated = 0;
1326 
1327  forAll(nPointLayers, patchPointi)
1328  {
1329  if (nPointLayers[patchPointi] > 0)
1330  {
1331  addedPoints_[patchPointi].setSize(nPointLayers[patchPointi]);
1332  }
1333  else
1334  {
1335  nTruncated++;
1336  }
1337  }
1338 
1339  if (debug)
1340  {
1341  Pout<< "Not adding points at " << nTruncated << " out of "
1342  << pp.nPoints() << " points" << endl;
1343  }
1344 
1345 
1346  //
1347  // Create new points
1348  //
1349 
1350  // If creating new mesh: copy existing patch points
1351  labelList copiedPatchPoints;
1352  if (!addToMesh_)
1353  {
1354  copiedPatchPoints.setSize(firstLayerDisp.size());
1355  forAll(firstLayerDisp, patchPointi)
1356  {
1357  if (addedPoints_[patchPointi].size())
1358  {
1359  label meshPointi = meshPoints[patchPointi];
1360  label zoneI = mesh_.pointZones().whichZone(meshPointi);
1361  copiedPatchPoints[patchPointi] = meshMod.setAction
1362  (
1363  polyAddPoint
1364  (
1365  mesh_.points()[meshPointi], // point
1366  -1, // master point
1367  zoneI, // zone for point
1368  true // supports a cell
1369  )
1370  );
1371  }
1372  }
1373  }
1374 
1375 
1376  // Create points for additional layers
1377  forAll(firstLayerDisp, patchPointi)
1378  {
1379  if (addedPoints_[patchPointi].size())
1380  {
1381  label meshPointi = meshPoints[patchPointi];
1382 
1383  label zoneI = mesh_.pointZones().whichZone(meshPointi);
1384 
1385  point pt = mesh_.points()[meshPointi];
1386 
1387  vector disp = firstLayerDisp[patchPointi];
1388 
1389  forAll(addedPoints_[patchPointi], i)
1390  {
1391  pt += disp;
1392 
1393  label addedVertI = meshMod.setAction
1394  (
1395  polyAddPoint
1396  (
1397  pt, // point
1398  (addToMesh_ ? meshPointi : -1), // master point
1399  zoneI, // zone for point
1400  true // supports a cell
1401  )
1402  );
1403 
1404  addedPoints_[patchPointi][i] = addedVertI;
1405 
1406  disp *= expansionRatio[patchPointi];
1407  }
1408  }
1409  }
1410 
1411 
1412  //
1413  // Add cells to all boundaryFaces
1414  //
1415 
1416  labelListList addedCells(pp.size());
1417 
1418  forAll(pp, patchFacei)
1419  {
1420  if (nFaceLayers[patchFacei] > 0)
1421  {
1422  addedCells[patchFacei].setSize(nFaceLayers[patchFacei]);
1423 
1424  label meshFacei = pp.addressing()[patchFacei];
1425 
1426  label ownZoneI = mesh_.cellZones().whichZone
1427  (
1428  mesh_.faceOwner()[meshFacei]
1429  );
1430 
1431  for (label i = 0; i < nFaceLayers[patchFacei]; i++)
1432  {
1433  // Note: add from cell (owner of patch face) or from face?
1434  // for now add from cell so we can map easily.
1435  addedCells[patchFacei][i] = meshMod.setAction
1436  (
1437  polyAddCell
1438  (
1439  -1, // master point
1440  -1, // master edge
1441  -1, // master face
1442  (addToMesh_ ? mesh_.faceOwner()[meshFacei] : -1),
1443  //master
1444  ownZoneI // zone for cell
1445  )
1446  );
1447  }
1448  }
1449  }
1450 
1451 
1452 
1453  // Create faces on top of the original patch faces.
1454  // These faces are created from original patch faces outwards so in order
1455  // of increasing cell number. So orientation should be same as original
1456  // patch face for them to have owner<neighbour.
1457 
1458  layerFaces_.setSize(pp.size());
1459 
1460  forAll(pp.localFaces(), patchFacei)
1461  {
1462  label meshFacei = pp.addressing()[patchFacei];
1463 
1464  if (addedCells[patchFacei].size())
1465  {
1466  layerFaces_[patchFacei].setSize(addedCells[patchFacei].size() + 1);
1467 
1468  // Get duplicated vertices on the patch face.
1469  const face& f = pp.localFaces()[patchFacei];
1470 
1471  face newFace(f.size());
1472 
1473  forAll(addedCells[patchFacei], i)
1474  {
1475  forAll(f, fp)
1476  {
1477  if (addedPoints_[f[fp]].empty())
1478  {
1479  // Keep original point
1480  newFace[fp] =
1481  (
1482  addToMesh_
1483  ? meshPoints[f[fp]]
1484  : copiedPatchPoints[f[fp]]
1485  );
1486  }
1487  else
1488  {
1489  // Get new outside point
1490  label offset =
1491  addedPoints_[f[fp]].size()
1492  - addedCells[patchFacei].size();
1493  newFace[fp] = addedPoints_[f[fp]][i+offset];
1494  }
1495  }
1496 
1497 
1498  // Get new neighbour
1499  label nei;
1500  label patchi;
1501  label zoneI = -1;
1502  bool flip = false;
1503 
1504 
1505  if (i == addedCells[patchFacei].size()-1)
1506  {
1507  // Top layer so is patch face.
1508  nei = -1;
1509  patchi = patchID[patchFacei];
1510  zoneI = mesh_.faceZones().whichZone(meshFacei);
1511  if (zoneI != -1)
1512  {
1513  const faceZone& fz = mesh_.faceZones()[zoneI];
1514  flip = fz.flipMap()[fz.whichFace(meshFacei)];
1515  }
1516  }
1517  else
1518  {
1519  // Internal face between layer i and i+1
1520  nei = addedCells[patchFacei][i+1];
1521  patchi = -1;
1522  }
1523 
1524 
1525  layerFaces_[patchFacei][i+1] = meshMod.setAction
1526  (
1527  polyAddFace
1528  (
1529  newFace, // face
1530  addedCells[patchFacei][i], // owner
1531  nei, // neighbour
1532  -1, // master point
1533  -1, // master edge
1534  (addToMesh_ ? meshFacei : -1), // master face
1535  false, // flux flip
1536  patchi, // patch for face
1537  zoneI, // zone for face
1538  flip // face zone flip
1539  )
1540  );
1541  }
1542  }
1543  }
1544 
1545  //
1546  // Modify old patch faces to be on the inside
1547  //
1548 
1549  if (addToMesh_)
1550  {
1551  forAll(pp, patchFacei)
1552  {
1553  if (addedCells[patchFacei].size())
1554  {
1555  label meshFacei = pp.addressing()[patchFacei];
1556 
1557  layerFaces_[patchFacei][0] = meshFacei;
1558 
1559  meshMod.setAction
1560  (
1562  (
1563  pp[patchFacei], // modified face
1564  meshFacei, // label of face
1565  mesh_.faceOwner()[meshFacei], // owner
1566  addedCells[patchFacei][0], // neighbour
1567  false, // face flip
1568  -1, // patch for face
1569  true, //false, // remove from zone
1570  -1, //zoneI, // zone for face
1571  false // face flip in zone
1572  )
1573  );
1574  }
1575  }
1576  }
1577  else
1578  {
1579  // If creating new mesh: reverse original faces and put them
1580  // in the exposed patch ID.
1581  forAll(pp, patchFacei)
1582  {
1583  if (nFaceLayers[patchFacei] > 0)
1584  {
1585  label meshFacei = pp.addressing()[patchFacei];
1586  label zoneI = mesh_.faceZones().whichZone(meshFacei);
1587  bool zoneFlip = false;
1588  if (zoneI != -1)
1589  {
1590  const faceZone& fz = mesh_.faceZones()[zoneI];
1591  zoneFlip = !fz.flipMap()[fz.whichFace(meshFacei)];
1592  }
1593 
1594  // Reverse and renumber old patch face.
1595  face f(pp.localFaces()[patchFacei].reverseFace());
1596  forAll(f, fp)
1597  {
1598  f[fp] = copiedPatchPoints[f[fp]];
1599  }
1600 
1601  layerFaces_[patchFacei][0] = meshMod.setAction
1602  (
1603  polyAddFace
1604  (
1605  f, // modified face
1606  addedCells[patchFacei][0], // owner
1607  -1, // neighbour
1608  -1, // masterPoint
1609  -1, // masterEdge
1610  -1, // masterFace
1611  true, // face flip
1612  exposedPatchID[patchFacei], // patch for face
1613  zoneI, // zone for face
1614  zoneFlip // face flip in zone
1615  )
1616  );
1617  }
1618  }
1619  }
1620 
1621 
1622 
1623  //
1624  // Create 'side' faces, one per edge that is being extended.
1625  //
1626 
1627  const labelListList& faceEdges = pp.faceEdges();
1628  const faceList& localFaces = pp.localFaces();
1629  const edgeList& edges = pp.edges();
1630 
1631  // Get number of layers per edge. This is 0 if edge is not extruded;
1632  // max of connected faces otherwise.
1633  labelList edgeLayers(pp.nEdges());
1634 
1635  {
1636  // Use list over mesh.nEdges() since syncTools does not yet support
1637  // partial list synchronisation.
1638  labelList meshEdgeLayers(mesh_.nEdges(), -1);
1639 
1640  forAll(meshEdges, edgei)
1641  {
1642  const edge& e = edges[edgei];
1643 
1644  label meshEdgei = meshEdges[edgei];
1645 
1646  if ((nPointLayers[e[0]] == 0) && (nPointLayers[e[1]] == 0))
1647  {
1648  meshEdgeLayers[meshEdgei] = 0;
1649  }
1650  else
1651  {
1652  const labelList& eFaces = pp.edgeFaces()[edgei];
1653 
1654  forAll(eFaces, i)
1655  {
1656  meshEdgeLayers[meshEdgei] = max
1657  (
1658  nFaceLayers[eFaces[i]],
1659  meshEdgeLayers[meshEdgei]
1660  );
1661  }
1662  }
1663  }
1664 
1666  (
1667  mesh_,
1668  meshEdgeLayers,
1669  maxEqOp<label>(),
1670  label(0) // initial value
1671  );
1672 
1673  forAll(meshEdges, edgei)
1674  {
1675  edgeLayers[edgei] = meshEdgeLayers[meshEdges[edgei]];
1676  }
1677  }
1678 
1679 
1680  // Mark off which edges have been extruded
1681  boolList doneEdge(pp.nEdges(), false);
1682 
1683 
1684  // Create faces. Per face walk connected edges and find string of edges
1685  // between the same two faces and extrude string into a single face.
1686  forAll(pp, patchFacei)
1687  {
1688  const labelList& fEdges = faceEdges[patchFacei];
1689 
1690  forAll(fEdges, fp)
1691  {
1692  // Get string of edges that needs to be extruded as a single face.
1693  // Returned as indices in fEdges.
1694  labelPair indexPair
1695  (
1696  getEdgeString
1697  (
1698  pp,
1699  globalEdgeFaces,
1700  doneEdge,
1701  patchFacei,
1702  globalFaces.toGlobal(pp.addressing()[patchFacei])
1703  )
1704  );
1705 
1706  //Pout<< "Found unextruded edges in edges:" << fEdges
1707  // << " start:" << indexPair[0]
1708  // << " end:" << indexPair[1]
1709  // << endl;
1710 
1711  const label startFp = indexPair[0];
1712  const label endFp = indexPair[1];
1713 
1714  if (startFp != -1)
1715  {
1716  // Extrude edges from indexPair[0] up to indexPair[1]
1717  // (note indexPair = indices of edges. There is one more vertex
1718  // than edges)
1719  const face& f = localFaces[patchFacei];
1720 
1721  labelList stringedVerts;
1722  if (endFp >= startFp)
1723  {
1724  stringedVerts.setSize(endFp-startFp+2);
1725  }
1726  else
1727  {
1728  stringedVerts.setSize(endFp+f.size()-startFp+2);
1729  }
1730 
1731  label fp = startFp;
1732 
1733  for (label i = 0; i < stringedVerts.size()-1; i++)
1734  {
1735  stringedVerts[i] = f[fp];
1736  doneEdge[fEdges[fp]] = true;
1737  fp = f.fcIndex(fp);
1738  }
1739  stringedVerts.last() = f[fp];
1740 
1741 
1742  // Now stringedVerts contains the vertices in order of face f.
1743  // This is consistent with the order if f becomes the owner cell
1744  // and nbrFacei the neighbour cell. Note that the cells get
1745  // added in order of pp so we can just use face ordering and
1746  // because we loop in incrementing order as well we will
1747  // always have nbrFacei > patchFacei.
1748 
1749  label startEdgei = fEdges[startFp];
1750 
1751  label meshEdgei = meshEdges[startEdgei];
1752 
1753  label numEdgeSideFaces = edgeLayers[startEdgei];
1754 
1755  for (label i = 0; i < numEdgeSideFaces; i++)
1756  {
1757  label vEnd = stringedVerts.last();
1758  label vStart = stringedVerts[0];
1759 
1760  // calculate number of points making up a face
1761  label newFp = 2*stringedVerts.size();
1762 
1763  if (i == 0)
1764  {
1765  // layer 0 gets all the truncation of neighbouring
1766  // faces with more layers.
1767  if (addedPoints_[vEnd].size())
1768  {
1769  newFp +=
1770  addedPoints_[vEnd].size() - numEdgeSideFaces;
1771  }
1772  if (addedPoints_[vStart].size())
1773  {
1774  newFp +=
1775  addedPoints_[vStart].size() - numEdgeSideFaces;
1776  }
1777  }
1778 
1779  face newFace(newFp);
1780 
1781  newFp = 0;
1782 
1783  // For layer 0 get pp points, for all other layers get
1784  // points of layer-1.
1785  if (i == 0)
1786  {
1787  forAll(stringedVerts, stringedI)
1788  {
1789  label v = stringedVerts[stringedI];
1790  addVertex
1791  (
1792  (
1793  addToMesh_
1794  ? meshPoints[v]
1795  : copiedPatchPoints[v]
1796  ),
1797  newFace,
1798  newFp
1799  );
1800  }
1801  }
1802  else
1803  {
1804  forAll(stringedVerts, stringedI)
1805  {
1806  label v = stringedVerts[stringedI];
1807  if (addedPoints_[v].size())
1808  {
1809  label offset =
1810  addedPoints_[v].size() - numEdgeSideFaces;
1811  addVertex
1812  (
1813  addedPoints_[v][i+offset-1],
1814  newFace,
1815  newFp
1816  );
1817  }
1818  else
1819  {
1820  addVertex
1821  (
1822  (
1823  addToMesh_
1824  ? meshPoints[v]
1825  : copiedPatchPoints[v]
1826  ),
1827  newFace,
1828  newFp
1829  );
1830  }
1831  }
1832  }
1833 
1834  // add points between stringed vertices (end)
1835  if (numEdgeSideFaces < addedPoints_[vEnd].size())
1836  {
1837  if (i == 0 && addedPoints_[vEnd].size())
1838  {
1839  label offset =
1840  addedPoints_[vEnd].size() - numEdgeSideFaces;
1841  for (label ioff = 0; ioff < offset; ioff++)
1842  {
1843  addVertex
1844  (
1845  addedPoints_[vEnd][ioff],
1846  newFace,
1847  newFp
1848  );
1849  }
1850  }
1851  }
1852 
1853  forAllReverse(stringedVerts, stringedI)
1854  {
1855  label v = stringedVerts[stringedI];
1856  if (addedPoints_[v].size())
1857  {
1858  label offset =
1859  addedPoints_[v].size() - numEdgeSideFaces;
1860  addVertex
1861  (
1862  addedPoints_[v][i+offset],
1863  newFace,
1864  newFp
1865  );
1866  }
1867  else
1868  {
1869  addVertex
1870  (
1871  (
1872  addToMesh_
1873  ? meshPoints[v]
1874  : copiedPatchPoints[v]
1875  ),
1876  newFace,
1877  newFp
1878  );
1879  }
1880  }
1881 
1882 
1883  // add points between stringed vertices (start)
1884  if (numEdgeSideFaces < addedPoints_[vStart].size())
1885  {
1886  if (i == 0 && addedPoints_[vStart].size())
1887  {
1888  label offset =
1889  addedPoints_[vStart].size() - numEdgeSideFaces;
1890  for (label ioff = offset-1; ioff >= 0; ioff--)
1891  {
1892  addVertex
1893  (
1894  addedPoints_[vStart][ioff],
1895  newFace,
1896  newFp
1897  );
1898  }
1899  }
1900  }
1901 
1902  if (newFp >= 3)
1903  {
1904  // Add face inbetween faces patchFacei and nbrFacei
1905  // (possibly -1 for external edges)
1906 
1907  newFace.setSize(newFp);
1908 
1909  if (debug)
1910  {
1911  labelHashSet verts(2*newFace.size());
1912  forAll(newFace, fp)
1913  {
1914  if (!verts.insert(newFace[fp]))
1915  {
1917  << "Duplicate vertex in face"
1918  << " to be added." << nl
1919  << "newFace:" << newFace << nl
1920  << "points:"
1922  (
1923  meshMod.points(),
1924  newFace
1925  ) << nl
1926  << "Layer:" << i
1927  << " out of:" << numEdgeSideFaces << nl
1928  << "ExtrudeEdge:" << meshEdgei
1929  << " at:"
1930  << mesh_.edges()[meshEdgei].line
1931  (
1932  mesh_.points()
1933  ) << nl
1934  << "string:" << stringedVerts
1935  << "stringpoints:"
1937  (
1938  pp.localPoints(),
1939  stringedVerts
1940  ) << nl
1941  << "stringNLayers:"
1942  << labelUIndList
1943  (
1944  nPointLayers,
1945  stringedVerts
1946  ) << nl
1947  << abort(FatalError);
1948  }
1949  }
1950  }
1951 
1952  label nbrFacei = nbrFace
1953  (
1954  pp.edgeFaces(),
1955  startEdgei,
1956  patchFacei
1957  );
1958 
1959  const labelList& meshFaces = mesh_.edgeFaces
1960  (
1961  meshEdgei,
1962  ef
1963  );
1964 
1965  // Because we walk in order of patch face and in order
1966  // of face edges so face orientation will be opposite
1967  // that of the patch edge
1968  bool zoneFlip = false;
1969  if (edgeZoneID[startEdgei] != -1)
1970  {
1971  zoneFlip = !edgeFlip[startEdgei];
1972  }
1973 
1974  addSideFace
1975  (
1976  pp,
1977  addedCells,
1978 
1979  newFace, // vertices of new face
1980  edgePatchID[startEdgei],// -1 or patch for face
1981  edgeZoneID[startEdgei],
1982  zoneFlip,
1983  inflateFaceID[startEdgei],
1984 
1985  patchFacei,
1986  nbrFacei,
1987  meshEdgei, // (mesh) edge to inflate
1988  i, // layer
1989  numEdgeSideFaces, // num layers
1990  meshFaces, // edgeFaces
1991  meshMod
1992  );
1993  }
1994  }
1995  }
1996  }
1997  }
1998 }
1999 
2000 
2003  const mapPolyMesh& morphMap,
2004  const labelList& faceMap, // new to old patch faces
2005  const labelList& pointMap // new to old patch points
2006 )
2007 {
2008  {
2009  labelListList newAddedPoints(pointMap.size());
2010 
2011  forAll(newAddedPoints, newPointi)
2012  {
2013  label oldPointi = pointMap[newPointi];
2014 
2015  const labelList& added = addedPoints_[oldPointi];
2016 
2017  labelList& newAdded = newAddedPoints[newPointi];
2018  newAdded.setSize(added.size());
2019  label newI = 0;
2020 
2021  forAll(added, i)
2022  {
2023  label newPointi = morphMap.reversePointMap()[added[i]];
2024 
2025  if (newPointi >= 0)
2026  {
2027  newAdded[newI++] = newPointi;
2028  }
2029  }
2030  newAdded.setSize(newI);
2031  }
2032  addedPoints_.transfer(newAddedPoints);
2033  }
2034 
2035  {
2036  labelListList newLayerFaces(faceMap.size());
2037 
2038  forAll(newLayerFaces, newFacei)
2039  {
2040  label oldFacei = faceMap[newFacei];
2041 
2042  const labelList& added = layerFaces_[oldFacei];
2043 
2044  labelList& newAdded = newLayerFaces[newFacei];
2045  newAdded.setSize(added.size());
2046  label newI = 0;
2047 
2048  forAll(added, i)
2049  {
2050  label newFacei = morphMap.reverseFaceMap()[added[i]];
2051 
2052  if (newFacei >= 0)
2053  {
2054  newAdded[newI++] = newFacei;
2055  }
2056  }
2057  newAdded.setSize(newI);
2058  }
2059  layerFaces_.transfer(newLayerFaces);
2060  }
2061 }
2062 
2063 
2064 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:74
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
addPatchCellLayer.H
Foam::polyMesh::points
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1038
meshTools.H
Foam::faceMap
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Definition: blockMeshMergeFast.C:94
Foam::PrimitivePatch::points
const Field< PointType > & points() const
Return reference to global points.
Definition: PrimitivePatch.H:300
Foam::PrimitivePatch::edgeFaces
const labelListList & edgeFaces() const
Return edge-face addressing.
Definition: PrimitivePatch.C:318
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:64
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:62
Foam::PrimitivePatch::edges
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
Definition: PrimitivePatch.C:238
nPatches
label nPatches
Definition: readKivaGrid.H:396
Foam::globalMeshData::globalEdgeSlavesMap
const mapDistribute & globalEdgeSlavesMap() const
Definition: globalMeshData.C:2265
Foam::Zero
static constexpr const zero Zero
Global zero.
Definition: zero.H:128
PatchTools.H
Foam::addPatchCellLayer::globalEdgeFaces
static labelListList globalEdgeFaces(const polyMesh &, const globalIndex &globalFaces, const indirectPrimitivePatch &pp)
Per patch edge the pp faces (in global indices) using it.
Definition: addPatchCellLayer.C:648
Foam::DynamicList< label >
Foam::globalMeshData::processorPatches
const labelList & processorPatches() const
Return list of processor patch labels.
Definition: globalMeshData.H:404
Foam::polyTopoChange::points
const DynamicList< point > & points() const
Points. Shrunk after constructing mesh (or calling of compact())
Definition: polyTopoChange.H:448
polyAddFace.H
Foam::PrimitivePatch::localPoints
const Field< PointType > & localPoints() const
Return pointField of points in patch.
Definition: PrimitivePatch.C:458
Foam::primitiveMesh::edgeFaces
const labelListList & edgeFaces() const
Definition: primitiveMeshEdgeFaces.C:33
mapPolyMesh.H
globalIndex.H
Foam::PrimitivePatch::nEdges
label nEdges() const
Return number of edges in patch.
Definition: PrimitivePatch.H:317
polyTopoChange.H
Foam::andEqOp
Definition: ops.H:85
Foam::UPstream::parRun
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:414
Foam::PrimitivePatch::meshEdges
labelList meshEdges(const edgeList &allEdges, const labelListList &cellEdges, const labelList &faceCells) const
Definition: PrimitivePatchMeshEdges.C:43
Foam::polyTopoChange
Direct mesh changes based on v1.3 polyTopoChange syntax.
Definition: polyTopoChange.H:100
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:63
Foam::primitiveMesh::nEdges
label nEdges() const
Number of mesh edges.
Definition: primitiveMeshI.H:67
dummyTransform.H
Dummy transform to be used with syncTools.
Foam::Map< label >
Foam::boolList
List< bool > boolList
A List of bools.
Definition: List.H:72
Foam::globalIndex::isLocal
bool isLocal(const label i) const
Is on local processor.
Definition: globalIndexI.H:148
Foam::polyModifyFace
Class describing modification of a face.
Definition: polyModifyFace.H:50
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:435
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::primitiveMesh::edges
const edgeList & edges() const
Return mesh edges. Uses calcEdges.
Definition: primitiveMeshEdges.C:505
Foam::dummyTransform
Definition: dummyTransform.H:46
Foam::PrimitivePatch::faceEdges
const labelListList & faceEdges() const
Return face-edge addressing.
Definition: PrimitivePatch.C:338
Foam::Pout
prefixOSstream Pout
An Ostream wrapper for parallel output to std::cout.
Foam::primitiveMesh::pointEdges
const labelListList & pointEdges() const
Definition: primitiveMeshEdges.C:516
polyMesh.H
Foam::HashSet< label, Hash< label > >
syncTools.H
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
Foam::syncTools::syncPointList
static void syncPointList(const polyMesh &mesh, List< T > &pointValues, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronize values on all mesh points.
Definition: syncToolsTemplates.C:747
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
Foam::minEqOp
Definition: ops.H:81
Foam::polyMesh::faceZones
const faceZoneMesh & faceZones() const
Return face zone mesh.
Definition: polyMesh.H:477
Foam::labelPair
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:54
n
label n
Definition: TABSMDCalcMethod2.H:31
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:62
Foam::Field< scalar >
Foam::faceZone
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:65
Foam::globalMeshData::globalTransforms
const globalIndexAndTransform & globalTransforms() const
Global transforms numbering.
Definition: globalMeshData.C:2180
Foam::syncTools::syncEdgeList
static void syncEdgeList(const polyMesh &mesh, List< T > &edgeValues, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronize values on all mesh edges.
Definition: syncToolsTemplates.C:826
Foam::mapDistribute
Class containing processor-to-processor mapping information.
Definition: mapDistribute.H:163
patchID
label patchID
Definition: boundaryProcessorFaPatchPoints.H:5
Foam::polyBoundaryMesh::whichPatch
label whichPatch(const label faceIndex) const
Return patch index for a given face label.
Definition: polyBoundaryMesh.C:805
Foam::globalMeshData::globalEdgeSlaves
const labelListList & globalEdgeSlaves() const
Definition: globalMeshData.C:2234
polyAddPoint.H
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::globalMeshData::syncData
static void syncData(List< Type > &elems, const labelListList &slaves, const labelListList &transformedSlaves, const mapDistribute &slavesMap, const globalIndexAndTransform &, const CombineOp &cop, const TransformOp &top)
Helper: synchronise data with transforms.
Definition: globalMeshDataTemplates.C:37
Foam::ZoneMesh::whichZone
label whichZone(const label objectIndex) const
Given a global object index, return the zone it is in.
Definition: ZoneMesh.C:315
newPointi
label newPointi
Definition: readKivaGrid.H:496
Foam::PrimitivePatch::nPoints
label nPoints() const
Return number of points supporting patch faces.
Definition: PrimitivePatch.H:311
Foam::FatalError
error FatalError
Foam::globalMeshData
Various mesh related information for a parallel run. Upon construction, constructs all info using par...
Definition: globalMeshData.H:106
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::faceZone::whichFace
label whichFace(const label globalCellID) const
Helper function to re-direct to zone::localID(...)
Definition: faceZone.C:388
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:137
Foam::globalIndex
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:68
Foam::polyAddCell
Class containing data for cell addition.
Definition: polyAddCell.H:48
Foam::ListOps::uniqueEqOp
List helper to append y unique elements onto the end of x.
Definition: ListOps.H:576
Foam::maxEqOp
Definition: ops.H:80
Foam::addPatchCellLayer::updateMesh
void updateMesh(const mapPolyMesh &, const labelList &faceMap, const labelList &pointMap)
Update any locally stored mesh information. Gets additional.
Definition: addPatchCellLayer.C:2002
polyModifyFace.H
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:444
Foam::mapPolyMesh::reverseFaceMap
const labelList & reverseFaceMap() const
Reverse face map.
Definition: mapPolyMesh.H:500
Foam::indirectPrimitivePatch
PrimitivePatch< face, IndirectList, const pointField & > indirectPrimitivePatch
A PrimitivePatch using an IndirectList for the faces.
Definition: indirectPrimitivePatch.H:47
Foam::PrimitivePatch::nInternalEdges
label nInternalEdges() const
Number of internal edges.
Definition: PrimitivePatch.C:258
found
bool found
Definition: TABSMDCalcMethod2.H:32
polyAddCell.H
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
Foam::polyMesh::faces
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1063
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:355
Foam::edge::compare
static int compare(const edge &a, const edge &b)
Compare edges.
Definition: edgeI.H:33
Foam::polyTopoChange::setAction
label setAction(const topoAction &action)
For compatibility with polyTopoChange: set topological action.
Definition: polyTopoChange.C:2458
Foam::nl
constexpr char nl
Definition: Ostream.H:372
Foam::Pair
An ordered pair of two objects of type <T> with first() and second() elements.
Definition: Pair.H:54
Foam::VectorSpace< Vector< scalar >, scalar, 3 >::max
static const Vector< scalar > max
Definition: VectorSpace.H:117
Foam::globalMeshData::globalEdgeTransformedSlaves
const labelListList & globalEdgeTransformedSlaves() const
Definition: globalMeshData.C:2244
f
labelList f(nPoints)
Foam::mapPolyMesh::reversePointMap
const labelList & reversePointMap() const
Reverse point map.
Definition: mapPolyMesh.H:468
Foam::Vector< scalar >
Foam::List< labelList >
Foam::addPatchCellLayer::calcExtrudeInfo
static void calcExtrudeInfo(const bool zoneFromAnyFace, const polyMesh &, const globalIndex &globalFaces, const labelListList &globalEdgeFaces, const indirectPrimitivePatch &pp, labelList &edgePatchID, label &nPatches, Map< label > &nbrProcToPatch, Map< label > &patchToNbrProc, labelList &edgeZoneID, boolList &edgeFlip, labelList &inflateFaceID)
Determine extrude information per patch edge:
Definition: addPatchCellLayer.C:693
Foam::globalMeshData::coupledPatch
const indirectPrimitivePatch & coupledPatch() const
Return patch of all coupled faces.
Definition: globalMeshData.C:2066
Foam::primitiveMesh::isInternalFace
bool isInternalFace(const label faceIndex) const
Return true if given face label is internal to the mesh.
Definition: primitiveMeshI.H:102
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::globalIndex::whichProcID
label whichProcID(const label i) const
Which processor does global come from? Binary search.
Definition: globalIndexI.H:235
k
label k
Boltzmann constant.
Definition: LISASMDCalcMethod2.H:41
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:65
Foam::polyAddPoint
Class containing data for point addition.
Definition: polyAddPoint.H:49
Foam::mapPolyMesh
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:160
forAllReverse
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: stdFoam.H:303
Foam::polyAddFace
A face addition data class. A face can be inflated either from a point or from another face and can e...
Definition: polyAddFace.H:53
Foam::PrimitivePatch::localFaces
const List< Face > & localFaces() const
Return patch faces addressing into local point list.
Definition: PrimitivePatch.C:398
Foam::UIndirectList
A List with indirect addressing.
Definition: fvMatrix.H:109
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:74
Foam::polyMesh::globalData
const globalMeshData & globalData() const
Return parallel info.
Definition: polyMesh.C:1241
Foam::PrimitivePatch::meshPoints
const labelList & meshPoints() const
Return labelList of mesh points in patch.
Definition: PrimitivePatch.C:418
Foam::List::setSize
void setSize(const label newSize)
Alias for resize(const label)
Definition: ListI.H:146
Foam::globalIndexAndTransform
Determination and storage of the possible independent transforms introduced by coupledPolyPatches,...
Definition: globalIndexAndTransform.H:64
Foam::faceZone::flipMap
const boolList & flipMap() const
Return face flip map.
Definition: faceZone.H:271
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::PatchTools::matchEdges
static void matchEdges(const PrimitivePatch< Face1, FaceList1, PointField1, PointType1 > &p1, const PrimitivePatch< Face2, FaceList2, PointField2, PointType2 > &p2, labelList &p1EdgeLabels, labelList &p2EdgeLabels, bitSet &sameOrientation)
Find corresponding edges on patches sharing the same points.
Definition: PatchToolsMatch.C:88
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:294
Foam::gMax
Type gMax(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:592
Foam::polyMesh::faceNeighbour
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1082
Foam::ProcessorTopology::procPatchMap
const labelList & procPatchMap() const
From neighbour processor to index in boundaryMesh. Local information.
Definition: ProcessorTopology.H:94
Foam::globalIndex::toGlobal
label toGlobal(const label i) const
From local to global index.
Definition: globalIndexI.H:164
Foam::PrimitivePatch
A list of faces which address into the list of points.
Definition: PrimitivePatch.H:90
Foam::addPatchCellLayer::setRefinement
void setRefinement(const globalIndex &globalFaces, const labelListList &globalEdgeFaces, const scalarField &expansionRatio, const indirectPrimitivePatch &pp, const labelList &sidePatchID, const labelList &sideZoneID, const boolList &sideFlip, const labelList &inflateFaceID, const labelList &exposedPatchID, const labelList &nFaceLayers, const labelList &nPointLayers, const vectorField &firstLayerDisp, polyTopoChange &meshMod)
Play commands into polyTopoChange to create layers on top.
Definition: addPatchCellLayer.C:1038
Foam::labelUIndList
UIndirectList< label > labelUIndList
UIndirectList of labels.
Definition: UIndirectList.H:59
Foam::addPatchCellLayer::addedCells
labelListList addedCells() const
Added cells given current mesh & layerfaces.
Definition: addPatchCellLayer.C:640