fvMeshToolsProcAddr.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) 2015-2023 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 \*---------------------------------------------------------------------------*/
27 
28 #include "fvMeshTools.H"
29 #include "fileOperation.H"
30 #include "IndirectList.H"
31 #include "labelRange.H"
33 #include "OSspecific.H"
34 
35 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
36 
37 namespace Foam
38 {
39 
40 // Create a reconstruct map.
41 // The baseMeshPtr is non-null (and probably has cells) on the master
42 // is ignored elsewhere.
43 //
44 // The incomming faceProcAddressing is assumed to have flip addressing.
46 (
47  const fvMesh& mesh,
48  const autoPtr<fvMesh>& baseMeshPtr,
49  const labelList& cellProcAddressing,
50  const labelList& faceProcAddressing,
51  const labelList& pointProcAddressing,
52  const labelList& boundaryProcAddressing
53 )
54 {
55  const label nOldPoints = mesh.nPoints();
56  const label nOldFaces = mesh.nFaces();
57  const label nOldCells = mesh.nCells();
58 
60 
61  labelList oldPatchStarts(pbm.size());
62  labelList oldPatchNumPoints(pbm.size());
63  forAll(pbm, patchi)
64  {
65  oldPatchStarts[patchi] = pbm[patchi].start();
66  oldPatchNumPoints[patchi] = pbm[patchi].nPoints();
67  }
68 
69  // Patches: purge -1 entries
70  labelList patchProcAddressing
71  (
73  (
74  boundaryProcAddressing,
75  labelRange::ge0()
76  )
77  );
78 
79 
80  labelListList cellSubMap(Pstream::nProcs());
81  cellSubMap[Pstream::masterNo()] = identity(nOldCells);
82 
83  labelListList faceSubMap(Pstream::nProcs());
84  faceSubMap[Pstream::masterNo()] = identity(nOldFaces);
85 
86  labelListList pointSubMap(Pstream::nProcs());
87  pointSubMap[Pstream::masterNo()] = identity(nOldPoints);
88 
89  labelListList patchSubMap(Pstream::nProcs());
90  patchSubMap[Pstream::masterNo()] = patchProcAddressing;
91 
92 
93  // Gather addressing on master
94  labelListList cellAddressing(Pstream::nProcs());
95  cellAddressing[Pstream::myProcNo()] = cellProcAddressing;
96  Pstream::gatherList(cellAddressing);
97 
98  labelListList faceAddressing(Pstream::nProcs());
99  faceAddressing[Pstream::myProcNo()] = faceProcAddressing;
100  Pstream::gatherList(faceAddressing);
101 
102  labelListList pointAddressing(Pstream::nProcs());
103  pointAddressing[Pstream::myProcNo()] = pointProcAddressing;
104  Pstream::gatherList(pointAddressing);
105 
106  labelListList patchAddressing(Pstream::nProcs());
107  patchAddressing[Pstream::myProcNo()] = patchProcAddressing;
108  Pstream::gatherList(patchAddressing);
109 
110 
111  // NB: can only have a reconstruct on master!
112  if (Pstream::master() && baseMeshPtr && baseMeshPtr->nCells())
113  {
114  const fvMesh& baseMesh = *baseMeshPtr;
115 
116  const label nNewPoints = baseMesh.nPoints();
117  const label nNewFaces = baseMesh.nFaces();
118  const label nNewCells = baseMesh.nCells();
119  const label nNewPatches = baseMesh.boundaryMesh().size();
120 
121  mapDistribute cellMap
122  (
123  nNewCells,
124  std::move(cellSubMap),
125  std::move(cellAddressing)
126  );
127 
129  (
130  nNewFaces,
131  std::move(faceSubMap),
132  std::move(faceAddressing),
133  false, // subHasFlip
134  true // constructHasFlip
135  );
136 
137  mapDistribute pointMap
138  (
139  nNewPoints,
140  std::move(pointSubMap),
141  std::move(pointAddressing)
142  );
143 
144  mapDistribute patchMap
145  (
146  nNewPatches,
147  std::move(patchSubMap),
148  std::move(patchAddressing)
149  );
150 
152  (
153  nOldPoints,
154  nOldFaces,
155  nOldCells,
156  std::move(oldPatchStarts),
157  std::move(oldPatchNumPoints),
158  std::move(pointMap),
159  std::move(faceMap),
160  std::move(cellMap),
161  std::move(patchMap)
162  );
163  }
164  else
165  {
166  // Zero-sized mesh (eg, processor mesh)
167 
168  mapDistribute cellMap
169  (
170  0, // nNewCells
171  std::move(cellSubMap),
172  labelListList(Pstream::nProcs()) // constructMap
173  );
174 
176  (
177  0, // nNewFaces
178  std::move(faceSubMap),
179  labelListList(Pstream::nProcs()), // constructMap
180  false, // subHasFlip
181  true // constructHasFlip
182  );
183 
184  mapDistribute pointMap
185  (
186  0, // nNewPoints
187  std::move(pointSubMap),
188  labelListList(Pstream::nProcs()) // constructMap
189  );
190 
191  mapDistribute patchMap
192  (
193  0, // nNewPatches
194  std::move(patchSubMap),
195  labelListList(Pstream::nProcs()) // constructMap
196  );
197 
199  (
200  nOldPoints,
201  nOldFaces,
202  nOldCells,
203  std::move(oldPatchStarts),
204  std::move(oldPatchNumPoints),
205  std::move(pointMap),
206  std::move(faceMap),
207  std::move(cellMap),
208  std::move(patchMap)
209  );
210  }
211 }
212 
213 } // End namespace Foam
214 
215 
216 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
217 
220 (
221  const fvMesh& mesh,
222  const autoPtr<fvMesh>& baseMeshPtr
223 )
224 {
225  // Processor-local reading
226  IOobject ioAddr
227  (
228  "procAddressing",
229  mesh.facesInstance(),
231  mesh.thisDb(),
235  );
236 
237  //if (ioAddr.typeHeaderOk<labelIOList>(true))
238  //{
239  // Pout<< "Reading addressing from " << io.name() << " at "
240  // << mesh.facesInstance() << nl << endl;
241  // mapDistributePolyMesh distMap = IOmapDistributePolyMesh(ioAddr);
242  // return autoPtr<mapDistributePolyMesh>::New(std::move(distMap));
243  //}
244  //else
245 
246  {
247  Info<< "Reading (cell|face|point|boundary)ProcAddressing from "
248  << mesh.facesInstance().c_str() << '/'
249  << polyMesh::meshSubDir << nl << endl;
250 
251  ioAddr.rename("cellProcAddressing");
252  labelIOList cellProcAddressing(ioAddr, Zero);
253 
254  ioAddr.rename("faceProcAddressing");
255  labelIOList faceProcAddressing(ioAddr, Zero);
256 
257  ioAddr.rename("pointProcAddressing");
258  labelIOList pointProcAddressing(ioAddr, Zero);
259 
260  ioAddr.rename("boundaryProcAddressing");
261  labelIOList boundaryProcAddressing(ioAddr, Zero);
262 
263  if
264  (
265  mesh.nCells() != cellProcAddressing.size()
266  || mesh.nPoints() != pointProcAddressing.size()
267  || mesh.nFaces() != faceProcAddressing.size()
268  || mesh.boundaryMesh().size() != boundaryProcAddressing.size()
269  )
270  {
272  << "Read addressing inconsistent with mesh sizes" << nl
273  << "cells:" << mesh.nCells()
274  << " addressing:" << cellProcAddressing.objectRelPath()
275  << " size:" << cellProcAddressing.size() << nl
276  << "faces:" << mesh.nFaces()
277  << " addressing:" << faceProcAddressing.objectRelPath()
278  << " size:" << faceProcAddressing.size() << nl
279  << "points:" << mesh.nPoints()
280  << " addressing:" << pointProcAddressing.objectRelPath()
281  << " size:" << pointProcAddressing.size()
282  << "patches:" << mesh.boundaryMesh().size()
283  << " addressing:" << boundaryProcAddressing.objectRelPath()
284  << " size:" << boundaryProcAddressing.size()
285  << exit(FatalError);
286  }
287 
288  return createReconstructMap
289  (
290  mesh,
291  baseMeshPtr,
292  cellProcAddressing,
293  faceProcAddressing,
294  pointProcAddressing,
295  boundaryProcAddressing
296  );
297  }
298 }
299 
300 
302 (
303  const fvMesh& mesh,
304  const mapDistributePolyMesh& map,
305  const bool decompose,
306  const fileName& writeHandlerInstance,
307  refPtr<fileOperation>& writeHandler
308 )
309 {
310  Info<< "Writing ("
311  << (decompose ? "decompose" : "reconstruct")
312  << ") procAddressing files to "
313  << mesh.facesInstance().c_str() << '/'
315 
316  // Processor-local outputs for components
317  // NB: the full "procAddressing" output is presumed to already have
318  // been done independently (as a registered object)
319  IOobject ioAddr
320  (
321  "proc-addressing",
324  mesh.thisDb(),
328  );
329 
330  // cellProcAddressing (polyMesh)
331  ioAddr.rename("cellProcAddressing");
332  labelIOList cellMap(ioAddr, Zero);
333 
334  // faceProcAddressing (polyMesh)
335  ioAddr.rename("faceProcAddressing");
336  labelIOList faceMap(ioAddr, Zero);
337 
338  // pointProcAddressing (polyMesh)
339  ioAddr.rename("pointProcAddressing");
340  labelIOList pointMap(ioAddr, Zero);
341 
342  // boundaryProcAddressing (polyMesh)
343  ioAddr.rename("boundaryProcAddressing");
344  labelIOList patchMap(ioAddr, Zero);
345 
346 
347  if (decompose)
348  {
349  // Decompose
350  // - forward map: [undecomposed] -> [decomposed]
351 
352  cellMap = identity(map.nOldCells());
353  map.distributeCellData(cellMap);
354 
355  faceMap = identity(map.nOldFaces());
356  {
357  const mapDistribute& faceDistMap = map.faceMap();
358 
359  if (faceDistMap.subHasFlip() || faceDistMap.constructHasFlip())
360  {
361  // Offset by 1
362  faceMap = faceMap + 1;
363  }
364 
365  faceDistMap.mapDistributeBase::distribute
366  (
368  faceMap,
369  flipLabelOp() // Apply face flips
370  );
371  }
372 
373  pointMap = identity(map.nOldPoints());
374  map.distributePointData(pointMap);
375 
376  patchMap = identity(map.oldPatchSizes().size());
377  map.patchMap().mapDistributeBase::distribute
378  (
380  label(-1), // nullValue for new patches...
381  patchMap,
382  flipOp() // negate op
383  );
384  }
385  else
386  {
387  // Reconstruct
388  // - reverse map: [undecomposed] <- [decomposed]
389 
390  cellMap = identity(mesh.nCells());
391  map.cellMap().reverseDistribute(map.nOldCells(), cellMap);
392 
394  {
395  const mapDistribute& faceDistMap = map.faceMap();
396 
397  if (faceDistMap.subHasFlip() || faceDistMap.constructHasFlip())
398  {
399  // Offset by 1
400  faceMap = faceMap + 1;
401  }
402 
403  faceDistMap.mapDistributeBase::reverseDistribute
404  (
406  map.nOldFaces(),
407  faceMap,
408  flipLabelOp() // Apply face flips
409  );
410  }
411 
412  pointMap = identity(mesh.nPoints());
413  map.pointMap().reverseDistribute(map.nOldPoints(), pointMap);
414 
415  patchMap = identity(mesh.boundaryMesh().size());
416  map.patchMap().mapDistributeBase::reverseDistribute
417  (
419  map.oldPatchSizes().size(),
420  label(-1), // nullValue for unmapped patches...
421  patchMap
422  );
423  }
424 
425 
426  // Switch to using the correct
427  // - fileHandler
428  // - instance
429  // to write to the original mesh/time in the original format. Clunky!
430  // Bypass regIOobject writing to avoid taking over the current time
431  // as instance so instead of e.g. 'celllMap.write()' directly call
432  // the chosen file-handler.
433 
434  const auto& tm = cellMap.time();
435  const IOstreamOption opt(tm.writeFormat(), tm.writeCompression());
436  {
437  auto oldHandler = fileOperation::fileHandler(writeHandler);
438 
439  cellMap.instance() = writeHandlerInstance;
440  const bool cellOk = fileHandler().writeObject(cellMap, opt, true);
441 
442  faceMap.instance() = writeHandlerInstance;
443  const bool faceOk = fileHandler().writeObject(faceMap, opt, true);
444 
445  pointMap.instance() = writeHandlerInstance;
446  const bool pointOk = fileHandler().writeObject(pointMap, opt, true);
447 
448  patchMap.instance() = writeHandlerInstance;
449  const bool patchOk = fileHandler().writeObject(patchMap, opt, true);
450 
451  writeHandler = fileOperation::fileHandler(oldHandler);
452 
453  if (!cellOk || !faceOk || !pointOk || !patchOk)
454  {
456  << "Failed to write some of "
457  << cellMap.objectRelPath() << ", "
458  << faceMap.objectRelPath() << ", "
459  << pointMap.objectRelPath() << ", "
460  << patchMap.objectRelPath() << endl;
461  }
462  }
463 }
464 
465 
466 // ************************************************************************* //
const polyBoundaryMesh & pbm
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
const fileName & facesInstance() const
Return the current instance directory for faces.
Definition: polyMesh.C:859
label nPoints() const noexcept
Number of mesh points.
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
static void writeProcAddressing(const fvMesh &procMesh, const mapDistributePolyMesh &map, const bool decompose, const fileName &writeHandlerInstance, refPtr< fileOperation > &writeHandler)
Write addressing if decomposing (1 to many) or reconstructing (many to 1)
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
label start() const noexcept
The start label of boundary faces in the polyMesh face list.
static word meshSubDir
Return the mesh sub-directory name (usually "polyMesh")
Definition: polyMesh.H:410
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
refPtr< fileOperation > fileHandler(std::nullptr_t)
Delete current file handler - forwards to fileOperation::handler()
Ignore writing from objectRegistry::writeObject()
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Can be negative if the process i...
Definition: UPstream.H:1074
label nFaces() const noexcept
Number of mesh faces.
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
virtual const objectRegistry & thisDb() const
Return the object registry - resolve conflict polyMesh/lduMesh.
Definition: fvMesh.H:376
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run. ...
Definition: UPstream.H:1065
static void gatherList(const List< commsStruct > &comms, List< T > &values, const int tag, const label comm)
Gather data, but keep individual values separate. Uses the specified communication schedule...
IOList< label > labelIOList
IO for a List of label.
Definition: labelIOList.H:32
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
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition: polyMesh.H:608
static constexpr int masterNo() noexcept
Relative rank for the master process - is always 0.
Definition: UPstream.H:1059
label size() const noexcept
The number of entries in the list.
Definition: UPtrListI.H:106
Reading is optional [identical to LAZY_READ].
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO...
static mapDistributePolyMesh createReconstructMap(const faMesh &mesh, const autoPtr< faMesh > &baseMeshPtr, const labelUList &faceProcAddr, const labelUList &edgeProcAddr, const labelUList &pointProcAddr, const labelUList &boundaryProcAddr)
Class containing processor-to-processor mapping information.
#define WarningInFunction
Report a warning using Foam::Warning.
label nCells() const noexcept
Number of mesh cells.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1082
Nothing to be read.
fileName objectRelPath() const
The object path relative to the root.
Definition: IOobject.C:524
"nonBlocking" : (MPI_Isend, MPI_Irecv)
messageStream Info
Information stream (stdout output on master, null elsewhere)
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
static const fileOperation & fileHandler()
Return the current file handler. Will create the default file handler if necessary.
static autoPtr< T > New(Args &&... args)
Construct autoPtr with forwarding arguments.
Definition: autoPtr.H:178
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:172
static autoPtr< mapDistributePolyMesh > readProcAddressing(const fvMesh &procMesh, const autoPtr< fvMesh > &baseMeshPtr)
Read procAddressing components (reconstructing)
A List with indirect addressing.
Definition: IndirectList.H:60
Do not request registration (bool: false)
Namespace for OpenFOAM.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127