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