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-------------------------------------------------------------------------------
10License
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
26Description
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"
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 (
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 (
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)
320
321 // Play changes into meshMod
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 {
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 );
417
418
419 // Dump for debugging
421 {
422 const_cast<Time&>(mesh.time())++;
423 Info<< "Writing mesh with layers but disconnected to time "
424 << meshRefiner_.timeName() << endl;
425 meshRefiner_.write
426 (
429 (
432 ),
433 mesh.time().path()/meshRefiner_.timeName()
434 );
435 }
436
437
438 // Map baffles, pointToMaster
439 mapFaceZonePoints(map, baffles, pointToMaster);
440 }
441
442
443 // Merge baffles
444 mergeFaceZonePoints
445 (
446 pointToMaster, // -1 or index of duplicated point
447 cellNLayers,
448 faceRealThickness,
449 faceWantedThickness
450 );
451
452
453 // Do final balancing
454 // ~~~~~~~~~~~~~~~~~~
455
456 if (Pstream::parRun())
457 {
458 Info<< nl
459 << "Doing final balancing" << nl
460 << "---------------------" << nl
461 << endl;
462
463 if (debug)
464 {
465 const_cast<Time&>(mesh.time())++;
466 }
467
468 // Balance. No restriction on face zones and baffles.
469 autoPtr<mapDistributePolyMesh> map = meshRefiner_.balance
470 (
471 false,
472 false,
473 scalarField(mesh.nCells(), 1.0),
474 decomposer,
475 distributor
476 );
477
478 // Re-distribute flag of layer faces and cells
479 map().distributeCellData(cellNLayers);
480 map().distributeFaceData(faceWantedThickness);
481 map().distributeFaceData(faceRealThickness);
482 }
483
484
485 // Write mesh data
486 // ~~~~~~~~~~~~~~~
487
488 if (!dryRun_)
489 {
490 writeLayerData
491 (
492 mesh,
493 patchIDs,
494 cellNLayers,
495 faceWantedThickness,
496 faceRealThickness
497 );
498 }
499}
500
501
502// ************************************************************************* //
bool found(const Key &key) const
Return true if hashed entry is found in table.
Definition: HashTableI.H:100
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:170
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:65
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:80
fileName path() const
Return path.
Definition: Time.H:358
A List with indirect addressing. Like IndirectList but does not store addressing.
Definition: IndirectList.H:79
T & first()
Return the first element of the list.
Definition: UListI.H:202
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:433
label size() const noexcept
The number of elements in the list.
Definition: UPtrListI.H:106
static labelListList globalEdgeFaces(const polyMesh &, const globalIndex &globalFaces, const indirectPrimitivePatch &pp)
Per patch edge the pp faces (in global indices) using it.
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: autoPtr.H:66
Abstract base class for domain decomposition.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
Sends/receives parts of mesh+fvfields to neighbouring processors. Used in load balancing.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:91
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:290
virtual void updateMesh(const mapPolyMesh &mpm)
Update mesh corresponding to the given map.
Definition: fvMesh.C:971
virtual void movePoints(const pointField &)
Move points, returns volumes swept by faces in motion.
Definition: fvMesh.C:895
void clearOut()
Clear all geometry and addressing.
Definition: fvMesh.C:239
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:68
const labelIOList & cellLevel() const
Definition: hexRef8.H:397
scalar level0EdgeLength() const
Typical edge length between unrefined points.
Definition: hexRef8.H:413
Simple container to keep together layer specific information.
label nRelaxedIter() const
Number of iterations after which relaxed motion rules.
label nLayerIter() const
Number of overall layer addition iterations.
const labelList & numLayers() const
How many layers to add.
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:162
const labelList & faceMap() const
Old face map.
Definition: mapPolyMesh.H:410
const pointField & preMotionPoints() const
Pre-motion point positions.
Definition: mapPolyMesh.H:613
bool hasMotionPoints() const
Has valid preMotionPoints?
Definition: mapPolyMesh.H:619
labelList getZones(const List< surfaceZonesInfo::faceZoneType > &fzTypes) const
Get zones of given type.
bool getFaceZoneInfo(const word &fzName, label &masterPatchID, label &slavePatchID, surfaceZonesInfo::faceZoneType &fzType) const
Lookup faceZone information. Return false if no information.
void updateMesh(const mapPolyMesh &, const labelList &changedFaces)
Update for external change to mesh. changedFaces are in new mesh.
writeType
Enumeration for what to write. Used as a bit-pattern.
const hexRef8 & meshCutter() const
Reference to meshcutting engine.
autoPtr< mapDistributePolyMesh > balance(const bool keepZoneFaces, const bool keepBaffles, const scalarField &cellWeights, decompositionMethod &decomposer, fvMeshDistribute &distributor)
Redecompose according to cell count.
autoPtr< mapPolyMesh > dupNonManifoldBoundaryPoints()
Find boundary points that are on faceZones of type boundary.
debugType
Enumeration for what to debug. Used as a bit-pattern.
const fvMesh & mesh() const
Reference to mesh.
static autoPtr< indirectPrimitivePatch > makePatch(const polyMesh &, const labelList &)
Create patch from set of patches.
static void updateList(const labelList &newToOld, const T &nullValue, List< T > &elems)
Helper: reorder list according to map.
bool write() const
Write mesh and all data.
static writeType writeLevel()
Get/set write level.
autoPtr< mapPolyMesh > createZoneBaffles(const labelList &zoneIDs, List< labelPair > &baffles, labelList &originatingFaceZone)
Create baffles for faces on faceZones. Return created baffles.
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition: polyMesh.H:498
void setInstance(const fileName &instance, const IOobject::writeOption wOpt=IOobject::AUTO_WRITE)
Set the instance for mesh files.
Definition: polyMeshIO.C:36
bool moving() const noexcept
Is mesh moving.
Definition: polyMesh.H:534
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:456
Direct mesh changes based on v1.3 polyTopoChange syntax.
autoPtr< mapPolyMesh > changeMesh(polyMesh &mesh, const labelUList &patchMap, const bool inflate, const bool syncParallel=true, const bool orderCells=false, const bool orderPoints=false)
Inplace changes mesh without change of patches.
label nCells() const noexcept
Number of mesh cells.
label nFaces() const noexcept
Number of mesh faces.
void addLayersSinglePass(const layerParameters &layerParams, const dictionary &motionDict, const labelList &patchIDs, const label nAllowableErrors, decompositionMethod &decomposer, fvMeshDistribute &distributor)
For debugging. Can be removed.
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)
faceZoneType
What to do with faceZone faces.
dynamicFvMesh & mesh
label nPoints
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:57
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i)
Definition: labelList.C:38
List< label > labelList
A List of labels.
Definition: List.H:66
messageStream Info
Information stream (stdout output on master, null elsewhere)
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Vector< scalar > vector
Definition: vector.H:61
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333