MPPICCloud.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) 2013-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 "MPPICCloud.H"
27 #include "NoPacking.H"
28 #include "ParticleStressModel.H"
29 #include "NoDamping.H"
30 #include "NoIsotropy.H"
31 #include "TimeScaleModel.H"
32 #include "pointFields.H"
33 
34 // * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
35 
36 template<class CloudType>
38 {
39  packingModel_.reset
40  (
42  (
43  this->subModelProperties(),
44  *this
45  ).ptr()
46  );
47  dampingModel_.reset
48  (
50  (
51  this->subModelProperties(),
52  *this
53  ).ptr()
54  );
55  isotropyModel_.reset
56  (
58  (
59  this->subModelProperties(),
60  *this
61  ).ptr()
62  );
63 }
64 
65 
66 template<class CloudType>
68 {
69  CloudType::cloudReset(c);
70 
71  packingModel_.reset(c.packingModel_.ptr());
72  dampingModel_.reset(c.dampingModel_.ptr());
73  isotropyModel_.reset(c.isotropyModel_.ptr());
74 }
75 
76 
77 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
78 
79 template<class CloudType>
81 (
82  const word& cloudName,
83  const volScalarField& rho,
84  const volVectorField& U,
85  const volScalarField& mu,
86  const dimensionedVector& g,
87  const bool readFields
88 )
89 :
90  CloudType(cloudName, rho, U, mu, g, false),
91  packingModel_(nullptr),
92  dampingModel_(nullptr),
93  isotropyModel_(nullptr)
94 {
95  if (this->solution().steadyState())
96  {
98  << "MPPIC modelling not available for steady state calculations"
99  << exit(FatalError);
100  }
101 
102  setModels();
103 
104  if (readFields)
105  {
106  parcelType::readFields(*this);
107  this->deleteLostParticles();
108  }
109 }
110 
111 
112 template<class CloudType>
114 (
115  const word& cloudName,
116  const volScalarField& rho,
117  const volVectorField& U,
118  const dimensionedVector& g,
119  const fluidThermo& carrierThermo,
120  const bool readFields
121 )
122 :
123  MPPICCloud(cloudName, rho, U, carrierThermo.mu(), g, readFields)
124 {}
125 
126 
127 template<class CloudType>
129 (
131  const word& name
132 )
133 :
134  CloudType(c, name),
135  packingModel_(c.packingModel_->clone()),
136  dampingModel_(c.dampingModel_->clone()),
137  isotropyModel_(c.isotropyModel_->clone())
138 {}
139 
140 
141 template<class CloudType>
143 (
144  const fvMesh& mesh,
145  const word& name,
146  const MPPICCloud<CloudType>& c
147 )
148 :
149  CloudType(mesh, name, c),
150  packingModel_(nullptr),
151  dampingModel_(nullptr),
152  isotropyModel_(nullptr)
153 {}
154 
155 
156 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
157 
158 template<class CloudType>
160 {}
161 
162 
163 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
164 
165 template<class CloudType>
167 {
168  cloudCopyPtr_.reset
169  (
170  static_cast<MPPICCloud<CloudType>*>
171  (
172  clone(this->name() + "Copy").ptr()
173  )
174  );
175 }
176 
177 
178 template<class CloudType>
180 {
181  cloudReset(cloudCopyPtr_());
182 
183  cloudCopyPtr_.clear();
184 }
185 
186 
187 template<class CloudType>
189 {
190  if (this->solution().canEvolve())
191  {
192  typename parcelType::trackingData td(*this);
193 
194  this->solve(*this, td);
195  }
196 }
197 
198 
199 template<class CloudType>
200 template<class TrackCloudType>
202 (
203  TrackCloudType& cloud,
204  typename parcelType::trackingData& td
205 )
206 {
207  // Assign parcel ID-s
208  label i = 0;
209  forAllIter(typename MPPICCloud<CloudType>, *this, iter)
210  {
211  iter().id() = labelPair(Pstream::myProcNo(), i ++);
212  }
213 
214  // Create a copy of all parcels and sources to use as a predictor
215  autoPtr<MPPICCloud<CloudType>> predictorCloudPtr
216  (
217  static_cast<MPPICCloud<CloudType>*>
218  (
219  clone(this->name() + "Predictor").ptr()
220  )
221  );
222  MPPICCloud<CloudType>& predictorCloud = predictorCloudPtr();
223 
224  // Predictor move
225  predictorCloud.CloudType::move(predictorCloud, td);
226 
227  // Calculate correction velocities
228  const scalar trackTime = td.trackTime();
229  td.updateAverages(predictorCloud);
230  predictorCloud.dampingModel().cacheFields(true);
231  predictorCloud.packingModel().cacheFields(true);
232  vectorField UCorr(this->size(), Zero);
235  forAllIter(typename MPPICCloud<CloudType>, predictorCloud, iter)
236  {
237  const labelPair& id = iter().id();
238 
239  const vector dU =
240  predictorCloud.packingModel().velocityCorrection(iter(), trackTime)
241  + predictorCloud.dampingModel().velocityCorrection(iter(), trackTime);
242 
243  if (id.first() == Pstream::myProcNo())
244  {
245  UCorr[id.second()] = dU;
246  }
247  else
248  {
249  UCorrProc[id.first()].append(dU);
250  IDProc[id.first()].append(id.second());
251  }
252  }
253  predictorCloud.dampingModel().cacheFields(false);
254  predictorCloud.packingModel().cacheFields(false);
255 
256  // Distribute the correction velocities
258  if (Pstream::parRun())
259  {
260  forAll(UCorrProc, proci)
261  {
262  if (proci == Pstream::myProcNo()) continue;
263 
264  UOPstream os(proci, pBufs);
265 
266  os << UCorrProc[proci] << IDProc[proci];
267  }
268 
269  pBufs.finishedSends();
270 
271  forAll(UCorrProc, proci)
272  {
273  if (proci == Pstream::myProcNo()) continue;
274 
275  UIPstream is(proci, pBufs);
276 
277  is >> UCorrProc[proci] >> IDProc[proci];
278  }
279  }
280  forAll(UCorrProc, proci)
281  {
282  if (proci == Pstream::myProcNo()) continue;
283 
284  forAll(UCorrProc[proci], i)
285  {
286  UCorr[IDProc[proci][i]] = UCorrProc[proci][i];
287  }
288  }
289 
290  // Apply the correction velocities to the parcels
291  forAllIter(typename MPPICCloud<CloudType>, *this, iter)
292  {
293  iter().U() += UCorr[iter().id().second()];
294  }
295 
296  // Corrector
297  CloudType::move(cloud, td);
298 
299  // Apply isotropy model
300  td.updateAverages(cloud);
301  isotropyModel_->calculate();
302 
303  // Update cell occupancy
304  this->updateCellOccupancy();
305 }
306 
307 
308 template<class CloudType>
310 {
311  CloudType::info();
312 
313  tmp<volScalarField> alpha = this->alpha();
314 
315  const scalar alphaMin = gMin(alpha().primitiveField());
316  const scalar alphaMax = gMax(alpha().primitiveField());
317 
318  Info<< " Min cell volume fraction = " << alphaMin << endl;
319  Info<< " Max cell volume fraction = " << alphaMax << endl;
320 
321  if (alphaMax < small)
322  {
323  return;
324  }
325 
326  scalar nMin = great;
327 
328  forAll(this->mesh().cells(), celli)
329  {
330  const label n = this->cellOccupancy()[celli].size();
331 
332  if (n > 0)
333  {
334  const scalar nPack = n*alphaMax/alpha()[celli];
335 
336  if (nPack < nMin)
337  {
338  nMin = nPack;
339  }
340  }
341  }
342 
343  reduce(nMin, minOp<scalar>());
344 
345  Info<< " Min dense number of parcels = " << nMin << endl;
346 }
347 
348 
349 // ************************************************************************* //
label n
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
#define forAllIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:474
const List< DynamicList< molecule * > > & cellOccupancy
Templated base class for dsmc cloud.
Definition: DSMCCloud.H:80
void info() const
Print cloud information.
Definition: DSMCCloud.C:1008
Base class for collisional damping models.
Definition: DampingModel.H:60
Generic GeometricField class.
Base class for collisional return-to-isotropy models.
Definition: IsotropyModel.H:60
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:91
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:178
Adds MPPIC modelling to clouds.
Definition: MPPICCloud.H:78
const DampingModel< MPPICCloud< CloudType > > & dampingModel() const
Return condt access to the damping model.
Definition: MPPICCloudI.H:54
void setModels()
Set cloud sub-models.
Definition: MPPICCloud.C:37
void motion(TrackCloudType &cloud, typename parcelType::trackingData &td)
Particle motion.
Definition: MPPICCloud.C:202
void storeState()
Store the current cloud state.
Definition: MPPICCloud.C:166
virtual ~MPPICCloud()
Destructor.
Definition: MPPICCloud.C:159
void evolve()
Evolve the cloud.
Definition: MPPICCloud.C:188
void info()
I-O.
Definition: MPPICCloud.C:309
void restoreState()
Reset the current cloud to the previously stored state.
Definition: MPPICCloud.C:179
void cloudReset(MPPICCloud< CloudType > &c)
Reset state of cloud.
Definition: MPPICCloud.C:67
MPPICCloud(const word &cloudName, const volScalarField &rho, const volVectorField &U, const volScalarField &mu, const dimensionedVector &g, const bool readFields=true)
Construct given carrier fields.
Definition: MPPICCloud.C:81
const PackingModel< MPPICCloud< CloudType > > & packingModel() const
Return const access to the packing model.
Definition: MPPICCloudI.H:38
Base class for packing models.
Definition: PackingModel.H:65
Buffers for inter-processor communications streams (UOPstream, UIPstream).
void finishedSends(const bool block=true)
Mark all sends as having been done. This will start receives.
Input inter-processor communications stream operating on external buffer.
Definition: UIPstream.H:57
Output inter-processor communications stream operating on external buffer.
Definition: UOPstream.H:58
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:411
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:399
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:429
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: autoPtr.H:51
Base class for clouds. Provides a basic evolution algorithm, models, and a database for caching deriv...
Definition: cloud.H:61
Base-class for fluid thermodynamic properties.
Definition: fluidThermo.H:56
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:98
void deleteLostParticles()
Remove lost particles from cloud and delete.
Definition: Cloud.C:241
void move(TrackCloudType &cloud, typename ParticleType::trackingData &td)
Move the particles.
Definition: Cloud.C:292
Selector class for relaxation factors, solver type and solution.
Definition: solution.H:51
A class for managing temporary objects.
Definition: tmp.H:55
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)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
const cellShapeList & cells
U
Definition: pEqn.H:72
rho
Definition: pEqn.H:1
dimensionedScalar alphaMax(viscosity->lookup("alphaMax"))
volScalarField alpha(IOobject("alpha", runTime.name(), mesh, IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE), lambda *max(Ua &U, zeroSensitivity))
const dimensionedScalar mu
Atomic mass unit.
const dimensionedScalar c
Speed of light in a vacuum.
Type gMin(const UList< Type > &f, const label comm)
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
static const zero Zero
Definition: zero.H:97
Pair< label > labelPair
Label pair.
Definition: labelPair.H:48
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
void readFields(const typename GeoFieldType::Mesh &mesh, const IOobjectList &objects, const HashSet< word > &selectedFields, LIFOStack< regIOobject * > &storedObjects)
Read the selected GeometricFields of the specified type.
Definition: ReadFields.C:244
messageStream Info
labelList second(const UList< labelPair > &p)
Definition: patchToPatch.C:49
labelList first(const UList< labelPair > &p)
Definition: patchToPatch.C:39
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
T clone(const T &t)
Definition: List.H:55
Type gMax(const UList< Type > &f, const label comm)
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
error FatalError
tmp< DimensionedField< TypeR, GeoMesh, Field > > New(const tmp< DimensionedField< TypeR, GeoMesh, Field >> &tdf1, const word &name, const dimensionSet &dimensions)
SolverPerformance< Type > solve(fvMatrix< Type > &, const word &)
Solve returning the solution statistics given convergence tolerance.
const word cloudName(propsDict.lookup("cloudName"))