Loading...
Searching...
No Matches
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"
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 {
119 autoPtr<mapPolyMesh> map = meshRefiner_.dupNonManifoldBoundaryPoints();
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;
181 (
182 meshRefiner_,
183 patchIDs, // patch indices
184 numLayers, // number of layers per patch
185 baffles,
186 pointToMaster
187 );
188
189
190 // Add layers to patches
191 // ~~~~~~~~~~~~~~~~~~~~~
192
193 // Now we have
194 // - mesh with optional baffles and duplicated points for faceZones
195 // where layers are to be added
196 // - pointToMaster : correspondence for duplicated points
197 // - baffles : list of pairs of faces
198
199
201 (
203 (
204 mesh,
206 )
207 );
208
209
210 // Global face indices engine
211 const globalIndex globalFaces(mesh.nFaces());
212
213 // Determine extrudePatch.edgeFaces in global numbering (so across
214 // coupled patches). This is used only to string up edges between coupled
215 // faces (all edges between same (global)face indices get extruded).
216 const labelListList edgeGlobalFaces
217 (
219 (
220 mesh,
221 globalFaces,
222 *pp
223 )
224 );
225
226 // Determine patches for extruded boundary edges. Calculates if any
227 // additional processor patches need to be constructed.
228
229 labelList edgePatchID;
230 labelList edgeZoneID;
231 boolList edgeFlip;
232 labelList inflateFaceID;
234 (
235 meshRefiner_,
236 globalFaces,
237 edgeGlobalFaces,
238 *pp,
239
240 edgePatchID,
241 edgeZoneID,
242 edgeFlip,
243 inflateFaceID
244 );
245
246
247 // Point-wise extrusion data
248 // ~~~~~~~~~~~~~~~~~~~~~~~~~
249
250 // Displacement for all pp.localPoints. Set to large value so does
251 // not trigger the minThickness truncation (see syncPatchDisplacement below)
252 vectorField patchDisp(pp().nPoints(), vector(GREAT, GREAT, GREAT));
253
254 // Number of layers for all pp.localPoints. Note: only valid if
255 // extrudeStatus = EXTRUDE.
256 labelList patchNLayers(pp().nPoints(), Zero);
257
258 // Whether to add edge for all pp.localPoints.
259 List<extrudeMode> extrudeStatus(pp().nPoints(), EXTRUDE);
260
261 // Ideal number of cells added
262 const label nIdealTotAddedCells = setPointNumLayers
263 (
264 layerParams,
265
266 numLayers,
267 patchIDs,
268 pp(),
269 edgeGlobalFaces,
270
271 patchDisp,
272 patchNLayers,
273 extrudeStatus
274 );
275
276 // Determine (wanted) point-wise overall layer thickness and expansion
277 // ratio
278 scalarField thickness(pp().nPoints());
279 scalarIOField minThickness
280 (
282 (
283 "minThickness",
284 meshRefiner_.timeName(),
285 mesh,
287 ),
288 pp().nPoints()
289 );
290 scalarField expansionRatio(pp().nPoints());
291 calculateLayerThickness
292 (
293 *pp,
294 patchIDs,
295 layerParams,
296 meshRefiner_.meshCutter().cellLevel(),
297 patchNLayers,
298 edge0Len,
299
300 thickness,
301 minThickness,
302 expansionRatio
303 );
304
305
306
307 // Per cell 0 or number of layers in the cell column it is part of
308 labelList cellNLayers;
309 // Per face actual overall layer thickness
310 scalarField faceRealThickness;
311 // Per face wanted overall layer thickness
312 scalarField faceWantedThickness(mesh.nFaces(), Zero);
313 {
314 UIndirectList<scalar>(faceWantedThickness, pp->addressing()) =
315 avgPointData(*pp, thickness);
316 }
317
318
319 // Current set of topology changes. (changing mesh clears out
320 // polyTopoChange)
321 polyTopoChange meshMod(mesh.boundaryMesh().size());
322
323 // Play changes into meshMod
325 (
326 layerParams,
327 layerParams.nLayerIter(),
328
329 // Mesh quality
330 motionDict,
331 layerParams.nRelaxedIter(),
332 nAllowableErrors,
333
334 patchIDs,
335 internalFaceZones,
336 baffles,
337 numLayers,
338 nIdealTotAddedCells,
339
340 // Patch information
341 globalFaces,
342 pp(),
343 edgeGlobalFaces,
344 edgePatchID,
345 edgeZoneID,
346 edgeFlip,
347 inflateFaceID,
348
349 // Per patch point the wanted thickness
350 thickness,
351 minThickness,
352 expansionRatio,
353
354 // Per patch point the obtained thickness
355 patchDisp,
356 patchNLayers,
357 extrudeStatus,
358
359 // Complete mesh changes
360 meshMod,
361
362 // Stats
363 cellNLayers,
364 faceRealThickness
365 );
366
367
368 // At this point we have a (shrunk) mesh and a set of topology changes
369 // which will make a valid mesh with layer. Apply these changes to the
370 // current mesh.
371
372 {
373 // Apply the stored topo changes to the current mesh.
374 autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh, false);
375
376 mapPolyMesh& map = *mapPtr;
377
378 // Hack to remove meshPhi - mapped incorrectly. TBD.
379 mesh.moving(false);
380 mesh.clearOut();
381
382 // Update fields
383 mesh.updateMesh(map);
384
385 // Move mesh (since morphing does not do this)
386 if (map.hasMotionPoints())
387 {
388 mesh.movePoints(map.preMotionPoints());
389 }
390 else
391 {
392 // Delete mesh volumes.
393 mesh.clearOut();
394 }
395
396 // Reset the instance for if in overwrite mode
397 mesh.setInstance(meshRefiner_.timeName());
398
399 meshRefiner_.updateMesh(map, labelList(0));
400
401 // Update numbering of faceWantedThickness
403 (
404 map.faceMap(),
405 scalar(0),
406 faceWantedThickness
407 );
408
409 // Print data now that we still have patches for the zones
410 //if (meshRefinement::outputLevel() & meshRefinement::OUTPUTLAYERINFO)
411 printLayerData
412 (
413 mesh,
414 patchIDs,
415 cellNLayers,
416 faceWantedThickness,
417 faceRealThickness,
418 layerParams
419 );
420
421
422 // Dump for debugging
424 {
425 const_cast<Time&>(mesh.time())++;
426 Info<< "Writing mesh with layers but disconnected to time "
427 << meshRefiner_.timeName() << endl;
428 meshRefiner_.write
429 (
432 (
435 ),
436 mesh.time().path()/meshRefiner_.timeName()
437 );
438 }
439
440
441 // Map baffles, pointToMaster
442 mapFaceZonePoints(meshRefiner_, map, baffles, pointToMaster);
443 }
444
445
446 // Merge baffles
447 mergeFaceZonePoints
448 (
449 pointToMaster, // -1 or index of duplicated point
450 cellNLayers,
451 faceRealThickness,
452 faceWantedThickness
453 );
454
455
456 // Do final balancing
457 // ~~~~~~~~~~~~~~~~~~
458
459 if (Pstream::parRun())
460 {
461 Info<< nl
462 << "Doing final balancing" << nl
463 << "---------------------" << nl
464 << endl;
465
466 if (debug)
467 {
468 const_cast<Time&>(mesh.time())++;
469 }
470
471 // Balance. No restriction on face zones and baffles.
472 autoPtr<mapDistributePolyMesh> map = meshRefiner_.balance
473 (
474 false,
475 false,
477 scalarField(mesh.nCells(), 1.0),
478 decomposer,
479 distributor
480 );
481
482 // Re-distribute flag of layer faces and cells
483 map().distributeCellData(cellNLayers);
484 map().distributeFaceData(faceWantedThickness);
485 map().distributeFaceData(faceRealThickness);
486 }
487
488
489 // Write mesh data
490 // ~~~~~~~~~~~~~~~
491
492 if (!dryRun_)
493 {
494 writeLayerData
495 (
496 mesh,
497 patchIDs,
498 cellNLayers,
499 faceWantedThickness,
500 faceRealThickness
501 );
502 }
503}
504
505
506// ************************************************************************* //
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
labelList patchIDs
const polyBoundaryMesh & pbm
bool found(const Key &key) const
Same as contains().
Definition HashTable.H:1370
@ NO_READ
Nothing to be read.
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition IOobject.H:191
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
static const List< label > & null() noexcept
Definition List.H:138
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition Time.H:75
A List with indirect addressing. Like IndirectList but does not store addressing.
T & first()
Access first element of the list, position [0].
Definition UList.H:957
static bool parRun(const bool on) noexcept
Set as parallel run on/off.
Definition UPstream.H:1669
static labelListList globalEdgeFaces(const polyMesh &, const globalIndex &globalFaces, const indirectPrimitivePatch &pp, const bitSet &orientation)
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:65
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:133
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:85
Calculates a non-overlapping list of offsets based on an input size (eg, number of cells) from differ...
Definition globalIndex.H:77
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.
const pointField & preMotionPoints() const noexcept
Pre-motion point positions.
const labelList & faceMap() const noexcept
Old face map.
bool hasMotionPoints() const noexcept
Has valid preMotionPoints?
writeType
Enumeration for what to write. Used as a bit-pattern.
debugType
Enumeration for what to debug. Used as a bit-pattern.
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.
static writeType writeLevel()
Get/set write level.
A polyBoundaryMesh is a polyPatch list with registered IO, a reference to the associated polyMesh,...
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.
void addLayersSinglePass(const layerParameters &layerParams, const dictionary &motionDict, const labelList &patchIDs, const label nAllowableErrors, decompositionMethod &decomposer, fvMeshDistribute &distributor)
For debugging. Can be removed.
static autoPtr< mapPolyMesh > dupFaceZonePoints(meshRefinement &meshRefiner, const labelList &patchIDs, const labelList &numLayers, List< labelPair > baffles, labelList &pointToMaster)
Duplicate points on faceZones with layers. Re-used when adding buffer layers. Can be made private aga...
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)
static void determineSidePatches(meshRefinement &meshRefiner, const globalIndex &globalFaces, const labelListList &edgeGlobalFaces, const indirectPrimitivePatch &pp, labelList &edgePatchID, labelList &edgeZoneID, boolList &edgeFlip, labelList &inflateFaceID)
Helper: see what zones and patches edges should be extruded into.
static void mapFaceZonePoints(meshRefinement &meshRefiner, const mapPolyMesh &map, labelPairList &baffles, labelList &pointToMaster)
Map numbering after adding cell layers.
faceZoneType
What to do with faceZone faces.
dynamicFvMesh & mesh
label nPoints
Namespace for handling debugging switches.
Definition debug.C:45
Pair< label > labelPair
A pair of labels.
Definition Pair.H:54
List< labelList > labelListList
List of labelList.
Definition labelList.H:38
List< label > labelList
A List of labels.
Definition List.H:62
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition HashSet.H:85
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:519
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...
Field< vector > vectorField
Specialisation of Field<T> for vector.
List< bool > boolList
A List of bools.
Definition List.H:60
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
Vector< scalar > vector
Definition vector.H:57
IOField< scalar > scalarIOField
IO for a Field of scalar.
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299