facePressureCorrector.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) 2022-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 "multiphaseEuler.H"
27 #include "constrainHbyA.H"
28 #include "constrainPressure.H"
29 #include "findRefCell.H"
30 #include "fvcDdt.H"
31 #include "fvcDiv.H"
32 #include "fvcSup.H"
33 #include "fvcSnGrad.H"
34 #include "fvmDdt.H"
35 #include "fvmDiv.H"
36 #include "fvmLaplacian.H"
37 #include "fvmSup.H"
38 #include "fvcFlux.H"
39 #include "fvcMeshPhi.H"
40 #include "fvcReconstruct.H"
41 
42 // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
43 
44 void Foam::solvers::multiphaseEuler::facePressureCorrector()
45 {
48 
49  // Face volume fractions
50  PtrList<surfaceScalarField> alphafs(phases.size());
51  forAll(phases, phasei)
52  {
53  const phaseModel& phase = phases[phasei];
54  const volScalarField& alpha = phase;
55 
56  alphafs.set(phasei, fvc::interpolate(alpha).ptr());
57  alphafs[phasei].rename("pEqn" + alphafs[phasei].name());
58  }
59 
60  // Diagonal coefficients
61  rAs.clear();
63  {
64  rAs.setSize(phases.size());
65  }
66 
67  PtrList<surfaceScalarField> HVmfs(movingPhases.size());
68  PtrList<PtrList<surfaceScalarField>> invADVfs;
69  {
70  PtrList<surfaceScalarField> Afs(movingPhases.size());
71 
72  forAll(movingPhases, movingPhasei)
73  {
74  const phaseModel& phase = movingPhases[movingPhasei];
75  const volScalarField& alpha = phase;
76 
77  const volScalarField A
78  (
79  byDt
80  (
81  max(alpha.oldTime(), phase.residualAlpha())
82  *phase.rho().oldTime()
83  )
84  + UEqns[phase.index()].A()
85  );
86 
88  {
89  rAs.set
90  (
91  phase.index(),
92  new volScalarField
93  (
94  IOobject::groupName("rA", phase.name()),
95  1/A
96  )
97  );
98  }
99 
100  Afs.set
101  (
102  movingPhasei,
104  (
105  IOobject::groupName("rAf", phase.name()),
107  )
108  );
109  }
110 
111  invADVfs = momentumTransferSystem_.invADVfs(Afs, HVmfs);
112  }
113 
114  volScalarField rho("rho", fluid.rho());
115 
116  // Phase diagonal coefficients
117  PtrList<surfaceScalarField> alphaByADfs;
118  PtrList<surfaceScalarField> FgByADfs;
119  {
120  // Explicit force fluxes
121  PtrList<surfaceScalarField> Ffs(momentumTransferSystem_.Ffs());
122 
123  const surfaceScalarField ghSnGradRho
124  (
125  "ghSnGradRho",
127  );
128 
129  UPtrList<surfaceScalarField> movingAlphafs(movingPhases.size());
130  PtrList<surfaceScalarField> Fgfs(movingPhases.size());
131 
132  forAll(movingPhases, movingPhasei)
133  {
134  const phaseModel& phase = movingPhases[movingPhasei];
135 
136  movingAlphafs.set(movingPhasei, &alphafs[phase.index()]);
137 
138  Fgfs.set
139  (
140  movingPhasei,
141  Ffs[phase.index()]
142  + alphafs[phase.index()]
143  *(
144  ghSnGradRho
145  - fluid.surfaceTension(phase)*mesh.magSf()
146  )
147  - max(alphafs[phase.index()], phase.residualAlpha())
148  *fvc::interpolate(phase.rho() - rho)*(buoyancy.g & mesh.Sf())
149  );
150  }
151 
152  alphaByADfs = invADVfs & movingAlphafs;
153  FgByADfs = invADVfs & Fgfs;
154  }
155 
156  // Mass transfer rates
157  PtrList<volScalarField::Internal> dmdts(populationBalanceSystem_.dmdts());
158 
159  // --- Pressure corrector loop
160  while (pimple.correct())
161  {
162  // Correct fixed-flux BCs to be consistent with the velocity BCs
164 
165  // Predicted fluxes for each phase
166  PtrList<surfaceScalarField> phiHbyADs;
167  {
168  PtrList<surfaceScalarField> phiHs(movingPhases.size());
169 
170  forAll(movingPhases, movingPhasei)
171  {
172  const phaseModel& phase = movingPhases[movingPhasei];
173  const volScalarField& alpha = phase;
174 
175  phiHs.set
176  (
177  movingPhasei,
178  (
180  (
181  max(alpha.oldTime(), phase.residualAlpha())
182  *phase.rho().oldTime()
183  )
184  *byDt
185  (
186  phase.Uf().valid()
187  ? (mesh.Sf() & phase.Uf()().oldTime())
188  : MRF.absolute(phase.phi()().oldTime())
189  )
190  + fvc::flux(UEqns[phase.index()].H())
191  )
192  );
193 
194  if (HVmfs.set(movingPhasei))
195  {
196  phiHs[movingPhasei] += HVmfs[movingPhasei];
197  }
198  }
199 
200  phiHbyADs = invADVfs & phiHs;
201  }
202 
203  forAll(movingPhases, movingPhasei)
204  {
205  const phaseModel& phase = movingPhases[movingPhasei];
206 
207  constrainPhiHbyA(phiHbyADs[movingPhasei], phase.U(), p_rgh);
208 
209  phiHbyADs[movingPhasei] -= FgByADfs[movingPhasei];
210  }
211 
212  // Total predicted flux
214  (
215  IOobject
216  (
217  "phiHbyA",
218  runTime.name(),
219  mesh,
222  ),
223  mesh,
225  );
226 
227  forAll(movingPhases, movingPhasei)
228  {
229  const phaseModel& phase = movingPhases[movingPhasei];
230 
231  phiHbyA += alphafs[phase.index()]*phiHbyADs[movingPhasei];
232  }
233 
236 
237  // Construct pressure "diffusivity"
239  (
240  IOobject
241  (
242  "rAf",
243  runTime.name(),
244  mesh
245  ),
246  mesh,
247  dimensionedScalar(dimensionSet(-1, 3, 1, 0, 0), 0)
248  );
249 
250  forAll(movingPhases, movingPhasei)
251  {
252  const phaseModel& phase = movingPhases[movingPhasei];
253 
254  rAf += alphafs[phase.index()]*alphaByADfs[movingPhasei];
255  }
256 
257  // Update the fixedFluxPressure BCs to ensure flux consistency
258  {
260  (
263  );
264  phib = 0;
265 
266  forAll(movingPhases, movingPhasei)
267  {
268  phaseModel& phase = movingPhases_[movingPhasei];
269 
270  phib +=
271  alphafs[phase.index()].boundaryField()
272  *phase.phi()().boundaryField();
273  }
274 
275  setSnGrad<fixedFluxPressureFvPatchScalarField>
276  (
278  (
279  phiHbyA.boundaryField() - phib
280  )/(mesh.magSf().boundaryField()*rAf.boundaryField())
281  );
282  }
283 
284  // Compressible pressure equations
285  PtrList<fvScalarMatrix> pEqnComps(compressibilityEqns(dmdts));
286 
287  // Cache p prior to solve for density update
288  volScalarField p_rgh_0(p_rgh);
289 
290  // Iterate over the pressure equation to correct for non-orthogonality
291  while (pimple.correctNonOrthogonal())
292  {
293  // Construct the transport part of the pressure equation
294  fvScalarMatrix pEqnIncomp
295  (
297  - fvm::laplacian(rAf, p_rgh)
298  );
299 
300  // Solve
301  {
302  fvScalarMatrix pEqn(pEqnIncomp);
303 
304  forAll(phases, phasei)
305  {
306  pEqn += pEqnComps[phasei];
307  }
308 
309  if (fluid.incompressible())
310  {
311  pEqn.setReference
312  (
315  );
316  }
317 
318  fvConstraints().constrain(pEqn);
319 
320  pEqn.solve();
321  }
322 
323  // Correct fluxes and velocities on last non-orthogonal iteration
325  {
326  phi_ = phiHbyA + pEqnIncomp.flux();
327 
328  surfaceScalarField mSfGradp("mSfGradp", pEqnIncomp.flux()/rAf);
329 
330  forAll(movingPhases, movingPhasei)
331  {
332  phaseModel& phase = movingPhases_[movingPhasei];
333  const label phasei = phase.index();
334 
335  phase.phiRef() =
336  phiHbyADs[movingPhasei]
337  + alphaByADfs[movingPhasei]*mSfGradp;
338 
339  // Set the phase dilatation rate
340  phase.divU(-pEqnComps[phasei] & p_rgh);
341  }
342 
343  forAll(movingPhases, movingPhasei)
344  {
345  phaseModel& phase = movingPhases_[movingPhasei];
346 
347  MRF.makeRelative(phase.phiRef());
348  fvc::makeRelative(phase.phiRef(), phase.U());
349 
350  phase.URef() = fvc::reconstruct
351  (
352  fvc::absolute(MRF.absolute(phase.phi()), phase.U())
353  );
354 
355  phase.URef().correctBoundaryConditions();
356  phase.correctUf();
357  fvConstraints().constrain(phase.URef());
358  }
359  }
360  }
361 
362  // Update and limit the static pressure
365 
366  // Account for static pressure reference
368  {
370  (
371  "p",
372  p.dimensions(),
375  );
376  }
377 
378  // Limit p_rgh
380 
381  // Update densities from change in p_rgh
382  forAll(phases, phasei)
383  {
384  phaseModel& phase = phases_[phasei];
385  if (!phase.incompressible())
386  {
387  phase.rho() += phase.fluidThermo().psi()*(p_rgh - p_rgh_0);
388  }
389  }
390 
391  // Correct p_rgh for consistency with p and the updated densities
392  rho = fluid.rho();
395  }
396 
397  UEqns.clear();
398 }
399 
400 
401 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:433
static const DimensionedField< Type, GeoMesh, PrimitiveField > & null()
Return a null DimensionedField.
const dimensionSet & dimensions() const
Return dimensions.
const Boundary & boundaryField() const
Return const-reference to the boundary field.
bool needReference() const
Does the field need a reference level for solution.
GeometricBoundaryField< Type, GeoMesh, PrimitiveField > Boundary
Type of the boundary field.
Boundary & boundaryFieldRef()
Return a reference to the boundary field.
void correctBoundaryConditions()
Correct boundary field.
IOobject(const word &name, const fileName &instance, const objectRegistry &registry, readOption r=NO_READ, writeOption w=NO_WRITE, bool registerObject=true)
Construct from name, instance, registry, io options.
Definition: IOobject.C:164
const word & name() const
Return name.
Definition: IOobject.H:307
static word groupName(Name name, const word &group)
tmp< surfaceScalarField > absolute(const tmp< surfaceScalarField > &phi) const
Return the given relative flux absolute within the MRF region.
Definition: MRFZoneList.C:291
void makeRelative(volVectorField &U) const
Make the given absolute velocity relative within the MRF region.
Definition: MRFZoneList.C:157
const Field0Type & oldTime() const
Return the old-time field.
Definition: OldTimeField.C:322
bool set(const label) const
Is element set.
Definition: UPtrListI.H:87
label size() const
Return the number of elements in the UPtrList.
Definition: UPtrListI.H:29
const word & name() const
Return const reference to name.
bool constrain(fvMatrix< Type > &eqn) const
Apply constraints to an equation.
const surfaceVectorField & Sf() const
Return cell face area vectors.
const surfaceScalarField & magSf() const
Return cell face area magnitudes.
PtrList< surfaceScalarField > Ffs() const
As Fs, but for the face-based algorithm.
PtrList< PtrList< surfaceScalarField > > invADVfs(const PtrList< surfaceScalarField > &Afs, PtrList< surfaceScalarField > &HVmfs) const
Return the inverse of the central + drag + virtual mass.
bool finalNonOrthogonalIter() const
Flag to indicate the last non-orthogonal iteration.
tmp< surfaceScalarField > surfaceTension(const phaseModel &) const
Return the surface tension force.
Definition: phaseSystem.C:569
void correctBoundaryFlux()
Correct fixed-flux BCs to be consistent with the velocity BCs.
Definition: phaseSystem.C:761
bool implicitPhasePressure() const
Returns true if the phase pressure is treated implicitly.
tmp< volScalarField > rho() const
Return the mixture density.
Definition: phaseSystem.C:452
bool incompressible() const
Return incompressibility.
Definition: phaseSystem.C:607
bool correct()
Piso loop within outer loop.
bool correctNonOrthogonal()
Non-orthogonal corrector loop.
PtrList< volScalarField::Internal > dmdts() const
Return the mass transfer rates for each phase.
scalar refValue() const
Return the pressure reference level.
label refCell() const
Return the cell in which the reference pressure is set.
pimpleNoLoopControl pimple
PIMPLE inner-loop controls.
Definition: solver.H:107
Foam::fvConstraints & fvConstraints() const
Return the fvConstraints that are created on demand.
Definition: solver.C:107
const Time & runTime
Time.
Definition: solver.H:104
const fvMesh & mesh
Region mesh.
Definition: solver.H:101
uniformDimensionedVectorField g
Gravitational acceleration.
Definition: buoyancy.H:83
volScalarField gh
(g & h) - ghRef
Definition: buoyancy.H:95
uniformDimensionedScalarField pRef
Reference pressure.
Definition: buoyancy.H:89
surfaceScalarField ghf
(g & hf) - ghRef
Definition: buoyancy.H:98
const surfaceScalarField & phi
Reference to the mass-flux field.
const volScalarField & p_rgh
Reference to the buoyant pressure for buoyant cases.
solvers::buoyancy buoyancy
Buoyancy force.
phaseSystem::phaseModelList & phases_
PtrList< fvVectorMatrix > UEqns
Temporary phase momentum matrices.
const phaseSystem::phaseModelPartialList & movingPhases
Reference to the moving phases.
momentumTransferSystem momentumTransferSystem_
volScalarField & p_rgh_
Reference to the buoyant pressure for buoyant cases.
Foam::pressureReference pressureReference
Pressure reference.
PtrList< volScalarField > rAs
Temporary storage for the reciprocal momentum equation diagonal.
const phaseSystem::phaseModelList & phases
Reference to the phases.
phaseSystem::phaseModelPartialList & movingPhases_
const volScalarField & p
Reference to the pressure field.
populationBalanceSystem populationBalanceSystem_
const phaseSystem & fluid
Reference to the multiphase fluid.
Find the reference cell nearest (in index) to the given cell but which is not on a cyclic,...
Calculate the first temporal derivative.
Calculate the divergence of the given field.
Calculate the face-flux of the given field.
Calculate the mesh motion flux and convert fluxes from absolute to relative and back.
Reconstruct volField from a face flux field.
Calculate the snGrad of the given volField.
Calculate the field for explicit evaluation of implicit and explicit sources.
Calculate the matrix for the first temporal derivative.
Calculate the matrix for the divergence of the given field and flux.
Calculate the matrix for the laplacian of the field.
Calculate the matrix for implicit and explicit sources.
U
Definition: pEqn.H:72
surfaceScalarField phiHbyA("phiHbyA", fvc::interpolate(rho) *fvc::flux(HbyA))
volScalarField alpha(IOobject("alpha", runTime.name(), mesh, IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE), lambda *max(Ua &U, zeroSensitivity))
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< typename outerProduct< vector, Type >::type > > reconstruct(const SurfaceField< Type > &ssf)
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
void makeRelative(surfaceScalarField &phi, const volVectorField &U)
Make the given flux relative.
Definition: fvcMeshPhi.C:89
tmp< SurfaceField< Type > > snGrad(const VolField< Type > &vf, const word &name)
Definition: fvcSnGrad.C:45
tmp< fvMatrix< Type > > laplacian(const VolField< Type > &vf, const word &name)
Definition: fvmLaplacian.C:47
static const coefficient A("A", dimPressure, 611.21)
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
fvMatrix< scalar > fvScalarMatrix
Definition: fvMatricesFwd.H:42
const dimensionSet dimVolumetricFlux
SurfaceField< scalar > surfaceScalarField
tmp< volScalarField > byDt(const volScalarField &vf)
Definition: phaseSystem.C:927
VolField< scalar > volScalarField
Definition: volFieldsFwd.H:62
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
scalar getRefCellValue(const volScalarField &field, const label refCelli)
Return the current value of field in the reference cell.
Definition: findRefCell.C:136
void constrainPhiHbyA(surfaceScalarField &phiHbyA, const volVectorField &U, const volScalarField &p)
Definition: constrainHbyA.C:60
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.