Files
openfoam/src/finiteVolume/fvMesh/fvMeshGeometry.C

460 lines
9.7 KiB
C

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2012 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 "fvMesh.H"
#include "Time.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "slicedVolFields.H"
#include "slicedSurfaceFields.H"
#include "SubField.H"
#include "cyclicFvPatchFields.H"
#include "cyclicAMIFvPatchFields.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void fvMesh::makeSf() const
{
if (debug)
{
Info<< "void fvMesh::makeSf() : "
<< "assembling face areas"
<< endl;
}
// It is an error to attempt to recalculate
// if the pointer is already set
if (SfPtr_)
{
FatalErrorIn("fvMesh::makeSf()")
<< "face areas already exist"
<< abort(FatalError);
}
SfPtr_ = new slicedSurfaceVectorField
(
IOobject
(
"S",
pointsInstance(),
meshSubDir,
*this,
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
*this,
dimArea,
faceAreas()
);
}
void fvMesh::makeMagSf() const
{
if (debug)
{
Info<< "void fvMesh::makeMagSf() : "
<< "assembling mag face areas"
<< endl;
}
// It is an error to attempt to recalculate
// if the pointer is already set
if (magSfPtr_)
{
FatalErrorIn("void fvMesh::makeMagSf()")
<< "mag face areas already exist"
<< abort(FatalError);
}
// Note: Added stabilisation for faces with exactly zero area.
// These should be caught on mesh checking but at least this stops
// the code from producing Nans.
magSfPtr_ = new surfaceScalarField
(
IOobject
(
"magSf",
pointsInstance(),
meshSubDir,
*this,
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
mag(Sf()) + dimensionedScalar("vs", dimArea, VSMALL)
);
}
void fvMesh::makeC() const
{
if (debug)
{
Info<< "void fvMesh::makeC() : "
<< "assembling cell centres"
<< endl;
}
// It is an error to attempt to recalculate
// if the pointer is already set
if (CPtr_)
{
FatalErrorIn("fvMesh::makeC()")
<< "cell centres already exist"
<< abort(FatalError);
}
// Construct as slices. Only preserve processor (not e.g. cyclic)
CPtr_ = new slicedVolVectorField
(
IOobject
(
"C",
pointsInstance(),
meshSubDir,
*this,
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
*this,
dimLength,
cellCentres(),
faceCentres(),
true, //preserveCouples
true //preserveProcOnly
);
}
void fvMesh::makeCf() const
{
if (debug)
{
Info<< "void fvMesh::makeCf() : "
<< "assembling face centres"
<< endl;
}
// It is an error to attempt to recalculate
// if the pointer is already set
if (CfPtr_)
{
FatalErrorIn("fvMesh::makeCf()")
<< "face centres already exist"
<< abort(FatalError);
}
CfPtr_ = new slicedSurfaceVectorField
(
IOobject
(
"Cf",
pointsInstance(),
meshSubDir,
*this,
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
*this,
dimLength,
faceCentres()
);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const volScalarField::DimensionedInternalField& fvMesh::V() const
{
if (!VPtr_)
{
VPtr_ = new slicedVolScalarField::DimensionedInternalField
(
IOobject
(
"V",
time().timeName(),
*this,
IOobject::NO_READ,
IOobject::NO_WRITE
),
*this,
dimVolume,
cellVolumes()
);
}
return *static_cast<slicedVolScalarField::DimensionedInternalField*>(VPtr_);
}
const volScalarField::DimensionedInternalField& fvMesh::V0() const
{
if (!V0Ptr_)
{
FatalErrorIn("fvMesh::V0() const")
<< "V0 is not available"
<< abort(FatalError);
}
return *V0Ptr_;
}
volScalarField::DimensionedInternalField& fvMesh::setV0()
{
if (!V0Ptr_)
{
FatalErrorIn("fvMesh::setV0()")
<< "V0 is not available"
<< abort(FatalError);
}
return *V0Ptr_;
}
const volScalarField::DimensionedInternalField& fvMesh::V00() const
{
if (!V00Ptr_)
{
V00Ptr_ = new DimensionedField<scalar, volMesh>
(
IOobject
(
"V00",
time().timeName(),
*this,
IOobject::NO_READ,
IOobject::NO_WRITE
),
V0()
);
// If V00 is used then V0 should be stored for restart
V0Ptr_->writeOpt() = IOobject::AUTO_WRITE;
}
return *V00Ptr_;
}
tmp<volScalarField::DimensionedInternalField> fvMesh::Vsc() const
{
if (moving() && time().subCycling())
{
const TimeState& ts = time();
const TimeState& ts0 = time().prevTimeState();
scalar tFrac =
(
ts.value() - (ts0.value() - ts0.deltaTValue())
)/ts0.deltaTValue();
if (tFrac < (1 - SMALL))
{
return V0() + tFrac*(V() - V0());
}
else
{
return V();
}
}
else
{
return V();
}
}
tmp<volScalarField::DimensionedInternalField> fvMesh::Vsc0() const
{
if (moving() && time().subCycling())
{
const TimeState& ts = time();
const TimeState& ts0 = time().prevTimeState();
scalar t0Frac =
(
(ts.value() - ts.deltaTValue())
- (ts0.value() - ts0.deltaTValue())
)/ts0.deltaTValue();
if (t0Frac > SMALL)
{
return V0() + t0Frac*(V() - V0());
}
else
{
return V0();
}
}
else
{
return V0();
}
}
const surfaceVectorField& fvMesh::Sf() const
{
if (!SfPtr_)
{
makeSf();
}
return *SfPtr_;
}
const surfaceScalarField& fvMesh::magSf() const
{
if (!magSfPtr_)
{
makeMagSf();
}
return *magSfPtr_;
}
const volVectorField& fvMesh::C() const
{
if (!CPtr_)
{
makeC();
}
return *CPtr_;
}
const surfaceVectorField& fvMesh::Cf() const
{
if (!CfPtr_)
{
makeCf();
}
return *CfPtr_;
}
tmp<surfaceVectorField> fvMesh::delta() const
{
if (debug)
{
Info<< "void fvMesh::delta() : "
<< "calculating face deltas"
<< endl;
}
tmp<surfaceVectorField> tdelta
(
new surfaceVectorField
(
IOobject
(
"delta",
pointsInstance(),
meshSubDir,
*this,
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
*this,
dimLength
)
);
surfaceVectorField& delta = tdelta();
const volVectorField& C = this->C();
const labelUList& owner = this->owner();
const labelUList& neighbour = this->neighbour();
forAll(owner, facei)
{
delta[facei] = C[neighbour[facei]] - C[owner[facei]];
}
forAll(delta.boundaryField(), patchi)
{
delta.boundaryField()[patchi] = boundary()[patchi].delta();
}
return tdelta;
}
const surfaceScalarField& fvMesh::phi() const
{
if (!phiPtr_)
{
FatalErrorIn("fvMesh::phi()")
<< "mesh flux field does not exist, is the mesh actually moving?"
<< exit(FatalError);
}
// Set zero current time
// mesh motion fluxes if the time has been incremented
if (phiPtr_->timeIndex() != time().timeIndex())
{
(*phiPtr_) = dimensionedScalar("0", dimVolume/dimTime, 0.0);
}
return *phiPtr_;
}
surfaceScalarField& fvMesh::setPhi()
{
if (!phiPtr_)
{
FatalErrorIn("fvMesh::setPhi()")
<< "mesh flux field does not exist, is the mesh actually moving?"
<< exit(FatalError);
}
return *phiPtr_;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //