diff --git a/applications/test/nullObject/Test-nullObject.C b/applications/test/nullObject/Test-nullObject.C index 9b43405f45..1ce9ed46f8 100644 --- a/applications/test/nullObject/Test-nullObject.C +++ b/applications/test/nullObject/Test-nullObject.C @@ -40,10 +40,34 @@ int main() } + // Test const pointer and const reference to the nullObject + + const SimpleClass* constPtrToNull(NullObjectConstPtr()); + const SimpleClass& constRefToNull(NullObjectRef()); + + if (isNull(constPtrToNull)) + { + Info<< "Pass: constPtrToNull is null" << endl; + } + else + { + Info<< "FAIL: constPtrToNull is not null" << endl; + } + + if (isNull(constRefToNull)) + { + Info<< "Pass: constRefToNull is null" << endl; + } + else + { + Info<< "FAIL: constRefToNull is not null" << endl; + } + + // Test pointer and reference to the nullObject - const SimpleClass* ptrToNull(NullObjectPtr()); - const SimpleClass& refToNull(*ptrToNull); + SimpleClass* ptrToNull(NullObjectPtr()); + SimpleClass& refToNull(*ptrToNull); if (isNull(ptrToNull)) { diff --git a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.C b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.C index 036475264e..4612a986a5 100644 --- a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.C +++ b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.C @@ -1069,21 +1069,29 @@ void Foam::GeometricField::storeOldTime() const { if (field0Ptr_) { - field0Ptr_->storeOldTime(); - - if (debug) + if (notNull(field0Ptr_)) { - InfoInFunction - << "Storing old time field for field" << endl - << this->info() << endl; + 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(); + } } - - *field0Ptr_ == *this; - field0Ptr_->timeIndex_ = timeIndex_; - - if (field0Ptr_->field0Ptr_) + else { - field0Ptr_->writeOpt() = this->writeOpt(); + // Reinstate old-time field + oldTime(); } } } @@ -1094,7 +1102,14 @@ Foam::label Foam::GeometricField::nOldTimes() const { if (field0Ptr_) { - return field0Ptr_->nOldTimes() + 1; + if (isNull(field0Ptr_)) + { + return 1; + } + else + { + return field0Ptr_->nOldTimes() + 1; + } } else { @@ -1107,8 +1122,12 @@ template class PatchField, class GeoMesh> const Foam::GeometricField& Foam::GeometricField::oldTime() const { - if (!field0Ptr_) + if (!field0Ptr_ || isNull(field0Ptr_)) { + // Set field0Ptr_ null to ensure the old-time field constructor + // does not construct the old-old-time field + field0Ptr_ = nullptr; + field0Ptr_ = new GeometricField ( IOobject @@ -1218,11 +1237,46 @@ Foam::GeometricField::prevIter() const template class PatchField, class GeoMesh> void Foam::GeometricField::clearOldTimes() { - deleteDemandDrivenData(field0Ptr_); + if (field0Ptr_ && notNull(field0Ptr_)) + { + deleteDemandDrivenData(field0Ptr_); + } + deleteDemandDrivenData(fieldPrevIterPtr_); } +template class PatchField, class GeoMesh> +void Foam::GeometricField::nullOldestTime() +{ + // Check that the field is not an old-time field + if (!isOldTime()) + { + // Search for the oldest old-time field and set to nullObject + nullOldestTimeFound(); + } +} + + +template class PatchField, class GeoMesh> +void Foam::GeometricField::nullOldestTimeFound() +{ + if (field0Ptr_ && notNull(field0Ptr_)) + { + if (field0Ptr_->field0Ptr_) + { + field0Ptr_->nullOldestTimeFound(); + } + else + { + deleteDemandDrivenData(field0Ptr_); + field0Ptr_ = + NullObjectPtr>(); + } + } +} + + template class PatchField, class GeoMesh> void Foam::GeometricField:: correctBoundaryConditions() diff --git a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.H b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.H index a2c00276a4..fe9a73c322 100644 --- a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.H +++ b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.H @@ -130,6 +130,12 @@ private: //- Read the field - create the field dictionary on-the-fly void readFields(); + //- Store the old-time field + void storeOldTime() const; + + //- Find oldest time and set to nullObject + void nullOldestTimeFound(); + public: @@ -407,9 +413,6 @@ public: //- Store the old-time fields void storeOldTimes() const; - //- Store the old-time field - void storeOldTime() const; - //- Return the number of old time fields stored label nOldTimes() const; @@ -439,6 +442,14 @@ public: //- Delete old time and previous iteration fields void clearOldTimes(); + //- Set oldest time field pointer to nullObjectPtr + // to remove the oldest time field while maintaining a tag + // so that it is reinstated on the next call to oldTime(). + // + // This is used to temporarily remove the oldest-time field + // prior to mesh topology change. + void nullOldestTime(); + //- Correct boundary field void correctBoundaryConditions(); diff --git a/src/OpenFOAM/fields/GeometricFields/GeometricField/MapGeometricFields.H b/src/OpenFOAM/fields/GeometricFields/GeometricField/MapGeometricFields.H index c85ce7c469..83c1fd2a5f 100644 --- a/src/OpenFOAM/fields/GeometricFields/GeometricField/MapGeometricFields.H +++ b/src/OpenFOAM/fields/GeometricFields/GeometricField/MapGeometricFields.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org - \\ / A nd | Copyright (C) 2011-2021 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -78,31 +78,6 @@ void MapGeometricFields lookupClass>() ); - // It is necessary to enforce that all old-time fields are stored - // before the mapping is performed. Otherwise, if the - // old-time-level field is mapped before the field itself, sizes - // will not match. - - for - ( - typename HashTable*>:: - iterator fieldIter = fields.begin(); - fieldIter != fields.end(); - ++fieldIter - ) - { - GeometricField& field = - const_cast&> - (*fieldIter()); - - // Note: check can be removed once pointFields are actually stored on - // the pointMesh instead of now on the polyMesh! - if (&field.mesh() == &mapper.mesh()) - { - field.storeOldTimes(); - } - } - for ( typename HashTable*>:: diff --git a/src/OpenFOAM/primitives/nullObject/nullObject.H b/src/OpenFOAM/primitives/nullObject/nullObject.H index 195b644acf..ea959a5425 100644 --- a/src/OpenFOAM/primitives/nullObject/nullObject.H +++ b/src/OpenFOAM/primitives/nullObject/nullObject.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org - \\ / A nd | Copyright (C) 2014-2019 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2014-2022 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -68,13 +68,17 @@ public: extern const NullObject* nullObjectPtr; -//- Return reference to the nullObject of type T +//- Return const reference to the nullObject of type T template inline const T& NullObjectRef(); +//- Return const pointer to the nullObject of type T +template +inline const T* NullObjectConstPtr(); + //- Return pointer to the nullObject of type T template -inline const T* NullObjectPtr(); +inline T* NullObjectPtr(); //- Return reference to the nullObject of type T template @@ -99,6 +103,15 @@ template inline bool notNull(const T* t); +//- Return true if t is a pointer to the nullObject of type T +template +inline bool isNull(T* t); + +//- Return true if t is not a pointer to the nullObject of type T +template +inline bool notNull(T* t); + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // } // End namespace Foam diff --git a/src/OpenFOAM/primitives/nullObject/nullObjectI.H b/src/OpenFOAM/primitives/nullObject/nullObjectI.H index df54a7fe4a..919ab6793f 100644 --- a/src/OpenFOAM/primitives/nullObject/nullObjectI.H +++ b/src/OpenFOAM/primitives/nullObject/nullObjectI.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org - \\ / A nd | Copyright (C) 2014-2019 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2014-2022 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -36,11 +36,17 @@ inline T&& Foam::NullObjectMove() } template -inline const T* Foam::NullObjectPtr() +inline const T* Foam::NullObjectConstPtr() { return reinterpret_cast(nullObjectPtr); } +template +inline T* Foam::NullObjectPtr() +{ + return const_cast(reinterpret_cast(nullObjectPtr)); +} + template inline bool Foam::isNull(const T& t) @@ -68,4 +74,17 @@ inline bool Foam::notNull(const T* t) } +template +inline bool Foam::isNull(T* t) +{ + return t == NullObjectPtr(); +} + +template +inline bool Foam::notNull(T* t) +{ + return t != NullObjectPtr(); +} + + // ************************************************************************* // diff --git a/src/dynamicMesh/fvMeshAdder/fvMeshAdderTemplates.C b/src/dynamicMesh/fvMeshAdder/fvMeshAdderTemplates.C index 18a54fa622..ad154342c1 100644 --- a/src/dynamicMesh/fvMeshAdder/fvMeshAdderTemplates.C +++ b/src/dynamicMesh/fvMeshAdder/fvMeshAdderTemplates.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org - \\ / A nd | Copyright (C) 2011-2021 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -270,30 +270,6 @@ void Foam::fvMeshAdder::MapVolFields () ); - // It is necessary to enforce that all old-time fields are stored - // before the mapping is performed. Otherwise, if the - // old-time-level field is mapped before the field itself, sizes - // will not match. - - for - ( - typename HashTable*>:: - iterator fieldIter = fields.begin(); - fieldIter != fields.end(); - ++fieldIter - ) - { - if (debug) - { - Pout<< "MapVolFields : Storing old time for " << fieldIter()->name() - << endl; - } - - const_cast*>(fieldIter()) - ->storeOldTimes(); - } - - for ( typename HashTable*>:: @@ -589,29 +565,6 @@ void Foam::fvMeshAdder::MapSurfaceFields meshToAdd.objectRegistry::lookupClass() ); - // It is necessary to enforce that all old-time fields are stored - // before the mapping is performed. Otherwise, if the - // old-time-level field is mapped before the field itself, sizes - // will not match. - - for - ( - typename HashTable:: - iterator fieldIter = fields.begin(); - fieldIter != fields.end(); - ++fieldIter - ) - { - if (debug) - { - Pout<< "MapSurfaceFields : Storing old time for " - << fieldIter()->name() << endl; - } - - const_cast(fieldIter())->storeOldTimes(); - } - - for ( typename HashTable:: @@ -908,29 +861,6 @@ void Foam::fvMeshAdder::MapPointFields HashTable fields(mesh.thisDb().lookupClass()); HashTable fieldsToAdd(meshToAdd.lookupClass()); - // It is necessary to enforce that all old-time fields are stored - // before the mapping is performed. Otherwise, if the - // old-time-level field is mapped before the field itself, sizes - // will not match. - - for - ( - typename HashTable:: - iterator fieldIter = fields.begin(); - fieldIter != fields.end(); - ++fieldIter - ) - { - if (debug) - { - Pout<< "MapPointFields : Storing old time for " - << fieldIter()->name() << endl; - } - - const_cast(fieldIter())->storeOldTimes(); - } - - for ( typename HashTable:: diff --git a/src/finiteVolume/fvMesh/fvMesh.C b/src/finiteVolume/fvMesh/fvMesh.C index 830af031b4..a6571bd66c 100644 --- a/src/finiteVolume/fvMesh/fvMesh.C +++ b/src/finiteVolume/fvMesh/fvMesh.C @@ -254,6 +254,22 @@ void Foam::fvMesh::storeOldVol(const scalarField& V) } +void Foam::fvMesh::storeOldTimeFields() +{ + storeOldTimeFields(); + storeOldTimeFields(); + storeOldTimeFields(); +} + + +void Foam::fvMesh::nullOldestTimeFields() +{ + nullOldestTimeFields(); + nullOldestTimeFields(); + nullOldestTimeFields(); +} + + void Foam::fvMesh::clearOut() { clearGeom(); @@ -584,6 +600,16 @@ bool Foam::fvMesh::update() { if (!conformal()) stitcher_->disconnect(true, true); + if + ( + stitcher_->stitches() + || topoChanger_->dynamic() + || distributor_->dynamic() + ) + { + nullOldestTimeFields(); + } + const bool hasV00 = V00Ptr_; deleteDemandDrivenData(V00Ptr_); @@ -625,6 +651,15 @@ bool Foam::fvMesh::move() { if (!conformal()) stitcher_->disconnect(true, true); + if (curTimeIndex_ < time().timeIndex() && stitcher_->stitches()) + { + // Store all old-time fields. If we don't do this then we risk + // triggering a store in the middle of mapping and potentially + // overwriting a mapped old-time field with a not-yet-mapped new-time + // field. + storeOldTimeFields(); + } + // Do not set moving false // Once the mesh starts moving it is considered to be moving // for the rest of the run diff --git a/src/finiteVolume/fvMesh/fvMesh.H b/src/finiteVolume/fvMesh/fvMesh.H index 34f1b04121..07ee4c8142 100644 --- a/src/finiteVolume/fvMesh/fvMesh.H +++ b/src/finiteVolume/fvMesh/fvMesh.H @@ -231,6 +231,36 @@ private: //- Preserve old volume(s) void storeOldVol(const scalarField&); + //- Return the list of current fields of type GeoField + // i.e. fields that are not old-time or old-old-time etc. + template class GeoField> + UPtrList> curFields(); + + //- Store old times fields for all fields of a given type and class + template class GeoField> + void storeOldTimeFields(); + + //- Store old times fields for all fields of a given class + template class GeoField> + void storeOldTimeFields(); + + //- Store old times fields for all fields + // Used prior to field mapping following mesh-motion + // and NCC stitching + void storeOldTimeFields(); + + //- Null oldest time field for all fields of a given type and class + template class GeoField> + void nullOldestTimeFields(); + + //- Null oldest time field for all fields of a given class + template class GeoField> + void nullOldestTimeFields(); + + //- Null oldest time field for all fields + // Used prior to field mapping following mesh topology change + void nullOldestTimeFields(); + // Make topological data diff --git a/src/finiteVolume/fvMesh/fvMeshStitchers/fvMeshStitcher/fvMeshStitcher.C b/src/finiteVolume/fvMesh/fvMeshStitchers/fvMeshStitcher/fvMeshStitcher.C index e6ee9734f3..a4ef6e3636 100644 --- a/src/finiteVolume/fvMesh/fvMeshStitchers/fvMeshStitcher/fvMeshStitcher.C +++ b/src/finiteVolume/fvMesh/fvMeshStitchers/fvMeshStitcher/fvMeshStitcher.C @@ -1369,12 +1369,6 @@ bool Foam::fvMeshStitcher::connect // Make the mesh non-conformal mesh_.unconform(polyFacesBf, Sf, Cf); - // Store all old-time fields. If we don't do this then we risk triggering a - // store in the middle of mapping and potentially overwriting a mapped - // old-time field with a not-yet-mapped new-time field. - storeOldTimeFields(); - storeOldTimeFields(); - // Resize all the affected patch fields resizePatchFields(); resizePatchFields(); diff --git a/src/finiteVolume/fvMesh/fvMeshStitchers/fvMeshStitcher/fvMeshStitcher.H b/src/finiteVolume/fvMesh/fvMeshStitchers/fvMeshStitcher/fvMeshStitcher.H index 01145396be..bd0b6d113f 100644 --- a/src/finiteVolume/fvMesh/fvMeshStitchers/fvMeshStitcher/fvMeshStitcher.H +++ b/src/finiteVolume/fvMesh/fvMeshStitchers/fvMeshStitcher/fvMeshStitcher.H @@ -174,14 +174,6 @@ private: // Field Mapping - //- Store old times for all fields of a given type and class - template class GeoField> - void storeOldTimeFields(); - - //- Store old times for all fields of a given class - template class GeoField> - void storeOldTimeFields(); - //- Resize the patch fields of a given type and class to match the // mesh template class GeoField> diff --git a/src/finiteVolume/fvMesh/fvMeshStitchers/fvMeshStitcher/fvMeshStitcherTemplates.C b/src/finiteVolume/fvMesh/fvMeshStitchers/fvMeshStitcher/fvMeshStitcherTemplates.C index e24e41b9ce..0879314964 100644 --- a/src/finiteVolume/fvMesh/fvMeshStitchers/fvMeshStitcher/fvMeshStitcherTemplates.C +++ b/src/finiteVolume/fvMesh/fvMeshStitchers/fvMeshStitcher/fvMeshStitcherTemplates.C @@ -40,27 +40,6 @@ Description // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // -template class GeoField> -void Foam::fvMeshStitcher::storeOldTimeFields() -{ - HashTable*> fields(mesh_.lookupClass>()); - forAllIter(typename HashTable*>, fields, iter) - { - iter()->storeOldTimes(); - } -} - - -template class GeoField> -void Foam::fvMeshStitcher::storeOldTimeFields() -{ - #define StoreOldTimeFields(Type, nullArg) \ - storeOldTimeFields(); - FOR_ALL_FIELD_TYPES(StoreOldTimeFields); - #undef StoreOldTimeFields -} - - template class GeoField> void Foam::fvMeshStitcher::resizePatchFields() { diff --git a/src/finiteVolume/fvMesh/fvMeshTemplates.C b/src/finiteVolume/fvMesh/fvMeshTemplates.C index b8d981b8ee..f419f4cf36 100644 --- a/src/finiteVolume/fvMesh/fvMeshTemplates.C +++ b/src/finiteVolume/fvMesh/fvMeshTemplates.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org - \\ / A nd | Copyright (C) 2015-2018 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2015-2022 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -42,4 +42,68 @@ typename Foam::pTraits::labelType Foam::fvMesh::validComponents() const } +template class GeoField> +Foam::UPtrList> Foam::fvMesh::curFields() +{ + HashTable*> fields(lookupClass>()); + UPtrList> curFields(fields.size()); + + label i = 0; + forAllIter(typename HashTable*>, fields, iter) + { + if (!iter()->isOldTime()) + { + curFields.set(i++, iter()); + } + } + curFields.setSize(i); + + return curFields; +} + + +template class GeoField> +void Foam::fvMesh::storeOldTimeFields() +{ + UPtrList> curFields(this->curFields()); + + forAll(curFields, i) + { + curFields[i].storeOldTimes(); + } +} + + +template class GeoField> +void Foam::fvMesh::storeOldTimeFields() +{ + #define StoreOldTimeFields(Type, nullArg) \ + storeOldTimeFields(); + FOR_ALL_FIELD_TYPES(StoreOldTimeFields); + #undef StoreOldTimeFields +} + + +template class GeoField> +void Foam::fvMesh::nullOldestTimeFields() +{ + UPtrList> curFields(this->curFields()); + + forAll(curFields, i) + { + curFields[i].nullOldestTime(); + } +} + + +template class GeoField> +void Foam::fvMesh::nullOldestTimeFields() +{ + #define nullOldestTimeFields(Type, nullArg) \ + nullOldestTimeFields(); + FOR_ALL_FIELD_TYPES(nullOldestTimeFields); + #undef nullOldestTimeFields +} + + // ************************************************************************* //