/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2015-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 .
Class
Foam::cellCoBlended
Group
grpFvSurfaceInterpolationSchemes
Description
Two-scheme cell-based Courant number based blending differencing scheme.
This scheme is equivalent to the CoBlended scheme except that the Courant
number is evaluated for cells using the same approach as use in the
finite-volume solvers and then interpolated to the faces rather than being
estimated directly at the faces based on the flux. This is a more
consistent method for evaluating the Courant number but suffers from the
need to interpolate which introduces a degree of freedom. However, the
interpolation scheme for "Co" is run-time selected and may be specified in
"interpolationSchemes" and "localMax" might be most appropriate.
Example of the cellCoBlended scheme specification using LUST for Courant
numbers less than 1 and linearUpwind for Courant numbers greater than 10:
\verbatim
divSchemes
{
.
.
div(phi,U) Gauss cellCoBlended 1 LUST grad(U) 10 linearUpwind grad(U);
.
.
}
interpolationSchemes
{
.
.
interpolate(Co) localMax;
.
.
}
\endverbatim
See also
Foam::CoBlended
Foam::localBlended
SourceFiles
cellCoBlended.C
\*---------------------------------------------------------------------------*/
#ifndef cellCoBlended_H
#define cellCoBlended_H
#include "surfaceInterpolationScheme.H"
#include "blendedSchemeBase.H"
#include "surfaceInterpolate.H"
#include "extrapolatedCalculatedFvPatchFields.H"
#include "fvcSurfaceIntegrate.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class cellCoBlended Declaration
\*---------------------------------------------------------------------------*/
template
class cellCoBlended
:
public surfaceInterpolationScheme,
public blendedSchemeBase
{
// Private data
//- Courant number below which scheme1 is used
const scalar Co1_;
//- Scheme 1
tmp> tScheme1_;
//- Courant number above which scheme2 is used
const scalar Co2_;
//- Scheme 2
tmp> tScheme2_;
//- The face-flux used to compute the face Courant number
const surfaceScalarField& faceFlux_;
// Private Member Functions
//- No copy construct
cellCoBlended(const cellCoBlended&) = delete;
//- No copy assignment
void operator=(const cellCoBlended&) = delete;
public:
//- Runtime type information
TypeName("cellCoBlended");
// Constructors
//- Construct from mesh and Istream.
// The name of the flux field is read from the Istream and looked-up
// from the mesh objectRegistry
cellCoBlended
(
const fvMesh& mesh,
Istream& is
)
:
surfaceInterpolationScheme(mesh),
Co1_(readScalar(is)),
tScheme1_
(
surfaceInterpolationScheme::New(mesh, is)
),
Co2_(readScalar(is)),
tScheme2_
(
surfaceInterpolationScheme::New(mesh, is)
),
faceFlux_
(
mesh.lookupObject(word(is))
)
{
if (Co1_ < 0 || Co2_ < 0 || Co1_ >= Co2_)
{
FatalIOErrorInFunction(is)
<< "coefficients = " << Co1_ << " and " << Co2_
<< " should be > 0 and Co2 > Co1"
<< exit(FatalIOError);
}
}
//- Construct from mesh, faceFlux and Istream
cellCoBlended
(
const fvMesh& mesh,
const surfaceScalarField& faceFlux,
Istream& is
)
:
surfaceInterpolationScheme(mesh),
Co1_(readScalar(is)),
tScheme1_
(
surfaceInterpolationScheme::New(mesh, faceFlux, is)
),
Co2_(readScalar(is)),
tScheme2_
(
surfaceInterpolationScheme::New(mesh, faceFlux, is)
),
faceFlux_(faceFlux)
{
if (Co1_ < 0 || Co2_ < 0 || Co1_ >= Co2_)
{
FatalIOErrorInFunction(is)
<< "coefficients = " << Co1_ << " and " << Co2_
<< " should be > 0 and Co2 > Co1"
<< exit(FatalIOError);
}
}
// Member Functions
//- Return the face-based blending factor
virtual tmp blendingFactor
(
const GeometricField& vf
) const
{
const fvMesh& mesh = this->mesh();
tmp tUflux = faceFlux_;
if (faceFlux_.dimensions() == dimMass/dimTime)
{
// Currently assume that the density field
// corresponding to the mass-flux is named "rho"
const volScalarField& rho =
mesh.objectRegistry::template lookupObject
("rho");
tUflux = faceFlux_/fvc::interpolate(rho);
}
else if (faceFlux_.dimensions() != dimVolume/dimTime)
{
FatalErrorInFunction
<< "dimensions of faceFlux are not correct"
<< exit(FatalError);
}
volScalarField Co
(
IOobject
(
"Co",
mesh.time().timeName(),
mesh
),
mesh,
dimensionedScalar(dimless, Zero),
fvPatchFieldBase::extrapolatedCalculatedType()
);
scalarField sumPhi
(
fvc::surfaceSum(mag(tUflux))().primitiveField()
);
Co.primitiveFieldRef() =
(sumPhi/mesh.V().field())*(0.5*mesh.time().deltaTValue());
Co.correctBoundaryConditions();
return tmp
(
new surfaceScalarField
(
vf.name() + "BlendingFactor",
scalar(1)
- clamp
(
(fvc::interpolate(Co) - Co1_)/(Co2_ - Co1_),
zero_one{}
)
)
);
}
//- Return the interpolation weighting factors
tmp
weights
(
const GeometricField& vf
) const
{
surfaceScalarField bf(blendingFactor(vf));
return
bf*tScheme1_().weights(vf)
+ (scalar(1) - bf)*tScheme2_().weights(vf);
}
//- Return the face-interpolate of the given cell field
// with explicit correction
tmp>
interpolate
(
const GeometricField& vf
) const
{
surfaceScalarField bf(blendingFactor(vf));
return
bf*tScheme1_().interpolate(vf)
+ (scalar(1) - bf)*tScheme2_().interpolate(vf);
}
//- Return true if this scheme uses an explicit correction
virtual bool corrected() const
{
return tScheme1_().corrected() || tScheme2_().corrected();
}
//- Return the explicit correction to the face-interpolate
// for the given field
virtual tmp>
correction
(
const GeometricField& vf
) const
{
surfaceScalarField bf(blendingFactor(vf));
if (tScheme1_().corrected())
{
if (tScheme2_().corrected())
{
return
(
bf
* tScheme1_().correction(vf)
+ (scalar(1) - bf)
* tScheme2_().correction(vf)
);
}
else
{
return
(
bf
* tScheme1_().correction(vf)
);
}
}
else if (tScheme2_().corrected())
{
return
(
(scalar(1) - bf)
* tScheme2_().correction(vf)
);
}
else
{
return nullptr;
}
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //