parLagrangianDistributor.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 OpenFOAM Foundation
9 Copyright (C) 2015-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 "ListOps.H"
31#include "passivePositionParticleCloud.H"
32
33// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34
36
37
38// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
39
41(
42 const fvMesh& srcMesh,
43 const fvMesh& tgtMesh,
44 const label nSrcCells,
45 const mapDistributePolyMesh& distMap
46)
47:
48 srcMesh_(srcMesh),
49 tgtMesh_(tgtMesh),
50 distMap_(distMap)
51{
52 const mapDistribute& cellMap = distMap_.cellMap();
53
54 // Get destination processors and cells
55 destinationProcID_ = labelList(tgtMesh_.nCells(), Pstream::myProcNo());
56 cellMap.reverseDistribute(nSrcCells, destinationProcID_);
57
58 destinationCell_ = identity(tgtMesh_.nCells());
59 cellMap.reverseDistribute(nSrcCells, destinationCell_);
60}
61
62
63// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
64
65// Find all clouds (on all processors) and for each cloud all the objects.
66// Result will be synchronised on all processors
68(
69 const fvMesh& mesh,
70 wordList& cloudNames,
71 List<wordList>& objectNames
72)
73{
74 fileNameList localCloudDirs
75 (
77 (
79 / mesh.dbDir()
82 )
83 );
84
85 cloudNames.setSize(localCloudDirs.size());
86 forAll(localCloudDirs, i)
87 {
88 cloudNames[i] = localCloudDirs[i];
89 }
90
91 // Synchronise cloud names
92 Pstream::combineGather(cloudNames, ListOps::uniqueEqOp<word>());
93 Pstream::broadcast(cloudNames);
94
95 objectNames.setSize(cloudNames.size());
96
97 for (const fileName& localCloudName : localCloudDirs)
98 {
99 // Do local scan for valid cloud objects
100 IOobjectList localObjs
101 (
102 mesh,
103 mesh.time().timeName(),
104 cloud::prefix/localCloudName
105 );
106
107 bool isCloud = false;
108 if (localObjs.erase("coordinates"))
109 {
110 isCloud = true;
111 }
112 if (localObjs.erase("positions"))
113 {
114 isCloud = true;
115 }
116
117 if (isCloud)
118 {
119 // Has coordinates/positions - so must be a valid cloud
120
121 const label cloudi = cloudNames.find(localCloudName);
122
123 objectNames[cloudi] = localObjs.sortedNames();
124 }
125 }
126
127 // Synchronise objectNames
128 forAll(objectNames, i)
129 {
130 Pstream::combineGather(objectNames[i], ListOps::uniqueEqOp<word>());
131 Pstream::broadcast(objectNames[i]);
132 }
133}
134
135
138(
139 passivePositionParticleCloud& lpi
140) const
141{
142 //Debug(lpi.size());
143
144 const label oldLpi = lpi.size();
145
146 labelListList subMap;
147
148
149 // Allocate transfer buffers
150 PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
151
152 {
153 // List of lists of particles to be transferred for all of the
154 // neighbour processors
155 List<IDLList<passivePositionParticle>> particleTransferLists
156 (
158 );
159
160 // Per particle the destination processor
161 labelList destProc(lpi.size());
162
163 label particleI = 0;
164 for (passivePositionParticle& ppi : lpi)
165 {
166 const label destProcI = destinationProcID_[ppi.cell()];
167 const label destCellI = destinationCell_[ppi.cell()];
168
169 ppi.cell() = destCellI;
170 destProc[particleI++] = destProcI;
171 particleTransferLists[destProcI].append(lpi.remove(&ppi));
172 }
173
174
175 // Per processor the indices of the particles to send
176 subMap = invertOneToMany(Pstream::nProcs(), destProc);
177
178
179 // Stream into send buffers
180 forAll(particleTransferLists, procI)
181 {
182 //Pout<< "To proc " << procI << " sending "
183 // << particleTransferLists[procI] << endl;
184 if (particleTransferLists[procI].size())
185 {
186 UOPstream particleStream(procI, pBufs);
187 particleStream << particleTransferLists[procI];
188 }
189 }
190 }
191
192
193 // Start sending
194 pBufs.finishedSends();
195
196
197 {
198 // Temporarily rename original cloud so we can construct a new one
199 // (to distribute the positions) without getting a duplicate
200 // registration warning
201 const word cloudName = lpi.name();
202 lpi.rename(cloudName + "_old");
203
204 // New cloud on tgtMesh
205 passivePositionParticleCloud lagrangianPositions
206 (
207 tgtMesh_,
208 cloudName,
209 IDLList<passivePositionParticle>()
210 );
211
212 // Retrieve from receive buffers
213 for (const int proci : pBufs.allProcs())
214 {
215 //Pout<< "Receive from processor" << proci << " : "
216 // << pBufs.recvDataCount(proci) << endl;
217
218 if (pBufs.recvDataCount(proci))
219 {
220 UIPstream particleStream(proci, pBufs);
221
222 // Receive particles and locate them
223 IDLList<passivePositionParticle> newParticles
224 (
225 particleStream,
226 passivePositionParticle::iNew(tgtMesh_)
227 );
228
229 for (passivePositionParticle& newp : newParticles)
230 {
231 lagrangianPositions.addParticle(newParticles.remove(&newp));
232 }
233 }
234 }
235
236 if (lagrangianPositions.size())
237 {
238 // Write coordinates file
239 IOPosition<passivePositionParticleCloud>
240 (
241 lagrangianPositions
242 ).write();
243
244 // Optionally write positions file in v1706 format and earlier
246 {
247 IOPosition<passivePositionParticleCloud>
248 (
249 lagrangianPositions,
251 ).write();
252 }
253 }
254 else if (oldLpi)
255 {
256 // When running with -overwrite it should also delete the old
257 // files. Below works but is not optimal.
258
259 // Remove any existing coordinates
260 const fileName oldCoords
261 (
262 IOPosition<passivePositionParticleCloud>
263 (
264 lagrangianPositions
265 ).objectPath()
266 );
267 Foam::rm(oldCoords);
268
269 // Remove any existing positions
270 const fileName oldPos
271 (
272 IOPosition<passivePositionParticleCloud>
273 (
274 lagrangianPositions,
276 ).objectPath()
277 );
278 Foam::rm(oldPos);
279 }
280
281 // Restore cloud name
282 lpi.rename(cloudName);
283 }
284
285 // Work the send indices (subMap) into a mapDistributeBase
287 labelList& nsTransPs = sizes[Pstream::myProcNo()];
288 nsTransPs.setSize(Pstream::nProcs());
289 forAll(subMap, sendProcI)
290 {
291 nsTransPs[sendProcI] = subMap[sendProcI].size();
292 }
293 // Send sizes across. Note: blocks.
294 Pstream::combineAllGather(sizes, Pstream::listEq());
295
296 labelListList constructMap(Pstream::nProcs());
297 label constructSize = 0;
298 forAll(constructMap, procI)
299 {
300 const label nRecv = sizes[procI][UPstream::myProcNo()];
301
302 labelList& map = constructMap[procI];
303
304 map.setSize(nRecv);
305 forAll(map, i)
306 {
307 map[i] = constructSize++;
308 }
309 }
310
311
313 (
314 constructSize,
315 std::move(subMap),
316 std::move(constructMap)
317 );
318}
319
320
323(
324 const word& cloudName
325) const
326{
327 // Load cloud and send particle
328 passivePositionParticleCloud lpi(srcMesh_, cloudName, false);
329
330 return distributeLagrangianPositions(lpi);
331}
332
333
334// ************************************************************************* //
Various functions to operate on Lists.
void setSize(const label n)
Alias for resize()
Definition: List.H:218
label nProcs() const noexcept
Number of ranks associated with PstreamBuffers.
static void combineGather(const List< commsStruct > &comms, T &value, const CombineOp &cop, const int tag, const label comm)
static void combineAllGather(const List< commsStruct > &comms, T &value, const CombineOp &cop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
static void broadcast(Type &value, const label comm=UPstream::worldComm)
static autoPtr< Time > New()
Construct (dummy) Time - no functionObjects or libraries.
Definition: Time.C:717
static word timeName(const scalar t, const int precision=precision_)
Definition: Time.C:780
fileName timePath() const
Return current time path.
Definition: Time.H:375
@ nonBlocking
"nonBlocking"
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: autoPtr.H:66
static const word prefix
The prefix to local: lagrangian.
Definition: cloud.H:87
@ DIRECTORY
A directory.
Definition: fileName.H:84
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:290
Lagrangian field redistributor.
static void findClouds(const fvMesh &, wordList &cloudNames, List< wordList > &objectNames)
autoPtr< mapDistributeBase > distributeLagrangianPositions(passivePositionParticleCloud &cloud) const
Redistribute and write lagrangian positions.
static int verbose_
Output verbosity when writing.
static bool writeLagrangianPositions
Definition: particle.H:383
virtual const fileName & dbDir() const
Override the objectRegistry dbDir for a single-region case.
Definition: polyMesh.C:837
int myProcNo() const noexcept
Return processor number.
dynamicFvMesh & mesh
bool rm(const fileName &file)
Remove a file (or its gz equivalent), returning true if successful.
Definition: MSwindows.C:1012
List< fileName > fileNameList
A List of fileNames.
Definition: fileNameList.H:58
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
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
fileNameList readDir(const fileName &directory, const fileName::Type type=fileName::FILE, const bool filtergz=true, const bool followLink=true)
Read a directory and return the entries as a fileName List.
Definition: MSwindows.C:715
labelListList invertOneToMany(const label len, const labelUList &map)
Invert one-to-many map. Unmapped elements will be size 0.
Definition: ListOps.C:114
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
const word cloudName(propsDict.get< word >("cloud"))