PDRMesh.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-2016 OpenFOAM Foundation
6  \\/ M anipulation |
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 Application
25  PDRMesh
26 
27 Description
28  Mesh and field preparation utility for PDR type simulations.
29 
30  Reads
31  - cellSet giving blockedCells
32  - faceSets giving blockedFaces and the patch they should go into
33 
34  NOTE: To avoid exposing wrong fields values faceSets should include
35  faces contained in the blockedCells cellset.
36 
37  - coupledFaces reads coupledFacesSet to introduces mixe-coupled baffles
38 
39  Subsets out the blocked cells and splits the blockedFaces and updates
40  fields.
41 
42  The face splitting is done by duplicating the faces. No duplication of
43  points for now (so checkMesh will show a lot of 'duplicate face' messages)
44 
45 \*---------------------------------------------------------------------------*/
46 
47 #include "fvMeshSubset.H"
48 #include "argList.H"
49 #include "cellSet.H"
50 #include "IOobjectList.H"
51 #include "volFields.H"
52 #include "mapPolyMesh.H"
53 #include "faceSet.H"
54 #include "cellSet.H"
55 #include "syncTools.H"
56 #include "polyTopoChange.H"
57 #include "polyModifyFace.H"
58 #include "polyAddFace.H"
59 #include "regionSplit.H"
60 #include "Tuple2.H"
61 #include "cyclicFvPatch.H"
62 
63 using namespace Foam;
64 
65 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
66 
67 void modifyOrAddFace
68 (
69  polyTopoChange& meshMod,
70  const face& f,
71  const label facei,
72  const label own,
73  const bool flipFaceFlux,
74  const label newPatchi,
75  const label zoneID,
76  const bool zoneFlip,
77 
78  PackedBoolList& modifiedFace
79 )
80 {
81  if (!modifiedFace[facei])
82  {
83  // First usage of face. Modify.
84  meshMod.setAction
85  (
87  (
88  f, // modified face
89  facei, // label of face
90  own, // owner
91  -1, // neighbour
92  flipFaceFlux, // face flip
93  newPatchi, // patch for face
94  false, // remove from zone
95  zoneID, // zone for face
96  zoneFlip // face flip in zone
97  )
98  );
99  modifiedFace[facei] = 1;
100  }
101  else
102  {
103  // Second or more usage of face. Add.
104  meshMod.setAction
105  (
107  (
108  f, // modified face
109  own, // owner
110  -1, // neighbour
111  -1, // master point
112  -1, // master edge
113  facei, // master face
114  flipFaceFlux, // face flip
115  newPatchi, // patch for face
116  zoneID, // zone for face
117  zoneFlip // face flip in zone
118  )
119  );
120  }
121 }
122 
123 
124 template<class Type>
125 void subsetVolFields
126 (
127  const fvMeshSubset& subsetter,
128  const IOobjectList& objectsList,
129  const label patchi,
130  const Type& exposedValue,
131  const word GeomVolType,
133 )
134 {
135  const fvMesh& baseMesh = subsetter.baseMesh();
136 
137  label i = 0;
138 
139  forAllConstIter(IOobjectList , objectsList, iter)
140  {
141  if (iter()->headerClassName() == GeomVolType)
142  {
143  const word fieldName = iter()->name();
144 
145  Info<< "Subsetting field " << fieldName << endl;
146 
148  (
149  *iter(),
150  baseMesh
151  );
152 
153  subFields.set(i, subsetter.interpolate(volField));
154 
155  // Explicitly set exposed faces (in patchi) to exposedValue.
156  if (patchi >= 0)
157  {
158  fvPatchField<Type>& fld =
159  subFields[i++].boundaryFieldRef()[patchi];
160 
161  label newStart = fld.patch().patch().start();
162 
163  label oldPatchi = subsetter.patchMap()[patchi];
164 
165  if (oldPatchi == -1)
166  {
167  // New patch. Reset whole value.
168  fld = exposedValue;
169  }
170  else
171  {
172  // Reset those faces that originate from different patch
173  // or internal faces.
174  label oldSize = volField.boundaryField()[oldPatchi].size();
175  label oldStart = volField.boundaryField()
176  [
177  oldPatchi
178  ].patch().patch().start();
179 
180  forAll(fld, j)
181  {
182  label oldFacei = subsetter.faceMap()[newStart+j];
183 
184  if (oldFacei < oldStart || oldFacei >= oldStart+oldSize)
185  {
186  fld[j] = exposedValue;
187  }
188  }
189  }
190  }
191  }
192  }
193 }
194 
195 
196 template<class Type>
197 void subsetSurfaceFields
198 (
199  const fvMeshSubset& subsetter,
200  const IOobjectList& objectsList,
201  const label patchi,
202  const Type& exposedValue,
203  const word GeomSurfType,
205 )
206 {
207  const fvMesh& baseMesh = subsetter.baseMesh();
208 
209  label i(0);
210 
211  forAllConstIter(IOobjectList , objectsList, iter)
212  {
213  if (iter()->headerClassName() == GeomSurfType)
214  {
215  const word& fieldName = iter.key();
216 
217  Info<< "Subsetting field " << fieldName << endl;
218 
220  (
221  *iter(),
222  baseMesh
223  );
224 
225  subFields.set(i, subsetter.interpolate(volField));
226 
227 
228  // Explicitly set exposed faces (in patchi) to exposedValue.
229  if (patchi >= 0)
230  {
231  fvsPatchField<Type>& fld =
232  subFields[i++].boundaryFieldRef()[patchi];
233 
234  label newStart = fld.patch().patch().start();
235 
236  label oldPatchi = subsetter.patchMap()[patchi];
237 
238  if (oldPatchi == -1)
239  {
240  // New patch. Reset whole value.
241  fld = exposedValue;
242  }
243  else
244  {
245  // Reset those faces that originate from different patch
246  // or internal faces.
247  label oldSize = volField.boundaryField()[oldPatchi].size();
248  label oldStart = volField.boundaryField()
249  [
250  oldPatchi
251  ].patch().patch().start();
252 
253  forAll(fld, j)
254  {
255  label oldFacei = subsetter.faceMap()[newStart+j];
256 
257  if (oldFacei < oldStart || oldFacei >= oldStart+oldSize)
258  {
259  fld[j] = exposedValue;
260  }
261  }
262  }
263  }
264  }
265  }
266 }
267 
268 
269 // Faces introduced into zero-sized patches don't get a value at all.
270 // This is hack to set them to an initial value.
271 template<class GeoField>
272 void initCreatedPatches
273 (
274  const fvMesh& mesh,
275  const mapPolyMesh& map,
276  const typename GeoField::value_type initValue
277 )
278 {
280  (
281  mesh.objectRegistry::lookupClass<GeoField>()
282  );
283 
284  for
285  (
286  typename HashTable<const GeoField*>::
287  iterator fieldIter = fields.begin();
288  fieldIter != fields.end();
289  ++fieldIter
290  )
291  {
292  GeoField& field = const_cast<GeoField&>(*fieldIter());
293 
294  typename GeoField::Boundary& fieldBf =
295  field.boundaryFieldRef();
296 
297  forAll(fieldBf, patchi)
298  {
299  if (map.oldPatchSizes()[patchi] == 0)
300  {
301  // Not mapped.
302  fieldBf[patchi] = initValue;
303 
304  if (fieldBf[patchi].fixesValue())
305  {
306  fieldBf[patchi] == initValue;
307  }
308  }
309  }
310  }
311 }
312 
313 
314 void createCoupledBaffles
315 (
316  fvMesh& mesh,
317  const labelList& coupledWantedPatch,
318  polyTopoChange& meshMod,
319  PackedBoolList& modifiedFace
320 )
321 {
322  const faceZoneMesh& faceZones = mesh.faceZones();
323 
324  forAll(coupledWantedPatch, facei)
325  {
326  if (coupledWantedPatch[facei] != -1)
327  {
328  const face& f = mesh.faces()[facei];
329  label zoneID = faceZones.whichZone(facei);
330  bool zoneFlip = false;
331 
332  if (zoneID >= 0)
333  {
334  const faceZone& fZone = faceZones[zoneID];
335  zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
336  }
337 
338  // Use owner side of face
339  modifyOrAddFace
340  (
341  meshMod,
342  f, // modified face
343  facei, // label of face
344  mesh.faceOwner()[facei], // owner
345  false, // face flip
346  coupledWantedPatch[facei], // patch for face
347  zoneID, // zone for face
348  zoneFlip, // face flip in zone
349  modifiedFace // modify or add status
350  );
351 
352  if (mesh.isInternalFace(facei))
353  {
354  label zoneID = faceZones.whichZone(facei);
355  bool zoneFlip = false;
356 
357  if (zoneID >= 0)
358  {
359  const faceZone& fZone = faceZones[zoneID];
360  zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
361  }
362  // Use neighbour side of face
363  modifyOrAddFace
364  (
365  meshMod,
366  f.reverseFace(), // modified face
367  facei, // label of face
368  mesh.faceNeighbour()[facei],// owner
369  false, // face flip
370  coupledWantedPatch[facei], // patch for face
371  zoneID, // zone for face
372  zoneFlip, // face flip in zone
373  modifiedFace // modify or add status
374  );
375  }
376  }
377  }
378 }
379 
380 
381 void createCyclicCoupledBaffles
382 (
383  fvMesh& mesh,
384  const labelList& cyclicMasterPatch,
385  const labelList& cyclicSlavePatch,
386  polyTopoChange& meshMod,
387  PackedBoolList& modifiedFace
388 )
389 {
390  const faceZoneMesh& faceZones = mesh.faceZones();
391 
392  forAll(cyclicMasterPatch, facei)
393  {
394  if (cyclicMasterPatch[facei] != -1)
395  {
396  const face& f = mesh.faces()[facei];
397 
398  label zoneID = faceZones.whichZone(facei);
399  bool zoneFlip = false;
400 
401  if (zoneID >= 0)
402  {
403  const faceZone& fZone = faceZones[zoneID];
404  zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
405  }
406 
407  modifyOrAddFace
408  (
409  meshMod,
410  f.reverseFace(), // modified face
411  facei, // label of face
412  mesh.faceNeighbour()[facei], // owner
413  false, // face flip
414  cyclicMasterPatch[facei], // patch for face
415  zoneID, // zone for face
416  zoneFlip, // face flip in zone
417  modifiedFace // modify or add
418  );
419  }
420  }
421 
422  forAll(cyclicSlavePatch, facei)
423  {
424  if (cyclicSlavePatch[facei] != -1)
425  {
426  const face& f = mesh.faces()[facei];
427  if (mesh.isInternalFace(facei))
428  {
429  label zoneID = faceZones.whichZone(facei);
430  bool zoneFlip = false;
431 
432  if (zoneID >= 0)
433  {
434  const faceZone& fZone = faceZones[zoneID];
435  zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
436  }
437  // Use owner side of face
438  modifyOrAddFace
439  (
440  meshMod,
441  f, // modified face
442  facei, // label of face
443  mesh.faceOwner()[facei], // owner
444  false, // face flip
445  cyclicSlavePatch[facei], // patch for face
446  zoneID, // zone for face
447  zoneFlip, // face flip in zone
448  modifiedFace // modify or add status
449  );
450  }
451  }
452  }
453 }
454 
455 
456 void createBaffles
457 (
458  fvMesh& mesh,
459  const labelList& wantedPatch,
460  polyTopoChange& meshMod
461 )
462 {
463  const faceZoneMesh& faceZones = mesh.faceZones();
464  Info << "faceZone:createBaffle " << faceZones << endl;
465  forAll(wantedPatch, facei)
466  {
467  if (wantedPatch[facei] != -1)
468  {
469  const face& f = mesh.faces()[facei];
470 
471  label zoneID = faceZones.whichZone(facei);
472  bool zoneFlip = false;
473 
474  if (zoneID >= 0)
475  {
476  const faceZone& fZone = faceZones[zoneID];
477  zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
478  }
479 
480  meshMod.setAction
481  (
483  (
484  f, // modified face
485  facei, // label of face
486  mesh.faceOwner()[facei], // owner
487  -1, // neighbour
488  false, // face flip
489  wantedPatch[facei], // patch for face
490  false, // remove from zone
491  zoneID, // zone for face
492  zoneFlip // face flip in zone
493  )
494  );
495 
496  if (mesh.isInternalFace(facei))
497  {
498  label zoneID = faceZones.whichZone(facei);
499  bool zoneFlip = false;
500 
501  if (zoneID >= 0)
502  {
503  const faceZone& fZone = faceZones[zoneID];
504  zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
505  }
506 
507  meshMod.setAction
508  (
510  (
511  f.reverseFace(), // modified face
512  mesh.faceNeighbour()[facei],// owner
513  -1, // neighbour
514  -1, // masterPointID
515  -1, // masterEdgeID
516  facei, // masterFaceID,
517  false, // face flip
518  wantedPatch[facei], // patch for face
519  zoneID, // zone for face
520  zoneFlip // face flip in zone
521  )
522  );
523  }
524  }
525  }
526 }
527 
528 
529 // Wrapper around find patch. Also makes sure same patch in parallel.
530 label findPatch(const polyBoundaryMesh& patches, const word& patchName)
531 {
532  label patchi = patches.findPatchID(patchName);
533 
534  if (patchi == -1)
535  {
537  << "Illegal patch " << patchName
538  << nl << "Valid patches are " << patches.names()
539  << exit(FatalError);
540  }
541 
542  // Check same patch for all procs
543  {
544  label newPatch = patchi;
545  reduce(newPatch, minOp<label>());
546 
547  if (newPatch != patchi)
548  {
550  << "Patch " << patchName
551  << " should have the same patch index on all processors." << nl
552  << "On my processor it has index " << patchi
553  << " ; on some other processor it has index " << newPatch
554  << exit(FatalError);
555  }
556  }
557  return patchi;
558 }
559 
560 
561 
562 int main(int argc, char *argv[])
563 {
564  #include "addOverwriteOption.H"
565  #include "setRootCase.H"
566  #include "createTime.H"
567  runTime.functionObjects().off();
568  #include "createMesh.H"
569 
570  // Read control dictionary
571  // ~~~~~~~~~~~~~~~~~~~~~~~
572 
574  (
575  IOobject
576  (
577  "PDRMeshDict",
578  runTime.system(),
579  mesh,
582  )
583  );
584 
585  // Per faceSet the patch to put the baffles into
586  const List<Pair<word>> setsAndPatches(dict.lookup("blockedFaces"));
587 
588  // Per faceSet the patch to put the coupled baffles into
589  DynamicList<FixedList<word, 3>> coupledAndPatches(10);
590  const dictionary& functionDicts = dict.subDict("coupledFaces");
591  forAllConstIter(dictionary, functionDicts, iter)
592  {
593  // safety:
594  if (!iter().isDict())
595  {
596  continue;
597  }
598  const word& key = iter().keyword();
599 
600  const dictionary& dict = iter().dict();
601  const word cyclicName = dict.lookup("cyclicMasterPatchName");
602  const word wallName = dict.lookup("wallPatchName");
603  FixedList<word, 3> nameAndType;
604  nameAndType[0] = key;
605  nameAndType[1] = wallName;
606  nameAndType[2] = cyclicName;
607  coupledAndPatches.append(nameAndType);
608  }
609 
610  forAll(setsAndPatches, setI)
611  {
612  Info<< "Faces in faceSet " << setsAndPatches[setI][0]
613  << " become baffles in patch " << setsAndPatches[setI][1]
614  << endl;
615  }
616 
617  forAll(coupledAndPatches, setI)
618  {
619  Info<< "Faces in faceSet " << coupledAndPatches[setI][0]
620  << " become coupled baffles in patch " << coupledAndPatches[setI][1]
621  << endl;
622  }
623 
624  // All exposed faces that are not explicitly marked to be put into a patch
625  const word defaultPatch(dict.lookup("defaultPatch"));
626 
627  Info<< "Faces that get exposed become boundary faces in patch "
628  << defaultPatch << endl;
629 
630  const word blockedSetName(dict.lookup("blockedCells"));
631 
632  Info<< "Reading blocked cells from cellSet " << blockedSetName
633  << endl;
634 
635  const bool overwrite = args.optionFound("overwrite");
636 
637 
638  // Read faceSets, lookup patches
639  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
640 
641  // Check that face sets don't have coincident faces
642  labelList wantedPatch(mesh.nFaces(), -1);
643  forAll(setsAndPatches, setI)
644  {
645  faceSet fSet(mesh, setsAndPatches[setI][0]);
646 
647  label patchi = findPatch
648  (
649  mesh.boundaryMesh(),
650  setsAndPatches[setI][1]
651  );
652 
653  forAllConstIter(faceSet, fSet, iter)
654  {
655  if (wantedPatch[iter.key()] != -1)
656  {
658  << "Face " << iter.key()
659  << " is in faceSet " << setsAndPatches[setI][0]
660  << " destined for patch " << setsAndPatches[setI][1]
661  << " but also in patch " << wantedPatch[iter.key()]
662  << exit(FatalError);
663  }
664  wantedPatch[iter.key()] = patchi;
665  }
666  }
667 
668  // Per face the patch for coupled baffle or -1.
669  labelList coupledWantedPatch(mesh.nFaces(), -1);
670  labelList cyclicWantedPatch_half0(mesh.nFaces(), -1);
671  labelList cyclicWantedPatch_half1(mesh.nFaces(), -1);
672 
673  forAll(coupledAndPatches, setI)
674  {
675  const polyBoundaryMesh& patches = mesh.boundaryMesh();
676  const label cyclicId =
677  findPatch(patches, coupledAndPatches[setI][2]);
678 
679  const label cyclicSlaveId = findPatch
680  (
681  patches,
682  refCast<const cyclicFvPatch>
683  (
684  mesh.boundary()[cyclicId]
685  ).neighbFvPatch().name()
686  );
687 
688  faceSet fSet(mesh, coupledAndPatches[setI][0]);
689  label patchi = findPatch(patches, coupledAndPatches[setI][1]);
690 
691  forAllConstIter(faceSet, fSet, iter)
692  {
693  if (coupledWantedPatch[iter.key()] != -1)
694  {
696  << "Face " << iter.key()
697  << " is in faceSet " << coupledAndPatches[setI][0]
698  << " destined for patch " << coupledAndPatches[setI][1]
699  << " but also in patch " << coupledWantedPatch[iter.key()]
700  << exit(FatalError);
701  }
702  coupledWantedPatch[iter.key()] = patchi;
703  cyclicWantedPatch_half0[iter.key()] = cyclicId;
704  cyclicWantedPatch_half1[iter.key()] = cyclicSlaveId;
705  }
706  }
707 
708  // Exposed faces patch
709  label defaultPatchi = findPatch(mesh.boundaryMesh(), defaultPatch);
710 
711 
712  //
713  // Removing blockedCells (like subsetMesh)
714  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
715  //
716 
717  // Create mesh subsetting engine
718  fvMeshSubset subsetter(mesh);
719 
720  {
721 
722  cellSet blockedCells(mesh, blockedSetName);
723 
724  // invert
725  blockedCells.invert(mesh.nCells());
726 
727  // Create subsetted mesh.
728  subsetter.setLargeCellSubset(blockedCells, defaultPatchi, true);
729  }
730 
731 
732  // Subset wantedPatch. Note that might also include boundary faces
733  // that have been exposed by subsetting.
734  wantedPatch = IndirectList<label>(wantedPatch, subsetter.faceMap())();
735 
736  coupledWantedPatch = IndirectList<label>
737  (
738  coupledWantedPatch,
739  subsetter.faceMap()
740  )();
741 
742  cyclicWantedPatch_half0 = IndirectList<label>
743  (
744  cyclicWantedPatch_half0,
745  subsetter.faceMap()
746  )();
747 
748  cyclicWantedPatch_half1 = IndirectList<label>
749  (
750  cyclicWantedPatch_half1,
751  subsetter.faceMap()
752  )();
753 
754  // Read all fields in time and constant directories
755  IOobjectList objects(mesh, runTime.timeName());
756  IOobjectList timeObjects(IOobjectList(mesh, mesh.facesInstance()));
757  forAllConstIter(IOobjectList, timeObjects, iter)
758  {
759  if
760  (
761  iter()->headerClassName() == volScalarField::typeName
762  || iter()->headerClassName() == volVectorField::typeName
763  || iter()->headerClassName() == volSphericalTensorField::typeName
764  || iter()->headerClassName() == volTensorField::typeName
765  || iter()->headerClassName() == volSymmTensorField::typeName
766  || iter()->headerClassName() == surfaceScalarField::typeName
767  || iter()->headerClassName() == surfaceVectorField::typeName
768  || iter()->headerClassName()
770  || iter()->headerClassName() == surfaceSymmTensorField::typeName
771  || iter()->headerClassName() == surfaceTensorField::typeName
772  )
773  {
774  objects.add(*iter());
775  }
776  }
777 
778  // Read vol fields and subset.
779 
780  wordList scalarNames(objects.names(volScalarField::typeName));
781  PtrList<volScalarField> scalarFlds(scalarNames.size());
782  subsetVolFields
783  (
784  subsetter,
785  objects,
786  defaultPatchi,
787  scalar(Zero),
789  scalarFlds
790  );
791 
792  wordList vectorNames(objects.names(volVectorField::typeName));
793  PtrList<volVectorField> vectorFlds(vectorNames.size());
794  subsetVolFields
795  (
796  subsetter,
797  objects,
798  defaultPatchi,
799  vector(Zero),
801  vectorFlds
802  );
803 
804  wordList sphericalTensorNames
805  (
806  objects.names(volSphericalTensorField::typeName)
807  );
808  PtrList<volSphericalTensorField> sphericalTensorFlds
809  (
810  sphericalTensorNames.size()
811  );
812  subsetVolFields
813  (
814  subsetter,
815  objects,
816  defaultPatchi,
819  sphericalTensorFlds
820  );
821 
822  wordList symmTensorNames(objects.names(volSymmTensorField::typeName));
823  PtrList<volSymmTensorField> symmTensorFlds(symmTensorNames.size());
824  subsetVolFields
825  (
826  subsetter,
827  objects,
828  defaultPatchi,
829  symmTensor(Zero),
831  symmTensorFlds
832  );
833 
834  wordList tensorNames(objects.names(volTensorField::typeName));
835  PtrList<volTensorField> tensorFlds(tensorNames.size());
836  subsetVolFields
837  (
838  subsetter,
839  objects,
840  defaultPatchi,
841  tensor(Zero),
843  tensorFlds
844  );
845 
846  // Read surface fields and subset.
847 
848  wordList surfScalarNames(objects.names(surfaceScalarField::typeName));
849  PtrList<surfaceScalarField> surfScalarFlds(surfScalarNames.size());
850  subsetSurfaceFields
851  (
852  subsetter,
853  objects,
854  defaultPatchi,
855  scalar(Zero),
857  surfScalarFlds
858  );
859 
860  wordList surfVectorNames(objects.names(surfaceVectorField::typeName));
861  PtrList<surfaceVectorField> surfVectorFlds(surfVectorNames.size());
862  subsetSurfaceFields
863  (
864  subsetter,
865  objects,
866  defaultPatchi,
867  vector(Zero),
869  surfVectorFlds
870  );
871 
872  wordList surfSphericalTensorNames
873  (
875  );
876  PtrList<surfaceSphericalTensorField> surfSphericalTensorFlds
877  (
878  surfSphericalTensorNames.size()
879  );
880  subsetSurfaceFields
881  (
882  subsetter,
883  objects,
884  defaultPatchi,
887  surfSphericalTensorFlds
888  );
889 
890  wordList surfSymmTensorNames
891  (
892  objects.names(surfaceSymmTensorField::typeName)
893  );
894 
895  PtrList<surfaceSymmTensorField> surfSymmTensorFlds
896  (
897  surfSymmTensorNames.size()
898  );
899 
900  subsetSurfaceFields
901  (
902  subsetter,
903  objects,
904  defaultPatchi,
905  symmTensor(Zero),
907  surfSymmTensorFlds
908  );
909 
910  wordList surfTensorNames(objects.names(surfaceTensorField::typeName));
911  PtrList<surfaceTensorField> surfTensorFlds(surfTensorNames.size());
912  subsetSurfaceFields
913  (
914  subsetter,
915  objects,
916  defaultPatchi,
917  tensor(Zero),
919  surfTensorFlds
920  );
921 
922  if (!overwrite)
923  {
924  runTime++;
925  }
926 
927  Info<< "Writing mesh without blockedCells to time " << runTime.value()
928  << endl;
929 
930  // Subsetting adds 'subset' prefix. Rename field to be like original.
931  forAll(scalarFlds, i)
932  {
933  scalarFlds[i].rename(scalarNames[i]);
934  scalarFlds[i].writeOpt() = IOobject::AUTO_WRITE;
935  }
936  forAll(vectorFlds, i)
937  {
938  vectorFlds[i].rename(vectorNames[i]);
939  vectorFlds[i].writeOpt() = IOobject::AUTO_WRITE;
940  }
941  forAll(sphericalTensorFlds, i)
942  {
943  sphericalTensorFlds[i].rename(sphericalTensorNames[i]);
944  sphericalTensorFlds[i].writeOpt() = IOobject::AUTO_WRITE;
945  }
946  forAll(symmTensorFlds, i)
947  {
948  symmTensorFlds[i].rename(symmTensorNames[i]);
949  symmTensorFlds[i].writeOpt() = IOobject::AUTO_WRITE;
950  }
951  forAll(tensorFlds, i)
952  {
953  tensorFlds[i].rename(tensorNames[i]);
954  tensorFlds[i].writeOpt() = IOobject::AUTO_WRITE;
955  }
956 
957  // Surface ones.
958  forAll(surfScalarFlds, i)
959  {
960  surfScalarFlds[i].rename(surfScalarNames[i]);
961  surfScalarFlds[i].writeOpt() = IOobject::AUTO_WRITE;
962  }
963  forAll(surfVectorFlds, i)
964  {
965  surfVectorFlds[i].rename(surfVectorNames[i]);
966  surfVectorFlds[i].writeOpt() = IOobject::AUTO_WRITE;
967  }
968  forAll(surfSphericalTensorFlds, i)
969  {
970  surfSphericalTensorFlds[i].rename(surfSphericalTensorNames[i]);
971  surfSphericalTensorFlds[i].writeOpt() = IOobject::AUTO_WRITE;
972  }
973  forAll(surfSymmTensorFlds, i)
974  {
975  surfSymmTensorFlds[i].rename(surfSymmTensorNames[i]);
976  surfSymmTensorFlds[i].writeOpt() = IOobject::AUTO_WRITE;
977  }
978  forAll(surfTensorNames, i)
979  {
980  surfTensorFlds[i].rename(surfTensorNames[i]);
981  surfTensorFlds[i].writeOpt() = IOobject::AUTO_WRITE;
982  }
983 
984  subsetter.subMesh().write();
985 
986 
987  //
988  // Splitting blockedFaces
989  // ~~~~~~~~~~~~~~~~~~~~~~
990  //
991 
992  // Synchronize wantedPatch across coupled patches.
994  (
995  subsetter.subMesh(),
996  wantedPatch,
998  );
999 
1000  // Synchronize coupledWantedPatch across coupled patches.
1002  (
1003  subsetter.subMesh(),
1004  coupledWantedPatch,
1005  maxEqOp<label>()
1006  );
1007 
1008  // Synchronize cyclicWantedPatch across coupled patches.
1010  (
1011  subsetter.subMesh(),
1012  cyclicWantedPatch_half0,
1013  maxEqOp<label>()
1014  );
1015 
1016  // Synchronize cyclicWantedPatch across coupled patches.
1018  (
1019  subsetter.subMesh(),
1020  cyclicWantedPatch_half1,
1021  maxEqOp<label>()
1022  );
1023 
1024  // Topochange container
1025  polyTopoChange meshMod(subsetter.subMesh());
1026 
1027 
1028  // Whether first use of face (modify) or consecutive (add)
1029  PackedBoolList modifiedFace(mesh.nFaces());
1030 
1031  // Create coupled wall-side baffles
1032  createCoupledBaffles
1033  (
1034  subsetter.subMesh(),
1035  coupledWantedPatch,
1036  meshMod,
1037  modifiedFace
1038  );
1039 
1040  // Create coupled master/slave cyclic baffles
1041  createCyclicCoupledBaffles
1042  (
1043  subsetter.subMesh(),
1044  cyclicWantedPatch_half0,
1045  cyclicWantedPatch_half1,
1046  meshMod,
1047  modifiedFace
1048  );
1049 
1050  // Create wall baffles
1051  createBaffles
1052  (
1053  subsetter.subMesh(),
1054  wantedPatch,
1055  meshMod
1056  );
1057 
1058  if (!overwrite)
1059  {
1060  runTime++;
1061  }
1062 
1063  // Change the mesh. Change points directly (no inflation).
1064  autoPtr<mapPolyMesh> map = meshMod.changeMesh(subsetter.subMesh(), false);
1065 
1066  // Update fields
1067  subsetter.subMesh().updateMesh(map);
1068 
1069  // Fix faces that get mapped to zero-sized patches (these don't get any
1070  // value)
1071  initCreatedPatches<volScalarField>
1072  (
1073  subsetter.subMesh(),
1074  map,
1075  0.0
1076  );
1077  initCreatedPatches<volVectorField>
1078  (
1079  subsetter.subMesh(),
1080  map,
1081  Zero
1082  );
1083  initCreatedPatches<volSphericalTensorField>
1084  (
1085  subsetter.subMesh(),
1086  map,
1087  Zero
1088  );
1089  initCreatedPatches<volSymmTensorField>
1090  (
1091  subsetter.subMesh(),
1092  map,
1093  Zero
1094  );
1095  initCreatedPatches<volTensorField>
1096  (
1097  subsetter.subMesh(),
1098  map,
1099  Zero
1100  );
1101 
1102  initCreatedPatches<surfaceScalarField>
1103  (
1104  subsetter.subMesh(),
1105  map,
1106  0.0
1107  );
1108  initCreatedPatches<surfaceVectorField>
1109  (
1110  subsetter.subMesh(),
1111  map,
1112  Zero
1113  );
1114  initCreatedPatches<surfaceSphericalTensorField>
1115  (
1116  subsetter.subMesh(),
1117  map,
1118  Zero
1119  );
1120  initCreatedPatches<surfaceSymmTensorField>
1121  (
1122  subsetter.subMesh(),
1123  map,
1124  Zero
1125  );
1126  initCreatedPatches<surfaceTensorField>
1127  (
1128  subsetter.subMesh(),
1129  map,
1130  Zero
1131  );
1132 
1133 
1134  // Move mesh (since morphing might not do this)
1135  if (map().hasMotionPoints())
1136  {
1137  subsetter.subMesh().movePoints(map().preMotionPoints());
1138  }
1139 
1140  Info<< "Writing mesh with split blockedFaces to time " << runTime.value()
1141  << endl;
1142 
1143  subsetter.subMesh().write();
1144 
1145 
1146  //
1147  // Removing inaccessible regions
1148  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1149  //
1150 
1151  // Determine connected regions. regionSplit is the labelList with the
1152  // region per cell.
1153  regionSplit cellRegion(subsetter.subMesh());
1154 
1155  if (cellRegion.nRegions() > 1)
1156  {
1158  << "Removing blocked faces and cells created "
1159  << cellRegion.nRegions()
1160  << " regions that are not connected via a face." << nl
1161  << " This is not supported in solvers." << nl
1162  << " Use" << nl << nl
1163  << " splitMeshRegions <root> <case> -largestOnly" << nl << nl
1164  << " to extract a single region of the mesh." << nl
1165  << " This mesh will be written to a new timedirectory"
1166  << " so might have to be moved back to constant/" << nl
1167  << endl;
1168 
1169  word startFrom(runTime.controlDict().lookup("startFrom"));
1170 
1171  if (startFrom != "latestTime")
1172  {
1174  << "To run splitMeshRegions please set your"
1175  << " startFrom entry to latestTime" << endl;
1176  }
1177  }
1178 
1179  Info << nl << "End" << endl;
1180 
1181  return 0;
1182 }
1183 
1184 
1185 // ************************************************************************* //
const fvPatch & patch() const
Return patch.
Definition: fvPatchField.H:339
This class separates the mesh into distinct unconnected regions, each of which is then given a label ...
Definition: regionSplit.H:116
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
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
A list of face labels.
Definition: faceSet.H:48
List of IOobjects with searching and retrieving facilities.
Definition: IOobjectList.H:50
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
wordList names() const
Return a list of patch names.
const boolList & flipMap() const
Return face flip map.
Definition: faceZone.H:253
Class describing modification of a face.
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
A 1D vector of objects of type <T> with a fixed size <Size>.
Definition: FixedList.H:53
error FatalError
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:137
const fileName & facesInstance() const
Return the current instance directory for faces.
Definition: polyMesh.C:778
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
static const char *const typeName
Definition: Field.H:94
Foam::tmp< Foam::GeometricField< Type, Foam::fvPatchField, Foam::volMesh > > volField(const Foam::fvMeshSubset &, const Foam::GeometricField< Type, Foam::fvPatchField, Foam::volMesh > &vf)
Wrapper to get hold of the field or the subsetted field.
const labelList & oldPatchSizes() const
Return list of the old patch sizes.
Definition: mapPolyMesh.H:620
const dictionary & subDict(const word &) const
Find and return a sub-dictionary.
Definition: dictionary.C:633
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:253
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
Definition: fvPatchField.H:65
Generic GeometricField class.
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
bool isInternalFace(const label faceIndex) const
Return true if given face label is internal to the mesh.
const polyPatch & patch() const
Return the polyPatch.
Definition: fvPatch.H:143
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:421
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:158
const fvMesh & subMesh() const
Return reference to subset mesh.
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
label nCells() const
multivariateSurfaceInterpolationScheme< scalar >::fieldTable fields
Definition: createFields.H:97
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:53
label whichFace(const label globalCellID) const
Helper function to re-direct to zone::localID(...)
Definition: faceZone.C:305
const labelList & faceMap() const
Return face map.
virtual void updateMesh(const mapPolyMesh &mpm)
Update mesh corresponding to the given map.
Definition: fvMesh.C:800
dynamicFvMesh & mesh
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:300
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:56
bool optionFound(const word &opt) const
Return true if the named option is found.
Definition: argListI.H:108
SymmTensor< scalar > symmTensor
SymmTensor of scalars.
Definition: symmTensor.H:48
A class for handling words, derived from string.
Definition: word.H:59
static const zero Zero
Definition: zero.H:91
const labelList & patchMap() const
Return patch map.
An STL-conforming hash table.
Definition: HashTable.H:61
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:29
Foam::polyBoundaryMesh.
static const char nl
Definition: Ostream.H:262
Post-processing mesh subset tool. Given the original mesh and the list of selected cells...
Definition: fvMeshSubset.H:73
const fvPatch & patch() const
Return patch.
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
virtual tmp< scalarField > movePoints(const pointField &)
Move points, returns volumes swept by faces in motion.
Definition: fvMesh.C:721
label nFaces() const
static void syncFaceList(const polyMesh &mesh, UList< T > &l, const CombineOp &cop)
Synchronize values on all mesh faces.
Definition: syncTools.H:381
A bit-packed bool list.
label patchi
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1023
#define WarningInFunction
Report a warning using Foam::Warning.
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
Definition: List.H:62
A collection of cell labels.
Definition: cellSet.H:48
label whichZone(const label objectIndex) const
Given a global object index, return the zone it is in.
Definition: ZoneMesh.C:221
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
Direct mesh changes based on v1.3 polyTopoChange syntax.
const fvMesh & baseMesh() const
Original mesh.
Definition: fvMeshSubset.H:217
messageStream Info
face reverseFace() const
Return face with reverse direction.
Definition: face.C:611
const faceZoneMesh & faceZones() const
Return face zone mesh.
Definition: polyMesh.H:463
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:53
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:64
SphericalTensor< scalar > sphericalTensor
SphericalTensor of scalars.
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1017
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1004
Foam::argList args(argc, argv)
label findPatchID(const word &patchName) const
Find patch index given a name.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:91
static tmp< GeometricField< Type, fvPatchField, volMesh > > interpolate(const GeometricField< Type, fvPatchField, volMesh > &, const fvMesh &sMesh, const labelList &patchMap, const labelList &cellMap, const labelList &faceMap)
Map volume field.
const fvBoundaryMesh & boundary() const
Return reference to boundary mesh.
Definition: fvMesh.C:545
A List with indirect addressing.
Definition: IndirectList.H:102
An abstract base class with a fat-interface to all derived classes covering all possible ways in whic...
Definition: fvsPatchField.H:65
Tensor< scalar > tensor
Tensor of scalars.
Definition: tensor.H:51
void setLargeCellSubset(const labelList &region, const label currentRegion, const label patchID=-1, const bool syncCouples=true)
Set the subset from all cells with region == currentRegion.
Definition: fvMeshSubset.C:795
virtual bool write() const
Write mesh using IO settings from time.
Definition: fvMesh.C:870
const word & name() const
Return name.
Definition: IOobject.H:260
Namespace for OpenFOAM.
label setAction(const topoAction &action)
For compatibility with polyTopoChange: set topological action.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:451