Commit fe4752d2 authored by Henry Weller's avatar Henry Weller Committed by Andrew Heather
Browse files

ENH: ddtScheme::fvcDdtPhiCoeff: Improved formulation providing better stability/accuracy balance

Resolves problem with pressure "staggering" when running with a very Courant
number.
parent 4272820f
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -148,7 +148,7 @@ int main(int argc, char *argv[])
volScalarField rAB(1.0/BEqn.A());
surfaceScalarField rABf("rABf", fvc::interpolate(rAB));
phiB = fvc::flux(B) + rABf*fvc::ddtCorr(B, phiB);
phiB = fvc::flux(B);
while (bpiso.correctNonOrthogonal())
{
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -649,14 +649,14 @@ CoEulerDdtScheme<Type>::fvcDdtUfCorr
const GeometricField<Type, fvsPatchField, surfaceMesh>& Uf
)
{
const surfaceScalarField rDeltaT(fvc::interpolate(CorDeltaT()));
if
(
U.dimensions() == dimVelocity
&& Uf.dimensions() == dimDensity*dimVelocity
)
{
const surfaceScalarField rDeltaT(fvc::interpolate(CorDeltaT()));
GeometricField<Type, fvPatchField, volMesh> rhoU0
(
rho.oldTime()*U.oldTime()
......@@ -676,7 +676,8 @@ CoEulerDdtScheme<Type>::fvcDdtUfCorr
mesh().time().timeName(),
mesh()
),
this->fvcDdtPhiCoeff(rhoU0, phiUf0, phiCorr)*rDeltaT*phiCorr
this->fvcDdtPhiCoeff(rhoU0, phiUf0, phiCorr, rho.oldTime())
*rDeltaT*phiCorr
)
);
}
......@@ -686,7 +687,32 @@ CoEulerDdtScheme<Type>::fvcDdtUfCorr
&& Uf.dimensions() == dimDensity*dimVelocity
)
{
return fvcDdtUfCorr(U, Uf);
fluxFieldType phiUf0(mesh().Sf() & Uf.oldTime());
fluxFieldType phiCorr
(
phiUf0 - fvc::dotInterpolate(mesh().Sf(), U.oldTime())
);
return tmp<fluxFieldType>
(
new fluxFieldType
(
IOobject
(
"ddtCorr("
+ rho.name() + ',' + U.name() + ',' + Uf.name() + ')',
mesh().time().timeName(),
mesh()
),
this->fvcDdtPhiCoeff
(
U.oldTime(),
phiUf0,
phiCorr,
rho.oldTime()
)*rDeltaT*phiCorr
)
);
}
else
{
......@@ -708,14 +734,14 @@ CoEulerDdtScheme<Type>::fvcDdtPhiCorr
const fluxFieldType& phi
)
{
dimensionedScalar rDeltaT = 1.0/mesh().time().deltaT();
if
(
U.dimensions() == dimVelocity
&& phi.dimensions() == rho.dimensions()*dimVelocity*dimArea
)
{
dimensionedScalar rDeltaT = 1.0/mesh().time().deltaT();
GeometricField<Type, fvPatchField, volMesh> rhoU0
(
rho.oldTime()*U.oldTime()
......@@ -737,8 +763,13 @@ CoEulerDdtScheme<Type>::fvcDdtPhiCorr
mesh().time().timeName(),
mesh()
),
this->fvcDdtPhiCoeff(rhoU0, phi.oldTime(), phiCorr)
*rDeltaT*phiCorr
this->fvcDdtPhiCoeff
(
rhoU0,
phi.oldTime(),
phiCorr,
rho.oldTime()
)*rDeltaT*phiCorr
)
);
}
......@@ -748,7 +779,31 @@ CoEulerDdtScheme<Type>::fvcDdtPhiCorr
&& phi.dimensions() == rho.dimensions()*dimVelocity*dimArea
)
{
return fvcDdtPhiCorr(U, phi);
fluxFieldType phiCorr
(
phi.oldTime() - fvc::dotInterpolate(mesh().Sf(), U.oldTime())
);
return tmp<fluxFieldType>
(
new fluxFieldType
(
IOobject
(
"ddtCorr("
+ rho.name() + ',' + U.name() + ',' + phi.name() + ')',
mesh().time().timeName(),
mesh()
),
this->fvcDdtPhiCoeff
(
U.oldTime(),
phi.oldTime(),
phiCorr,
rho.oldTime()
)*rDeltaT*phiCorr
)
);
}
else
{
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -1358,7 +1358,12 @@ CrankNicolsonDdtScheme<Type>::fvcDdtUfCorr
mesh().time().timeName(),
mesh()
),
this->fvcDdtPhiCoeff(rhoU0, mesh().Sf() & Uf.oldTime())
this->fvcDdtPhiCoeff
(
rhoU0,
mesh().Sf() & Uf.oldTime(),
rho.oldTime()
)
*(
mesh().Sf()
& (
......@@ -1377,7 +1382,64 @@ CrankNicolsonDdtScheme<Type>::fvcDdtUfCorr
&& Uf.dimensions() == rho.dimensions()*dimVelocity
)
{
return fvcDdtUfCorr(U, Uf);
DDt0Field<GeometricField<Type, fvPatchField, volMesh>>& ddt0 =
ddt0_<GeometricField<Type, fvPatchField, volMesh>>
(
"ddtCorrDdt0(" + U.name() + ')',
U.dimensions()
);
DDt0Field<GeometricField<Type, fvsPatchField, surfaceMesh>>& dUfdt0 =
ddt0_<GeometricField<Type, fvsPatchField, surfaceMesh>>
(
"ddtCorrDdt0(" + Uf.name() + ')',
Uf.dimensions()
);
dimensionedScalar rDtCoef = rDtCoef_(ddt0);
if (evaluate(ddt0))
{
ddt0 =
rDtCoef0_(ddt0)*(U.oldTime() - U.oldTime().oldTime())
- offCentre_(ddt0());
}
if (evaluate(dUfdt0))
{
dUfdt0 =
rDtCoef0_(dUfdt0)*(Uf.oldTime() - Uf.oldTime().oldTime())
- offCentre_(dUfdt0());
}
return tmp<fluxFieldType>
(
new fluxFieldType
(
IOobject
(
"ddtCorr(" + U.name() + ',' + Uf.name() + ')',
mesh().time().timeName(),
mesh()
),
this->fvcDdtPhiCoeff
(
U.oldTime(),
mesh().Sf() & Uf.oldTime(),
rho.oldTime()
)
*(
mesh().Sf()
& (
(rDtCoef*Uf.oldTime() + offCentre_(dUfdt0()))
- fvc::interpolate
(
rDtCoef*U.oldTime() + offCentre_(ddt0())
)
)
)
)
);
}
else
{
......@@ -1453,7 +1515,7 @@ CrankNicolsonDdtScheme<Type>::fvcDdtPhiCorr
mesh().time().timeName(),
mesh()
),
this->fvcDdtPhiCoeff(rhoU0, phi.oldTime())
this->fvcDdtPhiCoeff(rhoU0, phi.oldTime(), rho.oldTime())
*(
(rDtCoef*phi.oldTime() + offCentre_(dphidt0()))
- fvc::dotInterpolate
......@@ -1473,7 +1535,57 @@ CrankNicolsonDdtScheme<Type>::fvcDdtPhiCorr
&& phi.dimensions() == rho.dimensions()*dimVelocity*dimArea
)
{
return fvcDdtPhiCorr(U, phi);
DDt0Field<GeometricField<Type, fvPatchField, volMesh>>& ddt0 =
ddt0_<GeometricField<Type, fvPatchField, volMesh>>
(
"ddtCorrDdt0(" + U.name() + ')',
U.dimensions()
);
DDt0Field<fluxFieldType>& dphidt0 =
ddt0_<fluxFieldType>
(
"ddtCorrDdt0(" + phi.name() + ')',
phi.dimensions()
);
dimensionedScalar rDtCoef = rDtCoef_(ddt0);
if (evaluate(ddt0))
{
ddt0 =
rDtCoef0_(ddt0)*(U.oldTime() - U.oldTime().oldTime())
- offCentre_(ddt0());
}
if (evaluate(dphidt0))
{
dphidt0 =
rDtCoef0_(dphidt0)*(phi.oldTime() - phi.oldTime().oldTime())
- offCentre_(dphidt0());
}
return tmp<fluxFieldType>
(
new fluxFieldType
(
IOobject
(
"ddtCorr(" + U.name() + ',' + phi.name() + ')',
mesh().time().timeName(),
mesh()
),
this->fvcDdtPhiCoeff(U.oldTime(), phi.oldTime(), rho.oldTime())
*(
(rDtCoef*phi.oldTime() + offCentre_(dphidt0()))
- fvc::dotInterpolate
(
mesh().Sf(),
rDtCoef*U.oldTime() + offCentre_(ddt0())
)
)
)
);
}
else
{
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -557,14 +557,14 @@ EulerDdtScheme<Type>::fvcDdtUfCorr
const GeometricField<Type, fvsPatchField, surfaceMesh>& Uf
)
{
dimensionedScalar rDeltaT = 1.0/mesh().time().deltaT();
if
(
U.dimensions() == dimVelocity
&& Uf.dimensions() == rho.dimensions()*dimVelocity
)
{
dimensionedScalar rDeltaT = 1.0/mesh().time().deltaT();
GeometricField<Type, fvPatchField, volMesh> rhoU0
(
rho.oldTime()*U.oldTime()
......@@ -584,7 +584,8 @@ EulerDdtScheme<Type>::fvcDdtUfCorr
mesh().time().timeName(),
mesh()
),
this->fvcDdtPhiCoeff(rhoU0, phiUf0, phiCorr)*rDeltaT*phiCorr
this->fvcDdtPhiCoeff(rhoU0, phiUf0, phiCorr, rho.oldTime())
*rDeltaT*phiCorr
)
);
}
......@@ -594,7 +595,32 @@ EulerDdtScheme<Type>::fvcDdtUfCorr
&& Uf.dimensions() == rho.dimensions()*dimVelocity
)
{
return fvcDdtUfCorr(U, Uf);
fluxFieldType phiUf0(mesh().Sf() & Uf.oldTime());
fluxFieldType phiCorr
(
phiUf0 - fvc::dotInterpolate(mesh().Sf(), U.oldTime())
);
return tmp<fluxFieldType>
(
new fluxFieldType
(
IOobject
(
"ddtCorr("
+ rho.name() + ',' + U.name() + ',' + Uf.name() + ')',
mesh().time().timeName(),
mesh()
),
this->fvcDdtPhiCoeff
(
U.oldTime(),
phiUf0,
phiCorr,
rho.oldTime()
)*rDeltaT*phiCorr
)
);
}
else
{
......@@ -616,14 +642,14 @@ EulerDdtScheme<Type>::fvcDdtPhiCorr
const fluxFieldType& phi
)
{
dimensionedScalar rDeltaT = 1.0/mesh().time().deltaT();
if
(
U.dimensions() == dimVelocity
&& phi.dimensions() == rho.dimensions()*dimVelocity*dimArea
)
{
dimensionedScalar rDeltaT = 1.0/mesh().time().deltaT();
GeometricField<Type, fvPatchField, volMesh> rhoU0
(
rho.oldTime()*U.oldTime()
......@@ -645,8 +671,13 @@ EulerDdtScheme<Type>::fvcDdtPhiCorr
mesh().time().timeName(),
mesh()
),
this->fvcDdtPhiCoeff(rhoU0, phi.oldTime(), phiCorr)
*rDeltaT*phiCorr
this->fvcDdtPhiCoeff
(
rhoU0,
phi.oldTime(),
phiCorr,
rho.oldTime()
)*rDeltaT*phiCorr
)
);
}
......@@ -656,7 +687,31 @@ EulerDdtScheme<Type>::fvcDdtPhiCorr
&& phi.dimensions() == rho.dimensions()*dimVelocity*dimArea
)
{
return fvcDdtPhiCorr(U, phi);
fluxFieldType phiCorr
(
phi.oldTime() - fvc::dotInterpolate(mesh().Sf(), U.oldTime())
);
return tmp<fluxFieldType>
(
new fluxFieldType
(
IOobject
(
"ddtCorr("
+ rho.name() + ',' + U.name() + ',' + phi.name() + ')',
mesh().time().timeName(),
mesh()
),
this->fvcDdtPhiCoeff
(
U.oldTime(),
phi.oldTime(),
phiCorr,
rho.oldTime()
)*rDeltaT*phiCorr
)
);
}
else
{
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -654,14 +654,14 @@ SLTSDdtScheme<Type>::fvcDdtUfCorr
const GeometricField<Type, fvsPatchField, surfaceMesh>& Uf
)
{
const surfaceScalarField rDeltaT(fvc::interpolate(SLrDeltaT()));
if
(
U.dimensions() == dimVelocity
&& Uf.dimensions() == dimDensity*dimVelocity
)
{
const surfaceScalarField rDeltaT(fvc::interpolate(SLrDeltaT()));
GeometricField<Type, fvPatchField, volMesh> rhoU0
(
rho.oldTime()*U.oldTime()
......@@ -681,7 +681,8 @@ SLTSDdtScheme<Type>::fvcDdtUfCorr
mesh().time().timeName(),
mesh()
),
this->fvcDdtPhiCoeff(rhoU0, phiUf0, phiCorr)*rDeltaT*phiCorr
this->fvcDdtPhiCoeff(rhoU0, phiUf0, phiCorr, rho.oldTime())
*rDeltaT*phiCorr
)
);
}
......@@ -691,7 +692,32 @@ SLTSDdtScheme<Type>::fvcDdtUfCorr
&& Uf.dimensions() == dimDensity*dimVelocity
)
{
return fvcDdtUfCorr(U, Uf);
fluxFieldType phiUf0(mesh().Sf() & Uf.oldTime());
fluxFieldType phiCorr
(
phiUf0 - fvc::dotInterpolate(mesh().Sf(), U.oldTime())
);
return tmp<fluxFieldType>
(
new fluxFieldType
(
IOobject
(
"ddtCorr("
+ rho.name() + ',' + U.name() + ',' + Uf.name() + ')',
mesh().time().timeName(),
mesh()
),
this->fvcDdtPhiCoeff
(
U.oldTime(),
phiUf0,
phiCorr,
rho.oldTime()
)*rDeltaT*phiCorr
)
);
}
else
{
......@@ -713,14 +739,14 @@ SLTSDdtScheme<Type>::fvcDdtPhiCorr
const fluxFieldType& phi
)
{
dimensionedScalar rDeltaT = 1.0/mesh().time().deltaT();
if
(
U.dimensions() == dimVelocity
&& phi.dimensions() == rho.dimensions()*dimVelocity*dimArea
)
{
dimensionedScalar rDeltaT = 1.0/mesh().time().deltaT();
GeometricField<Type, fvPatchField, volMesh> rhoU0
(
rho.oldTime()*U.oldTime()
......@@ -742,8 +768,13 @@ SLTSDdtScheme<Type>::fvcDdtPhiCorr
mesh().time().timeName(),
mesh()
),
this->fvcDdtPhiCoeff(rhoU0, phi.oldTime(), phiCorr)
*rDeltaT*phiCorr
this->fvcDdtPhiCoeff
(
rhoU0,
phi.oldTime(),
phiCorr,
rho.oldTime()
)*rDeltaT*phiCorr
)
);
}
......@@ -753,7 +784,31 @@ SLTSDdtScheme<Type>::fvcDdtPhiCorr
&& phi.dimensions() == rho.dimensions()*dimVelocity*dimArea
)
{
return fvcDdtPhiCorr(U, phi);
fluxFieldType phiCorr
(
phi.oldTime() - fvc::dotInterpolate(mesh().Sf(), U.oldTime())
);
return tmp<fluxFieldType>
(
new fluxFieldType
(
IOobject
(
"ddtCorr("
+ rho.name() + ',' + U.name() + ',' + phi.name() + ')',
mesh().time().timeName(),
mesh()
),
this->fvcDdtPhiCoeff
(
U.oldTime(),
phi.oldTime(),
phiCorr,
rho.oldTime()
)*rDeltaT*phiCorr
)
);
}
else
{
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
......@@ -753,21 +753,21 @@ backwardDdtScheme<Type>::fvcDdtUfCorr
const GeometricField<Type, fvsPatchField, surfaceMesh>& Uf
)
{
dimensionedScalar rDeltaT = 1.0/mesh().time().deltaT();
<