cloud.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) 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 "cloud.H"
30 #include "LagrangianFields.H"
31 #include "LagrangianmDdt.H"
32 #include "LagrangianSubFields.H"
33 #include "dimensionedTypes.H"
36 #include "pimpleNoLoopControl.H"
37 #include "Time.H"
38 #include "fvMesh.H"
39 
40 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
41 
42 namespace Foam
43 {
46 }
47 
48 
49 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
50 
52 (
53  const polyMesh& pMesh,
54  const word& name,
55  const IOobject::readOption readOption,
56  const IOobject::writeOption writeOption
57 )
58 {
59  if (!pMesh.foundObject<LagrangianMesh>(name))
60  {
61  wordList wantedPatchTypes(pMesh.boundaryMesh().size());
62 
63  forAll(pMesh.boundaryMesh(), patchi)
64  {
65  const polyPatch& patch = pMesh.boundaryMesh()[patchi];
66 
67  wantedPatchTypes[patchi] =
68  polyPatch::constraintType(patch.type())
69  ? patch.type()
70  : cloudVelocityLagrangianPatch::typeName;
71  }
72 
73  LagrangianMesh* lMesh =
74  new LagrangianMesh
75  (
76  pMesh,
77  name,
78  wantedPatchTypes,
79  readOption,
81  );
82 
83  lMesh->store();
84  }
85 
86  return pMesh.lookupObjectRef<LagrangianMesh>(name);
87 }
88 
89 
90 #define ACCESS_STATE_FIELDS(Type, nullArg) \
91 namespace Foam \
92 { \
93  template<> \
94  PtrList<Foam::CloudStateField<Type>>& cloud::stateFields() const \
95  { \
96  return CAT3(state, CAPITALIZE(Type), Fields_); \
97  } \
98 }
100 #undef ACCESS_STATE_FIELDS
101 
102 
103 void Foam::cloud::clearStateFields()
104 {
105  #define CLEAR_TYPE_STATE_FIELDS(Type, nullArg) \
106  forAll(stateFields<Type>(), i) \
107  { \
108  stateFields<Type>()[i].clear(); \
109  }
111  #undef CLEAR_TYPE_STATE_FIELDS
112 }
113 
114 
115 #define ACCESS_DERIVED_FIELDS(Type, nullArg) \
116 namespace Foam \
117 { \
118  template<> \
119  PtrList<Foam::CloudDerivedField<Type>>& cloud::derivedFields() const \
120  { \
121  return CAT3(derived, CAPITALIZE(Type), Fields_); \
122  } \
123 }
125 #undef ACCESS_DERIVED_FIELDS
126 
127 
128 void Foam::cloud::clearDerivedFields(const bool final)
129 {
130  #define CLEAR_TYPE_DERIVED_FIELDS(Type, nullArg) \
131  forAll(derivedFields<Type>(), i) \
132  { \
133  derivedFields<Type>()[i].clear(final); \
134  }
136  #undef CLEAR_TYPE_DERIVED_FIELDS
137 }
138 
139 
140 #define ACCESS_AVERAGE_FIELDS(Type, nullArg) \
141 namespace Foam \
142 { \
143  template<> \
144  PtrList<Foam::CloudAverageField<Type>>& cloud::averageFields() const \
145  { \
146  return CAT3(average, CAPITALIZE(Type), Fields_); \
147  } \
148 }
150 #undef ACCESS_AVERAGE_FIELDS
151 
152 
153 void Foam::cloud::removeFromAverageFields(const LagrangianSubMesh& subMesh)
154 {
155  #define REMOVE_FROM_TYPE_AVERAGE_FIELDS(Type, nullArg) \
156  forAll(averageFields<Type>(), i) \
157  { \
158  averageFields<Type>()[i].remove(subMesh); \
159  }
161  #undef REMOVE_FROM_TYPE_AVERAGE_FIELDS
162 }
163 
164 
165 void Foam::cloud::addToAverageFields
166 (
167  const LagrangianSubMesh& subMesh,
168  const bool final
169 )
170 {
171  #define ADD_TO_TYPE_AVERAGE_FIELDS(Type, nullArg) \
172  forAll(averageFields<Type>(), i) \
173  { \
174  averageFields<Type>()[i].add(subMesh, !final); \
175  }
177  #undef ADD_TO_TYPE_AVERAGE_FIELDS
178 }
179 
180 
181 void Foam::cloud::correctAverageFields
182 (
183  const LagrangianSubMesh& subMesh,
184  const bool final
185 )
186 {
187  #define CORRECT_TYPE_AVERAGE_FIELDS(Type, nullArg) \
188  forAll(averageFields<Type>(), i) \
189  { \
190  averageFields<Type>()[i].correct(subMesh, !final); \
191  }
193  #undef CORRECT_TYPE_AVERAGE_FIELDS
194 }
195 
196 
197 void Foam::cloud::clearAverageFields()
198 {
199  #define CLEAR_TYPE_AVERAGE_FIELDS(Type, nullArg) \
200  forAll(averageFields<Type>(), i) \
201  { \
202  averageFields<Type>()[i].clear(true); \
203  }
205  #undef CLEAR_TYPE_AVERAGE_FIELDS
206 }
207 
208 
209 void Foam::cloud::resetAverageFields()
210 {
211  #define RESET_TYPE_AVERAGE_FIELDS(Type, nullArg) \
212  forAll(averageFields<Type>(), i) \
213  { \
214  averageFields<Type>()[i].reset(); \
215  }
217  #undef RESET_TYPE_AVERAGE_FIELDS
218 }
219 
220 
221 Foam::IOobject Foam::cloud::stateIo(const IOobject::readOption r) const
222 {
223  return
224  IOobject
225  (
226  "state",
227  time().name(),
228  mesh(),
229  r,
231  );
232 }
233 
234 
236 Foam::cloud::readStates() const
237 {
238  typeIOobject<LagrangianLabelDynamicField> stateIo
239  (
240  this->stateIo(IOobject::MUST_READ)
241  );
242 
243  return
244  autoPtr<Foam::LagrangianLabelDynamicField>
245  (
246  stateIo.headerOk()
247  ? new LagrangianLabelDynamicField(stateIo, mesh_)
248  : nullptr
249  );
250 }
251 
252 
254 Foam::cloud::initialStates() const
255 {
256  // Return an empty pointer if we have no states stored
257  if (!statePtr_.valid()) return autoPtr<List<LagrangianState>>();
258 
259  // Allocate a list of states
260  autoPtr<List<LagrangianState>> resultPtr
261  (
262  new List<LagrangianState>(mesh_.size(), LagrangianState::inCell)
263  );
264  List<LagrangianState>& result = resultPtr();
265 
266  // Convert from the state labels to state enumerations
267  forAll(mesh_, i)
268  {
269  const LagrangianState s =
270  static_cast<LagrangianState>(statePtr_()[i]);
271 
272  if (s != LagrangianState::none)
273  {
274  result[i] = s;
275  }
276  }
277 
278  return resultPtr;
279 }
280 
281 
282 void Foam::cloud::clearStates()
283 {
284  statePtr_.clear();
285 }
286 
287 
288 bool Foam::cloud::storeStates()
289 {
290  // Determine whether states are needed
291  bool needStates = false;
292 
293  forAll(mesh_.boundary(), patchi)
294  {
295  const LagrangianSubMesh& patchMesh =
296  mesh_.boundary()[patchi].mesh();
297 
298  if (!patchMesh.empty()) needStates = true;
299  }
300 
301  reduce(needStates, orOp<bool>());
302 
303  // Create the state labels field as appropriate
304  if (needStates && !statePtr_.valid())
305  {
306  statePtr_.set
307  (
309  (
310  stateIo(IOobject::NO_READ),
311  mesh_,
312  dimensioned<label>
313  (
315  dimless,
316  static_cast<label>(LagrangianState::none)
317  ),
318  wordList
319  (
320  mesh().boundary().size(),
321  calculatedLagrangianPatchLabelField::typeName
322  ),
323  wordList::null(),
324  LagrangianModels().modelTypeFieldSourceTypes
325  <
326  LagrangianInjection,
327  noneStateLagrangianLabelFieldSource
328  >()
329  )
330  );
331  }
332 
333  return needStates;
334 }
335 
336 
337 void Foam::cloud::storeStates(const LagrangianSubMesh& subMesh)
338 {
339  const LagrangianState state = groupToState(subMesh.group());
340 
341  forAll(subMesh, subi)
342  {
343  const label i = subMesh.start() + subi;
344 
345  // If this particle is complete, then store the sub-mesh state within
346  // the retained state labels. If it is not complete, then reset its
347  // state so that it continues to be associated with this sub-mesh.
348  if (mesh_.states()[i] == LagrangianState::complete)
349  {
350  statePtr_()[i] = static_cast<label>(state);
351  }
352  else
353  {
354  mesh_.states()[i] = state;
355  }
356  }
357 }
358 
359 
360 Foam::tmp<Foam::LagrangianSubScalarField> Foam::cloud::cellLengthScale
361 (
362  const LagrangianSubMesh& subMesh
363 ) const
364 {
365  return
367  (
368  "cellLengthScale",
369  subMesh,
370  dimLength,
371  scalarField(cellLengthScaleVf_, subMesh.sub(mesh_.celli()))
372  );
373 }
374 
375 
376 void Foam::cloud::track
377 (
378  LagrangianSubScalarSubField& fraction,
379  const scalar maxTimeStepFraction,
380  const scalar maxCellLengthScaleFraction
381 )
382 {
383  const LagrangianSubMesh& subMesh = fraction.mesh();
384 
385  // Initialise tracking to completion over the remaining fraction
386  List<LagrangianState> endState(subMesh.size(), LagrangianState::complete);
387  LagrangianSubScalarField deltaFraction(1 - fraction);
388 
389  // Evaluate the displacement over the entire time-step
390  const LagrangianSubVectorField displacement
391  (
392  time().deltaT()*U(subMesh)
393  );
394 
395  // Limit the track to the maximum allowed fraction of the time-step
396  if (maxTimeStepFraction < 1)
397  {
398  forAll(deltaFraction, subi)
399  {
400  if (deltaFraction[subi] > maxTimeStepFraction)
401  {
402  endState[subi] = LagrangianState::inCell;
403  deltaFraction[subi] = maxTimeStepFraction;
404  }
405  }
406  }
407 
408  // Limit the track to the maximum allowed fraction of the cell length scale
409  if (maxCellLengthScaleFraction < rootGreat)
410  {
411  const LagrangianSubScalarField maxDFraction
412  (
413  maxCellLengthScaleFraction
414  *cellLengthScale(subMesh)
415  /max
416  (
417  mag(displacement),
418  dimensionedScalar(dimLength, rootVSmall)
419  )
420  );
421 
422  forAll(deltaFraction, subi)
423  {
424  if (deltaFraction[subi] > maxDFraction[subi])
425  {
426  endState[subi] = LagrangianState::inCell;
427  deltaFraction[subi] = maxDFraction[subi];
428  }
429  }
430  }
431 
432  // Track the particles
433  switch (tracking)
434  {
435  case trackingType::linear:
436  mesh_.track
437  (
438  endState,
439  LagrangianMesh::linearDisplacement
440  (
441  deltaFraction*displacement
442  ),
443  deltaFraction,
444  fraction
445  );
446  break;
447 
448  case trackingType::parabolic:
449  {
450  mesh_.track
451  (
452  endState,
453  LagrangianMesh::parabolicDisplacement
454  (
455  deltaFraction*displacement,
456  sqr(deltaFraction*time().deltaT())/2*dUdt(subMesh)
457  ),
458  deltaFraction,
459  fraction
460  );
461  break;
462  }
463  }
464 }
465 
466 
467 bool Foam::cloud::writeData(Ostream&) const
468 {
470  return false;
471 }
472 
473 
474 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
475 
476 void Foam::cloud::initialise(const bool predict)
477 {
478  clearStateFields();
479  clearDerivedFields(true);
480  clearAverageFields();
481 }
482 
483 
485 {
486  clearStateFields();
487  clearDerivedFields(true);
488  clearAverageFields();
489 }
490 
491 
493 (
494  const LagrangianSubScalarField& deltaT,
495  const bool final
496 )
497 {}
498 
499 
500 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
501 
502 namespace Foam
503 {
505  {"linear", "parabolic"};
506 }
507 
508 
509 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
510 
512 (
513  const polyMesh& pMesh,
514  const word& name,
515  const contextType context,
518 )
519 :
521  (
522  IOobject
523  (
524  typeName,
525  pMesh.time().name(),
526  mesh(pMesh, name, readOption, writeOption)
527  )
528  ),
529  mesh_(mesh(pMesh, name, readOption, writeOption)),
530  LagrangianModelsPtr_(nullptr),
531  statePtr_(readStates()),
532  cellLengthScaleVf_(mag(cbrt(mesh_.mesh().cellVolumes()))),
533  context(context),
534  tracking
535  (
537  [
538  mesh().schemes().schemesDict().lookup<word>("tracking")
539  ]
540  ),
541  U
542  (
543  stateField<vector>
544  (
545  IOobject
546  (
547  "U",
548  time().name(),
549  mesh_,
550  IOobject::MUST_READ,
551  IOobject::AUTO_WRITE
552  ),
553  mesh_
554  )
555  )
556 {}
557 
558 
559 // * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
560 
562 (
563  const polyMesh& pMesh,
564  const word& name,
565  const word& type
566 )
567 {
568  Info<< "Selecting " << typeName
569  << " with name " << name
570  << " of type " << type << endl;
571 
572  if (!polyMeshConstructorTablePtr_)
573  {
575  << typeName << "s table is empty"
576  << exit(FatalError);
577  }
578 
579  polyMeshConstructorTable::iterator cstrIter;
580 
581  cstrIter = polyMeshConstructorTablePtr_->find(type);
582 
583  if (cstrIter == polyMeshConstructorTablePtr_->end())
584  {
585  libs.open("lib" + type + typeName.capitalise() + ".so");
586  }
587 
588  cstrIter = polyMeshConstructorTablePtr_->find(type);
589 
590  if (cstrIter == polyMeshConstructorTablePtr_->end())
591  {
593  << "Unknown " << typeName << " type "
594  << type << nl << nl
595  << "Valid " << typeName << "s are :" << endl
596  << polyMeshConstructorTablePtr_->sortedToc()
597  << exit(FatalError);
598  }
599 
600  autoPtr<cloud> cloudPtr(cstrIter()(pMesh, name, contextType::unknown));
601 
602  // Ensure LagrangianModels are constructed before time is incremented
603  cloudPtr->LagrangianModels();
604 
605  return cloudPtr;
606 }
607 
608 
609 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
610 
612 {}
613 
614 
615 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
616 
618 {
619  return mesh.lookupObject<cloud>(cloud::typeName);
620 }
621 
622 
624 {
625  if (!LagrangianModelsPtr_)
626  {
627  LagrangianModelsPtr_ = &Foam::LagrangianModels::New(mesh_);
628  }
629 
630  return *LagrangianModelsPtr_;
631 }
632 
633 
635 {
636  // Create the functions list
637  cloudFunctionObjectUList functions(*this);
638 
639  // Handle outer correctors
640  bool predict = false;
641  if (context == contextType::fvModel)
642  {
643  if
644  (
645  mesh_.mesh().foundObject<pimpleNoLoopControl>
646  (
647  solutionControl::typeName
648  )
649  )
650  {
651  const pimpleNoLoopControl& pimple =
653  (
654  solutionControl::typeName
655  );
656 
657  if (pimple.nCorr() > 1)
658  {
659  if (mesh_.solution().lookup<bool>("outerCorrectors"))
660  {
661  mesh_.reset(pimple.firstIter(), pimple.finalIter());
662  resetAverageFields();
663  }
664  else if (!pimple.firstIter())
665  {
666  return;
667  }
668  }
669 
670  predict = pimple.firstIter();
671  }
672  else
673  {
674  predict = true;
675  }
676  }
677 
678  // Initial reset of cached objects
679  initialise(predict);
680 
681  Info<< "Solving cloud " << mesh_.name() << ':' << endl << incrIndent;
682 
683  // Get solution controls
684  const scalar maxTimeStepFraction =
685  mesh_.solution().lookup<scalar>("maxTimeStepFraction");
686  const scalar maxCellLengthScaleFraction =
687  mesh_.solution().lookup<scalar>("maxCellLengthScaleFraction");
688  const label nCorrectors = mesh_.solution().lookup<label>("nCorrectors");
689 
690  // Correct the models
692 
693  // Initialise the tracked fraction to zero, representing all particles
694  // being at the start of the time-step
696  (
697  IOobject
698  (
700  time().name(),
701  mesh_
702  ),
703  mesh_,
704  dimensionedScalar("zero", dimless, 0)
705  );
706 
707  // Let the models do any instantaneous modifications, removals and
708  // injections/creations of existing particles
709  LagrangianSubMesh preModifiedMesh =
710  LagrangianModels().preModify(mesh_);
711  removeFromAverageFields(preModifiedMesh);
712  LagrangianSubMesh modifiedMesh =
713  LagrangianModels().modify(mesh_, preModifiedMesh);
714  addToAverageFields(modifiedMesh, true);
715 
716  // Do a calculation on modified particles (if necessary)
717  if (reCalculateModified())
718  {
719  removeFromAverageFields(modifiedMesh);
720 
721  const LagrangianSubScalarField zeroDeltaT
722  (
723  IOobject("zeroDeltaT", mesh().time().name(), mesh()),
724  modifiedMesh,
725  dimensionedScalar(dimTime, scalar(0))
726  );
727 
728  addToAverageFields(modifiedMesh, false);
729 
730  LagrangianModels().calculate(zeroDeltaT, true);
731  calculate(zeroDeltaT, true);
732  functions.calculate(zeroDeltaT, true);
733 
734  correctAverageFields(modifiedMesh, true);
735  }
736 
737  // Construct the object defining the scope of the Lagrangian mesh changes
738  autoPtr<List<LagrangianState>> statesPtr = initialStates();
739  LagrangianMesh::changer changer =
740  statesPtr.valid()
741  ? LagrangianMesh::changer(mesh_, statesPtr())
743  statesPtr.clear();
744 
745  // State information is now in the cloud. Clear the stored state labels so
746  // that they can be re-built (if necessary) by the cloud evolution below.
747  clearStates();
748 
749  // If we have initial states then we need to evaluate the
750  // derived/non-constraint boundary conditions so that any affected
751  // properties are up date. This evaluation of the velocity boundary fields
752  // is what ensures that "stuck" particles move consistently with their
753  // respective patches. In theory, though, it could apply to any field.
754  #define EVAL_TYPE_DERIVED_PATCH_FIELDS(Type, GeoField) \
755  { \
756  HashTable<GeoField<Type>*> fields \
757  ( \
758  mesh_.lookupClass<GeoField<Type>>() \
759  ); \
760  \
761  forAllIter(typename HashTable<GeoField<Type>*>, fields, iter) \
762  { \
763  forAll(mesh_.boundary(), patchi) \
764  { \
765  const LagrangianPatch& patch = mesh_.boundary()[patchi]; \
766  \
767  if \
768  ( \
769  patch.mesh().size() \
770  && !polyPatch::constraintType(patch.type()) \
771  ) \
772  { \
773  iter()->boundaryFieldRef()[patchi].evaluate \
774  ( \
775  NullObjectNonConstRef<PstreamBuffers>(), \
776  fraction \
777  ); \
778  } \
779  } \
780  } \
781  }
784  #undef EVAL_TYPE_DERIVED_PATCH_FIELDS
785 
786  // Iterate whilst there are incomplete particles
787  while
788  (
790  (
791  mesh_.sub(LagrangianGroup::complete).size() != mesh_.size(),
792  orOp<bool>()
793  )
794  )
795  {
796  // Internal tracking and calculation
797  {
798  LagrangianSubMesh internalMesh
799  (
801  );
802 
803  LagrangianSubScalarSubField internalFraction
804  (
805  internalMesh.sub(fraction)
806  );
807 
808  removeFromAverageFields(internalMesh);
809 
810  track
811  (
812  internalFraction,
813  maxTimeStepFraction,
814  maxCellLengthScaleFraction
815  );
816 
817  const LagrangianSubScalarField deltaT
818  (
819  (internalFraction - internalFraction.oldTime())
820  *mesh_.time().deltaT()
821  );
822 
823  addToAverageFields(internalMesh, false);
824 
825  for (label i = 0; i <= nCorrectors; ++ i)
826  {
827  const bool final = i == nCorrectors;
828 
829  LagrangianModels().calculate(deltaT, final);
830  calculate(deltaT, final);
831  functions.calculate(deltaT, final);
832 
833  clearDerivedFields(final);
834  correctAverageFields(internalMesh, final);
835  }
836 
837  clearStateFields();
838  }
839 
840  // Boundary tracking and calculation (if necessary)
841  if (storeStates())
842  {
843  const labelList subMeshGlobalSizes = mesh_.subMeshGlobalSizes();
844 
845  forAll(mesh_.boundary(), patchi)
846  {
847  static const label onPatchZeroi =
848  static_cast<label>(LagrangianGroup::onPatchZero);
849 
850  if (subMeshGlobalSizes[onPatchZeroi + patchi] <= 0) continue;
851 
852  LagrangianSubMesh patchMesh
853  (
854  mesh_.boundary()[patchi].mesh()
855  );
856 
857  LagrangianSubScalarSubField patchFraction
858  (
859  patchMesh.sub(fraction)
860  );
861 
862  removeFromAverageFields(patchMesh);
863 
864  track
865  (
866  patchFraction,
867  maxTimeStepFraction,
868  maxCellLengthScaleFraction
869  );
870 
871  storeStates(patchMesh);
872 
873  const LagrangianSubScalarField deltaT
874  (
875  (patchFraction - patchFraction.oldTime())
876  *mesh_.time().deltaT()
877  );
878 
879  addToAverageFields(patchMesh, false);
880 
881  for (label i = 0; i <= nCorrectors; ++ i)
882  {
883  const bool final = i == nCorrectors;
884 
885  LagrangianModels().calculate(deltaT, final);
886  calculate(deltaT, final);
887  functions.calculate(deltaT, final);
888 
889  clearDerivedFields(final);
890  correctAverageFields(patchMesh, final);
891  }
892 
893  clearStateFields();
894  }
895  }
896 
897  // Intermediate partitioning
898  mesh_.partition();
899  partition();
900 
901  removeFromAverageFields(mesh_.subIncomplete());
902 
903  // Cross the faces
904  functions.preCrossFaces(fraction);
905  mesh_.crossFaces(fraction);
906  functions.postCrossFaces(fraction);
907 
908  addToAverageFields(mesh_.subIncomplete(), true);
909 
910  // Final partitioning
911  mesh_.partition();
912  partition();
913  };
914 
915  Info<< decrIndent;
916 }
917 
918 
920 {
921  mesh_.storePosition();
922 }
923 
924 
926 {
927  cellLengthScaleVf_ = mag(cbrt(mesh_.mesh().cellVolumes()));
928 }
929 
930 
932 {
933  mesh_.topoChange(map);
934 
935  cellLengthScaleVf_ = mag(cbrt(mesh_.mesh().cellVolumes()));
936 }
937 
938 
940 {
941  mesh_.mapMesh(map);
942 
943  cellLengthScaleVf_ = mag(cbrt(mesh_.mesh().cellVolumes()));
944 }
945 
946 
948 {
949  mesh_.distribute(map);
950 
951  cellLengthScaleVf_ = mag(cbrt(mesh_.mesh().cellVolumes()));
952 }
953 
954 
955 // ************************************************************************* //
#define ACCESS_DERIVED_FIELDS(Type, nullArg)
Definition: cloud.C:115
#define CLEAR_TYPE_DERIVED_FIELDS(Type, nullArg)
#define CORRECT_TYPE_AVERAGE_FIELDS(Type, nullArg)
#define REMOVE_FROM_TYPE_AVERAGE_FIELDS(Type, nullArg)
#define CLEAR_TYPE_STATE_FIELDS(Type, nullArg)
#define RESET_TYPE_AVERAGE_FIELDS(Type, nullArg)
#define ACCESS_AVERAGE_FIELDS(Type, nullArg)
Definition: cloud.C:140
#define ADD_TO_TYPE_AVERAGE_FIELDS(Type, nullArg)
#define CLEAR_TYPE_AVERAGE_FIELDS(Type, nullArg)
#define EVAL_TYPE_DERIVED_PATCH_FIELDS(Type, GeoField)
#define ACCESS_STATE_FIELDS(Type, nullArg)
Definition: cloud.C:90
Functions for calculating the time derivative for a Lagrangian equation.
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:433
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
static tmp< DimensionedField< Type, GeoMesh, PrimitiveField > > New(const word &name, const Mesh &mesh, const dimensionSet &, const PrimitiveField< Type > &)
Return a temporary field constructed from name, mesh,.
Generic GeometricField class.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
readOption
Enumeration defining the read options.
Definition: IOobject.H:117
const word & name() const
Return name.
Definition: IOobject.H:307
writeOption
Enumeration defining the write options.
Definition: IOobject.H:126
Class to define the scope of Lagrangian mesh state changes.
Class containing Lagrangian geometry and topology.
static const word fractionName
Name of the tracked fraction field.
List of Lagrangian models, constructed as a (Lagrangian) mesh object. Provides similar functions to t...
void correct()
Correct the LagrangianModels.
LagrangianSubMesh preModify(LagrangianMesh &mesh) const
Identify elements in the Lagrangian mesh which are to be.
LagrangianSubMesh modify(LagrangianMesh &mesh, const LagrangianSubMesh &modifiedMesh) const
Instantaneously modify and/or create and remove elements in the.
void calculate(const LagrangianSubScalarField &deltaT, const bool final)
Solve equations and/or update continually changing properties.
Mesh that relates to a sub-section of a Lagrangian mesh. This is used to construct fields that relate...
SubList< Type > sub(const List< Type > &list) const
Return a sub-list corresponding to this sub-mesh.
static const List< word > & null()
Return a null List.
Definition: ListI.H:118
Initialise the NamedEnum HashTable from the static list of names.
Definition: NamedEnum.H:55
const Field0Type & oldTime() const
Return the old-time field.
Definition: OldTimeField.C:322
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: autoPtr.H:51
bool valid() const
Return true if the autoPtr valid (ie, the pointer is set)
Definition: autoPtrI.H:83
void clear()
Delete object (if the pointer is valid) and set pointer to.
Definition: autoPtrI.H:126
List of references to the cloud function objects. Designed to be constructed temporarily for the scop...
virtual void postCrossFaces(const LagrangianSubScalarSubField &fraction)
Hook following face crossings of a specific sub-mesh.
virtual void calculate(const LagrangianSubScalarField &deltaT, const bool final)
Solve equations and/or update continually changing properties.
virtual void preCrossFaces(const LagrangianScalarInternalDynamicField &fraction)
Hook before face crossings.
Base class for clouds. Provides a basic evolution algorithm, models, and a database for caching deriv...
Definition: cloud.H:63
contextType
Context in which this cloud is used.
Definition: cloud.H:222
virtual void initialise(const bool predict)
Initialisation hook.
Definition: cloud.C:476
cloud(const polyMesh &mesh, const word &name, const contextType context, const IOobject::readOption readOption=IOobject::READ_IF_PRESENT, const IOobject::writeOption writeOption=IOobject::AUTO_WRITE)
Construct from a mesh and a name.
Definition: cloud.C:512
virtual void topoChange(const polyTopoChangeMap &)
Update topology using the given map.
Definition: cloud.C:931
virtual void distribute(const polyDistributionMap &)
Redistribute or update using the given distribution map.
Definition: cloud.C:947
virtual void storePosition()
Store the positions for use during mapping.
Definition: cloud.C:919
virtual void mapMesh(const polyMeshMap &)
Update from another mesh using the given map.
Definition: cloud.C:939
Foam::LagrangianModels & LagrangianModels() const
Access the models.
Definition: cloud.C:623
static autoPtr< cloud > New(const polyMesh &mesh, const word &name, const word &type)
Selector.
Definition: cloud.C:562
virtual void movePoints(const polyMesh &)
Update for mesh motion.
Definition: cloud.C:925
static const Foam::cloud & lookup(const LagrangianMesh &mesh)
Lookup the cloud associated with a mesh.
Definition: cloud.C:617
virtual ~cloud()
Destructor.
Definition: cloud.C:611
virtual void partition()
Partition hook.
Definition: cloud.C:484
virtual void calculate(const LagrangianSubScalarField &deltaT, const bool final)
Update the cloud properties.
Definition: cloud.C:493
const LagrangianMesh & mesh() const
Access the mesh.
Definition: cloud.H:276
virtual void solve()
Solve the cloud's evolution over the current time-step.
Definition: cloud.C:634
static autoPtr< dictionary > New(Istream &)
Construct top-level dictionary on freestore from Istream.
Definition: dictionaryIO.C:103
bool open(const fileName &libName, const bool verbose=true)
Open the named library, optionally with warnings if problems occur.
const Type & lookupObject(const word &name) const
Lookup and return the object of the given Type and name.
Pimple no-loop control class. Implements various option flags, but leaves loop controls to the deriva...
bool finalIter() const
Flag to indicate the final iteration.
bool firstIter() const
Flag to indicate the first iteration.
label nCorr() const
Maximum number of correctors.
Class containing mesh-to-mesh mapping information after a mesh distribution where we send parts of me...
Class containing mesh-to-mesh mapping information.
Definition: polyMeshMap.H:51
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:80
static bool constraintType(const word &pt)
Return true if the given type is a constraint type.
Definition: polyPatch.C:238
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:55
const fvMesh & mesh() const
Return the mesh.
A class for managing temporary objects.
Definition: tmp.H:55
A class for handling words, derived from string.
Definition: word.H:62
pimpleControl pimple(mesh)
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
#define NotImplemented
Issue a FatalErrorIn for a function not currently implemented.
Definition: error.H:381
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
label patchi
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))
U
Definition: pEqn.H:72
label calculate(const fvMesh &mesh, const labelHashSet &patchIDs, const scalar minFaceFraction, GeometricField< scalar, GeoMesh > &distance)
Calculate distance data from patches.
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
dlLibraryTable libs
Table of loaded dynamic libraries.
List< word > wordList
A List of words.
Definition: fileName.H:54
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
Definition: Ostream.H:242
LagrangianState groupToState(const LagrangianGroup &group)
Convert from a state enumeration to the corresponding group enumerations.
const NamedEnum< enum cloud::trackingType, 2 > cloudTrackingNames
Definition: cloud.C:505
defineRunTimeSelectionTable(reactionRateFlameArea, dictionary)
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
LagrangianDynamicField< label > LagrangianLabelDynamicField
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:258
const dimensionSet dimless
messageStream Info
const dimensionSet dimLength
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition: Ostream.H:235
void mag(LagrangianPatchField< scalar > &f, const LagrangianPatchField< Type > &f1)
LagrangianState
Lagrangian state enumeration.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
const dimensionSet dimTime
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
defineTypeNameAndDebug(combustionModel, 0)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
void cbrt(LagrangianPatchField< scalar > &f, const LagrangianPatchField< scalar > &f1)
void sqr(LagrangianPatchField< typename outerProduct< Type, Type >::type > &f, const LagrangianPatchField< Type > &f1)
LagrangianSubSubField< scalar > LagrangianSubScalarSubField
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
error FatalError
FOR_ALL_FIELD_TYPES(makeFieldSourceTypedef)
LagrangianSubField< scalar > LagrangianSubScalarField
static const char nl
Definition: Ostream.H:267
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
fileType type(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file type: directory or file.
Definition: POSIX.C:488
LagrangianSubField< vector > LagrangianSubVectorField
faceListList boundary(nPatches)