MovingPhaseModel.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) 2015-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 "MovingPhaseModel.H"
27 #include "phaseSystem.H"
30 #include "wallFvPatch.H"
32 #include "slipFvPatchFields.H"
34 
35 #include "fvmDdt.H"
36 #include "fvmDiv.H"
37 #include "fvmSup.H"
38 #include "fvcDdt.H"
39 #include "fvcDiv.H"
40 #include "fvcFlux.H"
41 
42 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
43 
44 template<class BasePhaseModel>
47 {
48  word phiName(IOobject::groupName("phi", this->name()));
49 
50  typeIOobject<surfaceScalarField> phiHeader
51  (
52  phiName,
53  U.mesh().time().name(),
54  U.mesh(),
55  IOobject::NO_READ
56  );
57 
58  if (phiHeader.headerOk())
59  {
60  Info<< "Reading face flux field " << phiName << endl;
61 
62  return tmp<surfaceScalarField>
63  (
65  (
66  IOobject
67  (
68  phiName,
69  U.mesh().time().name(),
70  U.mesh(),
71  IOobject::MUST_READ,
72  IOobject::AUTO_WRITE
73  ),
74  U.mesh(),
76  )
77  );
78  }
79  else
80  {
81  Info<< indentOrNl << "Calculating face flux field " << phiName << endl;
82 
83  wordList phiTypes
84  (
85  U.boundaryField().size(),
87  );
88 
89  forAll(U.boundaryField(), patchi)
90  {
91  if (!U.boundaryField()[patchi].assignable())
92  {
94  }
95  }
96 
97  return tmp<surfaceScalarField>
98  (
100  (
101  IOobject
102  (
103  phiName,
104  U.mesh().time().name(),
105  U.mesh(),
106  IOobject::NO_READ,
107  IOobject::AUTO_WRITE
108  ),
109  fvc::flux(U),
110  phiTypes
111  )
112  );
113  }
114 }
115 
116 
117 template<class BasePhaseModel>
119 (
120  const volVectorField& U
121 ) const
122 {
123  wordList alphaPhiTypes
124  (
125  U.boundaryField().size(),
127  );
128 
129  forAll(U.boundaryField(), patchi)
130  {
131  const fvPatchVectorField& UPf = U.boundaryField()[patchi];
132 
133  if
134  (
135  // Check for fixedValue with a value of 0 for backward compatibility
136  (
137  isType<fixedValueFvPatchVectorField>(UPf)
138  && gSum(UPf) == vector::zero
139  )
140  // Check for wall patch type
141  || isType<wallFvPatch>(this->mesh().boundary()[patchi])
142  || isA<noSlipFvPatchVectorField>(UPf)
143  || isA<slipFvPatchVectorField>(UPf)
144  || isA<partialSlipFvPatchVectorField>(UPf)
145  )
146  {
148  }
149  }
150 
151  return alphaPhiTypes;
152 }
153 
154 
155 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
156 
157 template<class BasePhaseModel>
159 (
160  const phaseSystem& fluid,
161  const word& phaseName,
162  const bool referencePhase,
163  const label index
164 )
165 :
166  BasePhaseModel(fluid, phaseName, referencePhase, index),
167  U_
168  (
169  IOobject
170  (
171  IOobject::groupName("U", this->name()),
172  fluid.mesh().time().name(),
173  fluid.mesh(),
174  IOobject::MUST_READ,
175  IOobject::AUTO_WRITE
176  ),
177  fluid.mesh(),
178  dimensions::velocity
179  ),
180  phi_(phi(U_)),
181  alphaPhi_
182  (
183  IOobject
184  (
185  IOobject::groupName("alphaPhi", this->name()),
186  fluid.mesh().time().name(),
187  fluid.mesh(),
188  IOobject::READ_IF_PRESENT,
189  IOobject::NO_WRITE
190  ),
191  fluid.mesh(),
192  dimensionedScalar(dimensionSet(0, 3, -1, 0, 0), 0),
193  alphaPhiTypes(U_)
194  ),
195  alphaRhoPhi_
196  (
197  IOobject
198  (
199  IOobject::groupName("alphaRhoPhi", this->name()),
200  fluid.mesh().time().name(),
201  fluid.mesh(),
202  IOobject::READ_IF_PRESENT,
203  IOobject::AUTO_WRITE
204  ),
205  fluid.mesh(),
206  dimensionedScalar(dimensionSet(1, 0, -1, 0, 0), 0),
207  alphaPhiTypes(U_)
208  ),
209  Uf_(nullptr),
210  divU_(nullptr),
211  momentumTransport_
212  (
213  phaseCompressible::momentumTransportModel::New
214  (
215  *this,
216  this->rho(),
217  U_,
218  alphaRhoPhi_,
219  phi_,
220  *this
221  )
222  ),
223  continuityError_
224  (
225  IOobject
226  (
227  IOobject::groupName("continuityError", this->name()),
228  fluid.mesh().time().name(),
229  fluid.mesh()
230  ),
231  fluid.mesh(),
233  ),
234  K_(nullptr)
235 {
237 
238  if (fluid.mesh().dynamic() || this->fluid().MRF().size())
239  {
240  Uf_ = new surfaceVectorField
241  (
242  IOobject
243  (
244  IOobject::groupName("Uf", this->name()),
245  fluid.mesh().time().name(),
246  fluid.mesh(),
249  ),
251  );
252  }
253 
255 }
256 
257 
258 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
259 
260 template<class BasePhaseModel>
262 {}
263 
264 
265 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
266 
267 template<class BasePhaseModel>
269 (
270  const volScalarField& source
271 )
272 {
273  volScalarField& rho = this->rho();
274  continuityError_ = fvc::ddt(*this, rho) + fvc::div(alphaRhoPhi_) - source;
275 }
276 
277 
278 template<class BasePhaseModel>
280 {
282 }
283 
284 
285 template<class BasePhaseModel>
287 {
288  BasePhaseModel::correctKinematics();
289 
290  if (K_.valid())
291  {
292  K_.ref() = 0.5*magSqr(this->U());
293  }
294 }
295 
296 
297 template<class BasePhaseModel>
299 {
300  BasePhaseModel::predictMomentumTransport();
301  momentumTransport_->predict();
302 }
303 
304 
305 template<class BasePhaseModel>
307 {
308  BasePhaseModel::correctMomentumTransport();
309  momentumTransport_->correct();
310 }
311 
312 
313 template<class BasePhaseModel>
315 {
316  const fvMesh& mesh = this->fluid().mesh();
317 
318  if (Uf_.valid())
319  {
320  Uf_() = fvc::interpolate(U_);
322  Uf_() +=
323  n*(
324  this->fluid().MRF().absolute(fvc::absolute(phi_, U_))
325  /mesh.magSf()
326  - (n & Uf_())
327  );
328  }
329 }
330 
331 
332 template<class BasePhaseModel>
334 {
335  return false;
336 }
337 
338 
339 template<class BasePhaseModel>
342 {
343  const volScalarField& alpha = *this;
344  const volScalarField& rho = this->rho();
345 
346  return
347  (
348  fvm::ddt(alpha, rho, U_)
349  + fvm::div(alphaRhoPhi_, U_)
350  + fvm::SuSp(-this->continuityError(), U_)
351  + this->fluid().MRF().DDt(alpha*rho, U_)
352  + momentumTransport_->divDevTau(U_)
353  );
354 }
355 
356 
357 template<class BasePhaseModel>
360 {
361  // As the "normal" U-eqn but without the ddt terms
362 
363  const volScalarField& alpha = *this;
364  const volScalarField& rho = this->rho();
365 
366  return
367  (
368  fvm::div(alphaRhoPhi_, U_)
369  + fvm::SuSp(fvc::ddt(*this, rho) - this->continuityError(), U_)
370  + this->fluid().MRF().DDt(alpha*rho, U_)
371  + momentumTransport_->divDevTau(U_)
372  );
373 }
374 
375 
376 template<class BasePhaseModel>
379 {
380  return U_;
381 }
382 
383 
384 template<class BasePhaseModel>
387 {
388  return U_;
389 }
390 
391 
392 template<class BasePhaseModel>
395 {
396  return U_;
397 }
398 
399 
400 template<class BasePhaseModel>
403 {
404  return phi_;
405 }
406 
407 
408 template<class BasePhaseModel>
411 {
412  return phi_;
413 }
414 
415 
416 template<class BasePhaseModel>
419 {
420  return phi_;
421 }
422 
423 
424 template<class BasePhaseModel>
427 {
428  return Uf_;
429 }
430 
431 
432 template<class BasePhaseModel>
435 {
436  if (Uf_.valid())
437  {
438  return Uf_();
439  }
440  else
441  {
443  << "Uf has not been allocated."
444  << exit(FatalError);
445 
446  return const_cast<surfaceVectorField&>(surfaceVectorField::null());
447  }
448 }
449 
450 
451 template<class BasePhaseModel>
454 {
455  if (Uf_.valid())
456  {
457  return Uf_();
458  }
459  else
460  {
462  << "Uf has not been allocated."
463  << exit(FatalError);
464 
465  return const_cast<surfaceVectorField&>(surfaceVectorField::null());
466  }
467 }
468 
469 
470 template<class BasePhaseModel>
473 {
474  return alphaPhi_;
475 }
476 
477 
478 template<class BasePhaseModel>
481 {
482  return alphaPhi_;
483 }
484 
485 
486 template<class BasePhaseModel>
489 {
490  return alphaPhi_;
491 }
492 
493 
494 template<class BasePhaseModel>
497 {
498  return alphaRhoPhi_;
499 }
500 
501 
502 template<class BasePhaseModel>
505 {
506  return alphaRhoPhi_;
507 }
508 
509 
510 template<class BasePhaseModel>
513 {
514  return alphaRhoPhi_;
515 }
516 
517 
518 template<class BasePhaseModel>
521 {
522  const tmp<surfaceScalarField> taphi(fvc::absolute(phi_, U_));
523  const surfaceScalarField& aphi(taphi());
524 
525  return
526  fvm::div(aphi, U_) - fvm::Sp(fvc::div(aphi), U_)
527  + this->fluid().MRF().DDt(U_);
528 }
529 
530 
531 template<class BasePhaseModel>
534 {
535  return fvm::ddt(U_) + UgradU();
536 }
537 
538 
539 template<class BasePhaseModel>
542 {
543  return continuityError_;
544 }
545 
546 
547 template<class BasePhaseModel>
550 {
551  if (!K_.valid())
552  {
553  K_ =
554  new volScalarField
555  (
556  IOobject::groupName("K", this->name()),
557  0.5*magSqr(this->U())
558  );
559  }
560 
561  return tmp<volScalarField>(K_());
562 }
563 
564 
565 template<class BasePhaseModel>
568 {
569  return divU_;
570 }
571 
572 
573 template<class BasePhaseModel>
575 {
576  if (!divU_.valid())
577  {
578  divU_ = divU.ptr();
579  divU_().rename(IOobject::groupName("divU", this->name()));
580  divU_().checkIn();
581  }
582  else
583  {
584  divU_() = divU;
585  }
586 }
587 
588 
589 template<class BasePhaseModel>
592 {
593  return momentumTransport_->k();
594 }
595 
596 
597 template<class BasePhaseModel>
600 {
601  return momentumTransport_->pPrimef();
602 }
603 
604 
605 // ************************************************************************* //
label n
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
Generic GeometricField class.
static const GeometricField< Type, GeoMesh, PrimitiveField > & null()
Return a null geometric field.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
writeOption & writeOpt() const
Definition: IOobject.H:367
static word groupName(Name name, const word &group)
Class which represents a moving fluid phase. Holds the velocity, fluxes and momentumTransport model a...
virtual void correctUf()
Correct the face velocity for moving meshes.
virtual void correctKinematics()
Correct the kinematics.
virtual tmp< fvVectorMatrix > UEqn()
Return the momentum equation.
volVectorField U_
Velocity field.
virtual void correct()
Correct the phase properties other than the thermo.
virtual tmp< volScalarField > k() const
Return the turbulent kinetic energy.
virtual tmp< fvVectorMatrix > DUDt() const
Return the substantive acceleration matrix.
virtual ~MovingPhaseModel()
Destructor.
virtual tmp< volVectorField > U() const
Return the velocity.
virtual void correctMomentumTransport()
Correct the momentumTransport.
virtual surfaceScalarField & alphaRhoPhiRef()
Access the mass flux of the phase.
virtual const autoPtr< volScalarField > & divU() const
Return the phase dilatation rate (d(alpha)/dt + div(alpha*phi))
virtual surfaceScalarField & phiRef()
Access the volumetric flux.
virtual tmp< surfaceScalarField > alphaPhi() const
Return the volumetric flux of the phase.
virtual tmp< volScalarField > K() const
Return the phase kinetic energy.
surfaceScalarField phi_
Flux.
MovingPhaseModel(const phaseSystem &fluid, const word &phaseName, const bool referencePhase, const label index)
virtual tmp< surfaceScalarField > pPrimef() const
Return the face-phase-pressure'.
virtual const autoPtr< surfaceVectorField > & Uf() const
Return the face velocity.
virtual surfaceVectorField & UfRef()
Access the face velocity.
virtual surfaceScalarField & alphaPhiRef()
Access the volumetric flux of the phase.
virtual tmp< surfaceScalarField > alphaRhoPhi() const
Return the mass flux of the phase.
virtual tmp< surfaceScalarField > phi() const
Return the volumetric flux.
virtual tmp< fvVectorMatrix > UfEqn()
Return the momentum equation for the face-based algorithm.
virtual volVectorField & URef()
Access the velocity.
virtual bool stationary() const
Return whether the phase is stationary.
virtual void predictMomentumTransport()
Predict the momentumTransport.
virtual tmp< fvVectorMatrix > UgradU() const
Return the velocity transport matrix.
virtual tmp< volScalarField > continuityError() const
Return the continuity error.
virtual void correctContinuityError(const volScalarField &source)
Correct the continuity error.
autoPtr< surfaceVectorField > Uf_
Face velocity field.
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: autoPtr.H:51
Dimension set for the base types.
Definition: dimensionSet.H:125
const word & name() const
Return const reference to name.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:98
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:433
const surfaceVectorField & Sf() const
Return cell face area vectors.
const surfaceScalarField & magSf() const
Return cell face area magnitudes.
bool dynamic() const
Is this mesh dynamic?
Definition: fvMesh.C:697
Abstract base class for momentum transport models (RAS, LES and laminar).
Class to represent a system of phases.
Definition: phaseSystem.H:74
const fvMesh & mesh() const
Return the mesh.
Definition: phaseSystemI.H:91
A class for managing temporary objects.
Definition: tmp.H:55
T * ptr() const
Return tmp pointer for reuse.
Definition: tmpI.H:221
A class for handling words, derived from string.
Definition: word.H:63
const Foam::MRFZones & MRF(Foam::MRFZones::New(mesh))
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
Calculate the first temporal derivative.
Calculate the divergence of the given field.
Calculate the face-flux of the given field.
Calculate the matrix for the first temporal derivative.
Calculate the matrix for the divergence of the given field and flux.
Calculate the matrix for implicit and explicit sources.
label patchi
U
Definition: pEqn.H:72
rho
Definition: pEqn.H:1
volScalarField alpha(IOobject("alpha", runTime.name(), mesh, IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE), lambda *max(Ua &U, zeroSensitivity))
void correct(const RdeltaTType &rDeltaT, const RhoType &rho, volScalarField &psi, const surfaceScalarField &phiCorr, const SpType &Sp)
const dimensionSet velocity
const dimensionSet time
const dimensionSet volumetricFlux
tmp< VolField< Type > > DDt(const surfaceScalarField &phi, const VolField< Type > &psi)
Definition: fvcDDt.C:45
tmp< SurfaceField< typename innerProduct< vector, Type >::type > > flux(const VolField< Type > &vf)
Return the face-flux field obtained from the given volVectorField.
static tmp< SurfaceField< Type > > interpolate(const VolField< Type > &tvf, const surfaceScalarField &faceFlux, Istream &schemeData)
Interpolate field onto faces using scheme given by Istream.
tmp< VolField< Type > > ddt(const dimensioned< Type > dt, const fvMesh &mesh)
Definition: fvcDdt.C:45
tmp< VolField< Type > > div(const SurfaceField< Type > &ssf)
Definition: fvcDiv.C:47
tmp< surfaceScalarField > absolute(const tmp< surfaceScalarField > &tphi, const volVectorField &U)
Return the given relative flux in absolute form.
Definition: fvcMeshPhi.C:202
tmp< fvMatrix< Type > > div(const surfaceScalarField &flux, const VolField< Type > &vf, const word &name)
Definition: fvmDiv.C:48
tmp< fvMatrix< Type > > Sp(const volScalarField::Internal &, const VolField< Type > &)
tmp< fvMatrix< Type > > SuSp(const volScalarField::Internal &, const VolField< Type > &)
tmp< fvMatrix< Type > > ddt(const VolField< Type > &vf)
Definition: fvmDdt.C:46
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
List< word > wordList
A List of words.
Definition: fileName.H:54
VolField< vector > volVectorField
Definition: volFieldsFwd.H:63
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
String typeName(const std::type_info &info)
Return the un-mangled name given the standard type info.
SurfaceField< scalar > surfaceScalarField
messageStream Info
Type gSum(const UList< Type > &f, const label comm)
const dimensionSet & dimTime
Definition: dimensions.C:277
VolField< scalar > volScalarField
Definition: volFieldsFwd.H:62
const dimensionSet & dimDensity
Definition: dimensions.C:289
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
Ostream & indentOrNl(Ostream &os)
Indent stream or add newline if indent level == 0.
Definition: Ostream.H:250
error FatalError
SurfaceField< vector > surfaceVectorField
tmp< DimensionedField< scalar, GeoMesh, Field > > magSqr(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
tmp< DimensionedField< TypeR, GeoMesh, Field > > New(const tmp< DimensionedField< TypeR, GeoMesh, Field >> &tdf1, const word &name, const dimensionSet &dimensions)
fvPatchField< vector > fvPatchVectorField
faceListList boundary(nPatches)