mapClouds.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "mapClouds.H"
27 #include "fvMeshToFvMesh.H"
28 #include "IOobjectList.H"
29 #include "OSspecific.H"
30 #include "passiveParticleCloud.H"
31 #include "patchToPatchTools.H"
32 
33 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
34 
35 namespace Foam
36 {
37 
38 template<class Type>
39 List<Type> gatherAndFlatten(const List<Type>& l)
40 {
41  List<List<Type>> procLs(Pstream::nProcs());
42  procLs[Pstream::myProcNo()] = l;
43 
44  Pstream::gatherList(procLs);
45  Pstream::scatterList(procLs);
46 
47  return
48  HashSet<Type>
49  (
50  ListListOps::combine<List<Type>>
51  (
52  procLs,
53  accessOp<List<Type>>()
54  )
55  ).sortedToc();
56 }
57 
58 
59 template<class ReadIOField, class WriteIOField>
60 void mapCloudTypeFields
61 (
62  const fileName& cloudDir,
63  const IOobjectList& objects,
64  const polyMesh& srcMesh,
65  const polyMesh& tgtMesh,
66  const distributionMap& map
67 )
68 {
69  const wordList fieldNames =
70  gatherAndFlatten(objects.lookupClass(ReadIOField::typeName).names());
71 
72  forAll(fieldNames, fieldi)
73  {
74  const word& fieldName = fieldNames[fieldi];
75 
76  Info<< " mapping lagrangian field " << fieldName << endl;
77 
78  const IOobject* fieldIOPtr = objects.lookup(fieldName);
79 
80  // Read the field
81  ReadIOField field
82  (
83  fieldIOPtr != nullptr
84  ? *fieldIOPtr
85  : IOobject
86  (
87  fieldName,
88  srcMesh.time().name(),
89  cloud::prefix/cloudDir,
90  srcMesh,
93  false
94  )
95  );
96 
97  // Distribute the field
98  map.distribute(field);
99 
100  // Write it out into the target case
101  if (field.size())
102  {
103  WriteIOField
104  (
105  IOobject
106  (
107  fieldName,
108  tgtMesh.time().name(),
109  cloud::prefix/cloudDir,
110  tgtMesh,
113  false
114  ),
115  move(field)
116  ).write();
117  }
118  }
119 }
120 
121 
122 template<class Type>
123 void mapCloudTypeFieldsAndFieldFields
124 (
125  const fileName& cloudDir,
126  const IOobjectList& objects,
127  const polyMesh& srcMesh,
128  const polyMesh& tgtMesh,
129  const distributionMap& map
130 )
131 {
132  mapCloudTypeFields
133  <
134  IOField<Type>,
135  IOField<Type>
136  >
137  (
138  cloudDir,
139  objects,
140  srcMesh,
141  tgtMesh,
142  map
143  );
144 
145  mapCloudTypeFields
146  <
147  IOField<Field<Type>>,
148  CompactIOField<Field<Type>>
149  >
150  (
151  cloudDir,
152  objects,
153  srcMesh,
154  tgtMesh,
155  map
156  );
157 
158  mapCloudTypeFields
159  <
160  CompactIOField<Field<Type>>,
161  CompactIOField<Field<Type>>
162  >
163  (
164  cloudDir,
165  objects,
166  srcMesh,
167  tgtMesh,
168  map
169  );
170 }
171 
172 } // End namespace Foam
173 
174 
175 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
176 
177 void Foam::mapClouds(const fvMeshToFvMesh& interp)
178 {
179  const polyMesh& srcMesh = interp.srcMesh();
180  const polyMesh& tgtMesh = interp.tgtMesh();
181 
182  // Determine the clouds present in this mesh
183  const fileNameList cloudDirs =
185  (
186  readDir
187  (
188  srcMesh.time().timePath()/cloud::prefix,
189  fileType::directory
190  )
191  );
192 
193  forAll(cloudDirs, cloudi)
194  {
195  Info<< nl << "Mapping cloud " << cloudDirs[cloudi] << endl;
196 
197  // Read the source cloud positions
198  passiveParticleCloud srcCloud(srcMesh, cloudDirs[cloudi], false);
199 
200  Info<< " read "
201  << returnReduce(srcCloud.size(), sumOp<label>())
202  << " parcels from source mesh." << endl;
203 
204  // Unpack into position and cell lists and construct a send map
205  pointField positions(srcCloud.size());
206  labelList tgtCells(srcCloud.size(), -1);
207  List<DynamicList<label>> sendsDyn(Pstream::nProcs());
208  {
209  label srcParticlei = 0;
210  forAllConstIter(Cloud<passiveParticle>, srcCloud, iter)
211  {
212  const point pos = iter().position(srcMesh);
213 
214  const remote tgtProcCell =
215  interp.srcToTgtPoint(iter().cell(), pos);
216 
217  positions[srcParticlei] = pos;
218  tgtCells[srcParticlei] = tgtProcCell.elementi;
219 
220  sendsDyn[tgtProcCell.proci].append(srcParticlei ++);
221  }
222  }
223  labelListList sends;
224  patchToPatchTools::transferListList(sends, sendsDyn);
225 
226  // Build a distribution map from the send map
227  autoPtr<distributionMap> mapPtr =
229  const distributionMap& map = mapPtr();
230 
231  // Distribute the positions and target cell indices
232  map.distribute(positions);
233  map.distribute(tgtCells);
234 
235  // Construct the target cloud positions
236  passiveParticleCloud tgtCloud
237  (
238  tgtMesh,
239  cloudDirs[cloudi],
240  IDLList<passiveParticle>()
241  );
242  forAll(positions, tgtParticlei)
243  {
244  tgtCloud.addParticle
245  (
246  new passiveParticle
247  (
248  tgtMesh,
249  positions[tgtParticlei],
250  tgtCells[tgtParticlei]
251  )
252  );
253  }
254 
255  Info<< " mapped "
256  << returnReduce(tgtCloud.size(), sumOp<label>())
257  << " parcels to the target mesh." << endl;
258 
259  // Write the positions
260  IOPosition<passiveParticleCloud>(tgtCloud).write();
261 
262  // Search for Lagrangian objects for this time
263  IOobjectList objects
264  (
265  srcMesh,
266  srcMesh.time().name(),
267  cloud::prefix/cloudDirs[cloudi]
268  );
269 
270  // Map and write the fields
271  #define MapCloudTypeFields(Type, nullArg) \
272  mapCloudTypeFieldsAndFieldFields<Type> \
273  ( \
274  cloudDirs[cloudi], \
275  objects, \
276  srcMesh, \
277  tgtMesh, \
278  map \
279  );
280  MapCloudTypeFields(label, );
281  FOR_ALL_FIELD_TYPES(MapCloudTypeFields);
282  #undef MapCloudTypeFields
283  }
284 }
285 
286 
287 // ************************************************************************* //
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:477
virtual Ostream & write(const char)=0
Write character.
static void scatterList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Scatter data. Reverse of gatherList.
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:411
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:429
static const word prefix
The prefix to local: lagrangian.
Definition: cloud.H:63
#define FOR_ALL_FIELD_TYPES(Macro,...)
Definition: fieldTypes.H:51
static List< word > fieldNames
Definition: globalFoam.H:46
Maps Lagrangian clouds.
AccessType combine(const List< T > &, AccessOp aop=accessOp< T >())
Combines sublists into one big list.
Definition: ListListOps.C:34
autoPtr< distributionMap > constructDistributionMap(const labelListList &procSendIndices)
Turn a list of send-to-processor indices into a distribution map.
static void transferListList(List< SubListA > &a, List< SubListB > &b)
Transfer list-list b into list-list a.
Namespace for OpenFOAM.
dimensionedScalar pos(const dimensionedScalar &ds)
List< word > wordList
A List of words.
Definition: fileName.H:54
List< fileName > fileNameList
A List of fileNames.
Definition: fileNameList.H:50
List< label > labelList
A List of labels.
Definition: labelList.H:56
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
void mapClouds(const fvMeshToFvMesh &interp)
messageStream Info
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
vector point
Point is a vector.
Definition: point.H:41
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:57
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
void gatherAndFlatten(DynamicField< Type > &field)
Definition: streamlines.C:50
static const char nl
Definition: Ostream.H:260
fileNameList readDir(const fileName &, const fileType=fileType::file, const bool filterVariants=true, const bool followLink=true)
Read a directory and return the entries as a string list.
Definition: POSIX.C:662
objects