sampledSurfaces.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-2017 OpenFOAM Foundation
9  Copyright (C) 2016-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 "sampledSurfaces.H"
30 #include "polySurface.H"
31 
32 #include "mapPolyMesh.H"
33 #include "volFields.H"
34 #include "surfaceFields.H"
35 #include "HashOps.H"
36 #include "ListOps.H"
37 #include "Time.H"
38 #include "IndirectList.H"
40 
41 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
42 
43 namespace Foam
44 {
45  defineTypeNameAndDebug(sampledSurfaces, 0);
46 
48  (
49  functionObject,
50  sampledSurfaces,
51  dictionary
52  );
53 }
54 
55 Foam::scalar Foam::sampledSurfaces::mergeTol_ = 1e-10;
56 
57 
58 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
59 
60 Foam::polySurface* Foam::sampledSurfaces::getRegistrySurface
61 (
62  const sampledSurface& s
63 ) const
64 {
65  return s.getRegistrySurface
66  (
67  storedObjects(),
68  IOobject::groupName(name(), s.name())
69  );
70 }
71 
72 
73 Foam::polySurface* Foam::sampledSurfaces::storeRegistrySurface
74 (
75  const sampledSurface& s
76 )
77 {
78  return s.storeRegistrySurface
79  (
80  storedObjects(),
81  IOobject::groupName(name(), s.name())
82  );
83 }
84 
85 
86 bool Foam::sampledSurfaces::removeRegistrySurface
87 (
88  const sampledSurface& s
89 )
90 {
91  return s.removeRegistrySurface
92  (
93  storedObjects(),
94  IOobject::groupName(name(), s.name())
95  );
96 }
97 
98 
99 Foam::IOobjectList Foam::sampledSurfaces::preCheckFields()
100 {
101  wordList allFields; // Just needed for warnings
102  HashTable<wordHashSet> selected;
103 
104  IOobjectList objects(0);
105 
106  if (loadFromFiles_)
107  {
108  // Check files for a particular time
109  objects = IOobjectList(obr_, obr_.time().timeName());
110 
111  allFields = objects.names();
112  selected = objects.classes(fieldSelection_);
113  }
114  else
115  {
116  // Check currently available fields
117  allFields = obr_.names();
118  selected = obr_.classes(fieldSelection_);
119  }
120 
121  // Parallel consistency (no-op in serial)
122  Pstream::mapCombineReduce(selected, HashSetOps::plusEqOp<word>());
123 
124 
125  DynamicList<label> missed(fieldSelection_.size());
126 
127  // Detect missing fields
128  forAll(fieldSelection_, i)
129  {
130  if (!ListOps::found(allFields, fieldSelection_[i]))
131  {
132  missed.append(i);
133  }
134  }
135 
136  if (missed.size())
137  {
139  << nl
140  << "Cannot find "
141  << (loadFromFiles_ ? "field file" : "registered field")
142  << " matching "
143  << UIndirectList<wordRe>(fieldSelection_, missed) << endl;
144  }
145 
146 
147  // Currently only support volume and surface field types
148  label nVolumeFields = 0;
149  label nSurfaceFields = 0;
150 
151  forAllConstIters(selected, iter)
152  {
153  const word& clsName = iter.key();
154  const label n = iter.val().size();
155 
156  if (fieldTypes::volume.found(clsName))
157  {
158  nVolumeFields += n;
159  }
160  else if (fieldTypes::surface.found(clsName))
161  {
162  nSurfaceFields += n;
163  }
164  }
165 
166  // Now propagate field counts (per surface)
167  // - can update writer even when not writing without problem
168 
169  forAll(*this, surfi)
170  {
171  const sampledSurface& s = (*this)[surfi];
172  surfaceWriter& outWriter = writers_[surfi];
173 
174  outWriter.nFields
175  (
176  nVolumeFields
177  + (s.withSurfaceFields() ? nSurfaceFields : 0)
178  +
179  (
180  // Face-id field, but not if the writer manages that itself
181  !s.isPointData() && s.hasFaceIds() && !outWriter.usesFaceIds()
182  ? 1 : 0
183  )
184  );
185  }
186 
187  return objects;
188 }
189 
190 
191 Foam::autoPtr<Foam::surfaceWriter> Foam::sampledSurfaces::newWriter
192 (
193  word writerType,
194  const dictionary& topDict,
195  const dictionary& surfDict
196 )
197 {
198  // Per-surface adjustment
199  surfDict.readIfPresent<word>("surfaceFormat", writerType);
200 
201  return surfaceWriter::New
202  (
203  writerType,
204  // Top-level/surface-specific "formatOptions"
205  surfaceWriter::formatOptions(topDict, surfDict, writerType)
206  );
207 }
208 
209 
210 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
211 
212 Foam::sampledSurfaces::sampledSurfaces
213 (
214  const word& name,
215  const Time& runTime,
216  const dictionary& dict
217 )
218 :
219  functionObjects::fvMeshFunctionObject(name, runTime, dict),
221  loadFromFiles_(false),
222  verbose_(false),
223  onExecute_(false),
224  outputPath_
225  (
226  time_.globalPath()/functionObject::outputPrefix/name
227  ),
228  fieldSelection_(),
229  sampleFaceScheme_(),
230  sampleNodeScheme_(),
231  writers_(),
232  actions_(),
233  nFaces_()
234 {
235  outputPath_.clean(); // Remove unneeded ".."
236 
237  read(dict);
238 }
239 
240 
241 Foam::sampledSurfaces::sampledSurfaces
242 (
243  const word& name,
244  const objectRegistry& obr,
245  const dictionary& dict,
246  const bool loadFromFiles
247 )
248 :
249  functionObjects::fvMeshFunctionObject(name, obr, dict),
251  loadFromFiles_(loadFromFiles),
252  verbose_(false),
253  onExecute_(false),
254  outputPath_
255  (
256  time_.globalPath()/functionObject::outputPrefix/name
257  ),
258  fieldSelection_(),
259  sampleFaceScheme_(),
260  sampleNodeScheme_(),
261  writers_(),
262  actions_(),
263  nFaces_()
264 {
265  outputPath_.clean(); // Remove unneeded ".."
267  read(dict);
268 }
269 
270 
271 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
272 
273 bool Foam::sampledSurfaces::verbose(const bool on) noexcept
274 {
275  bool old(verbose_);
276  verbose_ = on;
277  return old;
278 }
279 
280 
282 {
284 
286  writers_.clear();
287  actions_.clear();
288  nFaces_.clear();
289  fieldSelection_.clear();
290 
291  verbose_ = dict.getOrDefault("verbose", false);
292  onExecute_ = dict.getOrDefault("sampleOnExecute", false);
293 
294  sampleFaceScheme_ =
295  dict.getOrDefault<word>("sampleScheme", "cell");
296 
297  sampleNodeScheme_ =
298  dict.getOrDefault<word>("interpolationScheme", "cellPoint");
299 
300  const entry* eptr = dict.findEntry("surfaces", keyType::LITERAL);
301 
302  // Surface writer type and format options
303  const word writerType =
304  (eptr ? dict.get<word>("surfaceFormat") : word::null);
305 
306  // Store on registry?
307  const bool dfltStore = dict.getOrDefault("store", false);
308 
309  if (eptr && eptr->isDict())
310  {
311  PtrList<sampledSurface> surfs(eptr->dict().size());
312 
313  actions_.resize(surfs.size(), ACTION_WRITE); // Default action
314  writers_.resize(surfs.size());
315  nFaces_.resize(surfs.size(), Zero);
316 
317  label surfi = 0;
318 
319  for (const entry& dEntry : eptr->dict())
320  {
321  if (!dEntry.isDict())
322  {
323  continue;
324  }
325 
326  const dictionary& surfDict = dEntry.dict();
327 
328  autoPtr<sampledSurface> surf =
330  (
331  dEntry.keyword(),
332  mesh_,
333  surfDict
334  );
335 
336  if (!surf || !surf->enabled())
337  {
338  continue;
339  }
340 
341  // Define the surface
342  surfs.set(surfi, surf);
343 
344  // Define additional action(s)
345  if (surfDict.getOrDefault("store", dfltStore))
346  {
347  actions_[surfi] |= ACTION_STORE;
348  }
349 
350  // Define surface writer, but do NOT yet attach a surface
351  writers_.set
352  (
353  surfi,
354  newWriter(writerType, dict, surfDict)
355  );
356 
357  writers_[surfi].isPointData(surfs[surfi].isPointData());
358 
359  // Use outputDir/TIME/surface-name
360  writers_[surfi].useTimeDir(true);
361  writers_[surfi].verbose(verbose_);
362 
363  ++surfi;
364  }
365 
366  surfs.resize(surfi);
367  actions_.resize(surfi);
368  writers_.resize(surfi);
369  surfaces().transfer(surfs);
370  }
371  else if (eptr)
372  {
373  // This is slightly trickier.
374  // We want access to the individual dictionaries used for construction
375 
376  DynamicList<dictionary> capture;
377 
378  PtrList<sampledSurface> input
379  (
380  eptr->stream(),
381  sampledSurface::iNewCapture(mesh_, capture)
382  );
383 
384  PtrList<sampledSurface> surfs(input.size());
385 
386  actions_.resize(surfs.size(), ACTION_WRITE); // Default action
387  writers_.resize(surfs.size());
388  nFaces_.resize(surfs.size(), Zero);
389 
390  label surfi = 0;
391 
392  forAll(input, inputi)
393  {
394  const dictionary& surfDict = capture[inputi];
395 
396  autoPtr<sampledSurface> surf = input.release(inputi);
397 
398  if (!surf || !surf->enabled())
399  {
400  continue;
401  }
402 
403  // Define the surface
404  surfs.set(surfi, surf);
405 
406  // Define additional action(s)
407  if (surfDict.getOrDefault("store", dfltStore))
408  {
409  actions_[surfi] |= ACTION_STORE;
410  }
411 
412  // Define surface writer, but do NOT yet attach a surface
413  writers_.set
414  (
415  surfi,
416  newWriter(writerType, dict, surfDict)
417  );
418 
419  writers_[surfi].isPointData(surfs[surfi].isPointData());
420 
421  // Use outputDir/TIME/surface-name
422  writers_[surfi].useTimeDir(true);
423  writers_[surfi].verbose(verbose_);
424 
425  ++surfi;
426  }
427 
428  surfs.resize(surfi);
429  actions_.resize(surfi);
430  writers_.resize(surfi);
431  surfaces().transfer(surfs);
432  }
433 
434 
435  const auto& surfs = surfaces();
436 
437  // Have some surfaces, so sort out which fields are needed and report
438 
439  if (surfs.size())
440  {
441  nFaces_.resize(surfs.size(), Zero);
442 
443  dict.readEntry("fields", fieldSelection_);
444  fieldSelection_.uniq();
445 
446  forAll(*this, surfi)
447  {
448  const sampledSurface& s = (*this)[surfi];
449 
450  if (!surfi)
451  {
452  Info<< "Sampled surface:" << nl;
453  }
454 
455  Info<< " " << s.name() << " -> " << writers_[surfi].type();
456  if (actions_[surfi] & ACTION_STORE)
457  {
458  Info<< ", store on registry ("
459  << IOobject::groupName(name(), s.name()) << ')';
460  }
461  Info<< nl;
462  Info<< " ";
463  s.print(Info, 0);
464  Info<< nl;
465  }
466  Info<< nl;
467  }
468 
469  if (debug && Pstream::master())
470  {
471  Pout<< "sample fields:" << fieldSelection_ << nl
472  << "sample surfaces:" << nl << '(' << nl;
473 
474  for (const sampledSurface& s : surfaces())
475  {
476  Pout<< " " << s << nl;
477  }
478  Pout<< ')' << endl;
479  }
480 
481  // Ensure all surfaces and merge information are expired
482  expire(true);
483 
484  return true;
485 }
486 
487 
488 bool Foam::sampledSurfaces::performAction(unsigned request)
489 {
490  // Update surfaces and store
491  bool ok = false;
492 
493  forAll(*this, surfi)
494  {
495  sampledSurface& s = (*this)[surfi];
496 
497  if (request & actions_[surfi])
498  {
499  if (s.update())
500  {
501  writers_[surfi].expire();
502  }
503 
504  nFaces_[surfi] = returnReduce(s.faces().size(), sumOp<label>());
505 
506  ok = ok || nFaces_[surfi];
507 
508 
509  // Store surfaces (even empty ones) otherwise we miss geometry
510  // updates.
511  // Any associated fields will be removed if the size changes
512 
513  if ((request & actions_[surfi]) & ACTION_STORE)
514  {
515  storeRegistrySurface(s);
516  }
517  }
518  }
519 
520  if (!ok)
521  {
522  // No surface with an applicable action or with faces to sample
523  return true;
524  }
525 
526 
527  // Determine availability of fields.
528  // Count per-surface number of fields, including Ids etc
529  // which only seems to be needed for VTK legacy
530 
531  IOobjectList objects = preCheckFields();
532 
533  // Update writers
534 
535  forAll(*this, surfi)
536  {
537  const sampledSurface& s = (*this)[surfi];
538 
539  if (((request & actions_[surfi]) & ACTION_WRITE) && nFaces_[surfi])
540  {
541  surfaceWriter& outWriter = writers_[surfi];
542 
543  if (outWriter.needsUpdate())
544  {
545  outWriter.setSurface(s);
546  }
547 
548  outWriter.open(outputPath_/s.name());
549 
550  outWriter.beginTime(obr_.time());
551 
552  // Face-id field, but not if the writer manages that itself
553  if (!s.isPointData() && s.hasFaceIds() && !outWriter.usesFaceIds())
554  {
555  // This is still quite horrible.
556 
557  Field<label> ids(s.faceIds());
558 
559  if
560  (
562  (
563  !ListOps::found(ids, lessOp1<label>(0))
564  )
565  )
566  {
567  // From 0-based to 1-based, provided there are no
568  // negative ids (eg, encoded solid/side)
569 
570  ids += label(1);
571  }
572 
573  writeSurface(outWriter, ids, "Ids");
574  }
575  }
576  }
577 
578  // Sample fields
579 
580  performAction<volScalarField>(objects, request);
581  performAction<volVectorField>(objects, request);
582  performAction<volSphericalTensorField>(objects, request);
583  performAction<volSymmTensorField>(objects, request);
584  performAction<volTensorField>(objects, request);
585 
586  // Only bother with surface fields if a sampler supports them
587  if
588  (
589  testAny
590  (
591  surfaces(),
592  [] (const sampledSurface& s) { return s.withSurfaceFields(); }
593  )
594  )
595  {
596  performAction<surfaceScalarField>(objects, request);
597  performAction<surfaceVectorField>(objects, request);
598  performAction<surfaceSphericalTensorField>(objects, request);
599  performAction<surfaceSymmTensorField>(objects, request);
600  performAction<surfaceTensorField>(objects, request);
601  }
602 
603 
604  // Finish this time step
605  forAll(writers_, surfi)
606  {
607  if (((request & actions_[surfi]) & ACTION_WRITE) && nFaces_[surfi])
608  {
609  // Write geometry if no fields were written so that we still
610  // can have something to look at
611 
612  if (!writers_[surfi].wroteData())
613  {
614  writers_[surfi].write();
615  }
616 
617  writers_[surfi].endTime();
618  }
619  }
620 
621  return true;
622 }
623 
624 
626 {
627  if (onExecute_)
628  {
629  return performAction(ACTION_ALL & ~ACTION_WRITE);
630  }
631 
632  return true;
633 }
634 
637 {
638  return performAction(ACTION_ALL);
639 }
640 
641 
643 {
644  if (&mpm.mesh() == &mesh_)
645  {
646  expire();
647  }
648 
649  // pointMesh and interpolation will have been reset in mesh.update
650 }
651 
652 
653 void Foam::sampledSurfaces::movePoints(const polyMesh& mesh)
654 {
655  if (&mesh == &mesh_)
656  {
657  expire();
658  }
659 }
660 
661 
663 {
664  if (state != polyMesh::UNCHANGED)
665  {
666  // May want to use force expiration here
667  expire();
668  }
669 }
670 
671 
672 bool Foam::sampledSurfaces::needsUpdate() const
673 {
674  for (const sampledSurface& s : surfaces())
675  {
676  if (s.needsUpdate())
677  {
678  return true;
679  }
680  }
681 
682  return false;
683 }
684 
685 
686 bool Foam::sampledSurfaces::expire(const bool force)
687 {
688  // Dimension as fraction of mesh bounding box
689  const scalar mergeDim = mergeTol_ * mesh_.bounds().mag();
690 
691  label nChanged = 0;
692 
693  forAll(*this, surfi)
694  {
695  sampledSurface& s = (*this)[surfi];
696 
697  if (s.invariant() && !force)
698  {
699  // 'Invariant' - does not change when geometry does
700  continue;
701  }
702  if (s.expire())
703  {
704  ++nChanged;
705  }
706 
707  writers_[surfi].expire();
708  writers_[surfi].mergeDim(mergeDim);
709  nFaces_[surfi] = 0;
710  }
711 
712  // True if any surfaces just expired
713  return nChanged;
714 }
715 
716 
717 bool Foam::sampledSurfaces::update()
718 {
719  if (!needsUpdate())
720  {
721  return false;
722  }
723 
724  label nUpdated = 0;
725 
726  forAll(*this, surfi)
727  {
728  sampledSurface& s = (*this)[surfi];
729 
730  if (s.update())
731  {
732  ++nUpdated;
733  writers_[surfi].expire();
734  }
735 
736  nFaces_[surfi] = returnReduce(s.faces().size(), sumOp<label>());
737  }
738 
739  return nUpdated;
740 }
741 
744 {
745  return mergeTol_;
746 }
747 
748 
749 Foam::scalar Foam::sampledSurfaces::mergeTol(const scalar tol) noexcept
750 {
751  const scalar old(mergeTol_);
752  mergeTol_ = tol;
753  return old;
754 }
755 
756 
757 // ************************************************************************* //
A surface mesh consisting of general polygon faces and capable of holding fields. ...
Definition: polySurface.H:62
Foam::surfaceFields.
virtual bool write()
Sample and write.
dictionary dict
objectRegistry & storedObjects()
Write access to the output objects ("functionObjectObjects") registered on Time.
List of IOobjects with searching and retrieving facilities. Implemented as a HashTable, so the various sorted methods should be used if traversing in parallel.
Definition: IOobjectList.H:55
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
An abstract class for surfaces with sampling.
virtual void movePoints(const polyMesh &mesh)
Update for mesh point-motion - expires the surfaces.
bool found(const ListType &input, const UnaryPredicate &pred, const label start=0)
Same as found_if.
Definition: ListOps.H:826
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
virtual const dictionary & dict() const =0
Return dictionary, if entry is a dictionary.
virtual void readUpdate(const polyMesh::readUpdateState state)
Update for changes of mesh due to readUpdate - expires the surfaces.
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T. FatalIOError if not found, or if the number of tokens is incorrect.
Abstract base-class for Time/database function objects.
static dictionary formatOptions(const dictionary &dict, const word &formatName, const word &entryName="formatOptions")
Same as fileFormats::getFormatOptions.
Definition: surfaceWriter.C:57
static autoPtr< sampledSurface > New(const word &name, const polyMesh &mesh, const dictionary &dict)
Return a reference to the selected surface.
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:157
Macros for easy insertion into run-time selection tables.
const word & name() const noexcept
Return the name of this functionObject.
static scalar mergeTol() noexcept
Get merge tolerance.
Various functions to operate on Lists.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
bool readEntry(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX, IOobjectOption::readOption readOpt=IOobjectOption::MUST_READ) const
Find entry and assign to T val. FatalIOError if it is found and the number of tokens is incorrect...
static word groupName(StringType base, const word &group)
Create dot-delimited name.group string.
bool returnReduceAnd(const bool value, const label comm=UPstream::worldComm)
Perform logical (and) MPI Allreduce on a copy. Uses UPstream::reduceAnd.
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
dynamicFvMesh & mesh
virtual bool read(const dictionary &dict)
Read the sampledSurfaces dictionary.
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
A class for handling words, derived from Foam::string.
Definition: word.H:63
static Istream & input(Istream &is, IntRange< T > &range)
Definition: IntRanges.C:33
static const word null
An empty word.
Definition: word.H:84
String literal.
Definition: keyType.H:82
const wordList surface
Standard surface field types (scalar, vector, tensor, etc)
const direction noexcept
Definition: Scalar.H:258
const wordList volume
Standard volume field types (scalar, vector, tensor, etc)
void read(Istream &, label &val, const dictionary &)
In-place read with dictionary lookup.
int debug
Static debugging option.
defineTypeNameAndDebug(combustionModel, 0)
static bool clean(std::string &str)
Cleanup filename string, possibly applies other transformations such as changing the path separator e...
Definition: fileName.C:192
virtual bool execute()
Sample and store if the sampleOnExecute is enabled.
void resize(const label newLen)
Adjust size of PtrList.
Definition: PtrList.C:95
List< word > wordList
List of word.
Definition: fileName.H:59
#define WarningInFunction
Report a warning using Foam::Warning.
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
Definition: List.H:55
bool verbose(const bool on) noexcept
Enable/disable verbose output.
const polyMesh & mesh() const
Return polyMesh.
Definition: mapPolyMesh.H:437
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1082
const entry * findEntry(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry (const access) with the given keyword.
Definition: dictionaryI.H:84
void clear()
Clear the PtrList. Delete allocated entries and set size to zero.
Definition: PtrListI.H:81
messageStream Info
Information stream (stdout output on master, null elsewhere)
label n
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
readUpdateState
Enumeration defining the state of the mesh after a read update.
Definition: polyMesh.H:90
Registry of regIOobjects.
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;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
static void mapCombineReduce(Container &values, const CombineOp &cop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce) applying cop to inplace combine map values from different processo...
bool found
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
static autoPtr< surfaceWriter > New(const word &writeType)
Return a reference to the selected surfaceWriter.
Definition: surfaceWriter.C:80
Namespace for OpenFOAM.
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
A keyword and a list of tokens is an &#39;entry&#39;.
Definition: entry.H:63
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)
virtual void updateMesh(const mapPolyMesh &mpm)
Update for changes of mesh - expires the surfaces.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127