cellPressureCorrector.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::cellPressureCorrector()
45 {
47 
48  // Face volume fractions
49  PtrList<surfaceScalarField> alphafs(phases.size());
50  forAll(phases, phasei)
51  {
52  const phaseModel& phase = phases[phasei];
53  const volScalarField& alpha = phase;
54 
55  alphafs.set(phasei, fvc::interpolate(max(alpha, scalar(0))).ptr());
56  alphafs[phasei].rename("pEqn" + alphafs[phasei].name());
57  }
58 
59  // Diagonal coefficients
60  rAUs.clear();
61  rAUs.setSize(phases.size());
62 
63  PtrList<surfaceScalarField> rAUfs(phases.size());
64 
65  {
66  PtrList<volScalarField> Kds(fluid.Kds());
67 
68  forAll(fluid.movingPhases(), movingPhasei)
69  {
70  const phaseModel& phase = fluid.movingPhases()[movingPhasei];
71  const volScalarField& alpha = phase;
72 
74  (
75  UEqns[phase.index()].A()
76  + byDt
77  (
78  max(phase.residualAlpha() - alpha, scalar(0))
79  *phase.rho()
80  )
81  );
82 
83  if (Kds.set(phase.index()))
84  {
85  AU += Kds[phase.index()];
86  }
87 
88  rAUs.set
89  (
90  phase.index(),
91  new volScalarField
92  (
93  IOobject::groupName("rAU", phase.name()),
94  1/AU
95  )
96  );
97 
98  rAUfs.set(phase.index(), 1/fvc::interpolate(AU));
99  }
102  }
103 
104  // Phase diagonal coefficients
105  PtrList<surfaceScalarField> alpharAUfs(phases.size());
106  forAll(phases, phasei)
107  {
108  const phaseModel& phase = phases[phasei];
109  const volScalarField& alpha = phase;
110 
111  alpharAUfs.set
112  (
113  phasei,
114  (
115  fvc::interpolate(max(alpha, phase.residualAlpha()))
116  *rAUfs[phasei]
117  ).ptr()
118  );
119  }
120 
121  // Explicit force fluxes
122  PtrList<surfaceScalarField> Fs(fluid.Fs());
123 
124  // Mass transfer rates
125  PtrList<volScalarField> dmdts(fluid.dmdts());
126  PtrList<volScalarField> d2mdtdps(fluid.d2mdtdps());
127 
128  // --- Pressure corrector loop
129  while (pimple.correct())
130  {
131  volScalarField rho("rho", fluid.rho());
132 
133  // Correct p_rgh for consistency with p and the updated densities
134  p_rgh = p - rho*buoyancy.gh;
135 
136  // Correct fixed-flux BCs to be consistent with the velocity BCs
138 
139  // Combined buoyancy and force fluxes
140  PtrList<surfaceScalarField> phigFs(phases.size());
141  {
142  const surfaceScalarField ghSnGradRho
143  (
144  "ghSnGradRho",
146  );
147 
148  forAll(phases, phasei)
149  {
150  const phaseModel& phase = phases[phasei];
151 
152  phigFs.set
153  (
154  phasei,
155  (
156  (
157  ghSnGradRho
158  - (fvc::interpolate(phase.rho() - rho))
159  *(buoyancy.g & mesh.Sf())
160  - fluid.surfaceTension(phase)*mesh.magSf()
161  )
162  ).ptr()
163  );
164  }
165  }
166 
167  // Predicted velocities and fluxes for each phase
168  PtrList<volVectorField> HbyAs(phases.size());
169  PtrList<surfaceScalarField> phiHbyAs(phases.size());
170  {
171  // Correction force fluxes
172  PtrList<surfaceScalarField> ddtCorrs(fluid.ddtCorrs());
173 
174  forAll(fluid.movingPhases(), movingPhasei)
175  {
176  const phaseModel& phase = fluid.movingPhases()[movingPhasei];
177  const volScalarField& alpha = phase;
178  const label phasei = phase.index();
179 
180  const volVectorField H
181  (
182  constrainH
183  (
184  UEqns[phasei].H()
185  + byDt
186  (
187  max(phase.residualAlpha() - alpha, scalar(0))
188  *phase.rho()
189  )
190  *phase.U()().oldTime(),
191  rAUs[phasei],
192  phase.U(),
193  p_rgh
194  )
195  );
196 
197  HbyAs.set(phasei, rAUs[phasei]*H);
198 
199  phiHbyAs.set
200  (
201  phasei,
203  (
204  IOobject::groupName("phiHbyA", phase.name()),
205  rAUfs[phasei]*(fvc::flux(H) + ddtCorrs[phasei])
206  - alpharAUfs[phasei]*phigFs[phasei]
207  - rAUfs[phasei]*Fs[phasei]
208  )
209  );
210  }
211  }
212  fluid.fillFields("HbyA", dimVelocity, HbyAs);
213  fluid.fillFields("phiHbyA", dimForce/dimDensity/dimVelocity, phiHbyAs);
214 
215  // Add explicit drag forces and fluxes
216  PtrList<volVectorField> KdUs(fluid.KdUs());
217  PtrList<surfaceScalarField> KdPhis(fluid.KdPhis());
218 
219  forAll(phases, phasei)
220  {
221  if (KdUs.set(phasei))
222  {
223  HbyAs[phasei] -= rAUs[phasei]*KdUs[phasei];
224  }
225 
226  if (KdPhis.set(phasei))
227  {
228  phiHbyAs[phasei] -= rAUfs[phasei]*KdPhis[phasei];
229  }
230  }
231 
232  // Total predicted flux
234  (
235  IOobject
236  (
237  "phiHbyA",
238  runTime.name(),
239  mesh,
242  ),
243  mesh,
245  );
246 
247  forAll(phases, phasei)
248  {
249  phiHbyA += alphafs[phasei]*phiHbyAs[phasei];
250  }
251 
254 
255  // Construct pressure "diffusivity"
256  surfaceScalarField rAUf
257  (
258  IOobject
259  (
260  "rAUf",
261  runTime.name(),
262  mesh
263  ),
264  mesh,
266  );
267 
268  forAll(phases, phasei)
269  {
270  rAUf += alphafs[phasei]*alpharAUfs[phasei];
271  }
272 
273  // Update the fixedFluxPressure BCs to ensure flux consistency
274  {
276  (
279  );
280  phib = 0;
281 
282  forAll(phases, phasei)
283  {
284  const phaseModel& phase = phases[phasei];
285  phib +=
286  alphafs[phasei].boundaryField()
287  *phase.phi()().boundaryField();
288  }
289 
290  setSnGrad<fixedFluxPressureFvPatchScalarField>
291  (
293  (
294  phiHbyA.boundaryField() - phib
295  )/(mesh.magSf().boundaryField()*rAUf.boundaryField())
296  );
297  }
298 
299  // Compressible pressure equations
300  PtrList<fvScalarMatrix> pEqnComps(compressibilityEqns(dmdts, d2mdtdps));
301 
302  // Cache p prior to solve for density update
303  volScalarField p_rgh_0(p_rgh);
304 
305  // Iterate over the pressure equation to correct for non-orthogonality
306  while (pimple.correctNonOrthogonal())
307  {
308  // Construct the transport part of the pressure equation
309  fvScalarMatrix pEqnIncomp
310  (
312  - fvm::laplacian(rAUf, p_rgh)
313  );
314 
315  // Solve
316  {
317  fvScalarMatrix pEqn(pEqnIncomp);
318 
319  forAll(phases, phasei)
320  {
321  pEqn += pEqnComps[phasei];
322  }
323 
324  if (fluid.incompressible())
325  {
326  pEqn.setReference
327  (
330  );
331  }
332 
333  fvConstraints().constrain(pEqn);
334 
335  pEqn.solve();
336  }
337 
338  // Correct fluxes and velocities on last non-orthogonal iteration
340  {
341  phi_ = phiHbyA + pEqnIncomp.flux();
342 
343  surfaceScalarField mSfGradp("mSfGradp", pEqnIncomp.flux()/rAUf);
344 
345  forAll(fluid.movingPhases(), movingPhasei)
346  {
347  phaseModel& phase = fluid_.movingPhases()[movingPhasei];
348 
349  phase.phiRef() =
350  phiHbyAs[phase.index()]
351  + alpharAUfs[phase.index()]*mSfGradp;
352 
353  // Set the phase dilatation rate
354  phase.divU(-pEqnComps[phase.index()] & p_rgh);
355  }
356 
357  // Optionally relax pressure for velocity correction
358  p_rgh.relax();
359 
360  mSfGradp = pEqnIncomp.flux()/rAUf;
361 
362  if (!dragCorrection)
363  {
364  forAll(fluid.movingPhases(), movingPhasei)
365  {
366  phaseModel& phase = fluid_.movingPhases()[movingPhasei];
367  const label phasei = phase.index();
368 
369  phase.URef() =
370  HbyAs[phasei]
372  (
373  alpharAUfs[phasei]*(mSfGradp - phigFs[phasei])
374  - rAUfs[phasei]*Fs[phasei]
375  );
376  }
377  }
378  else
379  {
380  PtrList<volVectorField> dragCorrs(phases.size());
381  PtrList<surfaceScalarField> dragCorrfs(phases.size());
382  fluid.dragCorrs(dragCorrs, dragCorrfs);
383 
384  forAll(fluid.movingPhases(), movingPhasei)
385  {
386  phaseModel& phase = fluid_.movingPhases()[movingPhasei];
387  const label phasei = phase.index();
388 
389  phase.URef() =
390  HbyAs[phasei]
392  (
393  alpharAUfs[phasei]*(mSfGradp - phigFs[phasei])
394  + rAUfs[phasei]*(dragCorrfs[phasei] - Fs[phasei])
395  )
396  - rAUs[phasei]*dragCorrs[phasei];
397  }
398  }
399 
400  if (partialElimination)
401  {
403  (
404  rAUs,
405  KdUs,
406  alphafs,
407  rAUfs,
408  KdPhis
409  );
410  }
411  else
412  {
413  forAll(fluid.movingPhases(), movingPhasei)
414  {
415  phaseModel& phase = fluid_.movingPhases()[movingPhasei];
416 
417  MRF.makeRelative(phase.phiRef());
418  fvc::makeRelative(phase.phiRef(), phase.U());
419  }
420  }
421 
422  forAll(fluid.movingPhases(), movingPhasei)
423  {
424  phaseModel& phase = fluid_.movingPhases()[movingPhasei];
425 
426  phase.URef().correctBoundaryConditions();
427  phase.correctUf();
428  fvConstraints().constrain(phase.URef());
429  }
430  }
431  }
432 
433  // Update and limit the static pressure
434  p_ = p_rgh + rho*buoyancy.gh;
436 
437  // Account for static pressure reference
439  {
441  (
442  "p",
443  p.dimensions(),
446  );
447  }
448 
449  // Limit p_rgh
450  p_rgh = p - rho*buoyancy.gh;
451 
452  // Update densities from change in p_rgh
453  forAll(phases, phasei)
454  {
455  phaseModel& phase = phases_[phasei];
456  phase.rho() += phase.thermo().psi()*(p_rgh - p_rgh_0);
457  }
458 
459  // Update mass transfer rates for change in p_rgh
460  forAll(phases, phasei)
461  {
462  if (dmdts.set(phasei) && d2mdtdps.set(phasei))
463  {
464  dmdts[phasei] += d2mdtdps[phasei]*(p_rgh - p_rgh_0);
465  }
466  }
467 
468  // Correct p_rgh for consistency with p and the updated densities
469  rho = fluid.rho();
470  p_rgh = p - rho*buoyancy.gh;
472  }
473 
474  UEqns.clear();
475 
477  {
478  rAUs.clear();
479  }
480 }
481 
482 
483 // ************************************************************************* //
#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.
void relax(const scalar alpha)
Relax field (for steady-state solution).
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)
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.
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 > KdPhis() const =0
Return the force fluxes for the cell-based algorithm.
virtual PtrList< volScalarField > Kds() const =0
Return the implicit part of the drag force.
virtual PtrList< surfaceScalarField > ddtCorrs() const =0
Return the flux corrections for the cell-based algorithm.
virtual PtrList< volVectorField > KdUs() const =0
Return the explicit part of the drag force.
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 dragCorrs(PtrList< volVectorField > &dragCorrs, PtrList< surfaceScalarField > &dragCorrf) const =0
Set the cell and faces drag correction fields.
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
virtual PtrList< surfaceScalarField > Fs() const =0
Return the force fluxes for the cell-based algorithm.
tmp< surfaceScalarField > surfaceTension(const phaseModel &phase) const
Return the surface tension force.
Definition: phaseSystem.C:520
virtual void partialElimination(const PtrList< volScalarField > &rAUs, const PtrList< volVectorField > &KdUs, const PtrList< surfaceScalarField > &alphafs, const PtrList< surfaceScalarField > &rAUfs, const PtrList< surfaceScalarField > &KdPhis)=0
Solve the drag system for the new velocities and fluxes.
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.
Switch dragCorrection
Cell/face drag correction for cell momentum corrector.
PtrList< surfaceScalarField > rAUfs
Temporary storage for the reciprocal momentum equation diagonal.
PtrList< volScalarField > rAUs
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.
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
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.
VolField< vector > volVectorField
Definition: volFieldsFwd.H:62
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
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
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
tmp< volVectorField > constrainH(const tmp< volVectorField > &tH, const volScalarField &rA, const volVectorField &U, const volScalarField &p)
Definition: constrainHbyA.C:79