Given that the type of the dimensioned internal field is encapsulated in the GeometricField class the name need not include "Field"; the type name is "Internal" so volScalarField::DimensionedInternalField -> volScalarField::Internal In addition to the ".dimensionedInternalField()" access function the simpler "()" de-reference operator is also provided to greatly simplify FV equation source term expressions which need not evaluate boundary conditions. To demonstrate this kEpsilon.C has been updated to use dimensioned internal field expressions in the k and epsilon equation source terms.
1284 lines
33 KiB
C
1284 lines
33 KiB
C
/*---------------------------------------------------------------------------*\
|
|
========= |
|
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
\\ / O peration |
|
|
\\ / A nd | Copyright (C) 2011-2016 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 "GeometricField.H"
|
|
#include "Time.H"
|
|
#include "demandDrivenData.H"
|
|
#include "dictionary.H"
|
|
#include "data.H"
|
|
|
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
|
|
#define checkField(gf1, gf2, op) \
|
|
if ((gf1).mesh() != (gf2).mesh()) \
|
|
{ \
|
|
FatalErrorInFunction \
|
|
<< "different mesh for fields " \
|
|
<< (gf1).name() << " and " << (gf2).name() \
|
|
<< " during operatrion " << op \
|
|
<< abort(FatalError); \
|
|
}
|
|
|
|
|
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::readFields
|
|
(
|
|
const dictionary& dict
|
|
)
|
|
{
|
|
DimensionedField<Type, GeoMesh>::readField(dict, "internalField");
|
|
|
|
boundaryField_.readField(*this, dict.subDict("boundaryField"));
|
|
|
|
if (dict.found("referenceLevel"))
|
|
{
|
|
Type fieldAverage(pTraits<Type>(dict.lookup("referenceLevel")));
|
|
|
|
Field<Type>::operator+=(fieldAverage);
|
|
|
|
forAll(boundaryField_, patchi)
|
|
{
|
|
boundaryField_[patchi] == boundaryField_[patchi] + fieldAverage;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::readFields()
|
|
{
|
|
const IOdictionary dict
|
|
(
|
|
IOobject
|
|
(
|
|
this->name(),
|
|
this->time().timeName(),
|
|
this->db(),
|
|
IOobject::NO_READ,
|
|
IOobject::NO_WRITE,
|
|
false
|
|
),
|
|
this->readStream(typeName)
|
|
);
|
|
|
|
this->close();
|
|
|
|
readFields(dict);
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
bool Foam::GeometricField<Type, PatchField, GeoMesh>::readIfPresent()
|
|
{
|
|
if
|
|
(
|
|
this->readOpt() == IOobject::MUST_READ
|
|
|| this->readOpt() == IOobject::MUST_READ_IF_MODIFIED
|
|
)
|
|
{
|
|
WarningInFunction
|
|
<< "read option IOobject::MUST_READ or MUST_READ_IF_MODIFIED"
|
|
<< " suggests that a read constructor for field " << this->name()
|
|
<< " would be more appropriate." << endl;
|
|
}
|
|
else if (this->readOpt() == IOobject::READ_IF_PRESENT && this->headerOk())
|
|
{
|
|
readFields();
|
|
|
|
// Check compatibility between field and mesh
|
|
if (this->size() != GeoMesh::size(this->mesh()))
|
|
{
|
|
FatalIOErrorInFunction(this->readStream(typeName))
|
|
<< " number of field elements = " << this->size()
|
|
<< " number of mesh elements = "
|
|
<< GeoMesh::size(this->mesh())
|
|
<< exit(FatalIOError);
|
|
}
|
|
|
|
readOldTimeIfPresent();
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
bool Foam::GeometricField<Type, PatchField, GeoMesh>::readOldTimeIfPresent()
|
|
{
|
|
// Read the old time field if present
|
|
IOobject field0
|
|
(
|
|
this->name() + "_0",
|
|
this->time().timeName(),
|
|
this->db(),
|
|
IOobject::READ_IF_PRESENT,
|
|
IOobject::AUTO_WRITE,
|
|
this->registerObject()
|
|
);
|
|
|
|
if (field0.headerOk())
|
|
{
|
|
if (debug)
|
|
{
|
|
InfoInFunction << "Reading old time level for field"
|
|
<< endl << this->info() << endl;
|
|
}
|
|
|
|
field0Ptr_ = new GeometricField<Type, PatchField, GeoMesh>
|
|
(
|
|
field0,
|
|
this->mesh()
|
|
);
|
|
|
|
field0Ptr_->timeIndex_ = timeIndex_ - 1;
|
|
|
|
if (!field0Ptr_->readOldTimeIfPresent())
|
|
{
|
|
field0Ptr_->oldTime();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
|
|
(
|
|
const IOobject& io,
|
|
const Mesh& mesh,
|
|
const dimensionSet& ds,
|
|
const word& patchFieldType
|
|
)
|
|
:
|
|
DimensionedField<Type, GeoMesh>(io, mesh, ds, false),
|
|
timeIndex_(this->time().timeIndex()),
|
|
field0Ptr_(NULL),
|
|
fieldPrevIterPtr_(NULL),
|
|
boundaryField_(mesh.boundary(), *this, patchFieldType)
|
|
{
|
|
if (debug)
|
|
{
|
|
InfoInFunction << "Creating temporary" << endl << this->info() << endl;
|
|
}
|
|
|
|
readIfPresent();
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
|
|
(
|
|
const IOobject& io,
|
|
const Mesh& mesh,
|
|
const dimensionSet& ds,
|
|
const wordList& patchFieldTypes,
|
|
const wordList& actualPatchTypes
|
|
)
|
|
:
|
|
DimensionedField<Type, GeoMesh>(io, mesh, ds, false),
|
|
timeIndex_(this->time().timeIndex()),
|
|
field0Ptr_(NULL),
|
|
fieldPrevIterPtr_(NULL),
|
|
boundaryField_(mesh.boundary(), *this, patchFieldTypes, actualPatchTypes)
|
|
{
|
|
if (debug)
|
|
{
|
|
InfoInFunction << "Creating temporary" << endl << this->info() << endl;
|
|
}
|
|
|
|
readIfPresent();
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
|
|
(
|
|
const IOobject& io,
|
|
const Mesh& mesh,
|
|
const dimensioned<Type>& dt,
|
|
const word& patchFieldType
|
|
)
|
|
:
|
|
DimensionedField<Type, GeoMesh>(io, mesh, dt, false),
|
|
timeIndex_(this->time().timeIndex()),
|
|
field0Ptr_(NULL),
|
|
fieldPrevIterPtr_(NULL),
|
|
boundaryField_(mesh.boundary(), *this, patchFieldType)
|
|
{
|
|
if (debug)
|
|
{
|
|
InfoInFunction << "Creating temporary" << endl << this->info() << endl;
|
|
}
|
|
|
|
boundaryField_ == dt.value();
|
|
|
|
readIfPresent();
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
|
|
(
|
|
const IOobject& io,
|
|
const Mesh& mesh,
|
|
const dimensioned<Type>& dt,
|
|
const wordList& patchFieldTypes,
|
|
const wordList& actualPatchTypes
|
|
)
|
|
:
|
|
DimensionedField<Type, GeoMesh>(io, mesh, dt, false),
|
|
timeIndex_(this->time().timeIndex()),
|
|
field0Ptr_(NULL),
|
|
fieldPrevIterPtr_(NULL),
|
|
boundaryField_(mesh.boundary(), *this, patchFieldTypes, actualPatchTypes)
|
|
{
|
|
if (debug)
|
|
{
|
|
InfoInFunction << "Creating temporary" << endl << this->info() << endl;
|
|
}
|
|
|
|
boundaryField_ == dt.value();
|
|
|
|
readIfPresent();
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
|
|
(
|
|
const IOobject& io,
|
|
const Mesh& mesh,
|
|
const dimensionSet& ds,
|
|
const Field<Type>& iField,
|
|
const PtrList<PatchField<Type>>& ptfl
|
|
)
|
|
:
|
|
DimensionedField<Type, GeoMesh>(io, mesh, ds, iField),
|
|
timeIndex_(this->time().timeIndex()),
|
|
field0Ptr_(NULL),
|
|
fieldPrevIterPtr_(NULL),
|
|
boundaryField_(mesh.boundary(), *this, ptfl)
|
|
{
|
|
if (debug)
|
|
{
|
|
InfoInFunction
|
|
<< "Constructing from components" << endl << this->info() << endl;
|
|
}
|
|
|
|
readIfPresent();
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
|
|
(
|
|
const IOobject& io,
|
|
const Mesh& mesh
|
|
)
|
|
:
|
|
DimensionedField<Type, GeoMesh>(io, mesh, dimless, false),
|
|
timeIndex_(this->time().timeIndex()),
|
|
field0Ptr_(NULL),
|
|
fieldPrevIterPtr_(NULL),
|
|
boundaryField_(mesh.boundary())
|
|
{
|
|
readFields();
|
|
|
|
// Check compatibility between field and mesh
|
|
|
|
if (this->size() != GeoMesh::size(this->mesh()))
|
|
{
|
|
FatalIOErrorInFunction(this->readStream(typeName))
|
|
<< " number of field elements = " << this->size()
|
|
<< " number of mesh elements = " << GeoMesh::size(this->mesh())
|
|
<< exit(FatalIOError);
|
|
}
|
|
|
|
readOldTimeIfPresent();
|
|
|
|
if (debug)
|
|
{
|
|
InfoInFunction
|
|
<< "Finishing read-construction of" << endl << this->info() << endl;
|
|
}
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
|
|
(
|
|
const IOobject& io,
|
|
const Mesh& mesh,
|
|
const dictionary& dict
|
|
)
|
|
:
|
|
DimensionedField<Type, GeoMesh>(io, mesh, dimless, false),
|
|
timeIndex_(this->time().timeIndex()),
|
|
field0Ptr_(NULL),
|
|
fieldPrevIterPtr_(NULL),
|
|
boundaryField_(mesh.boundary())
|
|
{
|
|
readFields(dict);
|
|
|
|
// Check compatibility between field and mesh
|
|
|
|
if (this->size() != GeoMesh::size(this->mesh()))
|
|
{
|
|
FatalErrorInFunction
|
|
<< " number of field elements = " << this->size()
|
|
<< " number of mesh elements = " << GeoMesh::size(this->mesh())
|
|
<< exit(FatalIOError);
|
|
}
|
|
|
|
readOldTimeIfPresent();
|
|
|
|
if (debug)
|
|
{
|
|
InfoInFunction
|
|
<< "Finishing dictionary-construct of "
|
|
<< endl << this->info() << endl;
|
|
}
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
|
|
(
|
|
const GeometricField<Type, PatchField, GeoMesh>& gf
|
|
)
|
|
:
|
|
DimensionedField<Type, GeoMesh>(gf),
|
|
timeIndex_(gf.timeIndex()),
|
|
field0Ptr_(NULL),
|
|
fieldPrevIterPtr_(NULL),
|
|
boundaryField_(*this, gf.boundaryField_)
|
|
{
|
|
if (debug)
|
|
{
|
|
InfoInFunction
|
|
<< "Constructing as copy" << endl << this->info() << endl;
|
|
}
|
|
|
|
if (gf.field0Ptr_)
|
|
{
|
|
field0Ptr_ = new GeometricField<Type, PatchField, GeoMesh>
|
|
(
|
|
*gf.field0Ptr_
|
|
);
|
|
}
|
|
|
|
this->writeOpt() = IOobject::NO_WRITE;
|
|
}
|
|
|
|
|
|
#ifndef NoConstructFromTmp
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
|
|
(
|
|
const tmp<GeometricField<Type, PatchField, GeoMesh>>& tgf
|
|
)
|
|
:
|
|
DimensionedField<Type, GeoMesh>
|
|
(
|
|
const_cast<GeometricField<Type, PatchField, GeoMesh>&>(tgf()),
|
|
tgf.isTmp()
|
|
),
|
|
timeIndex_(tgf().timeIndex()),
|
|
field0Ptr_(NULL),
|
|
fieldPrevIterPtr_(NULL),
|
|
boundaryField_(*this, tgf().boundaryField_)
|
|
{
|
|
if (debug)
|
|
{
|
|
InfoInFunction
|
|
<< "Constructing from tmp" << endl << this->info() << endl;
|
|
}
|
|
|
|
this->writeOpt() = IOobject::NO_WRITE;
|
|
|
|
tgf.clear();
|
|
}
|
|
#endif
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
|
|
(
|
|
const IOobject& io,
|
|
const GeometricField<Type, PatchField, GeoMesh>& gf
|
|
)
|
|
:
|
|
DimensionedField<Type, GeoMesh>(io, gf),
|
|
timeIndex_(gf.timeIndex()),
|
|
field0Ptr_(NULL),
|
|
fieldPrevIterPtr_(NULL),
|
|
boundaryField_(*this, gf.boundaryField_)
|
|
{
|
|
if (debug)
|
|
{
|
|
InfoInFunction
|
|
<< "Constructing as copy resetting IO params"
|
|
<< endl << this->info() << endl;
|
|
}
|
|
|
|
if (!readIfPresent() && gf.field0Ptr_)
|
|
{
|
|
field0Ptr_ = new GeometricField<Type, PatchField, GeoMesh>
|
|
(
|
|
io.name() + "_0",
|
|
*gf.field0Ptr_
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
#ifndef NoConstructFromTmp
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
|
|
(
|
|
const IOobject& io,
|
|
const tmp<GeometricField<Type, PatchField, GeoMesh>>& tgf
|
|
)
|
|
:
|
|
DimensionedField<Type, GeoMesh>
|
|
(
|
|
io,
|
|
const_cast<GeometricField<Type, PatchField, GeoMesh>&>(tgf()),
|
|
tgf.isTmp()
|
|
),
|
|
timeIndex_(tgf().timeIndex()),
|
|
field0Ptr_(NULL),
|
|
fieldPrevIterPtr_(NULL),
|
|
boundaryField_(*this, tgf().boundaryField_)
|
|
{
|
|
if (debug)
|
|
{
|
|
InfoInFunction
|
|
<< "Constructing from tmp resetting IO params"
|
|
<< endl << this->info() << endl;
|
|
}
|
|
|
|
tgf.clear();
|
|
|
|
readIfPresent();
|
|
}
|
|
#endif
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
|
|
(
|
|
const word& newName,
|
|
const GeometricField<Type, PatchField, GeoMesh>& gf
|
|
)
|
|
:
|
|
DimensionedField<Type, GeoMesh>(newName, gf),
|
|
timeIndex_(gf.timeIndex()),
|
|
field0Ptr_(NULL),
|
|
fieldPrevIterPtr_(NULL),
|
|
boundaryField_(*this, gf.boundaryField_)
|
|
{
|
|
if (debug)
|
|
{
|
|
InfoInFunction
|
|
<< "Constructing as copy resetting name"
|
|
<< endl << this->info() << endl;
|
|
}
|
|
|
|
if (!readIfPresent() && gf.field0Ptr_)
|
|
{
|
|
field0Ptr_ = new GeometricField<Type, PatchField, GeoMesh>
|
|
(
|
|
newName + "_0",
|
|
*gf.field0Ptr_
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
#ifndef NoConstructFromTmp
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
|
|
(
|
|
const word& newName,
|
|
const tmp<GeometricField<Type, PatchField, GeoMesh>>& tgf
|
|
)
|
|
:
|
|
DimensionedField<Type, GeoMesh>
|
|
(
|
|
newName,
|
|
const_cast<GeometricField<Type, PatchField, GeoMesh>&>(tgf()),
|
|
tgf.isTmp()
|
|
),
|
|
timeIndex_(tgf().timeIndex()),
|
|
field0Ptr_(NULL),
|
|
fieldPrevIterPtr_(NULL),
|
|
boundaryField_(*this, tgf().boundaryField_)
|
|
{
|
|
if (debug)
|
|
{
|
|
InfoInFunction
|
|
<< "Constructing from tmp resetting name"
|
|
<< endl << this->info() << endl;
|
|
}
|
|
|
|
tgf.clear();
|
|
}
|
|
#endif
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
|
|
(
|
|
const IOobject& io,
|
|
const GeometricField<Type, PatchField, GeoMesh>& gf,
|
|
const word& patchFieldType
|
|
)
|
|
:
|
|
DimensionedField<Type, GeoMesh>(io, gf),
|
|
timeIndex_(gf.timeIndex()),
|
|
field0Ptr_(NULL),
|
|
fieldPrevIterPtr_(NULL),
|
|
boundaryField_(this->mesh().boundary(), *this, patchFieldType)
|
|
{
|
|
if (debug)
|
|
{
|
|
InfoInFunction
|
|
<< "Constructing as copy resetting IO params"
|
|
<< endl << this->info() << endl;
|
|
}
|
|
|
|
boundaryField_ == gf.boundaryField_;
|
|
|
|
if (!readIfPresent() && gf.field0Ptr_)
|
|
{
|
|
field0Ptr_ = new GeometricField<Type, PatchField, GeoMesh>
|
|
(
|
|
io.name() + "_0",
|
|
*gf.field0Ptr_
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
|
|
(
|
|
const IOobject& io,
|
|
const GeometricField<Type, PatchField, GeoMesh>& gf,
|
|
const wordList& patchFieldTypes,
|
|
const wordList& actualPatchTypes
|
|
|
|
)
|
|
:
|
|
DimensionedField<Type, GeoMesh>(io, gf),
|
|
timeIndex_(gf.timeIndex()),
|
|
field0Ptr_(NULL),
|
|
fieldPrevIterPtr_(NULL),
|
|
boundaryField_
|
|
(
|
|
this->mesh().boundary(),
|
|
*this,
|
|
patchFieldTypes,
|
|
actualPatchTypes
|
|
)
|
|
{
|
|
if (debug)
|
|
{
|
|
InfoInFunction
|
|
<< "Constructing as copy resetting IO params and patch types"
|
|
<< endl << this->info() << endl;
|
|
}
|
|
|
|
boundaryField_ == gf.boundaryField_;
|
|
|
|
if (!readIfPresent() && gf.field0Ptr_)
|
|
{
|
|
field0Ptr_ = new GeometricField<Type, PatchField, GeoMesh>
|
|
(
|
|
io.name() + "_0",
|
|
*gf.field0Ptr_
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
#ifndef NoConstructFromTmp
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
|
|
(
|
|
const IOobject& io,
|
|
const tmp<GeometricField<Type, PatchField, GeoMesh>>& tgf,
|
|
const wordList& patchFieldTypes,
|
|
const wordList& actualPatchTypes
|
|
)
|
|
:
|
|
DimensionedField<Type, GeoMesh>
|
|
(
|
|
io,
|
|
const_cast<GeometricField<Type, PatchField, GeoMesh>&>(tgf()),
|
|
tgf.isTmp()
|
|
),
|
|
timeIndex_(tgf().timeIndex()),
|
|
field0Ptr_(NULL),
|
|
fieldPrevIterPtr_(NULL),
|
|
boundaryField_
|
|
(
|
|
this->mesh().boundary(),
|
|
*this,
|
|
patchFieldTypes,
|
|
actualPatchTypes
|
|
)
|
|
{
|
|
if (debug)
|
|
{
|
|
InfoInFunction
|
|
<< "Constructing from tmp resetting IO params and patch types"
|
|
<< endl << this->info() << endl;
|
|
}
|
|
|
|
boundaryField_ == tgf().boundaryField_;
|
|
|
|
tgf.clear();
|
|
}
|
|
#endif
|
|
|
|
|
|
// * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * * //
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::~GeometricField()
|
|
{
|
|
deleteDemandDrivenData(field0Ptr_);
|
|
deleteDemandDrivenData(fieldPrevIterPtr_);
|
|
}
|
|
|
|
|
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
typename
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::Internal&
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::dimensionedInternalFieldRef()
|
|
{
|
|
this->setUpToDate();
|
|
storeOldTimes();
|
|
return *this;
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
typename
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::Internal::FieldType&
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::internalField()
|
|
{
|
|
this->setUpToDate();
|
|
storeOldTimes();
|
|
return *this;
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
typename
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricBoundaryField&
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::boundaryFieldRef()
|
|
{
|
|
this->setUpToDate();
|
|
storeOldTimes();
|
|
return boundaryField_;
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::storeOldTimes() const
|
|
{
|
|
if
|
|
(
|
|
field0Ptr_
|
|
&& timeIndex_ != this->time().timeIndex()
|
|
&& !(
|
|
this->name().size() > 2
|
|
&& this->name()(this->name().size()-2, 2) == "_0"
|
|
)
|
|
)
|
|
{
|
|
storeOldTime();
|
|
}
|
|
|
|
// Correct time index
|
|
timeIndex_ = this->time().timeIndex();
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::storeOldTime() const
|
|
{
|
|
if (field0Ptr_)
|
|
{
|
|
field0Ptr_->storeOldTime();
|
|
|
|
if (debug)
|
|
{
|
|
InfoInFunction
|
|
<< "Storing old time field for field" << endl
|
|
<< this->info() << endl;
|
|
}
|
|
|
|
*field0Ptr_ == *this;
|
|
field0Ptr_->timeIndex_ = timeIndex_;
|
|
|
|
if (field0Ptr_->field0Ptr_)
|
|
{
|
|
field0Ptr_->writeOpt() = this->writeOpt();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::label Foam::GeometricField<Type, PatchField, GeoMesh>::nOldTimes() const
|
|
{
|
|
if (field0Ptr_)
|
|
{
|
|
return field0Ptr_->nOldTimes() + 1;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
const Foam::GeometricField<Type, PatchField, GeoMesh>&
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::oldTime() const
|
|
{
|
|
if (!field0Ptr_)
|
|
{
|
|
field0Ptr_ = new GeometricField<Type, PatchField, GeoMesh>
|
|
(
|
|
IOobject
|
|
(
|
|
this->name() + "_0",
|
|
this->time().timeName(),
|
|
this->db(),
|
|
IOobject::NO_READ,
|
|
IOobject::NO_WRITE,
|
|
this->registerObject()
|
|
),
|
|
*this
|
|
);
|
|
}
|
|
else
|
|
{
|
|
storeOldTimes();
|
|
}
|
|
|
|
return *field0Ptr_;
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>&
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::oldTime()
|
|
{
|
|
static_cast<const GeometricField<Type, PatchField, GeoMesh>&>(*this)
|
|
.oldTime();
|
|
|
|
return *field0Ptr_;
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::storePrevIter() const
|
|
{
|
|
if (!fieldPrevIterPtr_)
|
|
{
|
|
if (debug)
|
|
{
|
|
InfoInFunction
|
|
<< "Allocating previous iteration field" << endl
|
|
<< this->info() << endl;
|
|
}
|
|
|
|
fieldPrevIterPtr_ = new GeometricField<Type, PatchField, GeoMesh>
|
|
(
|
|
this->name() + "PrevIter",
|
|
*this
|
|
);
|
|
}
|
|
else
|
|
{
|
|
*fieldPrevIterPtr_ == *this;
|
|
}
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
const Foam::GeometricField<Type, PatchField, GeoMesh>&
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::prevIter() const
|
|
{
|
|
if (!fieldPrevIterPtr_)
|
|
{
|
|
FatalErrorInFunction
|
|
<< "previous iteration field" << endl << this->info() << endl
|
|
<< " not stored."
|
|
<< " Use field.storePrevIter() at start of iteration."
|
|
<< abort(FatalError);
|
|
}
|
|
|
|
return *fieldPrevIterPtr_;
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::
|
|
correctBoundaryConditions()
|
|
{
|
|
this->setUpToDate();
|
|
storeOldTimes();
|
|
boundaryField_.evaluate();
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
bool Foam::GeometricField<Type, PatchField, GeoMesh>::needReference() const
|
|
{
|
|
// Search all boundary conditions, if any are
|
|
// fixed-value or mixed (Robin) do not set reference level for solution.
|
|
|
|
bool needRef = true;
|
|
|
|
forAll(boundaryField_, patchi)
|
|
{
|
|
if (boundaryField_[patchi].fixesValue())
|
|
{
|
|
needRef = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
reduce(needRef, andOp<bool>());
|
|
|
|
return needRef;
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::relax(const scalar alpha)
|
|
{
|
|
if (debug)
|
|
{
|
|
InfoInFunction
|
|
<< "Relaxing" << endl << this->info() << " by " << alpha << endl;
|
|
}
|
|
|
|
operator==(prevIter() + alpha*(*this - prevIter()));
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::relax()
|
|
{
|
|
word name = this->name();
|
|
|
|
if
|
|
(
|
|
this->mesh().data::template lookupOrDefault<bool>
|
|
(
|
|
"finalIteration",
|
|
false
|
|
)
|
|
)
|
|
{
|
|
name += "Final";
|
|
}
|
|
|
|
if (this->mesh().relaxField(name))
|
|
{
|
|
relax(this->mesh().fieldRelaxationFactor(name));
|
|
}
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::word Foam::GeometricField<Type, PatchField, GeoMesh>::select
|
|
(
|
|
bool final
|
|
) const
|
|
{
|
|
if (final)
|
|
{
|
|
return this->name() + "Final";
|
|
}
|
|
else
|
|
{
|
|
return this->name();
|
|
}
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::writeMinMax
|
|
(
|
|
Ostream& os
|
|
) const
|
|
{
|
|
os << "min/max(" << this->name() << ") = "
|
|
<< Foam::min(*this).value() << ", "
|
|
<< Foam::max(*this).value()
|
|
<< endl;
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
bool Foam::GeometricField<Type, PatchField, GeoMesh>::
|
|
writeData(Ostream& os) const
|
|
{
|
|
os << *this;
|
|
return os.good();
|
|
}
|
|
|
|
|
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::tmp<Foam::GeometricField<Type, PatchField, GeoMesh>>
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::T() const
|
|
{
|
|
tmp<GeometricField<Type, PatchField, GeoMesh>> result
|
|
(
|
|
new GeometricField<Type, PatchField, GeoMesh>
|
|
(
|
|
IOobject
|
|
(
|
|
this->name() + ".T()",
|
|
this->instance(),
|
|
this->db()
|
|
),
|
|
this->mesh(),
|
|
this->dimensions()
|
|
)
|
|
);
|
|
|
|
Foam::T(result.ref().internalField(), internalField());
|
|
Foam::T(result.ref().boundaryFieldRef(), boundaryField());
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::tmp
|
|
<
|
|
Foam::GeometricField
|
|
<
|
|
typename Foam::GeometricField<Type, PatchField, GeoMesh>::cmptType,
|
|
PatchField,
|
|
GeoMesh
|
|
>
|
|
>
|
|
Foam::GeometricField<Type, PatchField, GeoMesh>::component
|
|
(
|
|
const direction d
|
|
) const
|
|
{
|
|
tmp<GeometricField<cmptType, PatchField, GeoMesh>> Component
|
|
(
|
|
new GeometricField<cmptType, PatchField, GeoMesh>
|
|
(
|
|
IOobject
|
|
(
|
|
this->name() + ".component(" + Foam::name(d) + ')',
|
|
this->instance(),
|
|
this->db()
|
|
),
|
|
this->mesh(),
|
|
this->dimensions()
|
|
)
|
|
);
|
|
|
|
Foam::component(Component.ref().internalField(), internalField(), d);
|
|
Foam::component(Component.ref().boundaryFieldRef(), boundaryField(), d);
|
|
|
|
return Component;
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::replace
|
|
(
|
|
const direction d,
|
|
const GeometricField
|
|
<
|
|
typename GeometricField<Type, PatchField, GeoMesh>::cmptType,
|
|
PatchField,
|
|
GeoMesh
|
|
>& gcf
|
|
)
|
|
{
|
|
internalField().replace(d, gcf.internalField());
|
|
boundaryFieldRef().replace(d, gcf.boundaryField());
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::replace
|
|
(
|
|
const direction d,
|
|
const dimensioned<cmptType>& ds
|
|
)
|
|
{
|
|
internalField().replace(d, ds.value());
|
|
boundaryFieldRef().replace(d, ds.value());
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::max
|
|
(
|
|
const dimensioned<Type>& dt
|
|
)
|
|
{
|
|
Foam::max(internalField(), internalField(), dt.value());
|
|
Foam::max(boundaryFieldRef(), boundaryField(), dt.value());
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::min
|
|
(
|
|
const dimensioned<Type>& dt
|
|
)
|
|
{
|
|
Foam::min(internalField(), internalField(), dt.value());
|
|
Foam::min(boundaryFieldRef(), boundaryField(), dt.value());
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::negate()
|
|
{
|
|
internalField().negate();
|
|
boundaryFieldRef().negate();
|
|
}
|
|
|
|
|
|
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::operator=
|
|
(
|
|
const GeometricField<Type, PatchField, GeoMesh>& gf
|
|
)
|
|
{
|
|
if (this == &gf)
|
|
{
|
|
FatalErrorInFunction
|
|
<< "attempted assignment to self"
|
|
<< abort(FatalError);
|
|
}
|
|
|
|
checkField(*this, gf, "=");
|
|
|
|
// Only assign field contents not ID
|
|
|
|
dimensionedInternalFieldRef() = gf.dimensionedInternalField();
|
|
boundaryFieldRef() = gf.boundaryField();
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::operator=
|
|
(
|
|
const tmp<GeometricField<Type, PatchField, GeoMesh>>& tgf
|
|
)
|
|
{
|
|
if (this == &(tgf()))
|
|
{
|
|
FatalErrorInFunction
|
|
<< "attempted assignment to self"
|
|
<< abort(FatalError);
|
|
}
|
|
|
|
const GeometricField<Type, PatchField, GeoMesh>& gf = tgf();
|
|
|
|
checkField(*this, gf, "=");
|
|
|
|
// Only assign field contents not ID
|
|
|
|
this->dimensions() = gf.dimensions();
|
|
|
|
// Transfer the storage from the tmp
|
|
internalField().transfer
|
|
(
|
|
const_cast<Field<Type>&>(gf.internalField())
|
|
);
|
|
|
|
boundaryFieldRef() = gf.boundaryField();
|
|
|
|
tgf.clear();
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::operator=
|
|
(
|
|
const dimensioned<Type>& dt
|
|
)
|
|
{
|
|
dimensionedInternalFieldRef() = dt;
|
|
boundaryFieldRef() = dt.value();
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::operator==
|
|
(
|
|
const tmp<GeometricField<Type, PatchField, GeoMesh>>& tgf
|
|
)
|
|
{
|
|
const GeometricField<Type, PatchField, GeoMesh>& gf = tgf();
|
|
|
|
checkField(*this, gf, "==");
|
|
|
|
// Only assign field contents not ID
|
|
|
|
dimensionedInternalFieldRef() = gf.dimensionedInternalField();
|
|
boundaryFieldRef() == gf.boundaryField();
|
|
|
|
tgf.clear();
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::operator==
|
|
(
|
|
const dimensioned<Type>& dt
|
|
)
|
|
{
|
|
dimensionedInternalFieldRef() = dt;
|
|
boundaryFieldRef() == dt.value();
|
|
}
|
|
|
|
|
|
#define COMPUTED_ASSIGNMENT(TYPE, op) \
|
|
\
|
|
template<class Type, template<class> class PatchField, class GeoMesh> \
|
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::operator op \
|
|
( \
|
|
const GeometricField<TYPE, PatchField, GeoMesh>& gf \
|
|
) \
|
|
{ \
|
|
checkField(*this, gf, #op); \
|
|
\
|
|
dimensionedInternalFieldRef() op gf.dimensionedInternalField(); \
|
|
boundaryFieldRef() op gf.boundaryField(); \
|
|
} \
|
|
\
|
|
template<class Type, template<class> class PatchField, class GeoMesh> \
|
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::operator op \
|
|
( \
|
|
const tmp<GeometricField<TYPE, PatchField, GeoMesh>>& tgf \
|
|
) \
|
|
{ \
|
|
operator op(tgf()); \
|
|
tgf.clear(); \
|
|
} \
|
|
\
|
|
template<class Type, template<class> class PatchField, class GeoMesh> \
|
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::operator op \
|
|
( \
|
|
const dimensioned<TYPE>& dt \
|
|
) \
|
|
{ \
|
|
dimensionedInternalFieldRef() op dt; \
|
|
boundaryFieldRef() op dt.value(); \
|
|
}
|
|
|
|
COMPUTED_ASSIGNMENT(Type, +=)
|
|
COMPUTED_ASSIGNMENT(Type, -=)
|
|
COMPUTED_ASSIGNMENT(scalar, *=)
|
|
COMPUTED_ASSIGNMENT(scalar, /=)
|
|
|
|
#undef COMPUTED_ASSIGNMENT
|
|
|
|
|
|
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::Ostream& Foam::operator<<
|
|
(
|
|
Ostream& os,
|
|
const GeometricField<Type, PatchField, GeoMesh>& gf
|
|
)
|
|
{
|
|
gf.dimensionedInternalField().writeData(os, "internalField");
|
|
os << nl;
|
|
gf.boundaryField().writeEntry("boundaryField", os);
|
|
|
|
// Check state of IOstream
|
|
os.check
|
|
(
|
|
"Ostream& operator<<(Ostream&, "
|
|
"const GeometricField<Type, PatchField, GeoMesh>&)"
|
|
);
|
|
|
|
return (os);
|
|
}
|
|
|
|
|
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
|
Foam::Ostream& Foam::operator<<
|
|
(
|
|
Ostream& os,
|
|
const tmp<GeometricField<Type, PatchField, GeoMesh>>& tgf
|
|
)
|
|
{
|
|
os << tgf();
|
|
tgf.clear();
|
|
return os;
|
|
}
|
|
|
|
|
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
|
|
#undef checkField
|
|
|
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
|
|
#include "GeometricBoundaryField.C"
|
|
#include "GeometricFieldFunctions.C"
|
|
|
|
// ************************************************************************* //
|