/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2015-2019 OpenCFD Ltd. ------------------------------------------------------------------------------- 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 . \*---------------------------------------------------------------------------*/ #include "GeometricField.H" #include "Time.H" #include "demandDrivenData.H" #include "dictionary.H" #include "localIOdictionary.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 operation " << op \ << abort(FatalError); \ } // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * // template class PatchField, class GeoMesh> void Foam::GeometricField::readFields ( const dictionary& dict ) { Internal::readField(dict, "internalField"); boundaryField_.readField(*this, dict.subDict("boundaryField")); Type refLevel; if (dict.readIfPresent("referenceLevel", refLevel)) { Field::operator+=(refLevel); forAll(boundaryField_, patchi) { boundaryField_[patchi] == boundaryField_[patchi] + refLevel; } } } template class PatchField, class GeoMesh> void Foam::GeometricField::readFields() { const localIOdictionary dict ( IOobject ( this->name(), this->instance(), this->local(), this->db(), IOobject::MUST_READ, IOobject::NO_WRITE, false ), typeName ); this->close(); readFields(dict); } template class PatchField, class GeoMesh> bool Foam::GeometricField::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->template typeHeaderOk> ( true ) ) { 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 PatchField, class GeoMesh> bool Foam::GeometricField::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.template typeHeaderOk> ( true ) ) { DebugInFunction << "Reading old time level for field" << nl << this->info() << endl; field0Ptr_ = new GeometricField ( field0, this->mesh() ); // Ensure the old time field oriented flag is set to the parent's state // Note: required for backwards compatibility in case of restarting from // an old run where the oriented state may not have been set field0Ptr_->oriented() = this->oriented(); field0Ptr_->timeIndex_ = timeIndex_ - 1; if (!field0Ptr_->readOldTimeIfPresent()) { field0Ptr_->oldTime(); } return true; } return false; } // * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * // template class PatchField, class GeoMesh> Foam::GeometricField::GeometricField ( const IOobject& io, const Mesh& mesh, const dimensionSet& ds, const word& patchFieldType ) : Internal(io, mesh, ds, false), timeIndex_(this->time().timeIndex()), field0Ptr_(nullptr), fieldPrevIterPtr_(nullptr), boundaryField_(mesh.boundary(), *this, patchFieldType) { DebugInFunction << "Creating temporary" << nl << this->info() << endl; readIfPresent(); } template class PatchField, class GeoMesh> Foam::GeometricField::GeometricField ( const IOobject& io, const Mesh& mesh, const dimensionSet& ds, const wordList& patchFieldTypes, const wordList& actualPatchTypes ) : Internal(io, mesh, ds, false), timeIndex_(this->time().timeIndex()), field0Ptr_(nullptr), fieldPrevIterPtr_(nullptr), boundaryField_(mesh.boundary(), *this, patchFieldTypes, actualPatchTypes) { DebugInFunction << "Creating temporary" << nl << this->info() << endl; readIfPresent(); } template class PatchField, class GeoMesh> Foam::GeometricField::GeometricField ( const IOobject& io, const Mesh& mesh, const dimensioned& dt, const word& patchFieldType ) : Internal(io, mesh, dt, false), timeIndex_(this->time().timeIndex()), field0Ptr_(nullptr), fieldPrevIterPtr_(nullptr), boundaryField_(mesh.boundary(), *this, patchFieldType) { DebugInFunction << "Creating temporary" << nl << this->info() << endl; boundaryField_ == dt.value(); readIfPresent(); } template class PatchField, class GeoMesh> Foam::GeometricField::GeometricField ( const IOobject& io, const Mesh& mesh, const dimensioned& dt, const wordList& patchFieldTypes, const wordList& actualPatchTypes ) : Internal(io, mesh, dt, false), timeIndex_(this->time().timeIndex()), field0Ptr_(nullptr), fieldPrevIterPtr_(nullptr), boundaryField_(mesh.boundary(), *this, patchFieldTypes, actualPatchTypes) { DebugInFunction << "Creating temporary" << nl << this->info() << endl; boundaryField_ == dt.value(); readIfPresent(); } template class PatchField, class GeoMesh> Foam::GeometricField::GeometricField ( const IOobject& io, const Internal& diField, const PtrList>& ptfl ) : Internal(io, diField), timeIndex_(this->time().timeIndex()), field0Ptr_(nullptr), fieldPrevIterPtr_(nullptr), boundaryField_(this->mesh().boundary(), *this, ptfl) { DebugInFunction << "Copy construct from components" << nl << this->info() << endl; readIfPresent(); } template class PatchField, class GeoMesh> Foam::GeometricField::GeometricField ( const IOobject& io, const Mesh& mesh, const dimensionSet& ds, const Field& iField, const word& patchFieldType ) : Internal(io, mesh, ds, iField), timeIndex_(this->time().timeIndex()), field0Ptr_(nullptr), fieldPrevIterPtr_(nullptr), boundaryField_(mesh.boundary(), *this, patchFieldType) { DebugInFunction << "Copy construct from internal field" << nl << this->info() << endl; readIfPresent(); } template class PatchField, class GeoMesh> Foam::GeometricField::GeometricField ( const IOobject& io, const Mesh& mesh, const dimensionSet& ds, Field&& iField, const word& patchFieldType ) : Internal(io, mesh, ds, std::move(iField)), timeIndex_(this->time().timeIndex()), field0Ptr_(nullptr), fieldPrevIterPtr_(nullptr), boundaryField_(mesh.boundary(), *this, patchFieldType) { DebugInFunction << "Move construct from internal field" << nl << this->info() << endl; readIfPresent(); } template class PatchField, class GeoMesh> Foam::GeometricField::GeometricField ( const IOobject& io, const Mesh& mesh, const dimensionSet& ds, const Field& iField, const PtrList>& ptfl ) : Internal(io, mesh, ds, iField), timeIndex_(this->time().timeIndex()), field0Ptr_(nullptr), fieldPrevIterPtr_(nullptr), boundaryField_(mesh.boundary(), *this, ptfl) { DebugInFunction << "Copy construct from components" << nl << this->info() << endl; readIfPresent(); } template class PatchField, class GeoMesh> Foam::GeometricField::GeometricField ( const IOobject& io, const Mesh& mesh, const bool readOldTime ) : Internal(io, mesh, dimless, false), timeIndex_(this->time().timeIndex()), field0Ptr_(nullptr), fieldPrevIterPtr_(nullptr), 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); } if (readOldTime) { readOldTimeIfPresent(); } DebugInFunction << "Finishing read-construction" << nl << this->info() << endl; } template class PatchField, class GeoMesh> Foam::GeometricField::GeometricField ( const IOobject& io, const Mesh& mesh, const dictionary& dict ) : Internal(io, mesh, dimless, false), timeIndex_(this->time().timeIndex()), field0Ptr_(nullptr), fieldPrevIterPtr_(nullptr), 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); } DebugInFunction << "Finishing dictionary-construct" << nl << this->info() << endl; } template class PatchField, class GeoMesh> Foam::GeometricField::GeometricField ( const GeometricField& gf ) : Internal(gf), timeIndex_(gf.timeIndex()), field0Ptr_(nullptr), fieldPrevIterPtr_(nullptr), boundaryField_(*this, gf.boundaryField_) { DebugInFunction << "Copy construct" << nl << this->info() << endl; if (gf.field0Ptr_) { field0Ptr_ = new GeometricField ( *gf.field0Ptr_ ); } this->writeOpt() = IOobject::NO_WRITE; } template class PatchField, class GeoMesh> Foam::GeometricField::GeometricField ( const tmp>& tgf ) : Internal(tgf.constCast(), tgf.movable()), timeIndex_(tgf().timeIndex()), field0Ptr_(nullptr), fieldPrevIterPtr_(nullptr), boundaryField_(*this, tgf().boundaryField_) { DebugInFunction << "Constructing from tmp" << nl << this->info() << endl; this->writeOpt() = IOobject::NO_WRITE; tgf.clear(); } template class PatchField, class GeoMesh> Foam::GeometricField::GeometricField ( const IOobject& io, const GeometricField& gf ) : Internal(io, gf), timeIndex_(gf.timeIndex()), field0Ptr_(nullptr), fieldPrevIterPtr_(nullptr), boundaryField_(*this, gf.boundaryField_) { DebugInFunction << "Copy construct, resetting IO params" << nl << this->info() << endl; if (!readIfPresent() && gf.field0Ptr_) { field0Ptr_ = new GeometricField ( io.name() + "_0", *gf.field0Ptr_ ); } } template class PatchField, class GeoMesh> Foam::GeometricField::GeometricField ( const IOobject& io, const tmp>& tgf ) : Internal(io, tgf.constCast(), tgf.movable()), timeIndex_(tgf().timeIndex()), field0Ptr_(nullptr), fieldPrevIterPtr_(nullptr), boundaryField_(*this, tgf().boundaryField_) { DebugInFunction << "Constructing from tmp resetting IO params" << nl << this->info() << endl; tgf.clear(); readIfPresent(); } template class PatchField, class GeoMesh> Foam::GeometricField::GeometricField ( const word& newName, const GeometricField& gf ) : Internal(newName, gf), timeIndex_(gf.timeIndex()), field0Ptr_(nullptr), fieldPrevIterPtr_(nullptr), boundaryField_(*this, gf.boundaryField_) { DebugInFunction << "Copy construct, resetting name" << nl << this->info() << endl; if (!readIfPresent() && gf.field0Ptr_) { field0Ptr_ = new GeometricField ( newName + "_0", *gf.field0Ptr_ ); } } template class PatchField, class GeoMesh> Foam::GeometricField::GeometricField ( const word& newName, const tmp>& tgf ) : Internal(newName, tgf.constCast(), tgf.movable()), timeIndex_(tgf().timeIndex()), field0Ptr_(nullptr), fieldPrevIterPtr_(nullptr), boundaryField_(*this, tgf().boundaryField_) { DebugInFunction << "Constructing from tmp resetting name" << nl << this->info() << endl; tgf.clear(); } template class PatchField, class GeoMesh> Foam::GeometricField::GeometricField ( const IOobject& io, const GeometricField& gf, const word& patchFieldType ) : Internal(io, gf), timeIndex_(gf.timeIndex()), field0Ptr_(nullptr), fieldPrevIterPtr_(nullptr), boundaryField_(this->mesh().boundary(), *this, patchFieldType) { DebugInFunction << "Copy construct, resetting IO params" << nl << this->info() << endl; boundaryField_ == gf.boundaryField_; if (!readIfPresent() && gf.field0Ptr_) { field0Ptr_ = new GeometricField ( io.name() + "_0", *gf.field0Ptr_ ); } } template class PatchField, class GeoMesh> Foam::GeometricField::GeometricField ( const IOobject& io, const GeometricField& gf, const wordList& patchFieldTypes, const wordList& actualPatchTypes ) : Internal(io, gf), timeIndex_(gf.timeIndex()), field0Ptr_(nullptr), fieldPrevIterPtr_(nullptr), boundaryField_ ( this->mesh().boundary(), *this, patchFieldTypes, actualPatchTypes ) { DebugInFunction << "Copy construct, resetting IO params and patch types" << nl << this->info() << endl; boundaryField_ == gf.boundaryField_; if (!readIfPresent() && gf.field0Ptr_) { field0Ptr_ = new GeometricField ( io.name() + "_0", *gf.field0Ptr_ ); } } template class PatchField, class GeoMesh> Foam::GeometricField::GeometricField ( const IOobject& io, const GeometricField& gf, const labelList& patchIDs, const word& patchFieldType ) : Internal(io, gf), timeIndex_(gf.timeIndex()), field0Ptr_(nullptr), fieldPrevIterPtr_(nullptr), boundaryField_(*this, gf.boundaryField_, patchIDs, patchFieldType) { DebugInFunction << "Copy construct, resetting IO params and setting patchFieldType " << "for patchIDs" << nl << this->info() << endl; if (!readIfPresent() && gf.field0Ptr_) { field0Ptr_ = new GeometricField ( io.name() + "_0", *gf.field0Ptr_ ); } } template class PatchField, class GeoMesh> Foam::GeometricField::GeometricField ( const IOobject& io, const tmp>& tgf, const wordList& patchFieldTypes, const wordList& actualPatchTypes ) : Internal(io, tgf.constCast(), tgf.movable()), timeIndex_(tgf().timeIndex()), field0Ptr_(nullptr), fieldPrevIterPtr_(nullptr), boundaryField_ ( this->mesh().boundary(), *this, patchFieldTypes, actualPatchTypes ) { DebugInFunction << "Constructing from tmp resetting IO params and patch types" << nl << this->info() << endl; boundaryField_ == tgf().boundaryField_; tgf.clear(); } template class PatchField, class GeoMesh> Foam::tmp> Foam::GeometricField::clone() const { return tmp>::New(*this); } // * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * * // template class PatchField, class GeoMesh> Foam::GeometricField::~GeometricField() { deleteDemandDrivenData(field0Ptr_); deleteDemandDrivenData(fieldPrevIterPtr_); } // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // template class PatchField, class GeoMesh> typename Foam::GeometricField::Internal& Foam::GeometricField::ref ( const bool updateAccessTime ) { if (updateAccessTime) { this->setUpToDate(); storeOldTimes(); } return *this; } template class PatchField, class GeoMesh> typename Foam::GeometricField::Internal::FieldType& Foam::GeometricField::primitiveFieldRef ( const bool updateAccessTime ) { if (updateAccessTime) { this->setUpToDate(); storeOldTimes(); } return *this; } template class PatchField, class GeoMesh> typename Foam::GeometricField::Boundary& Foam::GeometricField::boundaryFieldRef ( const bool updateAccessTime ) { if (updateAccessTime) { this->setUpToDate(); storeOldTimes(); } return boundaryField_; } template class PatchField, class GeoMesh> void Foam::GeometricField::storeOldTimes() const { if ( field0Ptr_ && timeIndex_ != this->time().timeIndex() && !this->name().ends_with("_0") ) { storeOldTime(); timeIndex_ = this->time().timeIndex(); } // Correct time index //timeIndex_ = this->time().timeIndex(); } template class PatchField, class GeoMesh> void Foam::GeometricField::storeOldTime() const { if (field0Ptr_) { field0Ptr_->storeOldTime(); DebugInFunction << "Storing old time field for field" << nl << this->info() << endl; *field0Ptr_ == *this; field0Ptr_->timeIndex_ = timeIndex_; if (field0Ptr_->field0Ptr_) { field0Ptr_->writeOpt() = this->writeOpt(); } } } template class PatchField, class GeoMesh> Foam::label Foam::GeometricField::nOldTimes() const { if (field0Ptr_) { return field0Ptr_->nOldTimes() + 1; } return 0; } template class PatchField, class GeoMesh> const Foam::GeometricField& Foam::GeometricField::oldTime() const { if (!field0Ptr_) { field0Ptr_ = new GeometricField ( IOobject ( this->name() + "_0", this->time().timeName(), this->db(), IOobject::NO_READ, IOobject::NO_WRITE, this->registerObject() ), *this ); if (debug) { InfoInFunction << "created old time field " << field0Ptr_->info() << endl; if (debug&2) { error::printStack(Info); } } } else { storeOldTimes(); } return *field0Ptr_; } template class PatchField, class GeoMesh> Foam::GeometricField& Foam::GeometricField::oldTime() { static_cast&>(*this) .oldTime(); return *field0Ptr_; } template class PatchField, class GeoMesh> void Foam::GeometricField::storePrevIter() const { if (!fieldPrevIterPtr_) { DebugInFunction << "Allocating previous iteration field" << nl << this->info() << endl; fieldPrevIterPtr_ = new GeometricField ( this->name() + "PrevIter", *this ); } else { *fieldPrevIterPtr_ == *this; } } template class PatchField, class GeoMesh> const Foam::GeometricField& Foam::GeometricField::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 PatchField, class GeoMesh> void Foam::GeometricField:: correctBoundaryConditions() { this->setUpToDate(); storeOldTimes(); boundaryField_.evaluate(); } template class PatchField, class GeoMesh> bool Foam::GeometricField::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()); return needRef; } template class PatchField, class GeoMesh> void Foam::GeometricField::relax(const scalar alpha) { DebugInFunction << "Relaxing" << nl << this->info() << " by " << alpha << endl; operator==(prevIter() + alpha*(*this - prevIter())); } template class PatchField, class GeoMesh> void Foam::GeometricField::relax() { word name = this->name(); if ( this->mesh().data::template lookupOrDefault ( "finalIteration", false ) ) { name += "Final"; } if (this->mesh().relaxField(name)) { relax(this->mesh().fieldRelaxationFactor(name)); } } template class PatchField, class GeoMesh> Foam::word Foam::GeometricField::select ( bool final ) const { if (final) { return this->name() + "Final"; } return this->name(); } template class PatchField, class GeoMesh> void Foam::GeometricField::writeMinMax ( Ostream& os ) const { MinMax range = Foam::minMax(*this).value(); os << "min/max(" << this->name() << ") = " << range.min() << ", " << range.max() << endl; } template class PatchField, class GeoMesh> bool Foam::GeometricField:: writeData(Ostream& os) const { os << *this; return os.good(); } // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // template class PatchField, class GeoMesh> Foam::tmp> Foam::GeometricField::T() const { auto tresult = tmp>::New ( IOobject ( this->name() + ".T()", this->instance(), this->db() ), this->mesh(), this->dimensions() ); Foam::T(tresult.ref().primitiveFieldRef(), primitiveField()); Foam::T(tresult.ref().boundaryFieldRef(), boundaryField()); return tresult; } template class PatchField, class GeoMesh> Foam::tmp < Foam::GeometricField < typename Foam::GeometricField::cmptType, PatchField, GeoMesh > > Foam::GeometricField::component ( const direction d ) const { auto tresult = tmp>::New ( IOobject ( this->name() + ".component(" + Foam::name(d) + ')', this->instance(), this->db() ), this->mesh(), this->dimensions() ); Foam::component(tresult.ref().primitiveFieldRef(), primitiveField(), d); Foam::component(tresult.ref().boundaryFieldRef(), boundaryField(), d); return tresult; } template class PatchField, class GeoMesh> void Foam::GeometricField::replace ( const direction d, const GeometricField < typename GeometricField::cmptType, PatchField, GeoMesh >& gcf ) { primitiveFieldRef().replace(d, gcf.primitiveField()); boundaryFieldRef().replace(d, gcf.boundaryField()); } template class PatchField, class GeoMesh> void Foam::GeometricField::replace ( const direction d, const dimensioned& ds ) { primitiveFieldRef().replace(d, ds.value()); boundaryFieldRef().replace(d, ds.value()); } template class PatchField, class GeoMesh> void Foam::GeometricField::min ( const dimensioned& dt ) { Foam::min(primitiveFieldRef(), primitiveField(), dt.value()); Foam::min(boundaryFieldRef(), boundaryField(), dt.value()); } template class PatchField, class GeoMesh> void Foam::GeometricField::max ( const dimensioned& dt ) { Foam::max(primitiveFieldRef(), primitiveField(), dt.value()); Foam::max(boundaryFieldRef(), boundaryField(), dt.value()); } template class PatchField, class GeoMesh> void Foam::GeometricField::clip ( const dimensioned>& range ) { Foam::clip(primitiveFieldRef(), primitiveField(), range.value()); Foam::clip(boundaryFieldRef(), boundaryField(), range.value()); } template class PatchField, class GeoMesh> void Foam::GeometricField::clip ( const dimensioned& minVal, const dimensioned& maxVal ) { MinMax range(minVal.value(), maxVal.value()); Foam::clip(primitiveFieldRef(), primitiveField(), range); Foam::clip(boundaryFieldRef(), boundaryField(), range); } template class PatchField, class GeoMesh> void Foam::GeometricField::maxMin ( const dimensioned& minVal, const dimensioned& maxVal ) { this->clip(minVal, maxVal); } template class PatchField, class GeoMesh> void Foam::GeometricField::negate() { primitiveFieldRef().negate(); boundaryFieldRef().negate(); } // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // template class PatchField, class GeoMesh> void Foam::GeometricField::operator= ( const GeometricField& gf ) { if (this == &gf) { return; // Self-assignment is a no-op } checkField(*this, gf, "="); // Only assign field contents not ID ref() = gf(); boundaryFieldRef() = gf.boundaryField(); } template class PatchField, class GeoMesh> void Foam::GeometricField::operator= ( const tmp>& tgf ) { const auto& gf = tgf(); if (this == &gf) { return; // Self-assignment is a no-op } checkField(*this, gf, "="); // Only assign field contents not ID this->dimensions() = gf.dimensions(); this->oriented() = gf.oriented(); if (tgf.movable()) { // Transfer storage from the tmp primitiveFieldRef().transfer(tgf.constCast().primitiveFieldRef()); } else { primitiveFieldRef() = gf.primitiveField(); } boundaryFieldRef() = gf.boundaryField(); tgf.clear(); } template class PatchField, class GeoMesh> void Foam::GeometricField::operator= ( const dimensioned& dt ) { ref() = dt; boundaryFieldRef() = dt.value(); } template class PatchField, class GeoMesh> void Foam::GeometricField::operator== ( const tmp>& tgf ) { const auto& gf = tgf(); checkField(*this, gf, "=="); // Only assign field contents not ID ref() = gf(); boundaryFieldRef() == gf.boundaryField(); tgf.clear(); } template class PatchField, class GeoMesh> void Foam::GeometricField::operator== ( const dimensioned& dt ) { ref() = dt; boundaryFieldRef() == dt.value(); } #define COMPUTED_ASSIGNMENT(TYPE, op) \ \ template class PatchField, class GeoMesh> \ void Foam::GeometricField::operator op \ ( \ const GeometricField& gf \ ) \ { \ checkField(*this, gf, #op); \ \ ref() op gf(); \ boundaryFieldRef() op gf.boundaryField(); \ } \ \ template class PatchField, class GeoMesh> \ void Foam::GeometricField::operator op \ ( \ const tmp>& tgf \ ) \ { \ operator op(tgf()); \ tgf.clear(); \ } \ \ template class PatchField, class GeoMesh> \ void Foam::GeometricField::operator op \ ( \ const dimensioned& dt \ ) \ { \ ref() 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 PatchField, class GeoMesh> Foam::Ostream& Foam::operator<< ( Ostream& os, const GeometricField& gf ) { gf().writeData(os, "internalField"); os << nl; gf.boundaryField().writeEntry("boundaryField", os); os.check(FUNCTION_NAME); return os; } template class PatchField, class GeoMesh> Foam::Ostream& Foam::operator<< ( Ostream& os, const tmp>& tgf ) { os << tgf(); tgf.clear(); return os; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // #undef checkField // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // #include "GeometricFieldNew.C" #include "GeometricBoundaryField.C" #include "GeometricFieldFunctions.C" // ************************************************************************* //