Loading...
Searching...
No Matches
singleCellFvMesh.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) 2011-2016 OpenFOAM Foundation
9 Copyright (C) 2019-2022 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
29#include "singleCellFvMesh.H"
30#include "syncTools.H"
32
33// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
34
35void Foam::singleCellFvMesh::agglomerateMesh
36(
37 const fvMesh& mesh,
38 const labelListList& agglom
39)
40{
41 // Conversion is a two step process:
42 // - from original (fine) patch faces to agglomerations (aggloms might not
43 // be in correct patch order)
44 // - from agglomerations to coarse patch faces
45
46 const polyBoundaryMesh& oldPatches = mesh.boundaryMesh();
47
48 // Check agglomeration within patch face range and continuous
49 labelList nAgglom(oldPatches.size(), Zero);
50
51 forAll(oldPatches, patchi)
52 {
53 const polyPatch& pp = oldPatches[patchi];
54 if (pp.size() > 0)
55 {
56 if (agglom[patchi].size() != pp.size())
57 {
59 << "agglomeration on patch " << patchi
60 << " (size " << pp.size()
61 << ") is of size " << agglom[patchi].size()
62 << exit(FatalError);
63 }
64
65 nAgglom[patchi] = max(agglom[patchi])+1;
66
67 forAll(pp, i)
68 {
69 if (agglom[patchi][i] < 0 || agglom[patchi][i] >= pp.size())
70 {
72 << "agglomeration on patch " << patchi
73 << " is out of range 0.." << pp.size()-1
74 << exit(FatalError);
75 }
76 }
77 }
78 }
79
80 // Check agglomeration is sync
81 {
82 // Get neighbouring agglomeration
83 labelList nbrAgglom(mesh.nBoundaryFaces());
84 forAll(oldPatches, patchi)
85 {
86 const polyPatch& pp = oldPatches[patchi];
87
88 if (pp.coupled())
89 {
90 label offset = pp.start()-mesh.nInternalFaces();
91 forAll(pp, i)
92 {
93 nbrAgglom[offset+i] = agglom[patchi][i];
94 }
95 }
96 }
98
99
100 // Get correspondence between this agglomeration and remote one
101 Map<label> localToNbr(nbrAgglom.size()/10);
102
103 forAll(oldPatches, patchi)
104 {
105 const polyPatch& pp = oldPatches[patchi];
106
107 if (pp.coupled())
108 {
109 label offset = pp.start()-mesh.nInternalFaces();
110
111 forAll(pp, i)
112 {
113 label bFacei = offset+i;
114 label myZone = agglom[patchi][i];
115 label nbrZone = nbrAgglom[bFacei];
116
117 const auto iter = localToNbr.cfind(myZone);
118
119 if (iter.good())
120 {
121 // Check that zone numbers are still the same.
122 if (iter.val() != nbrZone)
123 {
125 << "agglomeration is not synchronised across"
126 << " coupled patch " << pp.name()
127 << endl
128 << "Local agglomeration " << myZone
129 << ". Remote agglomeration " << nbrZone
130 << exit(FatalError);
131 }
132 }
133 else
134 {
135 // First occurrence of this zone. Store correspondence
136 // to remote zone number.
137 localToNbr.insert(myZone, nbrZone);
138 }
139 }
140 }
141 }
142 }
143
144
145 label coarseI = 0;
146 forAll(nAgglom, patchi)
147 {
148 coarseI += nAgglom[patchi];
149 }
150 // New faces
151 faceList patchFaces(coarseI);
152 // New patch start and size
153 labelList patchStarts(oldPatches.size());
154 labelList patchSizes(oldPatches.size());
155
156 // From new patch face back to agglomeration
157 patchFaceMap_.setSize(oldPatches.size());
158
159 // From fine face to coarse face (or -1)
160 reverseFaceMap_.setSize(mesh.nFaces());
161 reverseFaceMap_.labelList::operator=(-1);
162
163 // Face counter
164 coarseI = 0;
165
166
167 forAll(oldPatches, patchi)
168 {
169 patchStarts[patchi] = coarseI;
170
171 const polyPatch& pp = oldPatches[patchi];
172
173 if (pp.size() > 0)
174 {
175 patchFaceMap_[patchi].setSize(nAgglom[patchi]);
176
177 // Patchfaces per agglomeration
178 labelListList agglomToPatch
179 (
180 invertOneToMany(nAgglom[patchi], agglom[patchi])
181 );
182
183 // From agglomeration to compact patch face
184 labelList agglomToFace(nAgglom[patchi], -1);
185
186 forAll(pp, i)
187 {
188 label myAgglom = agglom[patchi][i];
189
190 if (agglomToFace[myAgglom] == -1)
191 {
192 // Agglomeration not yet done. We now have:
193 // - coarseI : current coarse mesh face
194 // - patchStarts[patchi] : coarse mesh patch start
195 // - myAgglom : agglomeration
196 // - agglomToPatch[myAgglom] : fine mesh faces for zone
197 label coarsePatchFacei = coarseI - patchStarts[patchi];
198 patchFaceMap_[patchi][coarsePatchFacei] = myAgglom;
199 agglomToFace[myAgglom] = coarsePatchFacei;
200
201 const labelList& fineFaces = agglomToPatch[myAgglom];
202
203 // Create overall map from fine mesh faces to coarseI.
204 forAll(fineFaces, fineI)
205 {
206 reverseFaceMap_[pp.start()+fineFaces[fineI]] = coarseI;
207 }
208
209 // Construct single face
211 (
212 UIndirectList<face>(pp, fineFaces),
213 pp.points()
214 );
215
216 if (upp.edgeLoops().size() != 1)
217 {
219 << "agglomeration does not create a"
220 << " single, non-manifold"
221 << " face for agglomeration " << myAgglom
222 << " on patch " << patchi
223 << exit(FatalError);
224 }
225
226 patchFaces[coarseI++] = face
227 (
229 (
230 upp.meshPoints(),
231 upp.edgeLoops()[0]
232 )
233 );
234 }
235 }
236 }
237
238 patchSizes[patchi] = coarseI-patchStarts[patchi];
239 }
240
241 //patchFaces.setSize(coarseI);
242 //Pout<< "patchStarts:" << patchStarts << endl;
243 //Pout<< "patchSizes:" << patchSizes << endl;
244
245 // Compact numbering for points
246 reversePointMap_.setSize(mesh.nPoints());
247 reversePointMap_.labelList::operator=(-1);
248 label newI = 0;
249
250 forAll(patchFaces, coarseI)
251 {
252 face& f = patchFaces[coarseI];
253
254 forAll(f, fp)
255 {
256 if (reversePointMap_[f[fp]] == -1)
257 {
258 reversePointMap_[f[fp]] = newI++;
259 }
260
261 f[fp] = reversePointMap_[f[fp]];
262 }
263 }
264
265 pointMap_ = invert(newI, reversePointMap_);
266
267 // Subset used points
268 pointField boundaryPoints(mesh.points(), pointMap_);
269
270 // Add patches (on still zero sized mesh)
271 polyPatchList newPatches(oldPatches.size());
272 forAll(oldPatches, patchi)
273 {
274 newPatches.set
275 (
276 patchi,
277 oldPatches[patchi].clone
278 (
279 boundaryMesh(),
280 patchi,
281 0,
282 0
283 )
284 );
285 }
286 addFvPatches(newPatches);
287
288 const label nFace = patchFaces.size();
289
290 // Actually change the mesh. // Owner, neighbour is trivial
292 (
293 autoPtr<pointField>::New(std::move(boundaryPoints)),
294 autoPtr<faceList>::New(std::move(patchFaces)),
295 autoPtr<labelList>::New(nFace, Zero), // owner
296 autoPtr<labelList>::New(), // neighbour
297 patchSizes,
298 patchStarts,
299 true // syncPar
300 );
301
302 // Adapt the zones
303 cellZones().clear();
304 cellZones().setSize(mesh.cellZones().size());
305 {
306 forAll(mesh.cellZones(), zoneI)
307 {
308 const cellZone& oldFz = mesh.cellZones()[zoneI];
309
310 DynamicList<label> newAddressing;
311
312 //Note: uncomment if you think it makes sense. Note that value
313 // of cell0 is the average.
315 //if (oldFz.localID(0) != -1)
316 //{
317 // newAddressing.append(0);
318 //}
319
320 cellZones().set
321 (
322 zoneI,
323 oldFz.clone
324 (
325 newAddressing,
326 zoneI,
327 cellZones()
328 )
329 );
330 }
331 }
332
333 faceZones().clear();
334 faceZones().setSize(mesh.faceZones().size());
335 {
336 forAll(mesh.faceZones(), zoneI)
337 {
338 const faceZone& oldFz = mesh.faceZones()[zoneI];
339
340 DynamicList<label> newAddressing(oldFz.size());
341 DynamicList<bool> newFlipMap(oldFz.size());
342
343 forAll(oldFz, i)
344 {
345 label newFacei = reverseFaceMap_[oldFz[i]];
346
347 if (newFacei != -1)
348 {
349 newAddressing.append(newFacei);
350 newFlipMap.append(oldFz.flipMap()[i]);
351 }
352 }
353
354 faceZones().set
355 (
356 zoneI,
357 oldFz.clone
358 (
359 newAddressing,
360 newFlipMap,
361 zoneI,
362 faceZones()
363 )
364 );
365 }
366 }
367
368
369 pointZones().clear();
370 pointZones().setSize(mesh.pointZones().size());
371 {
372 forAll(mesh.pointZones(), zoneI)
373 {
374 const pointZone& oldFz = mesh.pointZones()[zoneI];
375
376 DynamicList<label> newAddressing(oldFz.size());
377
378 forAll(oldFz, i)
379 {
380 label newPointi = reversePointMap_[oldFz[i]];
381 if (newPointi != -1)
382 {
383 newAddressing.append(newPointi);
384 }
385 }
386
388 (
389 zoneI,
390 oldFz.clone
391 (
392 pointZones(),
393 zoneI,
394 newAddressing
395 )
396 );
397 }
398 }
399
400 // Make sure we don't start dumping mesh every timestep (since
401 // resetPrimitives sets AUTO_WRITE)
403}
404
405
406// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
407
408Foam::singleCellFvMesh::singleCellFvMesh
409(
410 const IOobject& io,
411 const fvMesh& mesh,
412 const bool doInit
413)
414:
415 fvMesh(io, Zero, false),
416 patchFaceAgglomeration_
417 (
419 (
420 "patchFaceAgglomeration",
421 io.instance(),
422 fvMesh::meshSubDir,
423 *this,
424 io.readOpt(),
425 io.writeOpt()
426 ),
427 0
428 ),
429 patchFaceMap_
430 (
432 (
433 "patchFaceMap",
434 io.instance(),
435 fvMesh::meshSubDir,
436 *this,
437 io.readOpt(),
438 io.writeOpt()
439 ),
440 mesh.boundaryMesh().size()
441 ),
442 reverseFaceMap_
443 (
445 (
446 "reverseFaceMap",
447 io.instance(),
448 fvMesh::meshSubDir,
449 *this,
450 io.readOpt(),
451 io.writeOpt()
452 ),
453 mesh.nFaces()
454 ),
455 pointMap_
456 (
458 (
459 "pointMap",
460 io.instance(),
461 fvMesh::meshSubDir,
462 *this,
463 io.readOpt(),
464 io.writeOpt()
465 ),
466 mesh.nPoints()
467 ),
468 reversePointMap_
469 (
471 (
472 "reversePointMap",
473 io.instance(),
474 fvMesh::meshSubDir,
475 *this,
476 io.readOpt(),
477 io.writeOpt()
478 ),
479 mesh.nPoints()
480 )
481{
482 const polyBoundaryMesh& oldPatches = mesh.boundaryMesh();
483
484 labelListList agglom(oldPatches.size());
485
486 forAll(oldPatches, patchi)
487 {
488 agglom[patchi] = identity(oldPatches[patchi].size());
489 }
490
491 agglomerateMesh(mesh, agglom);
492
493 // initialise all (lower levels and current)
494 if (doInit)
495 {
496 fvMesh::init(true); // initialise fvMesh and underlying levels
497 }
498}
499
500
501Foam::singleCellFvMesh::singleCellFvMesh
502(
503 const IOobject& io,
504 const fvMesh& mesh,
505 const labelListList& patchFaceAgglomeration,
506 const bool doInit
507)
508:
509 fvMesh(io, Zero, false),
510 patchFaceAgglomeration_
511 (
512 IOobject
513 (
514 "patchFaceAgglomeration",
515 io.instance(),
516 fvMesh::meshSubDir,
517 *this,
518 io.readOpt(),
519 io.writeOpt()
520 ),
521 patchFaceAgglomeration
522 ),
523 patchFaceMap_
524 (
525 IOobject
526 (
527 "patchFaceMap",
528 io.instance(),
529 fvMesh::meshSubDir,
530 *this,
531 io.readOpt(),
532 io.writeOpt()
533 ),
534 mesh.boundaryMesh().size()
535 ),
536 reverseFaceMap_
537 (
538 IOobject
539 (
540 "reverseFaceMap",
541 io.instance(),
542 fvMesh::meshSubDir,
543 *this,
544 io.readOpt(),
545 io.writeOpt()
546 ),
547 mesh.nFaces()
548 ),
549 pointMap_
550 (
551 IOobject
552 (
553 "pointMap",
554 io.instance(),
555 fvMesh::meshSubDir,
556 *this,
557 io.readOpt(),
558 io.writeOpt()
559 ),
560 mesh.nPoints()
561 ),
562 reversePointMap_
563 (
564 IOobject
565 (
566 "reversePointMap",
567 io.instance(),
568 fvMesh::meshSubDir,
569 *this,
570 io.readOpt(),
571 io.writeOpt()
572 ),
573 mesh.nPoints()
574 )
575{
576 agglomerateMesh(mesh, patchFaceAgglomeration);
577 // initialise all (lower levels and current)
578 if (doInit)
579 {
580 fvMesh::init(true); // initialise fvMesh and underlying levels
581 }
582}
583
584
585Foam::singleCellFvMesh::singleCellFvMesh(const IOobject& io, const bool doInit)
586:
587 fvMesh(io, doInit),
588 patchFaceAgglomeration_
589 (
590 IOobject
591 (
592 "patchFaceAgglomeration",
593 io.instance(),
594 fvMesh::meshSubDir,
595 *this,
596 io.readOpt(),
597 io.writeOpt()
598 )
599 ),
600 patchFaceMap_
601 (
602 IOobject
603 (
604 "patchFaceMap",
605 io.instance(),
606 fvMesh::meshSubDir,
607 *this,
608 io.readOpt(),
609 io.writeOpt()
610 )
611 ),
612 reverseFaceMap_
613 (
614 IOobject
615 (
616 "reverseFaceMap",
617 io.instance(),
618 fvMesh::meshSubDir,
619 *this,
620 io.readOpt(),
621 io.writeOpt()
622 )
623 ),
624 pointMap_
625 (
626 IOobject
627 (
628 "pointMap",
629 io.instance(),
630 fvMesh::meshSubDir,
631 *this,
632 io.readOpt(),
633 io.writeOpt()
634 )
635 ),
636 reversePointMap_
637 (
638 IOobject
639 (
640 "reversePointMap",
641 io.instance(),
642 fvMesh::meshSubDir,
643 *this,
644 io.readOpt(),
645 io.writeOpt()
646 )
647 )
648{}
649
650
651// ************************************************************************* //
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
label size() const noexcept
Definition HashTable.H:358
readOption readOpt() const noexcept
Get the read option.
writeOption writeOpt() const noexcept
Get the write option.
@ NO_WRITE
Ignore writing from objectRegistry::writeObject().
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition IOobject.H:191
const fileName & instance() const noexcept
Read access to instance path component.
Definition IOobjectI.H:289
const T * set(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie,...
Definition PtrList.H:171
void setSize(const label n)
Same as resize().
Definition PtrList.H:357
label size() const noexcept
The number of entries in the list.
Definition UPtrListI.H:106
void clear()
Clear the zones.
Definition ZoneMesh.C:970
static autoPtr< T > New(Args &&... args)
Construct autoPtr with forwarding arguments.
Definition autoPtr.H:178
Addressing for all faces on surface of mesh. Can either be read from polyMesh or from triSurface....
autoPtr< dictionary > clone() const
Construct and return clone.
Definition dictionary.C:165
Mesh data needed to do the Finite Volume discretisation.
Definition fvMesh.H:85
void addFvPatches(polyPatchList &plist, const bool validBoundary=true)
Add boundary patches. Constructor helper.
Definition fvMesh.C:628
const Time & time() const
Return the top-level database.
Definition fvMesh.H:360
virtual bool init(const bool doInit)
Initialise all non-demand-driven data.
Definition fvMesh.C:262
fvMesh(const fvMesh &)=delete
No copy construct.
A polyBoundaryMesh is a polyPatch list with registered IO, a reference to the associated polyMesh,...
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition polyMesh.H:609
void setInstance(const fileName &instance, const IOobjectOption::writeOption wOpt=IOobject::AUTO_WRITE)
Set the instance for mesh files.
Definition polyMeshIO.C:29
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition polyMesh.H:671
const cellZoneMesh & cellZones() const noexcept
Return cell zone mesh.
Definition polyMesh.H:679
const pointZoneMesh & pointZones() const noexcept
Return point zone mesh.
Definition polyMesh.H:663
static word meshSubDir
Return the mesh sub-directory name (usually "polyMesh").
Definition polyMesh.H:411
void resetPrimitives(autoPtr< pointField > &&points, autoPtr< faceList > &&faces, autoPtr< labelList > &&owner, autoPtr< labelList > &&neighbour, const labelUList &patchSizes, const labelUList &patchStarts, const bool validBoundary=true)
Reset mesh primitive data. Assumes all patch info correct.
Definition polyMesh.C:689
label nPoints() const noexcept
Number of mesh points.
label nFaces() const noexcept
Number of mesh faces.
const labelListList & patchFaceAgglomeration() const noexcept
Fine patch face to agglomeration index addressing.
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues, const bool parRun=UPstream::parRun())
Swap coupled boundary face values. Uses eqOp.
Definition syncTools.H:524
dynamicFvMesh & mesh
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
const auto & io
label nPoints
Different types of constants.
PtrList< polyPatch > polyPatchList
Store lists of polyPatch as a PtrList.
Definition polyPatch.H:61
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:40
List< labelList > labelListList
List of labelList.
Definition labelList.H:38
List< label > labelList
A List of labels.
Definition List.H:62
IntListType renumber(const labelUList &oldToNew, const IntListType &input)
Renumber the values within a list.
List< face > faceList
List of faces.
Definition faceListFwd.H:41
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...
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
labelList invert(const label len, const labelUList &map)
Create an inverse one-to-one mapping.
Definition ListOps.C:28
PrimitivePatch< UIndirectList< face >, const pointField & > uindirectPrimitivePatch
A PrimitivePatch with UIndirectList for the faces, const reference for the point field.
vectorField pointField
pointField is a vectorField.
labelListList invertOneToMany(const label len, const labelUList &map)
Invert one-to-many map. Unmapped elements will be size 0.
Definition ListOps.C:125
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
label newPointi
labelList f(nPoints)
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299