snappyLayerDriverSinglePass.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2021 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 Description
27  Single pass layer addition. Can be removed once multi-pass works ok.
28 
29 \*----------------------------------------------------------------------------*/
30 
31 #include "snappyLayerDriver.H"
32 //#include "motionSmoother.H"
33 //#include "pointSet.H"
34 //#include "faceSet.H"
35 //#include "cellSet.H"
36 #include "polyTopoChange.H"
37 #include "mapPolyMesh.H"
38 #include "addPatchCellLayer.H"
39 #include "mapDistributePolyMesh.H"
40 //#include "OBJstream.H"
41 #include "layerParameters.H"
43 //#include "profiling.H"
44 
45 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
46 
48 (
49  const layerParameters& layerParams,
50  const dictionary& motionDict,
51  const labelList& patchIDs,
52  const label nAllowableErrors,
53  decompositionMethod& decomposer,
54  fvMeshDistribute& distributor
55 )
56 {
57  fvMesh& mesh = meshRefiner_.mesh();
58 
59  // Undistorted edge length
60  const scalar edge0Len = meshRefiner_.meshCutter().level0EdgeLength();
61 
62  // faceZones of type internal or baffle (for merging points across)
63  labelList internalOrBaffleFaceZones;
64  {
66  fzTypes[0] = surfaceZonesInfo::INTERNAL;
67  fzTypes[1] = surfaceZonesInfo::BAFFLE;
68  internalOrBaffleFaceZones = meshRefiner_.getZones(fzTypes);
69  }
70 
71  // faceZones of type internal (for checking mesh quality across and
72  // merging baffles)
73  const labelList internalFaceZones
74  (
75  meshRefiner_.getZones
76  (
78  (
79  1,
81  )
82  )
83  );
84 
85  // Create baffles (pairs of faces that share the same points)
86  // Baffles stored as owner and neighbour face that have been created.
87  List<labelPair> baffles;
88  {
89  labelList originatingFaceZone;
90  meshRefiner_.createZoneBaffles
91  (
92  identity(mesh.faceZones().size()),
93  baffles,
94  originatingFaceZone
95  );
96 
98  {
99  const_cast<Time&>(mesh.time())++;
100  Info<< "Writing baffled mesh to time "
101  << meshRefiner_.timeName() << endl;
102  meshRefiner_.write
103  (
106  (
109  ),
110  mesh.time().path()/meshRefiner_.timeName()
111  );
112  }
113  }
114 
115 
116  // Duplicate points on faceZones of type boundary. Should normally already
117  // be done by snapping phase
118  {
120  if (map)
121  {
122  const labelList& reverseFaceMap = map->reverseFaceMap();
123  forAll(baffles, i)
124  {
125  label f0 = reverseFaceMap[baffles[i].first()];
126  label f1 = reverseFaceMap[baffles[i].second()];
127  baffles[i] = labelPair(f0, f1);
128  }
129  }
130  }
131 
132 
133 
134  // Now we have all patches determine the number of layer per patch
135  // This will be layerParams.numLayers() except for faceZones where one
136  // side does get layers and the other not in which case we want to
137  // suppress movement by explicitly setting numLayers 0
138  labelList numLayers(layerParams.numLayers());
139  {
140  labelHashSet layerIDs(patchIDs);
141  forAll(mesh.faceZones(), zonei)
142  {
143  label mpi, spi;
145  bool hasInfo = meshRefiner_.getFaceZoneInfo
146  (
147  mesh.faceZones()[zonei].name(),
148  mpi,
149  spi,
150  fzType
151  );
152  if (hasInfo)
153  {
154  const polyBoundaryMesh& pbm = mesh.boundaryMesh();
155  if (layerIDs.found(mpi) && !layerIDs.found(spi))
156  {
157  // Only layers on master side. Fix points on slave side
158  Info<< "On faceZone " << mesh.faceZones()[zonei].name()
159  << " adding layers to master patch " << pbm[mpi].name()
160  << " only. Freezing points on slave patch "
161  << pbm[spi].name() << endl;
162  numLayers[spi] = 0;
163  }
164  else if (!layerIDs.found(mpi) && layerIDs.found(spi))
165  {
166  // Only layers on slave side. Fix points on master side
167  Info<< "On faceZone " << mesh.faceZones()[zonei].name()
168  << " adding layers to slave patch " << pbm[spi].name()
169  << " only. Freezing points on master patch "
170  << pbm[mpi].name() << endl;
171  numLayers[mpi] = 0;
172  }
173  }
174  }
175  }
176 
177 
178  // Duplicate points on faceZones that layers are added to
179  labelList pointToMaster;
180  dupFaceZonePoints
181  (
182  patchIDs, // patch indices
183  numLayers, // number of layers per patch
184  baffles,
185  pointToMaster
186  );
187 
188 
189  // Add layers to patches
190  // ~~~~~~~~~~~~~~~~~~~~~
191 
192  // Now we have
193  // - mesh with optional baffles and duplicated points for faceZones
194  // where layers are to be added
195  // - pointToMaster : correspondence for duplicated points
196  // - baffles : list of pairs of faces
197 
198 
200  (
202  (
203  mesh,
204  patchIDs
205  )
206  );
207 
208 
209  // Global face indices engine
210  const globalIndex globalFaces(mesh.nFaces());
211 
212  // Determine extrudePatch.edgeFaces in global numbering (so across
213  // coupled patches). This is used only to string up edges between coupled
214  // faces (all edges between same (global)face indices get extruded).
215  const labelListList edgeGlobalFaces
216  (
218  (
219  mesh,
220  globalFaces,
221  *pp
222  )
223  );
224 
225  // Determine patches for extruded boundary edges. Calculates if any
226  // additional processor patches need to be constructed.
227 
228  labelList edgePatchID;
229  labelList edgeZoneID;
230  boolList edgeFlip;
231  labelList inflateFaceID;
232  determineSidePatches
233  (
234  globalFaces,
235  edgeGlobalFaces,
236  *pp,
237 
238  edgePatchID,
239  edgeZoneID,
240  edgeFlip,
241  inflateFaceID
242  );
243 
244 
245  // Point-wise extrusion data
246  // ~~~~~~~~~~~~~~~~~~~~~~~~~
247 
248  // Displacement for all pp.localPoints. Set to large value so does
249  // not trigger the minThickness truncation (see syncPatchDisplacement below)
250  vectorField patchDisp(pp().nPoints(), vector(GREAT, GREAT, GREAT));
251 
252  // Number of layers for all pp.localPoints. Note: only valid if
253  // extrudeStatus = EXTRUDE.
254  labelList patchNLayers(pp().nPoints(), Zero);
255 
256  // Whether to add edge for all pp.localPoints.
257  List<extrudeMode> extrudeStatus(pp().nPoints(), EXTRUDE);
258 
259  // Ideal number of cells added
260  const label nIdealTotAddedCells = setPointNumLayers
261  (
262  layerParams,
263 
264  numLayers,
265  patchIDs,
266  pp(),
267  edgeGlobalFaces,
268 
269  patchDisp,
270  patchNLayers,
271  extrudeStatus
272  );
273 
274  // Determine (wanted) point-wise overall layer thickness and expansion
275  // ratio
276  scalarField thickness(pp().nPoints());
277  scalarIOField minThickness
278  (
279  IOobject
280  (
281  "minThickness",
282  meshRefiner_.timeName(),
283  mesh,
285  ),
286  pp().nPoints()
287  );
288  scalarField expansionRatio(pp().nPoints());
289  calculateLayerThickness
290  (
291  *pp,
292  patchIDs,
293  layerParams,
294  meshRefiner_.meshCutter().cellLevel(),
295  patchNLayers,
296  edge0Len,
297 
298  thickness,
299  minThickness,
300  expansionRatio
301  );
302 
303 
304 
305  // Per cell 0 or number of layers in the cell column it is part of
306  labelList cellNLayers;
307  // Per face actual overall layer thickness
308  scalarField faceRealThickness;
309  // Per face wanted overall layer thickness
310  scalarField faceWantedThickness(mesh.nFaces(), Zero);
311  {
312  UIndirectList<scalar>(faceWantedThickness, pp->addressing()) =
313  avgPointData(*pp, thickness);
314  }
315 
316 
317  // Current set of topology changes. (changing mesh clears out
318  // polyTopoChange)
319  polyTopoChange meshMod(mesh.boundaryMesh().size());
320 
321  // Play changes into meshMod
322  addLayers
323  (
324  layerParams,
325  layerParams.nLayerIter(),
326 
327  // Mesh quality
328  motionDict,
329  layerParams.nRelaxedIter(),
330  nAllowableErrors,
331 
332  patchIDs,
333  internalFaceZones,
334  baffles,
335  numLayers,
336  nIdealTotAddedCells,
337 
338  // Patch information
339  globalFaces,
340  pp(),
341  edgeGlobalFaces,
342  edgePatchID,
343  edgeZoneID,
344  edgeFlip,
345  inflateFaceID,
346 
347  // Per patch point the wanted thickness
348  thickness,
349  minThickness,
350  expansionRatio,
351 
352  // Per patch point the obtained thickness
353  patchDisp,
354  patchNLayers,
355  extrudeStatus,
356 
357  // Complete mesh changes
358  meshMod,
359 
360  // Stats
361  cellNLayers,
362  faceRealThickness
363  );
364 
365 
366  // At this point we have a (shrunk) mesh and a set of topology changes
367  // which will make a valid mesh with layer. Apply these changes to the
368  // current mesh.
369 
370  {
371  // Apply the stored topo changes to the current mesh.
372  autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh, false);
373 
374  mapPolyMesh& map = *mapPtr;
375 
376  // Hack to remove meshPhi - mapped incorrectly. TBD.
377  mesh.moving(false);
378  mesh.clearOut();
379 
380  // Update fields
381  mesh.updateMesh(map);
382 
383  // Move mesh (since morphing does not do this)
384  if (map.hasMotionPoints())
385  {
386  mesh.movePoints(map.preMotionPoints());
387  }
388  else
389  {
390  // Delete mesh volumes.
391  mesh.clearOut();
392  }
393 
394  // Reset the instance for if in overwrite mode
395  mesh.setInstance(meshRefiner_.timeName());
396 
397  meshRefiner_.updateMesh(map, labelList(0));
398 
399  // Update numbering of faceWantedThickness
401  (
402  map.faceMap(),
403  scalar(0),
404  faceWantedThickness
405  );
406 
407  // Print data now that we still have patches for the zones
408  //if (meshRefinement::outputLevel() & meshRefinement::OUTPUTLAYERINFO)
409  printLayerData
410  (
411  mesh,
412  patchIDs,
413  cellNLayers,
414  faceWantedThickness,
415  faceRealThickness,
416  layerParams
417  );
418 
419 
420  // Dump for debugging
422  {
423  const_cast<Time&>(mesh.time())++;
424  Info<< "Writing mesh with layers but disconnected to time "
425  << meshRefiner_.timeName() << endl;
426  meshRefiner_.write
427  (
430  (
433  ),
434  mesh.time().path()/meshRefiner_.timeName()
435  );
436  }
437 
438 
439  // Map baffles, pointToMaster
440  mapFaceZonePoints(map, baffles, pointToMaster);
441  }
442 
443 
444  // Merge baffles
445  mergeFaceZonePoints
446  (
447  pointToMaster, // -1 or index of duplicated point
448  cellNLayers,
449  faceRealThickness,
450  faceWantedThickness
451  );
452 
453 
454  // Do final balancing
455  // ~~~~~~~~~~~~~~~~~~
456 
457  if (Pstream::parRun())
458  {
459  Info<< nl
460  << "Doing final balancing" << nl
461  << "---------------------" << nl
462  << endl;
463 
464  if (debug)
465  {
466  const_cast<Time&>(mesh.time())++;
467  }
468 
469  // Balance. No restriction on face zones and baffles.
470  autoPtr<mapDistributePolyMesh> map = meshRefiner_.balance
471  (
472  false,
473  false,
474  scalarField(mesh.nCells(), 1.0),
475  decomposer,
476  distributor
477  );
478 
479  // Re-distribute flag of layer faces and cells
480  map().distributeCellData(cellNLayers);
481  map().distributeFaceData(faceWantedThickness);
482  map().distributeFaceData(faceRealThickness);
483  }
484 
485 
486  // Write mesh data
487  // ~~~~~~~~~~~~~~~
488 
489  if (!dryRun_)
490  {
491  writeLayerData
492  (
493  mesh,
494  patchIDs,
495  cellNLayers,
496  faceWantedThickness,
497  faceRealThickness
498  );
499  }
500 }
501 
502 
503 // ************************************************************************* //
const labelList patchIDs(pbm.indices(polyPatchNames, true))
const polyBoundaryMesh & pbm
Simple container to keep together layer specific information.
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
bool found(const Key &key) const
Same as contains()
Definition: HashTable.H:1354
bool getFaceZoneInfo(const word &fzName, label &masterPatchID, label &slavePatchID, surfaceZonesInfo::faceZoneType &fzType) const
Lookup faceZone information. Return false if no information.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1049
static writeType writeLevel()
Get/set write level.
labelList getZones(const List< surfaceZonesInfo::faceZoneType > &fzTypes) const
Get zones of given type.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
bool hasMotionPoints() const
Has valid preMotionPoints?
Definition: mapPolyMesh.H:764
const labelList & numLayers() const
How many layers to add.
scalar level0EdgeLength() const
Typical edge length between unrefined points.
Definition: hexRef8.H:499
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:157
const fvMesh & mesh() const
Reference to mesh.
label nRelaxedIter() const
Number of iterations after which relaxed motion rules.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
static void updateList(const labelList &newToOld, const T &nullValue, List< T > &elems)
Helper: reorder list according to map.
void addLayersSinglePass(const layerParameters &layerParams, const dictionary &motionDict, const labelList &patchIDs, const label nAllowableErrors, decompositionMethod &decomposer, fvMeshDistribute &distributor)
For debugging. Can be removed.
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:61
Sends/receives parts of mesh+fvfields to neighbouring processors. Used in load balancing.
dynamicFvMesh & mesh
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i), works like std::iota() but returning a...
Definition: labelLists.C:44
label nPoints
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Abstract base class for domain decomposition.
autoPtr< mapDistributePolyMesh > balance(const bool keepZoneFaces, const bool keepBaffles, const scalarField &cellWeights, decompositionMethod &decomposer, fvMeshDistribute &distributor)
Redecompose according to cell count.
Vector< scalar > vector
Definition: vector.H:57
label nLayerIter() const
Number of overall layer addition iterations.
word timeName() const
Replacement for Time::timeName() that returns oldInstance (if overwrite_)
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO...
const hexRef8 & meshCutter() const
Reference to meshcutting engine.
int debug
Static debugging option.
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:51
static autoPtr< indirectPrimitivePatch > makePatch(const polyMesh &, const labelList &)
Create patch from set of patches.
const labelList & faceMap() const
Old face map.
Definition: mapPolyMesh.H:500
void updateMesh(const mapPolyMesh &, const labelList &changedFaces)
Update for external change to mesh. changedFaces are in new mesh.
autoPtr< mapPolyMesh > createZoneBaffles(const labelList &zoneIDs, List< labelPair > &baffles, labelList &originatingFaceZone)
Create baffles for faces on faceZones. Return created baffles.
autoPtr< mapPolyMesh > dupNonManifoldBoundaryPoints()
Find boundary points that are on faceZones of type boundary.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
A List with indirect addressing. Like IndirectList but does not store addressing. ...
Definition: faMatrix.H:56
Direct mesh changes based on v1.3 polyTopoChange syntax.
Nothing to be read.
messageStream Info
Information stream (stdout output on master, null elsewhere)
writeType
Enumeration for what to write. Used as a bit-pattern.
static labelListList globalEdgeFaces(const polyMesh &, const globalIndex &globalFaces, const indirectPrimitivePatch &pp)
Per patch edge the pp faces (in global indices) using it.
faceZoneType
What to do with faceZone faces.
debugType
Enumeration for what to debug. Used as a bit-pattern.
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
void addLayers(const layerParameters &layerParams, const label nLayerIter, const dictionary &motionDict, const label nRelaxedIter, const label nAllowableErrors, const labelList &patchIDs, const labelList &internalFaceZones, const List< labelPair > &baffles, const labelList &numLayers, const label nIdealTotAddedCells, const globalIndex &globalFaces, indirectPrimitivePatch &pp, const labelListList &edgeGlobalFaces, const labelList &edgePatchID, const labelList &edgeZoneID, const boolList &edgeFlip, const labelList &inflateFaceID, const scalarField &thickness, const scalarIOField &minThickness, const scalarField &expansionRatio, vectorField &patchDisp, labelList &patchNLayers, List< extrudeMode > &extrudeStatus, polyTopoChange &savedMeshMod, labelList &cellNLayers, scalarField &faceRealThickness)
bool write() const
Write mesh and all data.
List< label > labelList
A List of labels.
Definition: List.H:62
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:172
A primitive field of type <T> with automated input and output.
const labelIOList & cellLevel() const
Definition: hexRef8.H:481
const pointField & preMotionPoints() const
Pre-motion point positions.
Definition: mapPolyMesh.H:756
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127