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