Commit ea17556c authored by shunbo's avatar shunbo
Browse files

Initial commit

parents
// Pressure-velocity SIMPLE corrector
{
if (frozenFlow)
{
#include "EEqn.H"
}
else
{
p_rgh.storePrevIter();
rho.storePrevIter();
#include "UEqn.H"
#include "EEqn.H"
if (!coupled)
{
#include "pEqn.H"
turb.correct();
}
}
}
const dictionary& simple = mesh.solutionDict().subDict("SIMPLE");
const int nNonOrthCorr =
simple.getOrDefault<int>("nNonOrthogonalCorrectors", 0);
{
for (int nonOrth=0; nonOrth<=nNonOrthCorr; ++nonOrth)
{
fvScalarMatrix hEqn
(
(
thermo.isotropic()
? -fvm::laplacian(betav*thermo.alpha(), h, "laplacian(alpha,h)")
: -fvm::laplacian(betav*taniAlpha(), h, "laplacian(alpha,h)")
)
==
fvOptions(rho, h)
);
hEqn.relax();
fvOptions.constrain(hEqn);
if (coupled)
{
fvMatrixAssemblyPtr->addFvMatrix(hEqn);
}
else
{
Info<< "\nSolving for solid region "
<< solidRegions[i].name() << endl;
hEqn.solve();
fvOptions.correct(h);
thermo.correct();
Info<< "Min/max T:" << min(thermo.T()).value() << ' '
<< max(thermo.T()).value() << endl;
}
}
}
#include "createFluidFields.H"
#include "createSolidFields.H"
regionProperties rp(runTime);
#include "createFluidMeshes.H"
#include "createSolidMeshes.H"
#include "createMeshes.H"
if (!fluidRegions.size() && !solidRegions.size())
{
FatalErrorIn(args.executable())
<< "No region meshes present" << exit(FatalError);
}
fvMesh& mesh = fluidRegions.size() ? fluidRegions[0] : solidRegions[0];
{
volScalarField& he = thermo.he();
fvScalarMatrix EEqn
(
fvm::ddt(rho, he) + fvm::div(phi, he)
+ fvc::ddt(rho, K) + fvc::div(phi, K)
+ (
he.name() == "e"
? fvc::div
(
fvc::absolute(phi/fvc::interpolate(rho), U),
p,
"div(phiv,p)"
)
: -dpdt
)
- fvm::laplacian(turbulence.alphaEff(), he)
==
rho*(U&g)
+ rad.Sh(thermo, he)
+ Qdot
+ fvOptions(rho, he)
);
EEqn.relax();
fvOptions.constrain(EEqn);
if (coupled)
{
fvMatrixAssemblyPtr->addFvMatrix(EEqn);
}
else
{
EEqn.solve(mesh.solver(he.select(finalIter)));
fvOptions.correct(he);
thermo.correct();
rad.correct();
Info<< "Min/max T:" << min(thermo.T()).value() << ' '
<< max(thermo.T()).value() << endl;
}
}
// Solve the Momentum equation
MRF.correctBoundaryVelocity(U);
UEqn =
(
fvm::ddt(rho, U) + fvm::div(phi, U)
+ MRF.DDt(rho, U)
+ turbulence.divDevRhoReff(U)
==
fvOptions(rho, U)
);
UEqn.relax();
fvOptions.constrain(UEqn);
if (momentumPredictor)
{
solve
(
UEqn
==
fvc::reconstruct
(
(
- ghf*fvc::snGrad(rho)
- fvc::snGrad(p_rgh)
)*mesh.magSf()
),
mesh.solver(U.select(finalIter))
);
fvOptions.correct(U);
K = 0.5*magSqr(U);
}
tmp<fv::convectionScheme<scalar>> mvConvection(nullptr);
if (Y.size())
{
mvConvection = tmp<fv::convectionScheme<scalar>>
(
fv::convectionScheme<scalar>::New
(
mesh,
fields,
phi,
mesh.divScheme("div(phi,Yi_h)")
)
);
}
{
reaction.correct();
Qdot = reaction.Qdot();
volScalarField Yt
(
IOobject("Yt", runTime.timeName(), mesh),
mesh,
dimensionedScalar("Yt", dimless, 0)
);
forAll(Y, i)
{
if (i != inertIndex && composition.active(i))
{
volScalarField& Yi = Y[i];
fvScalarMatrix YiEqn
(
fvm::ddt(rho, Yi)
+ mvConvection->fvmDiv(phi, Yi)
- fvm::laplacian(turbulence.muEff(), Yi)
==
reaction.R(Yi)
+ fvOptions(rho, Yi)
);
YiEqn.relax();
fvOptions.constrain(YiEqn);
YiEqn.solve(mesh.solver("Yi"));
fvOptions.correct(Yi);
Yi.max(0.0);
Yt += Yi;
}
}
if (Y.size())
{
Y[inertIndex] = scalar(1) - Yt;
Y[inertIndex].max(0.0);
}
}
{
dimensionedScalar totalMass = fvc::domainIntegrate(rho);
scalar sumLocalContErr =
(
fvc::domainIntegrate(mag(rho - thermo.rho()))/totalMass
).value();
scalar globalContErr =
(
fvc::domainIntegrate(rho - thermo.rho())/totalMass
).value();
cumulativeContErr[i] += globalContErr;
Info<< "time step continuity errors (" << mesh.name() << ")"
<< ": sum local = " << sumLocalContErr
<< ", global = " << globalContErr
<< ", cumulative = " << cumulativeContErr[i]
<< endl;
}
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
-------------------------------------------------------------------------------
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 "compressibleCourantNo.H"
#include "fvc.H"
Foam::scalar Foam::compressibleCourantNo
(
const fvMesh& mesh,
const Time& runTime,
const volScalarField& rho,
const surfaceScalarField& phi
)
{
scalarField sumPhi
(
fvc::surfaceSum(mag(phi))().primitiveField()
/ rho.primitiveField()
);
scalar CoNum = 0.5*gMax(sumPhi/mesh.V().field())*runTime.deltaTValue();
scalar meanCoNum =
0.5*(gSum(sumPhi)/gSum(mesh.V().field()))*runTime.deltaTValue();
Info<< "Region: " << mesh.name() << " Courant Number mean: " << meanCoNum
<< " max: " << CoNum << endl;
return CoNum;
}
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation
-------------------------------------------------------------------------------
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/>.
Description
Calculates and outputs the mean and maximum Courant Numbers for the fluid
regions
\*---------------------------------------------------------------------------*/
#ifndef compressibleCourantNo_H
#define compressibleCourantNo_H
#include "fvMesh.H"
namespace Foam
{
scalar compressibleCourantNo
(
const fvMesh& mesh,
const Time& runTime,
const volScalarField& rho,
const surfaceScalarField& phi
);
}
#endif
// ************************************************************************* //
scalar CoNum = -GREAT;
forAll(fluidRegions, regioni)
{
CoNum = max
(
compressibleCourantNo
(
fluidRegions[regioni],
runTime,
rhoFluid[regioni],
phiFluid[regioni]
),
CoNum
);
}
/*
forAll(porousFluidRegions, porousi)
{
CoNum = max
(
compressibleCourantNo
(
porousFluidRegions[porousi],
runTime,
rhoPorous[porousi],
phiPorous[porousi]
),
CoNum
);
}
*/
// Initialise fluid field pointer lists
PtrList<rhoReactionThermo> thermoFluid(fluidRegions.size());
PtrList<volScalarField> rhoFluid(fluidRegions.size());
PtrList<volVectorField> UFluid(fluidRegions.size());
PtrList<surfaceScalarField> phiFluid(fluidRegions.size());
PtrList<uniformDimensionedScalarField> hRefFluid(fluidRegions.size());
PtrList<volScalarField> ghFluid(fluidRegions.size());
PtrList<surfaceScalarField> ghfFluid(fluidRegions.size());
PtrList<compressible::turbulenceModel> turbulenceFluid(fluidRegions.size());
PtrList<CombustionModel<rhoReactionThermo>> reactionFluid(fluidRegions.size());
PtrList<volScalarField> p_rghFluid(fluidRegions.size());
PtrList<radiation::radiationModel> radiation(fluidRegions.size());
PtrList<volScalarField> KFluid(fluidRegions.size());
PtrList<volScalarField> dpdtFluid(fluidRegions.size());
PtrList<multivariateSurfaceInterpolationScheme<scalar>::fieldTable>
fieldsFluid(fluidRegions.size());
PtrList<volScalarField> QdotFluid(fluidRegions.size());
PtrList<fvVectorMatrix> UEqFluid(fluidRegions.size());
List<scalar> initialMassFluid(fluidRegions.size());
List<bool> frozenFlowFluid(fluidRegions.size(), false);
PtrList<IOMRFZoneList> MRFfluid(fluidRegions.size());
PtrList<fv::options> fluidFvOptions(fluidRegions.size());
List<label> pRefCellFluid(fluidRegions.size());
List<scalar> pRefValueFluid(fluidRegions.size());
PtrList<dimensionedScalar> rhoMinFluid(fluidRegions.size());
PtrList<dimensionedScalar> rhoMaxFluid(fluidRegions.size());
PtrList<pressureControl> pressureControls(fluidRegions.size());
const uniformDimensionedVectorField& g = meshObjects::gravity::New(runTime);
// Populate fluid field pointer lists
forAll(fluidRegions, i)
{
Info<< "*** Reading fluid mesh thermophysical properties for region "
<< fluidRegions[i].name() << nl << endl;
Info<< " Adding to thermoFluid\n" << endl;
thermoFluid.set(i, rhoReactionThermo::New(fluidRegions[i]).ptr());
Info<< " Adding to rhoFluid\n" << endl;
rhoFluid.set
(
i,
new volScalarField
(
IOobject
(
"rho",
runTime.timeName(),
fluidRegions[i],
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
thermoFluid[i].rho()
)
);
Info<< " Adding to UFluid\n" << endl;
UFluid.set
(
i,
new volVectorField
(
IOobject
(
"U",
runTime.timeName(),
fluidRegions[i],
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
fluidRegions[i]
)
);
Info<< " Adding to phiFluid\n" << endl;
phiFluid.set
(
i,
new surfaceScalarField
(
IOobject
(
"phi",
runTime.timeName(),
fluidRegions[i],
IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE
),
linearInterpolate(rhoFluid[i]*UFluid[i])
& fluidRegions[i].Sf()
)
);
Info<< " Adding to hRefFluid\n" << endl;
hRefFluid.set
(
i,
new uniformDimensionedScalarField
(
IOobject
(
"hRef",
runTime.constant(),
fluidRegions[i],
IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE
),
dimensionedScalar("hRef", dimLength, Zero) // uses name
)
);
dimensionedScalar ghRef
(
mag(g.value()) > SMALL
? g & (cmptMag(g.value())/mag(g.value()))*hRefFluid[i]
: dimensionedScalar("ghRef", g.dimensions()*dimLength, 0)
);
Info<< " Adding to ghFluid\n" << endl;
ghFluid.set
(
i,
new volScalarField
(
"gh",
(g & fluidRegions[i].C()) - ghRef
)
);
Info<< " Adding to ghfFluid\n" << endl;
ghfFluid.set
(
i,
new surfaceScalarField
(
"ghf",
(g & fluidRegions[i].Cf()) - ghRef
)
);
Info<< " Adding to turbulenceFluid\n" << endl;
turbulenceFluid.set
(
i,
compressible::turbulenceModel::New
(
rhoFluid[i],
UFluid[i],
phiFluid[i],
thermoFluid[i]
).ptr()
);
Info<< " Adding to reactionFluid\n" << endl;
reactionFluid.set
(
i,
CombustionModel<rhoReactionThermo>::New
(
thermoFluid[i],
turbulenceFluid[i]
)
);
p_rghFluid.set
(
i,
new volScalarField
(
IOobject
(
"p_rgh",
runTime.timeName(),
fluidRegions[i],
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
fluidRegions[i]
)
);
// Force p_rgh to be consistent with p
p_rghFluid[i] = thermoFluid[i].p() - rhoFluid[i]*ghFluid[i];
fluidRegions[i].setFluxRequired(p_rghFluid[i].name());
Info<< " Adding to radiationFluid\n" << endl;
radiation.set
(
i,
radiation::radiationModel::New(thermoFluid[i].T())
);
initialMassFluid[i] = fvc::domainIntegrate(rhoFluid[i]).value();
Info<< " Adding to KFluid\n" << endl;
KFluid.set
(
i,
new volScalarField
(
"K",
0.5*magSqr(UFluid[i])
)
);
Info<< " Adding to dpdtFluid\n" << endl;
dpdtFluid.set
(
i,
new volScalarField
(
IOobject
(
"dpdt",
runTime.timeName(),
fluidRegions[i]
),
fluidRegions[i],
dimensionedScalar(thermoFluid[i].p().dimensions()/dimTime, Zero)
)
);
Info<< " Adding to fieldsFluid\n" << endl;
fieldsFluid.set
(
i,
new multivariateSurfaceInterpolationScheme<scalar>::fieldTable
);
forAll(thermoFluid[i].composition().Y(), j)
{
fieldsFluid[i].add(thermoFluid[i].composition().Y()[j]);
}
fieldsFluid[i].add(thermoFluid[i].he());
Info<< " Adding to QdotFluid\n" << endl;
QdotFluid.set
(
i,
new volScalarField
(
IOobject
(
"Qdot",
runTime.timeName(),
fluidRegions[i],
IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE
),
fluidRegions[i],
dimensionedScalar(dimEnergy/dimVolume/dimTime, Zero)
)
);
const dictionary& pimpleDict =
fluidRegions[i].solutionDict().subDict("PIMPLE");
pimpleDict.readIfPresent("frozenFlow", frozenFlowFluid[i]);
rhoMaxFluid.set
(
i,
new dimensionedScalar("rhoMax", dimDensity, GREAT, pimpleDict)
);
rhoMinFluid.set
(
i,
new dimensionedScalar("rhoMin", dimDensity, Zero, pimpleDict)
);
pressureControls.set
(
i,
new pressureControl(thermoFluid[i].p(), rhoFluid[i], pimpleDict, false)
);
Info<< " Adding MRF\n" << endl;
MRFfluid.set
(
i,
new IOMRFZoneList(fluidRegions[i])
);
Info<< " Adding fvOptions\n" << endl;
fluidFvOptions.set
(
i,
new fv::options(fluidRegions[i])
);
UEqFluid.set
(
i,
new fvVectorMatrix(UFluid[i], dimForce)
);
turbulenceFluid[i].validate();
pRefCellFluid[i] = -1;
pRefValueFluid[i] = 0.0;
if (p_rghFluid[i].needReference())
{
setRefCell
(
thermoFluid[i].p(),
p_rghFluid[i],
pimpleDict,
pRefCellFluid[i],
pRefValueFluid[i]
);
}
}
const wordList fluidNames(rp["fluid"]);
PtrList<fvMesh> fluidRegions(fluidNames.size());
forAll(fluidNames, i)
{
Info<< "Create fluid mesh for region " << fluidNames[i]
<< " for time = " << runTime.timeName() << nl << endl;
fluidRegions.set
(
i,
new fvMesh
(
IOobject
(
fluidNames[i],
runTime.timeName(),
runTime,
IOobject::MUST_READ
)
)
);
}
PtrList<uniformDimensionedScalarField> cumulativeContErrIO(fluidRegions.size());
forAll(cumulativeContErrIO, i)
{
const fvMesh& mesh = fluidRegions[i];
cumulativeContErrIO.set
(
i,
new uniformDimensionedScalarField
(
IOobject
(
"cumulativeContErr",
runTime.timeName(),
"uniform",
mesh,
IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE
),
dimensionedScalar(dimless, Zero)
)
);
}
UPtrList<scalar> cumulativeContErr(cumulativeContErrIO.size());
forAll(cumulativeContErrIO, i)
{
cumulativeContErr.set(i, &cumulativeContErrIO[i].value());
}
bool closedVolume = p_rgh.needReference();
dimensionedScalar compressibility = fvc::domainIntegrate(psi);
bool compressible = (compressibility.value() > SMALL);
rho = thermo.rho();
// Thermodynamic density needs to be updated by psi*d(p) after the
// pressure solution
const volScalarField psip0(psi*p);
volScalarField rAU("rAU", 1.0/UEqn.A());
surfaceScalarField rhorAUf("rhorAUf", fvc::interpolate(rho*rAU));
volVectorField HbyA(constrainHbyA(rAU*UEqn.H(), U, p_rgh));
surfaceScalarField phig(-rhorAUf*ghf*fvc::snGrad(rho)*mesh.magSf());
surfaceScalarField phiHbyA
(
"phiHbyA",
(
fvc::flux(rho*HbyA)
+ MRF.zeroFilter(rhorAUf*fvc::ddtCorr(rho, U, phi))
)
+ phig
);
MRF.makeRelative(fvc::interpolate(rho), phiHbyA);
// Update the pressure BCs to ensure flux consistency
constrainPressure(p_rgh, rho, U, phiHbyA, rhorAUf, MRF);
{
fvScalarMatrix p_rghDDtEqn
(
fvc::ddt(rho) + psi*correction(fvm::ddt(p_rgh))
+ fvc::div(phiHbyA)
);
for (int nonOrth=0; nonOrth<=nNonOrthCorr; nonOrth++)
{
fvScalarMatrix p_rghEqn
(
p_rghDDtEqn
- fvm::laplacian(rhorAUf, p_rgh)
);
p_rghEqn.setReference
(
pRefCell,
compressible ? getRefCellValue(p_rgh, pRefCell) : pRefValue
);
p_rghEqn.solve
(
mesh.solver
(
p_rgh.select
(
(
oCorr == nOuterCorr-1
&& corr == nCorr-1
&& nonOrth == nNonOrthCorr
)
)
)
);
if (nonOrth == nNonOrthCorr)
{
phi = phiHbyA + p_rghEqn.flux();
p_rgh.relax();
U = HbyA
+ rAU*fvc::reconstruct((phig + p_rghEqn.flux())/rhorAUf);
U.correctBoundaryConditions();
fvOptions.correct(U);
K = 0.5*magSqr(U);
}
}
p = p_rgh + rho*gh;
}
pressureControl.limit(p);
// For closed-volume cases adjust the pressure and density levels
// to obey overall mass continuity
if (closedVolume)
{
if (!compressible)
{
p += dimensionedScalar
(
"p",
p.dimensions(),
pRefValue - getRefCellValue(p, pRefCell)
);
}
else
{
p += (initialMass - fvc::domainIntegrate(psi*p))
/compressibility;
thermo.correctRho(psi*p - psip0, rhoMin, rhoMax);
rho = thermo.rho();
p_rgh = p - rho*gh;
p_rgh.correctBoundaryConditions();
}
}
else
{
thermo.correctRho(psi*p - psip0, rhoMin, rhoMax);
}
#include "rhoEqn.H"
#include "compressibleContinuityErrors.H"
rho = thermo.rho();
// Update pressure time derivative if needed
if (thermo.dpdt())
{
dpdt = fvc::ddt(p);
}
const dictionary& pimple = mesh.solutionDict().subDict("PIMPLE");
const int nCorr =
pimple.getOrDefault<int>("nCorrectors", 1);
const int nNonOrthCorr =
pimple.getOrDefault<int>("nNonOrthogonalCorrectors", 0);
const bool momentumPredictor =
pimple.getOrDefault("momentumPredictor", true);
fvMesh& mesh = fluidRegions[i];
CombustionModel<rhoReactionThermo>& reaction = reactionFluid[i];
rhoReactionThermo& thermo = reaction.thermo();
thermo.validate(args.executable(), "h", "e");
basicMultiComponentMixture& composition = thermo.composition();
PtrList<volScalarField>& Y = composition.Y();
label inertIndex = -1;
if (Y.size())
{
const word inertSpecie(thermo.get<word>("inertSpecie"));
if (!composition.species().found(inertSpecie))
{
FatalIOErrorIn(args.executable().c_str(), thermo)
<< "Inert specie " << inertSpecie
<< " not found in available species "
<< composition.species()
<< exit(FatalIOError);
}
inertIndex = composition.species()[inertSpecie];
}
volScalarField& rho = rhoFluid[i];
volVectorField& U = UFluid[i];
surfaceScalarField& phi = phiFluid[i];
compressible::turbulenceModel& turbulence = turbulenceFluid[i];
volScalarField& K = KFluid[i];
volScalarField& dpdt = dpdtFluid[i];
volScalarField& p = thermo.p();
const volScalarField& psi = thermo.psi();
volScalarField& p_rgh = p_rghFluid[i];
const volScalarField& gh = ghFluid[i];
const surfaceScalarField& ghf = ghfFluid[i];
multivariateSurfaceInterpolationScheme<scalar>::fieldTable& fields =
fieldsFluid[i];
volScalarField& Qdot = QdotFluid[i];
radiation::radiationModel& rad = radiation[i];
IOMRFZoneList& MRF = MRFfluid[i];
fv::options& fvOptions = fluidFvOptions[i];
fvVectorMatrix& UEqn = UEqFluid[i];
const dimensionedScalar initialMass
(
"initialMass",
dimMass,
initialMassFluid[i]
);
bool frozenFlow = frozenFlowFluid[i];
const label pRefCell = pRefCellFluid[i];
const scalar pRefValue = pRefValueFluid[i];
const dimensionedScalar rhoMax = rhoMaxFluid[i];
const dimensionedScalar rhoMin = rhoMinFluid[i];
const pressureControl& pressureControl = pressureControls[i];
if (finalIter)
{
mesh.data::add("finalIteration", true);
}
if (frozenFlow)
{
#include "EEqn.H"
}
else
{
if (oCorr == 0)
{
#include "rhoEqn.H"
}
#include "UEqn.H"
#include "YEqn.H"
#include "EEqn.H"
if (!coupled)
{
Info<< "\nSolving for fluid region " << fluidRegions[i].name() << endl;
// --- PISO loop
for (int corr=0; corr<nCorr; corr++)
{
#include "pEqn.H"
}
turbulence.correct();
rho = thermo.rho();
}
}
if (finalIter)
{
mesh.data::remove("finalIteration");
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment