fvMeshDistributeTemplates.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) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2015-2022 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 "mapPolyMesh.H"
30 
31 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
32 
33 template<class ZoneType, class ZoneMesh>
34 void Foam::fvMeshDistribute::reorderZones
35 (
36  const wordList& zoneNames,
37  ZoneMesh& zones
38 )
39 {
40  zones.clearAddressing();
41 
42  // Shift old ones to new position
43  UPtrList<ZoneType> newZonePtrs(zoneNames.size());
44  forAll(zones, zonei)
45  {
46  auto* zonePtr = zones.get(zonei);
47  if (!zonePtr)
48  {
49  FatalErrorInFunction << "Problem with zones " << zones.names()
50  << exit(FatalError);
51  }
52  const label newIndex = zoneNames.find(zonePtr->name());
53  zonePtr->index() = newIndex;
54  newZonePtrs.set(newIndex, zonePtr);
55  }
56 
57  // Add empty zones for unknown ones
58  forAll(newZonePtrs, i)
59  {
60  if (!newZonePtrs.get(i))
61  {
62  newZonePtrs.set
63  (
64  i,
65  new ZoneType
66  (
67  zoneNames[i],
68  i,
69  zones
70  )
71  );
72  }
73  }
74 
75  // Transfer
76  zones.swap(newZonePtrs);
77 }
78 
79 
80 template<class GeoField>
82 {
83  typedef GeometricField
84  <
85  typename GeoField::value_type,
87  volMesh
88  > excludeType;
89 
91  (
92  mesh.objectRegistry::lookupClass<GeoField>()
93  );
94 
95  forAllConstIters(flds, iter)
96  {
97  const GeoField& fld = *iter();
98  if (!isA<excludeType>(fld))
99  {
100  Pout<< "Field:" << iter.key() << " internalsize:" << fld.size()
101  //<< " value:" << fld
102  << endl;
103  }
104  }
105 }
106 
107 
108 template<class GeoField>
110 {
111  const HashTable<const GeoField*> flds
112  (
113  mesh.objectRegistry::lookupClass<GeoField>()
114  );
115 
116  forAllConstIters(flds, iter)
117  {
118  const GeoField& fld = *iter();
119 
120  Pout<< "Field:" << iter.key() << " internalsize:" << fld.size()
121  //<< " value:" << fld
122  << endl;
123 
124  for (const auto& patchFld : fld.boundaryField())
125  {
126  Pout<< " " << patchFld.patch().index()
127  << ' ' << patchFld.patch().name()
128  << ' ' << patchFld.type()
129  << ' ' << patchFld.size()
130  << nl;
131  }
132  }
133 }
134 
135 
136 template<class T, class Mesh>
137 void Foam::fvMeshDistribute::saveBoundaryFields
138 (
139  PtrList<FieldField<fvsPatchField, T>>& bflds
140 ) const
141 {
142  // Save whole boundary field
143 
144  typedef GeometricField<T, fvsPatchField, Mesh> fldType;
145 
146  HashTable<const fldType*> flds
147  (
148  mesh_.objectRegistry::lookupClass<const fldType>()
149  );
150 
151  bflds.resize(flds.size());
152 
153  label i = 0;
154  forAllConstIters(flds, iter)
155  {
156  const fldType& fld = *iter();
157 
158  bflds.set(i, fld.boundaryField().clone());
159 
160  ++i;
161  }
162 }
163 
164 
165 template<class T, class Mesh>
166 void Foam::fvMeshDistribute::mapBoundaryFields
167 (
168  const mapPolyMesh& map,
169  const PtrList<FieldField<fvsPatchField, T>>& oldBflds
170 )
171 {
172  // Map boundary field
173 
174  const labelList& oldPatchStarts = map.oldPatchStarts();
175  const labelList& faceMap = map.faceMap();
176 
177  typedef GeometricField<T, fvsPatchField, Mesh> fldType;
178 
179  HashTable<fldType*> flds
180  (
181  mesh_.objectRegistry::lookupClass<fldType>()
182  );
183 
184  if (flds.size() != oldBflds.size())
185  {
187  << abort(FatalError);
188  }
189 
190  label fieldi = 0;
191 
192  forAllIters(flds, iter)
193  {
194  fldType& fld = *iter();
195  auto& bfld = fld.boundaryFieldRef();
196 
197  const FieldField<fvsPatchField, T>& oldBfld = oldBflds[fieldi++];
198 
199  // Pull from old boundary field into bfld.
200 
201  forAll(bfld, patchi)
202  {
203  fvsPatchField<T>& patchFld = bfld[patchi];
204  label facei = patchFld.patch().start();
205 
206  forAll(patchFld, i)
207  {
208  label oldFacei = faceMap[facei++];
209 
210  // Find patch and local patch face oldFacei was in.
211  forAll(oldPatchStarts, oldPatchi)
212  {
213  label oldLocalI = oldFacei - oldPatchStarts[oldPatchi];
214 
215  if (oldLocalI >= 0 && oldLocalI < oldBfld[oldPatchi].size())
216  {
217  patchFld[i] = oldBfld[oldPatchi][oldLocalI];
218  }
219  }
220  }
221  }
222  }
223 }
224 
225 
226 template<class T>
227 void Foam::fvMeshDistribute::saveInternalFields
228 (
229  PtrList<Field<T>>& iflds
230 ) const
231 {
232  typedef GeometricField<T, fvsPatchField, surfaceMesh> fldType;
233 
234  HashTable<const fldType*> flds
235  (
236  mesh_.objectRegistry::lookupClass<const fldType>()
237  );
238 
239  iflds.resize(flds.size());
240 
241  label i = 0;
242 
243  forAllConstIters(flds, iter)
244  {
245  const fldType& fld = *iter();
246 
247  iflds.set(i, fld.primitiveField().clone());
248 
249  ++i;
250  }
251 }
252 
253 
254 template<class T>
255 void Foam::fvMeshDistribute::mapExposedFaces
256 (
257  const mapPolyMesh& map,
258  const PtrList<Field<T>>& oldFlds
259 )
260 {
261  // Set boundary values of exposed internal faces
262 
263  const labelList& faceMap = map.faceMap();
264 
265  typedef GeometricField<T, fvsPatchField, surfaceMesh> fldType;
266 
267  HashTable<fldType*> flds
268  (
269  mesh_.objectRegistry::lookupClass<fldType>()
270  );
271 
272  if (flds.size() != oldFlds.size())
273  {
275  << "problem"
276  << abort(FatalError);
277  }
278 
279 
280  label fieldI = 0;
281 
282  forAllIters(flds, iter)
283  {
284  fldType& fld = *iter();
285  const bool oriented = fld.is_oriented();
286 
287  typename fldType::Boundary& bfld = fld.boundaryFieldRef();
288 
289  const Field<T>& oldInternal = oldFlds[fieldI++];
290 
291  // Pull from old internal field into bfld.
292 
293  forAll(bfld, patchi)
294  {
295  fvsPatchField<T>& patchFld = bfld[patchi];
296 
297  forAll(patchFld, i)
298  {
299  const label faceI = patchFld.patch().start()+i;
300 
301  label oldFaceI = faceMap[faceI];
302 
303  if (oldFaceI < oldInternal.size())
304  {
305  patchFld[i] = oldInternal[oldFaceI];
306 
307  if (oriented && map.flipFaceFlux().found(faceI))
308  {
309  patchFld[i] = flipOp()(patchFld[i]);
310  }
311  }
312  }
313  }
314  }
315 }
316 
317 
318 template<class GeoField, class PatchFieldType>
319 void Foam::fvMeshDistribute::initPatchFields
320 (
321  const typename GeoField::value_type& initVal
322 )
323 {
324  // Init patch fields of certain type
325 
326  HashTable<GeoField*> flds
327  (
328  mesh_.objectRegistry::lookupClass<GeoField>()
329  );
330 
331  forAllIters(flds, iter)
332  {
333  GeoField& fld = *iter();
334 
335  auto& bfld = fld.boundaryFieldRef();
336 
337  forAll(bfld, patchi)
338  {
339  if (isA<PatchFieldType>(bfld[patchi]))
340  {
341  bfld[patchi] == initVal;
342  }
343  }
344  }
345 }
346 
347 
348 //template<class GeoField>
349 //void Foam::fvMeshDistribute::correctBoundaryConditions()
350 //{
351 // // CorrectBoundaryConditions patch fields of certain type
352 //
353 // HashTable<GeoField*> flds
354 // (
355 // mesh_.objectRegistry::lookupClass<GeoField>()
356 // );
357 //
358 // forAllIters(flds, iter)
359 // {
360 // GeoField& fld = *iter();
361 // fld.correctBoundaryConditions();
362 // }
363 //}
364 
365 
366 template<class GeoField>
367 void Foam::fvMeshDistribute::getFieldNames
368 (
369  const fvMesh& mesh,
370  HashTable<wordList>& allFieldNames,
371  const word& excludeType,
372  const bool syncPar
373 )
374 {
375  wordList& list = allFieldNames(GeoField::typeName);
376  list = mesh.sortedNames<GeoField>();
377 
378  if (!excludeType.empty())
379  {
380  const wordList& excludeList = allFieldNames(excludeType);
381 
382  DynamicList<word> newList(list.size());
383  for(const auto& name : list)
384  {
385  if (!excludeList.found(name))
386  {
387  newList.append(name);
388  }
389  }
390  if (newList.size() < list.size())
391  {
392  list = std::move(newList);
393  }
394  }
395 
396 
397  // Check all procs have same names
398  if (syncPar && Pstream::parRun())
399  {
400  // Check and report error(s) on master
401  // - don't need indexing on master itself
402 
403  const globalIndex procAddr(globalIndex::gatherNonLocal{}, list.size());
404 
405  const wordList allNames(procAddr.gather(list));
406 
407  // Automatically restricted to master
408  for (const int proci : procAddr.subProcs())
409  {
410  const auto procNames(allNames.slice(procAddr.range(proci)));
411 
412  if (procNames != list)
413  {
415  << "When checking for equal " << GeoField::typeName
416  << " :" << nl
417  << "processor0 has:" << list << nl
418  << "processor" << proci << " has:" << procNames << nl
419  << GeoField::typeName
420  << " need to be synchronised on all processors."
421  << exit(FatalError);
422  break;
423  }
424  }
425  }
426 }
427 
428 
429 template<class GeoField>
430 void Foam::fvMeshDistribute::sendFields
431 (
432  const label domain,
433  const HashTable<wordList>& allFieldNames,
434  const fvMeshSubset& subsetter,
435  Ostream& toNbr
436 )
437 {
438  // Send fields. Note order supplied so we can receive in exactly the same
439  // order.
440  // Note that field gets written as entry in dictionary so we
441  // can construct from subdictionary.
442  // (since otherwise the reading as-a-dictionary mixes up entries from
443  // consecutive fields)
444  // The dictionary constructed is:
445  // volScalarField
446  // {
447  // p {internalField ..; boundaryField ..;}
448  // k {internalField ..; boundaryField ..;}
449  // }
450  // volVectorField
451  // {
452  // U {internalField ... }
453  // }
454 
455  // volVectorField {U {internalField ..; boundaryField ..;}}
456 
457  const wordList& fieldNames =
458  allFieldNames.lookup(GeoField::typeName, wordList::null());
459 
460  toNbr << GeoField::typeName << token::NL << token::BEGIN_BLOCK << token::NL;
461 
462  for (const word& fieldName : fieldNames)
463  {
464  if (debug)
465  {
466  Pout<< "Subsetting " << GeoField::typeName
467  << " field " << fieldName
468  << " for domain:" << domain << endl;
469  }
470 
471  // Send all fieldNames. This has to be exactly the same set as is
472  // being received!
473  const GeoField& fld =
474  subsetter.baseMesh().lookupObject<GeoField>(fieldName);
475 
476  // Note: use subsetter to get sub field. Override default behaviour
477  // to warn for unset fields since they will be reset later on
478  tmp<GeoField> tsubfld = subsetter.interpolate(fld, true);
479 
480  toNbr
481  << fieldName << token::NL << token::BEGIN_BLOCK
482  << tsubfld
484  }
485  toNbr << token::END_BLOCK << token::NL;
486 }
487 
488 
489 template<class GeoField>
490 void Foam::fvMeshDistribute::receiveFields
491 (
492  const label domain,
493  const HashTable<wordList>& allFieldNames,
494  fvMesh& mesh,
495  PtrList<GeoField>& fields,
496  const dictionary& allFieldsDict
497 )
498 {
499  // Opposite of sendFields
500 
501  const wordList& fieldNames =
502  allFieldNames.lookup(GeoField::typeName, wordList::null());
503 
504  const dictionary& fieldDicts =
505  allFieldsDict.subDict(GeoField::typeName);
506 
507 
508  if (debug)
509  {
510  Pout<< "Receiving:" << GeoField::typeName
511  << " fields:" << fieldNames
512  << " from domain:" << domain << endl;
513  }
514 
515  fields.resize(fieldNames.size());
516 
517  label fieldi = 0;
518  for (const word& fieldName : fieldNames)
519  {
520  if (debug)
521  {
522  Pout<< "Constructing type:" << GeoField::typeName
523  << " field:" << fieldName
524  << " from domain:" << domain << endl;
525  }
526 
527  fields.set
528  (
529  fieldi++,
530  new GeoField
531  (
532  IOobject
533  (
534  fieldName,
535  mesh.time().timeName(),
536  mesh,
539  ),
540  mesh,
541  fieldDicts.subDict(fieldName)
542  )
543  );
544  }
545 }
546 
547 
548 // ************************************************************************* //
Begin block [isseparator].
Definition: token.H:162
virtual const fileName & name() const
Get the name of the output serial stream. (eg, the name of the Fstream file name) ...
Definition: OSstream.H:128
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
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:578
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
Type type(bool followLink=true, bool checkGzip=false) const
Return the directory entry type: UNDEFINED, FILE, DIRECTORY (or SYMLINK).
Definition: fileName.C:353
Newline [isspace].
Definition: token.H:127
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:639
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
Generic GeometricField class.
Definition: areaFieldsFwd.H:50
static const List< word > & null()
Return a null List.
Definition: ListI.H:102
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:361
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
Definition: dictionary.C:453
labelRange range() const
Return start/size range of local processor data.
Definition: globalIndexI.H:250
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
multivariateSurfaceInterpolationScheme< scalar >::fieldTable fields
Definition: createFields.H:97
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:413
Mesh data needed to do the Finite Volume discretisation.
Definition: volMesh.H:45
dynamicFvMesh & mesh
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:52
wordList sortedNames() const
The sorted names of all objects.
#define forAllIters(container, iter)
Iterate across all elements in the container object.
Definition: stdFoam.H:328
A HashTable similar to std::unordered_map.
Definition: HashTable.H:102
errorManip< error > abort(error &err)
Definition: errorManip.H:139
static word timeName(const scalar t, const int precision=precision_)
Return time name of given scalar time formatted with the given precision.
Definition: Time.C:760
static void printFieldInfo(const fvMesh &)
Print some field info.
int debug
Static debugging option.
labelRange subProcs() const noexcept
Range of process indices for addressed sub-offsets (processes)
Definition: globalIndexI.H:171
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< ' ';}gmvFile<< nl;for(const word &name :lagrangianScalarNames){ IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
List< word > wordList
A List of words.
Definition: fileName.H:58
globalIndex procAddr(aMesh.nFaces())
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:79
Nothing to be read.
Automatically write from objectRegistry::writeObject()
static void gather(const labelUList &offsets, const label comm, const ProcIDsContainer &procIDs, const UList< Type > &fld, List< Type > &allFld, const int tag=UPstream::msgType(), const UPstream::commsTypes=UPstream::commsTypes::nonBlocking)
Collect data in processor order on master (== procIDs[0]).
List< label > labelList
A List of labels.
Definition: List.H:62
End block [isseparator].
Definition: token.H:163
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
static void printIntFieldInfo(const fvMesh &)
Print some field info.
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28