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-2023 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 {
47 
48  // Face volume fractions
49  PtrList<surfaceScalarField> alphafs(phases.size());
50  PtrList<surfaceScalarField> alphaRho0fs(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  alphaRho0fs.set
60  (
61  phasei,
62  (
64  (
65  max(alpha.oldTime(), phase.residualAlpha())
66  *phase.rho().oldTime()
67  )
68  ).ptr()
69  );
70  }
71 
72  // Diagonal coefficients
73  rAUfs.clear();
74  rAUfs.setSize(phases.size());
75  {
76  PtrList<surfaceScalarField> KdVmfs(fluid.KdVmfs());
77 
78  forAll(fluid.movingPhases(), movingPhasei)
79  {
80  const phaseModel& phase = fluid.movingPhases()[movingPhasei];
81 
82  rAUfs.set
83  (
84  phase.index(),
86  (
87  IOobject::groupName("rAUf", phase.name()),
88  1.0
89  /(
90  byDt(alphaRho0fs[phase.index()])
91  + fvc::interpolate(UEqns[phase.index()].A())
92  + KdVmfs[phase.index()]
93  )
94  )
95  );
96  }
97  }
99 
100  // Phase diagonal coefficients
101  PtrList<surfaceScalarField> alpharAUfs(phases.size());
102  forAll(phases, phasei)
103  {
104  const phaseModel& phase = phases[phasei];
105  alpharAUfs.set
106  (
107  phase.index(),
108  (
109  max(alphafs[phase.index()], phase.residualAlpha())
110  *rAUfs[phase.index()]
111  ).ptr()
112  );
113  }
114 
115  // Explicit force fluxes
116  PtrList<surfaceScalarField> Ffs(fluid.Ffs());
117 
118  // Mass transfer rates
119  PtrList<volScalarField> dmdts(fluid.dmdts());
120  PtrList<volScalarField> d2mdtdps(fluid.d2mdtdps());
121 
122  // --- Pressure corrector loop
123  while (pimple.correct())
124  {
125  volScalarField rho("rho", fluid.rho());
126 
127  // Correct p_rgh for consistency with p and the updated densities
128  p_rgh = p - rho*buoyancy.gh;
129 
130  // Correct fixed-flux BCs to be consistent with the velocity BCs
132 
133  // Combined buoyancy and force fluxes
134  PtrList<surfaceScalarField> phigFs(phases.size());
135  {
136  const surfaceScalarField ghSnGradRho
137  (
138  "ghSnGradRho",
140  );
141 
142  forAll(phases, phasei)
143  {
144  const phaseModel& phase = phases[phasei];
145 
146  phigFs.set
147  (
148  phasei,
149  (
150  alpharAUfs[phasei]
151  *(
152  ghSnGradRho
153  - (fvc::interpolate(phase.rho() - rho))
154  *(buoyancy.g & mesh.Sf())
155  - fluid.surfaceTension(phase)*mesh.magSf()
156  )
157  ).ptr()
158  );
159 
160  if (Ffs.set(phasei))
161  {
162  phigFs[phasei] += rAUfs[phasei]*Ffs[phasei];
163  }
164  }
165  }
166 
167  // Predicted fluxes for each phase
168  PtrList<surfaceScalarField> phiHbyAs(phases.size());
169  forAll(fluid.movingPhases(), movingPhasei)
170  {
171  const phaseModel& phase = fluid.movingPhases()[movingPhasei];
172 
173  phiHbyAs.set
174  (
175  phase.index(),
177  (
178  rAUfs[phase.index()]
179  *(
180  fvc::flux(UEqns[phase.index()].H())
181  + alphaRho0fs[phase.index()]
182  *byDt
183  (
184  phase.Uf().valid()
185  ? (mesh.Sf() & phase.Uf()().oldTime())
186  : MRF.absolute(phase.phi()().oldTime())
187  )
188  )
189  - phigFs[phase.index()],
190  phase.U(),
191  p_rgh
192  )
193  );
194  }
195  fluid.fillFields("phiHbyA", dimForce/dimDensity/dimVelocity, phiHbyAs);
196 
197  // Add explicit drag forces and fluxes
198  PtrList<surfaceScalarField> KdPhifs(fluid.KdPhifs());
199 
200  forAll(phases, phasei)
201  {
202  if (KdPhifs.set(phasei))
203  {
204  phiHbyAs[phasei] -= rAUfs[phasei]*KdPhifs[phasei];
205  }
206  }
207 
208  // Total predicted flux
210  (
211  IOobject
212  (
213  "phiHbyA",
214  runTime.name(),
215  mesh,
218  ),
219  mesh,
221  );
222 
223  forAll(phases, phasei)
224  {
225  phiHbyA += alphafs[phasei]*phiHbyAs[phasei];
226  }
227 
230 
231  // Construct pressure "diffusivity"
232  surfaceScalarField rAUf
233  (
234  IOobject
235  (
236  "rAUf",
237  runTime.name(),
238  mesh
239  ),
240  mesh,
241  dimensionedScalar(dimensionSet(-1, 3, 1, 0, 0), 0)
242  );
243 
244  forAll(phases, phasei)
245  {
246  rAUf += alphafs[phasei]*alpharAUfs[phasei];
247  }
248 
249  rAUf = mag(rAUf);
250 
251  // Update the fixedFluxPressure BCs to ensure flux consistency
252  {
254  (
257  );
258  phib = 0;
259 
260  forAll(phases, phasei)
261  {
262  const phaseModel& phase = phases[phasei];
263  phib +=
264  alphafs[phasei].boundaryField()
265  *phase.phi()().boundaryField();
266  }
267 
268  setSnGrad<fixedFluxPressureFvPatchScalarField>
269  (
271  (
272  phiHbyA.boundaryField() - phib
273  )/(mesh.magSf().boundaryField()*rAUf.boundaryField())
274  );
275  }
276 
277  // Compressible pressure equations
278  PtrList<fvScalarMatrix> pEqnComps(compressibilityEqns(dmdts, d2mdtdps));
279 
280  // Cache p prior to solve for density update
281  volScalarField p_rgh_0(p_rgh);
282 
283  // Iterate over the pressure equation to correct for non-orthogonality
284  while (pimple.correctNonOrthogonal())
285  {
286  // Construct the transport part of the pressure equation
287  fvScalarMatrix pEqnIncomp
288  (
290  - fvm::laplacian(rAUf, p_rgh)
291  );
292 
293  // Solve
294  {
295  fvScalarMatrix pEqn(pEqnIncomp);
296 
297  forAll(phases, phasei)
298  {
299  pEqn += pEqnComps[phasei];
300  }
301 
302  if (fluid.incompressible())
303  {
304  pEqn.setReference
305  (
308  );
309  }
310 
311  fvConstraints().constrain(pEqn);
312 
313  pEqn.solve();
314  }
315 
316  // Correct fluxes and velocities on last non-orthogonal iteration
318  {
319  phi_ = phiHbyA + pEqnIncomp.flux();
320 
321  surfaceScalarField mSfGradp("mSfGradp", pEqnIncomp.flux()/rAUf);
322 
323  forAll(fluid.movingPhases(), movingPhasei)
324  {
325  phaseModel& phase = fluid_.movingPhases()[movingPhasei];
326 
327  phase.phiRef() =
328  phiHbyAs[phase.index()]
329  + alpharAUfs[phase.index()]*mSfGradp;
330 
331  // Set the phase dilatation rate
332  phase.divU(-pEqnComps[phase.index()] & p_rgh);
333  }
334 
335  if (partialElimination)
336  {
337  fluid_.partialEliminationf(rAUfs, alphafs, KdPhifs);
338  }
339  else
340  {
341  forAll(fluid.movingPhases(), movingPhasei)
342  {
343  phaseModel& phase = fluid_.movingPhases()[movingPhasei];
344 
345  MRF.makeRelative(phase.phiRef());
346  fvc::makeRelative(phase.phiRef(), phase.U());
347  }
348  }
349 
350  forAll(fluid.movingPhases(), movingPhasei)
351  {
352  phaseModel& phase = fluid_.movingPhases()[movingPhasei];
353 
354  phase.URef() = fvc::reconstruct
355  (
356  fvc::absolute(MRF.absolute(phase.phi()), phase.U())
357  );
358 
359  phase.URef().correctBoundaryConditions();
360  phase.correctUf();
361  fvConstraints().constrain(phase.URef());
362  }
363  }
364  }
365 
366  // Update and limit the static pressure
367  p = p_rgh + rho*buoyancy.gh;
369 
370  // Account for static pressure reference
372  {
374  (
375  "p",
376  p.dimensions(),
379  );
380  }
381 
382  // Limit p_rgh
383  p_rgh = p - rho*buoyancy.gh;
384 
385  // Update densities from change in p_rgh
386  forAll(phases, phasei)
387  {
388  phaseModel& phase = phases_[phasei];
389  phase.rho() += phase.thermo().psi()*(p_rgh - p_rgh_0);
390  }
391 
392  // Update mass transfer rates for change in p_rgh
393  forAll(phases, phasei)
394  {
395  if (dmdts.set(phasei) && d2mdtdps.set(phasei))
396  {
397  dmdts[phasei] += d2mdtdps[phasei]*(p_rgh - p_rgh_0);
398  }
399  }
400 
401  // Correct p_rgh for consistency with p and the updated densities
402  rho = fluid.rho();
403  p_rgh = p - rho*buoyancy.gh;
405  }
406 
407  UEqns.clear();
408 
410  {
411  rAUfs.clear();
412  }
413 }
414 
415 
416 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
const dimensionSet & dimensions() const
Return dimensions.
static const DimensionedField< Type, GeoMesh > & null()
Return a null DimensionedField.
const GeometricField< Type, PatchField, GeoMesh > & oldTime() const
Return old time field.
GeometricBoundaryField< Type, PatchField, GeoMesh > Boundary
Type of the boundary field.
const Boundary & boundaryField() const
Return const-reference to the boundary field.
bool needReference() const
Does the field need a reference level for solution.
void correctBoundaryConditions()
Correct boundary field.
Boundary & boundaryFieldRef()
Return a reference to the 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:167
const word & name() const
Return name.
Definition: IOobject.H:310
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
autoPtr< T > set(const label, const word &key, T *)
Set element to pointer provided and return old element.
bool set(const label) const
Is element set.
Definition: UPtrListI.H:78
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.
bool finalNonOrthogonalIter() const
Flag to indicate the last non-orthogonal iteration.
virtual PtrList< surfaceScalarField > Ffs() const =0
Return the force fluxes for the face-based algorithm.
virtual PtrList< surfaceScalarField > KdVmfs() const =0
Return the implicit force coefficients for the face-based.
const phaseModelPartialList & movingPhases() const
Return the models for phases that are moving.
Definition: phaseSystemI.H:55
void correctBoundaryFlux()
Correct fixed-flux BCs to be consistent with the velocity BCs.
Definition: phaseSystem.C:698
virtual bool implicitPhasePressure(const phaseModel &phase) const
Returns true if the phase pressure is treated implicitly.
Definition: phaseSystem.C:507
virtual void partialEliminationf(const PtrList< surfaceScalarField > &rAUfs, const PtrList< surfaceScalarField > &alphafs, const PtrList< surfaceScalarField > &KdPhifs)=0
Solve the drag system for the new fluxes.
void fillFields(const word &name, const dimensionSet &dims, PtrList< GeometricField< Type, PatchField, GeoMesh >> &fieldList) const
Fill up gaps in a phase-indexed list of fields with zeros.
virtual PtrList< volScalarField > dmdts() const
Return the mass transfer rates for each phase.
Definition: phaseSystem.C:481
tmp< surfaceScalarField > surfaceTension(const phaseModel &phase) const
Return the surface tension force.
Definition: phaseSystem.C:520
virtual PtrList< surfaceScalarField > KdPhifs() const =0
Return the force fluxes for the face-based algorithm.
tmp< volScalarField > rho() const
Return the mixture density.
Definition: phaseSystem.C:351
virtual PtrList< volScalarField > d2mdtdps() const
Return the mass transfer pressure implicit coefficients.
Definition: phaseSystem.C:487
bool incompressible() const
Return incompressibility.
Definition: phaseSystem.C:493
bool correct()
Piso loop within outer loop.
bool correctNonOrthogonal()
Non-orthogonal corrector loop.
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:100
Foam::fvConstraints & fvConstraints() const
Return the fvConstraints that are created on demand.
Definition: solver.C:96
const Time & runTime
Time.
Definition: solver.H:97
const fvMesh & mesh
Region mesh.
Definition: solver.H:94
uniformDimensionedVectorField g
Gravitational acceleration.
Definition: buoyancy.H:83
volScalarField gh
(g & h) - ghRef
Definition: buoyancy.H:95
surfaceScalarField ghf
(g & hf) - ghRef
Definition: buoyancy.H:98
volScalarField & p_rgh
Reference to the buoyant pressure for buoyant cases.
const surfaceScalarField & phi
Reference to the mass-flux field.
solvers::buoyancy buoyancy
Buoyancy force.
phaseSystem::phaseModelList & phases_
Switch partialElimination
Partial elimination drag contribution optimisation.
PtrList< fvVectorMatrix > UEqns
Temporary phase momentum matrices.
PtrList< surfaceScalarField > rAUfs
Temporary storage for the reciprocal momentum equation diagonal.
Foam::pressureReference pressureReference
Pressure reference.
const phaseSystem::phaseModelList & phases
Reference to the phases.
const volScalarField & p
Reference to the pressure field.
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
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
tmp< surfaceScalarField > constrainPhiHbyA(const tmp< surfaceScalarField > &tphiHbyA, const volVectorField &U, const volScalarField &p)
fvMatrix< scalar > fvScalarMatrix
Definition: fvMatricesFwd.H:42
SurfaceField< scalar > surfaceScalarField
const dimensionSet dimForce
tmp< volScalarField > byDt(const volScalarField &vf)
Definition: phaseSystem.C:853
const dimensionSet dimTime
const dimensionSet dimDensity
VolField< scalar > volScalarField
Definition: volFieldsFwd.H:61
dimensioned< scalar > mag(const dimensioned< Type > &)
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
const dimensionSet dimVelocity
const dimensionSet dimFlux