sampledSurfaces.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-2026 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 "sampledSurfaces.H"
27 #include "PatchTools.H"
28 #include "polyTopoChangeMap.H"
29 #include "polyMeshMap.H"
30 #include "polyDistributionMap.H"
31 #include "OSspecific.H"
32 #include "writeFile.H"
34 
35 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 
37 namespace Foam
38 {
39 namespace functionObjects
40 {
42 
44  (
48  );
49 }
50 }
51 
52 Foam::scalar Foam::functionObjects::sampledSurfaces::mergeTol_ = 1e-10;
53 
54 
55 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
56 
57 bool Foam::functionObjects::sampledSurfaces::needsUpdate() const
58 {
59  forAll(*this, si)
60  {
61  if (operator[](si).needsUpdate())
62  {
63  return true;
64  }
65  }
66 
67  return false;
68 }
69 
70 
71 bool Foam::functionObjects::sampledSurfaces::update()
72 {
73  bool updated = false;
74 
75  if (!needsUpdate())
76  {
77  return updated;
78  }
79 
80  // Serial: quick and easy, no merging required
81  if (!Pstream::parRun())
82  {
83  forAll(*this, si)
84  {
85  if (operator[](si).update())
86  {
87  updated = true;
88  }
89  }
90 
91  return updated;
92  }
93 
94  // Dimension as fraction of mesh bounding box
95  scalar mergeDim = mergeTol_*mesh_.bounds().mag();
96 
97  if (Pstream::master() && debug)
98  {
99  Pout<< nl << "Merging all points within "
100  << mergeDim << " metre" << endl;
101  }
102 
103  forAll(*this, si)
104  {
105  sampledSurface& s = operator[](si);
106 
107  if (s.update())
108  {
109  updated = true;
110  }
111  else
112  {
113  continue;
114  }
115 
117  (
118  mergeDim,
120  (
121  SubList<face>(s.faces(), s.faces().size()),
122  s.points()
123  ),
124  mergeList_[si].points,
125  mergeList_[si].faces,
126  mergeList_[si].pointsMap
127  );
128  }
129 
130  return updated;
131 }
132 
133 
134 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
135 
137 (
138  const word& name,
139  const Time& t,
140  const dictionary& dict
141 )
142 :
145  outputPath_
146  (
147  mesh_.time().globalPath()
148  /writeFile::outputPrefix
149  /(mesh_.name() != polyMesh::defaultRegion ? mesh_.name() : word())
150  /name
151  ),
152  fields_(),
153  interpolationScheme_(word::null),
154  writeEmpty_(false),
155  mergeList_(),
156  formatter_(nullptr)
157 {
158  read(dict);
159 }
160 
161 
162 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
163 
165 {}
166 
167 
168 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
169 
171 {
172  bool surfacesFound = dict.found("surfaces");
173 
174  if (surfacesFound)
175  {
176  dict.lookup("fields") >> fields_;
177 
178  dict.lookup("interpolationScheme") >> interpolationScheme_;
179 
180  dict.readIfPresent("writeEmpty", writeEmpty_);
181 
182  const word writeType(dict.lookup("surfaceFormat"));
183 
184  // Define the surface formatter
185  formatter_ = surfaceWriter::New(writeType, dict);
186 
187  if (dict.isDict("surfaces"))
188  {
189  const dictionary& surfacesDict = dict.subDict("surfaces");
190 
191  setSize(surfacesDict.size());
192 
193  label i = 0;
194 
195  forAllConstIter(dictionary, surfacesDict, iter)
196  {
197  set
198  (
199  i++,
200  sampledSurface::New(iter().keyword(), mesh_, iter().dict())
201  );
202  }
203  }
204  else
205  {
207  (
208  dict.lookup("surfaces"),
209  sampledSurface::iNew(mesh_)
210  );
211 
212  transfer(newList);
213  }
214 
215  if (Pstream::parRun())
216  {
217  mergeList_.setSize(size());
218 
219  forAll(*this, si)
220  {
221  mergeList_[si].clear();
222  }
223  }
224 
225  if (this->size())
226  {
227  Info<< indent << "Reading surface description:" << nl;
228  Info << incrIndent;
229  forAll(*this, si)
230  {
231  Info<< indent << operator[](si).name() << nl;
232  }
233  Info << decrIndent;
234  }
235  }
236 
237  if (Pstream::master() && debug)
238  {
239  Pout<< "sample fields:" << fields_ << nl
240  << "sample surfaces:" << nl << "(" << nl;
241 
242  forAll(*this, si)
243  {
244  Pout<< " " << operator[](si) << endl;
245  }
246  Pout<< ")" << endl;
247  }
248 
249  return true;
250 }
251 
252 
254 {
255  wordList fields(fields_);
256 
257  forAll(*this, si)
258  {
259  fields.append(operator[](si).fields());
260  }
261 
262  return fields;
263 }
264 
265 
267 {
268  return true;
269 }
270 
271 
273 {
274  if (size())
275  {
276  // Finalise surfaces, merge points etc.
277  update();
278 
279  // Create the output directory
280  if (Pstream::master())
281  {
282  if (debug)
283  {
284  Pout<< "Creating directory "
285  << outputPath_/mesh_.time().name() << nl << endl;
286 
287  }
288 
289  mkDir(outputPath_/mesh_.time().name());
290  }
291 
292  // Create a list of names of fields that are actually available
294  forAll(fields_, fieldi)
295  {
296  #define FoundFieldType(Type, nullArg) \
297  || foundObject<VolField<Type>>(fields_[fieldi]) \
298  || foundObject<SurfaceField<Type>>(fields_[fieldi])
300  {
301  fieldNames.append(fields_[fieldi]);
302  }
303  else
304  {
305  cannotFindObject(fields_[fieldi]);
306  }
307  #undef FoundFieldType
308  }
309 
310  // Create table of cached interpolations, to prevent unnecessary work
311  // when interpolating fields over multiple surfaces
312  #define DeclareInterpolations(Type, nullArg) \
313  HashPtrTable<interpolation<Type>> interpolation##Type##s;
315  #undef DeclareInterpolations
316 
317  // Sample and write the surfaces
318  forAll(*this, surfi)
319  {
320  const sampledSurface& s = operator[](surfi);
321 
322  #define GenerateFieldTypeValues(Type, nullArg) \
323  PtrList<Field<Type>> field##Type##Values = \
324  sampleType<Type>(surfi, fieldNames, interpolation##Type##s);
326  #undef GenerateFieldTypeValues
327 
328  if (Pstream::parRun())
329  {
330  if
331  (
333  && (mergeList_[surfi].faces.size() || writeEmpty_)
334  )
335  {
336  formatter_->write
337  (
338  outputPath_/mesh_.time().name(),
339  s.name(),
340  mergeList_[surfi].points,
341  mergeList_[surfi].faces,
342  fieldNames,
343  s.interpolate()
344  #define FieldTypeValuesParameter(Type, nullArg) \
345  , field##Type##Values
348  );
349  }
350  }
351  else
352  {
353  if (s.faces().size() || writeEmpty_)
354  {
355  formatter_->write
356  (
357  outputPath_/mesh_.time().name(),
358  s.name(),
359  s.points(),
360  s.faces(),
361  fieldNames,
362  s.interpolate()
363  #define FieldTypeValuesParameter(Type, nullArg) \
364  , field##Type##Values
367  );
368  }
369  }
370  }
371  }
372 
373  return true;
374 }
375 
376 
378 {
379  if (&mesh == &mesh_)
380  {
381  forAll(*this, si)
382  {
383  operator[](si).movePoints();
384 
385  if (Pstream::parRun())
386  {
387  mergeList_[si].clear();
388  }
389  }
390  }
391 }
392 
393 
395 (
396  const polyTopoChangeMap& map
397 )
398 {
399  if (&map.mesh() == &mesh_)
400  {
401  forAll(*this, si)
402  {
403  operator[](si).topoChange(map);
404 
405  if (Pstream::parRun())
406  {
407  mergeList_[si].clear();
408  }
409  }
410  }
411 }
412 
413 
415 (
416  const polyMeshMap& map
417 )
418 {
419  if (&map.mesh() == &mesh_)
420  {
421  forAll(*this, si)
422  {
423  operator[](si).mapMesh(map);
424 
425  if (Pstream::parRun())
426  {
427  mergeList_[si].clear();
428  }
429  }
430  }
431 }
432 
433 
435 (
436  const polyDistributionMap& map
437 )
438 {
439  if (&map.mesh() == &mesh_)
440  {
441  forAll(*this, si)
442  {
443  operator[](si).distribute(map);
444 
445  if (Pstream::parRun())
446  {
447  mergeList_[si].clear();
448  }
449  }
450  }
451 }
452 
453 
454 // ************************************************************************* //
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
Macros for easy insertion into run-time selection tables.
virtual const fileName & name() const
Return the name of the stream.
Definition: IOstream.H:297
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:178
virtual const fileName & name() const
Return the name of the stream.
Definition: OSstream.H:85
static void gatherAndMerge(const scalar mergeDist, const PrimitivePatch< FaceList, PointField > &p, Field< typename PrimitivePatch< FaceList, PointField >::PointType > &mergedPoints, List< typename PrimitivePatch< FaceList, PointField >::FaceType > &mergedFaces, labelList &pointMergeMap)
Gather points and faces onto master and merge into single patch.
const Field< PointType > & points() const
Return reference to global points.
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
Definition: PtrList.H:75
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:76
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:423
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:399
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
Abstract base-class for Time/database functionObjects.
Specialisation of Foam::functionObject for an Foam::fvMesh, providing a reference to the Foam::fvMesh...
virtual wordList fields() const
Return the list of fields required.
virtual void topoChange(const polyTopoChangeMap &)
Update topology using the given map.
virtual void distribute(const polyDistributionMap &)
Redistribute or update using the given distribution map.
virtual void mapMesh(const polyMeshMap &)
Update from another mesh using the given map.
virtual void movePoints(const polyMesh &)
Update for mesh point-motion.
sampledSurfaces(const word &name, const Time &time, const dictionary &dict)
Construct from Time and dictionary.
virtual bool execute()
Execute, currently does nothing.
virtual bool write()
Sample and write.
virtual bool read(const dictionary &)
Read the sampledSurfaces dictionary.
Writes run time, CPU time and clock time and optionally the CPU and clock times per time step.
functionObject base class for writing single files
Definition: writeFile.H:56
Class containing mesh-to-mesh mapping information after a mesh distribution where we send parts of me...
const polyMesh & mesh() const
Return polyMesh.
Class containing mesh-to-mesh mapping information.
Definition: polyMeshMap.H:51
const polyMesh & mesh() const
Return polyMesh.
Definition: polyMeshMap.H:75
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:78
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
const polyMesh & mesh() const
Return polyMesh.
Class used for the PtrLists read-construction.
An abstract class for surfaces with sampling.
static autoPtr< sampledSurface > New(const word &name, const polyMesh &, const dictionary &)
Return a reference to the selected surface.
static autoPtr< surfaceWriter > New(const word &writeType, const IOstream::streamFormat writeFormat, const IOstream::compressionType writeCompression)
Select given write options.
Definition: surfaceWriter.C:75
A class for handling words, derived from string.
Definition: word.H:63
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
static List< word > fieldNames
Definition: globalFoam.H:46
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(lagrangian::Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(lagrangian::Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(lagrangian::Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.name(), lagrangian::cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Info<< "Calculating turbulent flame speed field St\n"<< endl;volScalarField St(IOobject("St", runTime.name(), mesh, IOobject::NO_READ, IOobject::AUTO_WRITE), flameWrinkling->Xi() *Su);multivariateSurfaceInterpolationScheme< scalar >::fieldTable fields
Definition: createFields.H:234
const dimensionedScalar e
Elementary charge.
defineTypeNameAndDebug(fvMeshFunctionObject, 0)
addToRunTimeSelectionTable(functionObject, fvModel, dictionary)
Namespace for OpenFOAM.
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
Definition: Ostream.H:272
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
bool mkDir(const fileName &, mode_t=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:290
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
FOR_ALL_FIELD_TYPES(makeDimensionedPointFieldFunctions)
messageStream Info
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition: Ostream.H:265
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
Addressing for a faceList slice.
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
Ostream & indent(Ostream &os)
Indent stream.
Definition: Ostream.H:243
static const char nl
Definition: Ostream.H:297
points setSize(newPointi)
#define FoundFieldType(Type, nullArg)
#define FieldTypeValuesParameter(Type, nullArg)
#define DeclareInterpolations(Type, nullArg)
#define GenerateFieldTypeValues(Type, nullArg)
dictionary dict