solvers::incompressibleVoF: New solver module for incompressible two-phase flow with VoF
executed with foamRun for single region simulations of foamMultiRun for
multi-region simulations. Replaces interFoam and all the corresponding
tutorials have been updated and moved to tutorials/modules/incompressibleVoF.
Both incompressibleVoF and compressibleVoF solver modules are derived from the
common two-phase VoF base-class solvers::VoFSolver which handles the
complexities of VoF interface-compression, boundedness and conservation with
2nd-order schemes in space and time using the semi-implicit MULES limiter and
solution proceedure. This maximises code re-use, improves readability and
simplifies maintenance.
Class
Foam::solvers::incompressibleVoF
Description
Solver module for for 2 incompressible, isothermal immiscible fluids using a
VOF (volume of fluid) phase-fraction based interface capturing approach,
with optional mesh motion and mesh topology changes including adaptive
re-meshing.
The momentum and other fluid properties are of the "mixture" and a single
momentum equation is solved.
Either mixture or two-phase transport modelling may be selected. In the
mixture approach a single laminar, RAS or LES model is selected to model the
momentum stress. In the Euler-Euler two-phase approach separate laminar,
RAS or LES selected models are selected for each of the phases.
Uses the flexible PIMPLE (PISO-SIMPLE) solution for time-resolved and
pseudo-transient and steady simulations.
Optional fvModels and fvConstraints are provided to enhance the simulation
in many ways including adding various sources, Lagrangian
particles, surface film etc. and constraining or limiting the solution.
SourceFiles
incompressibleVoF.C
See also
Foam::solvers::VoFSolver
Foam::solvers::compressibleVoF
This commit is contained in:
7
applications/solvers/modules/VoFSolver/Make/files
Normal file
7
applications/solvers/modules/VoFSolver/Make/files
Normal file
@ -0,0 +1,7 @@
|
||||
setRDeltaT.C
|
||||
moveMesh.C
|
||||
alphaPredictor.C
|
||||
momentumPredictor.C
|
||||
VoFSolver.C
|
||||
|
||||
LIB = $(FOAM_LIBBIN)/libVoFSolver
|
||||
22
applications/solvers/modules/VoFSolver/Make/options
Normal file
22
applications/solvers/modules/VoFSolver/Make/options
Normal file
@ -0,0 +1,22 @@
|
||||
EXE_INC = \
|
||||
-I$(FOAM_SOLVERS)/modules/fluidSolver/lnInclude \
|
||||
-I$(LIB_SRC)/physicalProperties/lnInclude \
|
||||
-I$(LIB_SRC)/twoPhaseModels/VoF \
|
||||
-I$(LIB_SRC)/twoPhaseModels/interfaceCompression/lnInclude \
|
||||
-I$(LIB_SRC)/twoPhaseModels/interfaceProperties/lnInclude \
|
||||
-I$(LIB_SRC)/twoPhaseModels/twoPhaseMixture/lnInclude \
|
||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||
-I$(LIB_SRC)/sampling/lnInclude
|
||||
|
||||
LIB_LIBS = \
|
||||
-lfluidSolver \
|
||||
-lphysicalProperties \
|
||||
-linterfaceCompression \
|
||||
-linterfaceProperties \
|
||||
-ltwoPhaseMixture \
|
||||
-lfiniteVolume \
|
||||
-lmeshTools \
|
||||
-lfvModels \
|
||||
-lfvConstraints \
|
||||
-lsampling
|
||||
314
applications/solvers/modules/VoFSolver/VoFSolver.C
Normal file
314
applications/solvers/modules/VoFSolver/VoFSolver.C
Normal file
@ -0,0 +1,314 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2022 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "VoFSolver.H"
|
||||
#include "localEulerDdtScheme.H"
|
||||
#include "CorrectPhi.H"
|
||||
#include "geometricZeroField.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace solvers
|
||||
{
|
||||
defineTypeNameAndDebug(VoFSolver, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::solvers::VoFSolver::correctCoNum()
|
||||
{
|
||||
fluidSolver::correctCoNum(phi);
|
||||
|
||||
const scalarField sumPhi
|
||||
(
|
||||
interface.nearInterface()().primitiveField()
|
||||
*fvc::surfaceSum(mag(phi))().primitiveField()
|
||||
);
|
||||
|
||||
alphaCoNum = 0.5*gMax(sumPhi/mesh.V().field())*runTime.deltaTValue();
|
||||
|
||||
const scalar meanAlphaCoNum =
|
||||
0.5*(gSum(sumPhi)/gSum(mesh.V().field()))*runTime.deltaTValue();
|
||||
|
||||
Info<< "Interface Courant Number mean: " << meanAlphaCoNum
|
||||
<< " max: " << alphaCoNum << endl;
|
||||
}
|
||||
|
||||
|
||||
void Foam::solvers::VoFSolver::continuityErrors()
|
||||
{
|
||||
fluidSolver::continuityErrors(phi);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::solvers::VoFSolver::VoFSolver
|
||||
(
|
||||
fvMesh& mesh,
|
||||
autoPtr<twoPhaseMixture> mixturePtr
|
||||
)
|
||||
:
|
||||
fluidSolver(mesh),
|
||||
|
||||
mixture_(mixturePtr),
|
||||
mixture(mixture_()),
|
||||
|
||||
alpha1(mixture.alpha1()),
|
||||
alpha2(mixture.alpha2()),
|
||||
|
||||
alphaRestart
|
||||
(
|
||||
typeIOobject<surfaceScalarField>
|
||||
(
|
||||
IOobject::groupName("alphaPhi", alpha1.group()),
|
||||
runTime.name(),
|
||||
mesh,
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::AUTO_WRITE
|
||||
).headerOk()
|
||||
),
|
||||
|
||||
divAlphaName("div(phi,alpha)"),
|
||||
|
||||
U
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"U",
|
||||
runTime.name(),
|
||||
mesh,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
mesh
|
||||
),
|
||||
|
||||
phi
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"phi",
|
||||
runTime.name(),
|
||||
mesh,
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
linearInterpolate(U) & mesh.Sf()
|
||||
),
|
||||
|
||||
interface(mixture, alpha1, alpha2, U),
|
||||
|
||||
buoyancy(mesh),
|
||||
|
||||
p_rgh(buoyancy.p_rgh),
|
||||
|
||||
rho(mixture.rho()),
|
||||
|
||||
rhoPhi
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"rhoPhi",
|
||||
runTime.name(),
|
||||
mesh,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
fvc::interpolate(rho)*phi
|
||||
),
|
||||
|
||||
alphaPhi1
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
IOobject::groupName("alphaPhi", alpha1.group()),
|
||||
runTime.name(),
|
||||
mesh,
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
phi*fvc::interpolate(alpha1)
|
||||
),
|
||||
|
||||
MRF(mesh)
|
||||
{
|
||||
// Read the controls
|
||||
read();
|
||||
|
||||
mesh.schemes().setFluxRequired(p_rgh.name());
|
||||
mesh.schemes().setFluxRequired(alpha1.name());
|
||||
|
||||
if (alphaRestart)
|
||||
{
|
||||
Info << "Restarting alpha" << endl;
|
||||
}
|
||||
|
||||
if (mesh.dynamic())
|
||||
{
|
||||
Info<< "Constructing face momentum Uf" << endl;
|
||||
|
||||
Uf = new surfaceVectorField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"Uf",
|
||||
runTime.name(),
|
||||
mesh,
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
fvc::interpolate(U)
|
||||
);
|
||||
}
|
||||
|
||||
if (transient())
|
||||
{
|
||||
correctCoNum();
|
||||
}
|
||||
else if (LTS)
|
||||
{
|
||||
Info<< "Using LTS" << endl;
|
||||
|
||||
trDeltaT = tmp<volScalarField>
|
||||
(
|
||||
new volScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
fv::localEulerDdt::rDeltaTName,
|
||||
runTime.name(),
|
||||
mesh,
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
mesh,
|
||||
dimensionedScalar(dimless/dimTime, 1),
|
||||
extrapolatedCalculatedFvPatchScalarField::typeName
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::solvers::VoFSolver::~VoFSolver()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::scalar Foam::solvers::VoFSolver::maxDeltaT() const
|
||||
{
|
||||
const scalar maxAlphaCo
|
||||
(
|
||||
runTime.controlDict().lookup<scalar>("maxAlphaCo")
|
||||
);
|
||||
|
||||
const scalar deltaT = fluidSolver::maxDeltaT();
|
||||
|
||||
if (alphaCoNum > small)
|
||||
{
|
||||
return min
|
||||
(
|
||||
deltaT,
|
||||
maxAlphaCo/(alphaCoNum + small)*runTime.deltaTValue()
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
return deltaT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::solvers::VoFSolver::preSolve()
|
||||
{
|
||||
// Read the controls
|
||||
read();
|
||||
|
||||
if (transient())
|
||||
{
|
||||
correctCoNum();
|
||||
}
|
||||
else if (LTS)
|
||||
{
|
||||
setRDeltaT();
|
||||
}
|
||||
|
||||
fvModels().preUpdateMesh();
|
||||
|
||||
// Store divU from the previous mesh so that it can be mapped
|
||||
// and used in correctPhi to ensure the corrected phi has the
|
||||
// same divergence
|
||||
if
|
||||
(
|
||||
correctPhi
|
||||
&& divergent()
|
||||
&& mesh.topoChanged())
|
||||
{
|
||||
// Construct and register divU for mapping
|
||||
divU = new volScalarField
|
||||
(
|
||||
"divU0",
|
||||
fvc::div(fvc::absolute(phi, U))
|
||||
);
|
||||
}
|
||||
|
||||
// Update the mesh for topology change, mesh to mesh mapping
|
||||
const bool topoChanged = mesh.update();
|
||||
|
||||
// Do not apply previous time-step mesh compression flux
|
||||
// if the mesh topology changed
|
||||
if (topoChanged)
|
||||
{
|
||||
talphaPhi1Corr0.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::solvers::VoFSolver::prePredictor()
|
||||
{
|
||||
fvModels().correct();
|
||||
alphaPredictor();
|
||||
}
|
||||
|
||||
|
||||
void Foam::solvers::VoFSolver::postCorrector()
|
||||
{}
|
||||
|
||||
|
||||
void Foam::solvers::VoFSolver::postSolve()
|
||||
{
|
||||
divU.clear();
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
282
applications/solvers/modules/VoFSolver/VoFSolver.H
Normal file
282
applications/solvers/modules/VoFSolver/VoFSolver.H
Normal file
@ -0,0 +1,282 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2022 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::solvers::VoFSolver
|
||||
|
||||
Description
|
||||
Solver module base-class for for 2 immiscible fluids using a VOF (volume
|
||||
of fluid) phase-fraction based interface capturing approach, with optional
|
||||
mesh motion and mesh topology changes including adaptive re-meshing.
|
||||
|
||||
The momentum and other fluid properties are of the "mixture" and a single
|
||||
momentum equation is solved.
|
||||
|
||||
Either mixture or two-phase transport modelling may be selected. In the
|
||||
mixture approach a single laminar, RAS or LES model is selected to model the
|
||||
momentum stress. In the Euler-Euler two-phase approach separate laminar,
|
||||
RAS or LES selected models are selected for each of the phases.
|
||||
|
||||
Uses the flexible PIMPLE (PISO-SIMPLE) solution for time-resolved and
|
||||
pseudo-transient and steady simulations.
|
||||
|
||||
Optional fvModels and fvConstraints are provided to enhance the simulation
|
||||
in many ways including adding various sources, Lagrangian
|
||||
particles, surface film etc. and constraining or limiting the solution.
|
||||
|
||||
SourceFiles
|
||||
VoFSolver.C
|
||||
|
||||
See also
|
||||
Foam::solvers::fluidSolver
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef VoFSolver_H
|
||||
#define VoFSolver_H
|
||||
|
||||
#include "fluidSolver.H"
|
||||
#include "twoPhaseMixture.H"
|
||||
#include "interfaceProperties.H"
|
||||
#include "buoyancy.H"
|
||||
#include "pressureReference.H"
|
||||
#include "IOMRFZoneList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace solvers
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class VoFSolver Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class VoFSolver
|
||||
:
|
||||
public fluidSolver
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
// Phase properties
|
||||
|
||||
//- The compressible two-phase mixture
|
||||
autoPtr<twoPhaseMixture> mixture_;
|
||||
|
||||
twoPhaseMixture& mixture;
|
||||
|
||||
//- Reference to the phase1-fraction
|
||||
volScalarField& alpha1;
|
||||
|
||||
//- Reference to the phase2-fraction
|
||||
volScalarField& alpha2;
|
||||
|
||||
//- Switch indicating if this is a restart
|
||||
bool alphaRestart;
|
||||
|
||||
//- Name of the alpha convection scheme
|
||||
const word divAlphaName;
|
||||
|
||||
//- Phase-fraction flux Courant number
|
||||
scalar alphaCoNum;
|
||||
|
||||
|
||||
// Kinematic properties
|
||||
|
||||
//- Velocity field
|
||||
volVectorField U;
|
||||
|
||||
//- Volumetric-flux field
|
||||
surfaceScalarField phi;
|
||||
|
||||
|
||||
// Interface properties
|
||||
|
||||
interfaceProperties interface;
|
||||
|
||||
|
||||
// Thermophysical properties
|
||||
|
||||
//- Buoyancy force
|
||||
solvers::buoyancy buoyancy;
|
||||
|
||||
//- Reference to the buoyant pressure for buoyant cases
|
||||
// otherwise to the pressure
|
||||
volScalarField& p_rgh;
|
||||
|
||||
//- Reference to the mixture continuity density field
|
||||
const volScalarField& rho;
|
||||
|
||||
|
||||
// Kinematic properties
|
||||
|
||||
//- Mass flux field
|
||||
surfaceScalarField rhoPhi;
|
||||
|
||||
// Phase-1 volumetric flux
|
||||
surfaceScalarField alphaPhi1;
|
||||
|
||||
|
||||
// Optional models
|
||||
|
||||
//- MRF zone list
|
||||
IOMRFZoneList MRF;
|
||||
|
||||
|
||||
// Cached temporary fields
|
||||
|
||||
tmp<volScalarField> rAU;
|
||||
|
||||
//- MULES Correction
|
||||
tmp<surfaceScalarField> talphaPhi1Corr0;
|
||||
|
||||
//- Pointer to the surface momentum field
|
||||
// used to recreate the flux after mesh-change
|
||||
autoPtr<surfaceVectorField> Uf;
|
||||
|
||||
//- Pointer to the momentum divergence field
|
||||
// used in correctPhi to ensure the corrected phi has the
|
||||
// same divergence
|
||||
autoPtr<volScalarField> divU;
|
||||
|
||||
//- Optional LTS reciprocal time-step field
|
||||
tmp<volScalarField> trDeltaT;
|
||||
|
||||
//- Cached momentum matrix
|
||||
// shared between the momentum predictor and pressure corrector
|
||||
tmp<fvVectorMatrix> tUEqn;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Set rDeltaT for LTS
|
||||
virtual void setRDeltaT();
|
||||
|
||||
//- Correct the cached Courant numbers
|
||||
void correctCoNum();
|
||||
|
||||
//- Solve for the phase-fractions
|
||||
void alphaSolve(const dictionary& alphaControls);
|
||||
|
||||
//- Solve for the phase-fractions
|
||||
void alphaPredictor();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Calculate and print the continuity errors
|
||||
void continuityErrors();
|
||||
|
||||
//- Return the pressure reference
|
||||
virtual const Foam::pressureReference& pressureReference() const = 0;
|
||||
|
||||
//- Is the flow divergent?
|
||||
// i.e. compressible or include phase-fraction sources
|
||||
virtual bool divergent() = 0;
|
||||
|
||||
//- Calculate the alpha equation sources
|
||||
virtual void alphaSuSp
|
||||
(
|
||||
tmp<volScalarField::Internal>& Su,
|
||||
tmp<volScalarField::Internal>& Sp
|
||||
) = 0;
|
||||
|
||||
//- Return the momentum equation stress term
|
||||
virtual tmp<fvVectorMatrix> divDevTau(volVectorField& U) = 0;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("VoFSolver");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from region mesh
|
||||
VoFSolver(fvMesh& mesh, autoPtr<twoPhaseMixture>);
|
||||
|
||||
//- Disallow default bitwise copy construction
|
||||
VoFSolver(const VoFSolver&) = delete;
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~VoFSolver();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Return the current maximum time-step for stable solution
|
||||
virtual scalar maxDeltaT() const;
|
||||
|
||||
//- Called at the start of the time-step, before the PIMPLE loop
|
||||
virtual void preSolve();
|
||||
|
||||
//- Called at the start of the PIMPLE loop to move the mesh
|
||||
virtual bool moveMesh();
|
||||
|
||||
//- Called at the start of the PIMPLE loop
|
||||
virtual void prePredictor() = 0;
|
||||
|
||||
//- Construct and optionally solve the momentum equation
|
||||
virtual void momentumPredictor();
|
||||
|
||||
//- Construct and solve the energy equation,
|
||||
// convert to temperature
|
||||
// and update thermophysical and transport properties
|
||||
virtual void thermophysicalPredictor() = 0;
|
||||
|
||||
//- Construct and solve the pressure equation in the PISO loop
|
||||
virtual void pressureCorrector() = 0;
|
||||
|
||||
//- Correct the momentum transport modelling
|
||||
virtual void postCorrector();
|
||||
|
||||
//- Called after the PIMPLE loop at the end of the time-step
|
||||
virtual void postSolve();
|
||||
|
||||
|
||||
// Member Operators
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const VoFSolver&) = delete;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace solvers
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
398
applications/solvers/modules/VoFSolver/alphaPredictor.C
Normal file
398
applications/solvers/modules/VoFSolver/alphaPredictor.C
Normal file
@ -0,0 +1,398 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2022 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "VoFSolver.H"
|
||||
#include "subCycle.H"
|
||||
#include "interfaceCompression.H"
|
||||
#include "CMULES.H"
|
||||
#include "CrankNicolsonDdtScheme.H"
|
||||
#include "fvcFlux.H"
|
||||
#include "fvmSup.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::solvers::VoFSolver::alphaSolve(const dictionary& alphaControls)
|
||||
{
|
||||
const label nAlphaSubCycles(alphaControls.lookup<label>("nAlphaSubCycles"));
|
||||
|
||||
const label nAlphaCorr(alphaControls.lookup<label>("nAlphaCorr"));
|
||||
|
||||
const bool MULESCorr
|
||||
(
|
||||
alphaControls.lookupOrDefault<Switch>("MULESCorr", false)
|
||||
);
|
||||
|
||||
// Apply the compression correction from the previous iteration
|
||||
// Improves efficiency for steady-simulations but can only be applied
|
||||
// once the alpha field is reasonably steady, i.e. fully developed
|
||||
const bool alphaApplyPrevCorr
|
||||
(
|
||||
alphaControls.lookupOrDefault<Switch>("alphaApplyPrevCorr", false)
|
||||
);
|
||||
|
||||
const word alphaScheme(mesh.schemes().div(divAlphaName)[1].wordToken());
|
||||
|
||||
ITstream compressionScheme
|
||||
(
|
||||
compressionSchemes.found(alphaScheme)
|
||||
? mesh.schemes().div(divAlphaName)
|
||||
: ITstream
|
||||
(
|
||||
divAlphaName,
|
||||
tokenList
|
||||
{
|
||||
word("Gauss"),
|
||||
word("interfaceCompression"),
|
||||
alphaScheme,
|
||||
alphaControls.lookup<scalar>("cAlpha")
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
// Set the off-centering coefficient according to ddt scheme
|
||||
scalar ocCoeff = 0;
|
||||
{
|
||||
tmp<fv::ddtScheme<scalar>> tddtAlpha
|
||||
(
|
||||
fv::ddtScheme<scalar>::New
|
||||
(
|
||||
mesh,
|
||||
mesh.schemes().ddt("ddt(alpha)")
|
||||
)
|
||||
);
|
||||
const fv::ddtScheme<scalar>& ddtAlpha = tddtAlpha();
|
||||
|
||||
if
|
||||
(
|
||||
isType<fv::EulerDdtScheme<scalar>>(ddtAlpha)
|
||||
|| isType<fv::localEulerDdtScheme<scalar>>(ddtAlpha)
|
||||
)
|
||||
{
|
||||
ocCoeff = 0;
|
||||
}
|
||||
else if (isType<fv::CrankNicolsonDdtScheme<scalar>>(ddtAlpha))
|
||||
{
|
||||
if (nAlphaSubCycles > 1)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Sub-cycling is not supported "
|
||||
"with the CrankNicolson ddt scheme"
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
if
|
||||
(
|
||||
alphaRestart
|
||||
|| mesh.time().timeIndex() > mesh.time().startTimeIndex() + 1
|
||||
)
|
||||
{
|
||||
ocCoeff =
|
||||
refCast<const fv::CrankNicolsonDdtScheme<scalar>>(ddtAlpha)
|
||||
.ocCoeff();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Only Euler and CrankNicolson ddt schemes are supported"
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the time blending factor, 1 for Euler
|
||||
scalar cnCoeff = 1.0/(1.0 + ocCoeff);
|
||||
|
||||
tmp<surfaceScalarField> phiCN(phi);
|
||||
|
||||
// Calculate the Crank-Nicolson off-centred volumetric flux
|
||||
if (ocCoeff > 0)
|
||||
{
|
||||
phiCN = surfaceScalarField::New
|
||||
(
|
||||
"phiCN",
|
||||
cnCoeff*phi + (1.0 - cnCoeff)*phi.oldTime()
|
||||
);
|
||||
}
|
||||
|
||||
tmp<volScalarField> divU;
|
||||
|
||||
if (divergent())
|
||||
{
|
||||
divU =
|
||||
(
|
||||
mesh.moving()
|
||||
? fvc::div(phiCN + mesh.phi())
|
||||
: fvc::div(phiCN)
|
||||
);
|
||||
}
|
||||
|
||||
tmp<volScalarField::Internal> Su;
|
||||
tmp<volScalarField::Internal> Sp;
|
||||
|
||||
alphaSuSp(Su, Sp);
|
||||
|
||||
if (MULESCorr)
|
||||
{
|
||||
fvScalarMatrix alpha1Eqn
|
||||
(
|
||||
(
|
||||
LTS
|
||||
? fv::localEulerDdtScheme<scalar>(mesh).fvmDdt(alpha1)
|
||||
: fv::EulerDdtScheme<scalar>(mesh).fvmDdt(alpha1)
|
||||
)
|
||||
+ fv::gaussConvectionScheme<scalar>
|
||||
(
|
||||
mesh,
|
||||
phiCN,
|
||||
upwind<scalar>(mesh, phiCN)
|
||||
).fvmDiv(phiCN, alpha1)
|
||||
);
|
||||
|
||||
if (divU.valid())
|
||||
{
|
||||
alpha1Eqn -= Su() + fvm::Sp(Sp() + divU(), alpha1);
|
||||
}
|
||||
|
||||
alpha1Eqn.solve();
|
||||
|
||||
Info<< "Phase-1 volume fraction = "
|
||||
<< alpha1.weightedAverage(mesh.Vsc()).value()
|
||||
<< " Min(" << alpha1.name() << ") = " << min(alpha1).value()
|
||||
<< " Max(" << alpha1.name() << ") = " << max(alpha1).value()
|
||||
<< endl;
|
||||
|
||||
tmp<surfaceScalarField> talphaPhi1UD(alpha1Eqn.flux());
|
||||
alphaPhi1 = talphaPhi1UD();
|
||||
|
||||
if (alphaApplyPrevCorr && talphaPhi1Corr0.valid())
|
||||
{
|
||||
Info<< "Applying the previous iteration compression flux" << endl;
|
||||
MULES::correct
|
||||
(
|
||||
geometricOneField(),
|
||||
alpha1,
|
||||
alphaPhi1,
|
||||
talphaPhi1Corr0.ref(),
|
||||
oneField(),
|
||||
zeroField()
|
||||
);
|
||||
|
||||
alphaPhi1 += talphaPhi1Corr0();
|
||||
}
|
||||
|
||||
// Cache the upwind-flux
|
||||
talphaPhi1Corr0 = talphaPhi1UD;
|
||||
|
||||
alpha2 = 1.0 - alpha1;
|
||||
|
||||
interface.correct();
|
||||
}
|
||||
|
||||
for (int aCorr=0; aCorr<nAlphaCorr; aCorr++)
|
||||
{
|
||||
// Split operator
|
||||
tmp<surfaceScalarField> talphaPhi1Un
|
||||
(
|
||||
fvc::flux
|
||||
(
|
||||
phiCN(),
|
||||
(cnCoeff*alpha1 + (1.0 - cnCoeff)*alpha1.oldTime())(),
|
||||
compressionScheme.rewind()
|
||||
)
|
||||
);
|
||||
|
||||
if (MULESCorr)
|
||||
{
|
||||
tmp<surfaceScalarField> talphaPhi1Corr(talphaPhi1Un() - alphaPhi1);
|
||||
volScalarField alpha10("alpha10", alpha1);
|
||||
|
||||
if (divU.valid())
|
||||
{
|
||||
MULES::correct
|
||||
(
|
||||
geometricOneField(),
|
||||
alpha1,
|
||||
talphaPhi1Un(),
|
||||
talphaPhi1Corr.ref(),
|
||||
Sp(),
|
||||
(-Sp()*alpha1)(),
|
||||
oneField(),
|
||||
zeroField()
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
MULES::correct
|
||||
(
|
||||
geometricOneField(),
|
||||
alpha1,
|
||||
talphaPhi1Un(),
|
||||
talphaPhi1Corr.ref(),
|
||||
oneField(),
|
||||
zeroField()
|
||||
);
|
||||
}
|
||||
|
||||
// Under-relax the correction for all but the 1st corrector
|
||||
if (aCorr == 0)
|
||||
{
|
||||
alphaPhi1 += talphaPhi1Corr();
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha1 = 0.5*alpha1 + 0.5*alpha10;
|
||||
alphaPhi1 += 0.5*talphaPhi1Corr();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
alphaPhi1 = talphaPhi1Un;
|
||||
|
||||
if (divU.valid())
|
||||
{
|
||||
MULES::explicitSolve
|
||||
(
|
||||
geometricOneField(),
|
||||
alpha1,
|
||||
phiCN,
|
||||
alphaPhi1,
|
||||
Sp(),
|
||||
(Su() + divU()*min(alpha1(), scalar(1)))(),
|
||||
oneField(),
|
||||
zeroField()
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
MULES::explicitSolve
|
||||
(
|
||||
geometricOneField(),
|
||||
alpha1,
|
||||
phiCN,
|
||||
alphaPhi1,
|
||||
oneField(),
|
||||
zeroField()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
alpha2 = 1.0 - alpha1;
|
||||
|
||||
// Correct only the mixture interface for the interface compression flux
|
||||
interface.correct();
|
||||
}
|
||||
|
||||
if (alphaApplyPrevCorr && MULESCorr)
|
||||
{
|
||||
talphaPhi1Corr0 = alphaPhi1 - talphaPhi1Corr0;
|
||||
talphaPhi1Corr0.ref().rename("alphaPhi1Corr0");
|
||||
}
|
||||
else
|
||||
{
|
||||
talphaPhi1Corr0.clear();
|
||||
}
|
||||
|
||||
if
|
||||
(
|
||||
word(mesh.schemes().ddt("ddt(rho,U)"))
|
||||
!= fv::EulerDdtScheme<vector>::typeName
|
||||
&& word(mesh.schemes().ddt("ddt(rho,U)"))
|
||||
!= fv::localEulerDdtScheme<vector>::typeName
|
||||
)
|
||||
{
|
||||
if (ocCoeff > 0)
|
||||
{
|
||||
// Calculate the end-of-time-step alpha flux
|
||||
alphaPhi1 =
|
||||
(alphaPhi1 - (1.0 - cnCoeff)*alphaPhi1.oldTime())/cnCoeff;
|
||||
}
|
||||
}
|
||||
|
||||
Info<< "Phase-1 volume fraction = "
|
||||
<< alpha1.weightedAverage(mesh.Vsc()).value()
|
||||
<< " Min(" << alpha1.name() << ") = " << min(alpha1).value()
|
||||
<< " Max(" << alpha1.name() << ") = " << max(alpha1).value()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
|
||||
void Foam::solvers::VoFSolver::alphaPredictor()
|
||||
{
|
||||
const dictionary& alphaControls = mesh.solution().solverDict(alpha1.name());
|
||||
|
||||
const label nAlphaSubCycles(alphaControls.lookup<label>("nAlphaSubCycles"));
|
||||
|
||||
|
||||
if (nAlphaSubCycles > 1)
|
||||
{
|
||||
dimensionedScalar totalDeltaT = runTime.deltaT();
|
||||
tmp<volScalarField> trSubDeltaT;
|
||||
|
||||
if (LTS)
|
||||
{
|
||||
trSubDeltaT =
|
||||
fv::localEulerDdt::localRSubDeltaT(mesh, nAlphaSubCycles);
|
||||
}
|
||||
|
||||
// Create a temporary alphaPhi1 to accumulate the sub-cycled alphaPhi1
|
||||
tmp<surfaceScalarField> talphaPhi1
|
||||
(
|
||||
surfaceScalarField::New
|
||||
(
|
||||
"alphaPhi1",
|
||||
mesh,
|
||||
dimensionedScalar(alphaPhi1.dimensions(), 0)
|
||||
)
|
||||
);
|
||||
|
||||
List<volScalarField*> alphaPtrs({&alpha1, &alpha2});
|
||||
|
||||
for
|
||||
(
|
||||
subCycle<volScalarField, subCycleFields> alphaSubCycle
|
||||
(
|
||||
alphaPtrs,
|
||||
nAlphaSubCycles
|
||||
);
|
||||
!(++alphaSubCycle).end();
|
||||
)
|
||||
{
|
||||
alphaSolve(alphaControls);
|
||||
talphaPhi1.ref() += (runTime.deltaT()/totalDeltaT)*alphaPhi1;
|
||||
}
|
||||
|
||||
alphaPhi1 = talphaPhi1();
|
||||
}
|
||||
else
|
||||
{
|
||||
alphaSolve(alphaControls);
|
||||
}
|
||||
|
||||
mixture.correct();
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
19
applications/solvers/modules/VoFSolver/alphaSuSp.H
Normal file
19
applications/solvers/modules/VoFSolver/alphaSuSp.H
Normal file
@ -0,0 +1,19 @@
|
||||
tmp<volScalarField> divU;
|
||||
tmp<volScalarField::Internal> Su;
|
||||
tmp<volScalarField::Internal> Sp;
|
||||
|
||||
if (divergent())
|
||||
{
|
||||
// Phase change alpha1 source
|
||||
const fvScalarMatrix alphaSup(fvModels().source(alpha1));
|
||||
|
||||
Su = alphaSup.Su();
|
||||
Sp = alphaSup.Sp();
|
||||
|
||||
divU =
|
||||
(
|
||||
mesh.moving()
|
||||
? fvc::div(phiCN() + mesh.phi())
|
||||
: fvc::div(phiCN())
|
||||
);
|
||||
}
|
||||
70
applications/solvers/modules/VoFSolver/momentumPredictor.C
Normal file
70
applications/solvers/modules/VoFSolver/momentumPredictor.C
Normal file
@ -0,0 +1,70 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2022 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "VoFSolver.H"
|
||||
#include "fvmDiv.H"
|
||||
#include "fvcSnGrad.H"
|
||||
#include "fvcReconstruct.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::solvers::VoFSolver::momentumPredictor()
|
||||
{
|
||||
tUEqn =
|
||||
(
|
||||
fvm::ddt(rho, U) + fvm::div(rhoPhi, U)
|
||||
+ MRF.DDt(rho, U)
|
||||
+ divDevTau(U)
|
||||
==
|
||||
fvModels().source(rho, U)
|
||||
);
|
||||
fvVectorMatrix& UEqn = tUEqn.ref();
|
||||
|
||||
UEqn.relax();
|
||||
|
||||
fvConstraints().constrain(UEqn);
|
||||
|
||||
if (pimple.momentumPredictor())
|
||||
{
|
||||
solve
|
||||
(
|
||||
UEqn
|
||||
==
|
||||
fvc::reconstruct
|
||||
(
|
||||
(
|
||||
interface.surfaceTensionForce()
|
||||
- buoyancy.ghf*fvc::snGrad(rho)
|
||||
- fvc::snGrad(p_rgh)
|
||||
) * mesh.magSf()
|
||||
)
|
||||
);
|
||||
|
||||
fvConstraints().constrain(U);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
118
applications/solvers/modules/VoFSolver/moveMesh.C
Normal file
118
applications/solvers/modules/VoFSolver/moveMesh.C
Normal file
@ -0,0 +1,118 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2022 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "VoFSolver.H"
|
||||
#include "CorrectPhi.H"
|
||||
#include "geometricZeroField.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::solvers::VoFSolver::moveMesh()
|
||||
{
|
||||
if (pimple.firstIter() || pimple.moveMeshOuterCorrectors())
|
||||
{
|
||||
if
|
||||
(
|
||||
correctPhi
|
||||
&& divergent()
|
||||
&& !divU.valid()
|
||||
)
|
||||
{
|
||||
// Construct and register divU for correctPhi
|
||||
divU = new volScalarField
|
||||
(
|
||||
"divU0",
|
||||
fvc::div(fvc::absolute(phi, U))
|
||||
);
|
||||
}
|
||||
|
||||
// Move the mesh
|
||||
mesh.move();
|
||||
|
||||
if (mesh.changing())
|
||||
{
|
||||
buoyancy.moveMesh();
|
||||
|
||||
MRF.update();
|
||||
|
||||
if (correctPhi || mesh.topoChanged())
|
||||
{
|
||||
// Calculate absolute flux
|
||||
// from the mapped surface velocity
|
||||
phi = mesh.Sf() & Uf();
|
||||
|
||||
correctUphiBCs(U, phi, true);
|
||||
|
||||
if (correctPhi)
|
||||
{
|
||||
if (divU.valid())
|
||||
{
|
||||
CorrectPhi
|
||||
(
|
||||
phi,
|
||||
U,
|
||||
p_rgh,
|
||||
surfaceScalarField("rAUf", fvc::interpolate(rAU())),
|
||||
divU(),
|
||||
pressureReference(),
|
||||
pimple
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
CorrectPhi
|
||||
(
|
||||
phi,
|
||||
U,
|
||||
p_rgh,
|
||||
surfaceScalarField("rAUf", fvc::interpolate(rAU())),
|
||||
geometricZeroField(),
|
||||
pressureReference(),
|
||||
pimple
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Make the fluxes relative to the mesh motion
|
||||
fvc::makeRelative(phi, U);
|
||||
}
|
||||
|
||||
meshCourantNo();
|
||||
|
||||
interface.correct();
|
||||
|
||||
divU.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
divU.clear();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
183
applications/solvers/modules/VoFSolver/setRDeltaT.C
Normal file
183
applications/solvers/modules/VoFSolver/setRDeltaT.C
Normal file
@ -0,0 +1,183 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2022 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "VoFSolver.H"
|
||||
#include "fvcSmooth.H"
|
||||
#include "fvcSurfaceIntegrate.H"
|
||||
#include "fvcAverage.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::solvers::VoFSolver::setRDeltaT()
|
||||
{
|
||||
volScalarField& rDeltaT = trDeltaT.ref();
|
||||
|
||||
const dictionary& pimpleDict = pimple.dict();
|
||||
|
||||
const scalar maxCo
|
||||
(
|
||||
pimpleDict.lookupOrDefault<scalar>("maxCo", 0.9)
|
||||
);
|
||||
|
||||
const scalar maxAlphaCo
|
||||
(
|
||||
pimpleDict.lookupOrDefault<scalar>("maxAlphaCo", 0.2)
|
||||
);
|
||||
|
||||
const scalar rDeltaTSmoothingCoeff
|
||||
(
|
||||
pimpleDict.lookupOrDefault<scalar>("rDeltaTSmoothingCoeff", 0.1)
|
||||
);
|
||||
|
||||
const label nAlphaSpreadIter
|
||||
(
|
||||
pimpleDict.lookupOrDefault<label>("nAlphaSpreadIter", 1)
|
||||
);
|
||||
|
||||
const scalar alphaSpreadDiff
|
||||
(
|
||||
pimpleDict.lookupOrDefault<scalar>("alphaSpreadDiff", 0.2)
|
||||
);
|
||||
|
||||
const scalar alphaSpreadMax
|
||||
(
|
||||
pimpleDict.lookupOrDefault<scalar>("alphaSpreadMax", 0.99)
|
||||
);
|
||||
|
||||
const scalar alphaSpreadMin
|
||||
(
|
||||
pimpleDict.lookupOrDefault<scalar>("alphaSpreadMin", 0.01)
|
||||
);
|
||||
|
||||
const label nAlphaSweepIter
|
||||
(
|
||||
pimpleDict.lookupOrDefault<label>("nAlphaSweepIter", 5)
|
||||
);
|
||||
|
||||
const scalar maxDeltaT
|
||||
(
|
||||
pimpleDict.lookupOrDefault<scalar>("maxDeltaT", great)
|
||||
);
|
||||
|
||||
const scalar minDeltaT
|
||||
(
|
||||
pimpleDict.lookupOrDefault<scalar>("minDeltaT", small)
|
||||
);
|
||||
|
||||
const volScalarField rDeltaT0("rDeltaT0", rDeltaT);
|
||||
|
||||
// Set the reciprocal time-step from the local Courant number
|
||||
// and maximum and minimum time-steps
|
||||
rDeltaT.ref() = min
|
||||
(
|
||||
1/dimensionedScalar(dimTime, minDeltaT),
|
||||
max
|
||||
(
|
||||
1/dimensionedScalar(dimTime, maxDeltaT),
|
||||
fvc::surfaceSum(mag(phi))()()
|
||||
/((2*maxCo)*mesh.V())
|
||||
)
|
||||
);
|
||||
|
||||
if (maxAlphaCo < maxCo)
|
||||
{
|
||||
// Further limit the reciprocal time-step
|
||||
// in the vicinity of the interface
|
||||
|
||||
volScalarField alpha1Bar(fvc::average(alpha1));
|
||||
|
||||
rDeltaT.ref() = max
|
||||
(
|
||||
rDeltaT(),
|
||||
pos0(alpha1Bar() - alphaSpreadMin)
|
||||
*pos0(alphaSpreadMax - alpha1Bar())
|
||||
*fvc::surfaceSum(mag(phi))()()
|
||||
/((2*maxAlphaCo)*mesh.V())
|
||||
);
|
||||
}
|
||||
|
||||
// Update the boundary values of the reciprocal time-step
|
||||
rDeltaT.correctBoundaryConditions();
|
||||
|
||||
Info<< "Flow time scale min/max = "
|
||||
<< gMin(1/rDeltaT.primitiveField())
|
||||
<< ", " << gMax(1/rDeltaT.primitiveField()) << endl;
|
||||
|
||||
if (rDeltaTSmoothingCoeff < 1.0)
|
||||
{
|
||||
fvc::smooth(rDeltaT, rDeltaTSmoothingCoeff);
|
||||
}
|
||||
|
||||
if (nAlphaSpreadIter > 0)
|
||||
{
|
||||
fvc::spread
|
||||
(
|
||||
rDeltaT,
|
||||
alpha1,
|
||||
nAlphaSpreadIter,
|
||||
alphaSpreadDiff,
|
||||
alphaSpreadMax,
|
||||
alphaSpreadMin
|
||||
);
|
||||
}
|
||||
|
||||
if (nAlphaSweepIter > 0)
|
||||
{
|
||||
fvc::sweep(rDeltaT, alpha1, nAlphaSweepIter, alphaSpreadDiff);
|
||||
}
|
||||
|
||||
Info<< "Smoothed flow time scale min/max = "
|
||||
<< gMin(1/rDeltaT.primitiveField())
|
||||
<< ", " << gMax(1/rDeltaT.primitiveField()) << endl;
|
||||
|
||||
// Limit rate of change of time scale
|
||||
// - reduce as much as required
|
||||
// - only increase at a fraction of old time scale
|
||||
if
|
||||
(
|
||||
pimpleDict.found("rDeltaTDampingCoeff")
|
||||
&& runTime.timeIndex() > runTime.startTimeIndex() + 1
|
||||
)
|
||||
{
|
||||
// Damping coefficient (1-0)
|
||||
const scalar rDeltaTDampingCoeff
|
||||
(
|
||||
pimpleDict.lookup<scalar>("rDeltaTDampingCoeff")
|
||||
);
|
||||
|
||||
rDeltaT = max
|
||||
(
|
||||
rDeltaT,
|
||||
(scalar(1) - rDeltaTDampingCoeff)*rDeltaT0
|
||||
);
|
||||
|
||||
Info<< "Damped flow time scale min/max = "
|
||||
<< gMin(1/rDeltaT.primitiveField())
|
||||
<< ", " << gMax(1/rDeltaT.primitiveField()) << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
Reference in New Issue
Block a user