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-2025 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 {
42  procLs[Pstream::myProcNo()] = l;
43 
44  Pstream::gatherList(procLs);
45  Pstream::scatterList(procLs);
46 
47  return
48  HashSet<Type>
49  (
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(),
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  lagrangian::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  const meshSearch& tgtSearchEngine = meshSearch::New(tgtMesh);
183 
184  // Determine the clouds present in this mesh
185  const fileNameList cloudDirs =
186  gatherAndFlatten
187  (
188  readDir
189  (
190  srcMesh.time().timePath()/lagrangian::cloud::prefix,
191  fileType::directory
192  )
193  );
194 
195  forAll(cloudDirs, cloudi)
196  {
197  Info<< nl << "Mapping cloud " << cloudDirs[cloudi] << endl;
198 
199  // Read the source cloud positions
200  passiveParticleCloud srcCloud(srcMesh, cloudDirs[cloudi], false);
201 
202  Info<< " read "
203  << returnReduce(srcCloud.size(), sumOp<label>())
204  << " parcels from source mesh." << endl;
205 
206  // Unpack into position and cell lists and construct a send map
207  pointField positions(srcCloud.size());
208  labelList tgtCells(srcCloud.size(), -1);
209  List<DynamicList<label>> sendsDyn(Pstream::nProcs());
210  {
211  label srcParticlei = 0;
212  forAllConstIter(lagrangian::Cloud<passiveParticle>, srcCloud, iter)
213  {
214  const point pos = iter().position(srcMesh);
215 
216  const remote tgtProcCell =
217  interp.srcToTgtPoint(iter().cell(), pos);
218 
219  positions[srcParticlei] = pos;
220  tgtCells[srcParticlei] = tgtProcCell.elementi;
221 
222  sendsDyn[tgtProcCell.proci].append(srcParticlei ++);
223  }
224  }
225  labelListList sends;
226  patchToPatchTools::transferListList(sends, sendsDyn);
227 
228  // Build a distribution map from the send map
229  autoPtr<distributionMap> mapPtr =
231  const distributionMap& map = mapPtr();
232 
233  // Distribute the positions and target cell indices
234  map.distribute(positions);
235  map.distribute(tgtCells);
236 
237  // Construct the target cloud positions
238  passiveParticleCloud tgtCloud
239  (
240  tgtMesh,
241  cloudDirs[cloudi],
242  IDLList<passiveParticle>()
243  );
244  forAll(positions, tgtParticlei)
245  {
246  label nLocateBoundaryHits = 0;
247  autoPtr<passiveParticle> pPtr
248  (
249  new passiveParticle
250  (
251  tgtSearchEngine,
252  positions[tgtParticlei],
253  tgtCells[tgtParticlei],
254  nLocateBoundaryHits
255  )
256  );
257 
258  if (nLocateBoundaryHits == 0)
259  {
260  tgtCloud.addParticle(pPtr.ptr());
261  }
262  }
263 
264  Info<< " mapped "
265  << returnReduce(tgtCloud.size(), sumOp<label>())
266  << " parcels to the target mesh." << endl;
267 
268  // Write the positions
269  IOPosition<passiveParticleCloud>(tgtCloud).write();
270 
271  // Search for Lagrangian objects for this time
272  IOobjectList objects
273  (
274  srcMesh,
275  srcMesh.time().name(),
276  lagrangian::cloud::prefix/cloudDirs[cloudi]
277  );
278 
279  // Map and write the fields
280  #define MapCloudTypeFields(Type, nullArg) \
281  mapCloudTypeFieldsAndFieldFields<Type> \
282  ( \
283  cloudDirs[cloudi], \
284  objects, \
285  srcMesh, \
286  tgtMesh, \
287  map \
288  );
289  MapCloudTypeFields(label, );
290  FOR_ALL_FIELD_TYPES(MapCloudTypeFields);
291  #undef MapCloudTypeFields
292  }
293 }
294 
295 
296 // ************************************************************************* //
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:449
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:492
virtual Ostream & write(const token &)
Write token.
Definition: Ostream.C:51
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:69
Motion of the mesh specified as a list of pointMeshMovers.
#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:288
String typeName(const std::type_info &info)
Return the un-mangled name given the standard type info.
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)
tmp< DimensionedField< TypeR, GeoMesh, Field > > New(const tmp< DimensionedField< TypeR, GeoMesh, Field >> &tdf1, const word &name, const dimensionSet &dimensions)
static const char nl
Definition: Ostream.H:297
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