diff --git a/applications/test/gravityMeshObject/Test-gravityMeshObject.C b/applications/test/gravityMeshObject/Test-gravityMeshObject.C index f95a39fe49afcd50d420837cd78cabf8efbb4415..c6d93c7bc9d2c287bc580246622f6ed816b3bc15 100644 --- a/applications/test/gravityMeshObject/Test-gravityMeshObject.C +++ b/applications/test/gravityMeshObject/Test-gravityMeshObject.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2023 OpenCFD Ltd. + Copyright (C) 2023-2024 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -50,6 +50,9 @@ void printInfo(const meshObjects::gravity& g) int main(int argc, char *argv[]) { + argList::addBoolOption("checkout", "Test checkout with release"); + argList::addBoolOption("release", "Test release instead of delete"); + #include "setRootCase.H" #include "createTime.H" @@ -70,14 +73,81 @@ int main(int argc, char *argv[]) printInfo(g); } - Pout<< "registered:" << flatOutput(runTime.sortedToc()) << nl << endl; + Pout<< "registered:" + << flatOutput(runTime.sortedToc()) << nl << endl; + } + + std::unique_ptr<meshObjects::gravity> release1; + std::unique_ptr<meshObjects::gravity> release2; + + if (args.found("release")) + { + // Ugly! + typedef + MeshObject<Time, TopologicalMeshObject, meshObjects::gravity> + parent_type; + + release1 = meshObjects::gravity::Release("g", runTime); + release2 = meshObjects::gravity::Release("#none#", runTime); + + Info<< "release: " << Switch::name(bool(release1)) + << ", " << Switch::name(bool(release2)) << nl; + + Info<< "after Release: " + << flatOutput(runTime.sortedToc()) << endl; + + // Do checkout by hand (ugly) + if (args.found("checkout")) + { + if (release1) + { + release1->parent_type::checkOut(); + } + + if (release2) + { + release2->parent_type::checkOut(); + } + + Info<< "after checkout: " + << flatOutput(runTime.sortedToc()) << endl; + } + } + else if (args.found("checkout")) + { + // Do checkout as part of release + release1 = meshObjects::gravity::Release("g", runTime, true); + release2 = meshObjects::gravity::Release("#none#", runTime, true); + + Info<< "release: " << Switch::name(bool(release1)) + << ", " << Switch::name(bool(release2)) << nl; + + Info<< "after Release/Checkout(true) : " + << flatOutput(runTime.sortedToc()) << endl; + } + else + { + meshObjects::gravity::Delete("g", runTime); + meshObjects::gravity::Delete("#none#", runTime); + + Info<< "after Delete: " + << flatOutput(runTime.sortedToc()) << endl; } - meshObjects::gravity::Delete("g", runTime); - meshObjects::gravity::Delete("something-not-in-registry", runTime); - Info<< "after Delete" << nl; - Pout<< "registered:" << flatOutput(runTime.sortedToc()) << endl; + if (meshObjects::gravity::Store(std::move(release1))) + { + Info<< "Store pointer" << endl; + } + + if (release2) + { + release2.reset(); + Info<< "Clear pointer" << endl; + } + + Info<< "Before exit: " + << flatOutput(runTime.sortedToc()) << endl; Info<< "\nEnd\n" << endl; diff --git a/src/OpenFOAM/db/regIOobject/regIOobject.H b/src/OpenFOAM/db/regIOobject/regIOobject.H index 6dad7249ca71f7be7efbf3a4cbebe604594b2ba2..76fbd3ea2ec3c8b7053f93fbf6bfe18f80d074b6 100644 --- a/src/OpenFOAM/db/regIOobject/regIOobject.H +++ b/src/OpenFOAM/db/regIOobject/regIOobject.H @@ -33,8 +33,10 @@ Description SourceFiles regIOobject.C + regIOobjectI.H regIOobjectRead.C regIOobjectWrite.C + regIOobjectMetaData.C \*---------------------------------------------------------------------------*/ @@ -170,7 +172,7 @@ public: // or was newly registered bool checkIn(); - //- Remove all file watches and remove object from registry + //- Remove object from registry, and remove all file watches // \return true if object was registered and was removed bool checkOut(); diff --git a/src/OpenFOAM/meshes/MeshObject/MeshObject.C b/src/OpenFOAM/meshes/MeshObject/MeshObject.C index 26bbf42e81a33220821171415e71f34b6c652a59..0551457350e3ef58fab1d28969b4889e8eb80ca6 100644 --- a/src/OpenFOAM/meshes/MeshObject/MeshObject.C +++ b/src/OpenFOAM/meshes/MeshObject/MeshObject.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2018-2023 OpenCFD Ltd. + Copyright (C) 2018-2024 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -74,8 +74,8 @@ const Type& Foam::MeshObject<Mesh, MeshObjectType, Type>::New if (meshObject::debug) { Pout<< "MeshObject::New(const " << Mesh::typeName - << "&, ...) : constructing " << Type::typeName - << " for region " << mesh.name() << endl; + << "&, ...) : constructing <" << Type::typeName + << ">, region=" << mesh.name() << endl; } ptr = new Type(mesh, std::forward<Args>(args)...); @@ -108,9 +108,8 @@ const Type& Foam::MeshObject<Mesh, MeshObjectType, Type>::New { Pout<< "MeshObject::New('" << objName << "', const " << Mesh::typeName - << "&, ...) : constructing " << objName - << " of type " << Type::typeName - << " for region " << mesh.name() << endl; + << "&, ...) : constructing <" << Type::typeName + << ">, region=" << mesh.name() << endl; } ptr = new Type(objName, mesh, std::forward<Args>(args)...); @@ -138,8 +137,8 @@ bool Foam::MeshObject<Mesh, MeshObjectType, Type>::Delete { if (meshObject::debug) { - Pout<< "MeshObject::Delete(const Mesh&) : deleting " - << objName << endl; + Pout<< "MeshObject::Delete() : deleting <" << Type::typeName + << "> " << objName << endl; } return mesh.thisDb().checkOut(static_cast<MeshObjectType<Mesh>*>(ptr)); @@ -149,31 +148,114 @@ bool Foam::MeshObject<Mesh, MeshObjectType, Type>::Delete } +template<class Mesh, template<class> class MeshObjectType, class Type> +std::unique_ptr<Type> Foam::MeshObject<Mesh, MeshObjectType, Type>::Release +( + const word& objName, + const Mesh& mesh, + const bool checkout +) +{ + Type* ptr = + mesh.thisDb().objectRegistry::template + getObjectPtr<Type>(objName); + + std::unique_ptr<Type> released; + + if (ptr) + { + auto* casted = static_cast<MeshObjectType<Mesh>*>(ptr); + + if (casted->regIOobject::ownedByRegistry()) + { + // Release ownership from registry and transfer to unique_ptr + casted->regIOobject::release(); + released.reset(ptr); + + // Allow removal from the registry (ie, checkOut) but leave its + // 'registered' status untouched since this is equivalent to + // IOobject::registerObject(). + // + // Do not use regIOobject::release(unregister) since this + // will prevent later re-storing + + if (checkout) + { + casted->regIOobject::checkOut(); + } + } + + if (meshObject::debug) + { + Pout<< "MeshObject::Release() : release <" << Type::typeName + << "> " << objName << ", owned=" << bool(released) << endl; + } + } + + return released; +} + + +// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // + +template<class Mesh, template<class> class MeshObjectType, class Type> +bool Foam::MeshObject<Mesh, MeshObjectType, Type>::Store +( + std::unique_ptr<Type>&& ptr +) +{ + bool ok = false; + + if (ptr) + { + auto* casted = static_cast<MeshObjectType<Mesh>*>(ptr.get()); + + ok = casted->regIOobject::store(); + + if (ok) + { + // Took ownership + (void) ptr.release(); + } + + if (meshObject::debug) + { + Pout<< "MeshObject::Store() : store <" << Type::typeName + << ">, owned=" << ok << endl; + } + } + + return ok; +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + template<class Mesh> void Foam::meshObject::movePoints(objectRegistry& obr) { - HashTable<GeometricMeshObject<Mesh>*> meshObjects + UPtrList<GeometricMeshObject<Mesh>> meshObjects ( - obr.lookupClass<GeometricMeshObject<Mesh>>() + obr.sorted<GeometricMeshObject<Mesh>>() ); if (meshObject::debug) { - Pout<< "meshObject::movePoints(objectRegistry&) :" - << " moving " << Mesh::typeName - << " meshObjects for region " << obr.name() << endl; + Pout<< "meshObject::movePoints() : moving " + << meshObjects.size() << " <" << Mesh::typeName + << "> meshObjects, region=" << obr.name() << endl; } - forAllIters(meshObjects, iter) + for (auto& item : meshObjects) { - // isA<MoveableMeshObject<Mesh>> - auto* objectPtr = dynamic_cast<MoveableMeshObject<Mesh>*>(*iter); + // isA_constCast<MoveableMeshObject<Mesh>> + auto* objectPtr = dynamic_cast<MoveableMeshObject<Mesh>*>(&item); if (objectPtr) { if (meshObject::debug) { - Pout<< " Moving " << (*iter)->name() << endl; + Pout<< " Moving " << item.name() << endl; } objectPtr->movePoints(); } @@ -181,9 +263,9 @@ void Foam::meshObject::movePoints(objectRegistry& obr) { if (meshObject::debug) { - Pout<< " Destroying " << (*iter)->name() << endl; + Pout<< " Destroying " << item.name() << endl; } - obr.checkOut(*iter); + obr.checkOut(item); } } } @@ -192,28 +274,28 @@ void Foam::meshObject::movePoints(objectRegistry& obr) template<class Mesh> void Foam::meshObject::updateMesh(objectRegistry& obr, const mapPolyMesh& mpm) { - HashTable<GeometricMeshObject<Mesh>*> meshObjects + UPtrList<GeometricMeshObject<Mesh>> meshObjects ( - obr.lookupClass<GeometricMeshObject<Mesh>>() + obr.sorted<GeometricMeshObject<Mesh>>() ); if (meshObject::debug) { - Pout<< "meshObject::updateMesh(objectRegistry&, " - "const mapPolyMesh& mpm) : updating " << Mesh::typeName - << " meshObjects for region " << obr.name() << endl; + Pout<< "meshObject::updateMesh() : updating " + << meshObjects.size() << " <" << Mesh::typeName + << "> meshObjects, region=" << obr.name() << endl; } - forAllIters(meshObjects, iter) + for (auto& item : meshObjects) { - // isA<UpdateableMeshObject<Mesh>> - auto* objectPtr = dynamic_cast<UpdateableMeshObject<Mesh>*>(*iter); + // isA_constCast<UpdateableMeshObject<Mesh>> + auto* objectPtr = dynamic_cast<UpdateableMeshObject<Mesh>*>(&item); if (objectPtr) { if (meshObject::debug) { - Pout<< " Updating " << (*iter)->name() << endl; + Pout<< " Updating " << item.name() << endl; } objectPtr->updateMesh(mpm); } @@ -221,9 +303,9 @@ void Foam::meshObject::updateMesh(objectRegistry& obr, const mapPolyMesh& mpm) { if (meshObject::debug) { - Pout<< " Destroying " << (*iter)->name() << endl; + Pout<< " Destroying " << item.name() << endl; } - obr.checkOut(*iter); + obr.checkOut(item); } } } @@ -232,25 +314,25 @@ void Foam::meshObject::updateMesh(objectRegistry& obr, const mapPolyMesh& mpm) template<class Mesh, template<class> class MeshObjectType> void Foam::meshObject::clear(objectRegistry& obr) { - HashTable<MeshObjectType<Mesh>*> meshObjects + UPtrList<MeshObjectType<Mesh>> meshObjects ( - obr.lookupClass<MeshObjectType<Mesh>>() + obr.sorted<MeshObjectType<Mesh>>() ); if (meshObject::debug) { - Pout<< "meshObject::clear(objectRegistry&) :" - << " clearing " << Mesh::typeName - << " meshObjects for region " << obr.name() << endl; + Pout<< "meshObject::clear() : clearing " + << meshObjects.size() << " <" << Mesh::typeName + << "> meshObjects, region=" << obr.name() << endl; } - forAllIters(meshObjects, iter) + for (auto& item : meshObjects) { if (meshObject::debug) { - Pout<< " Destroying " << (*iter)->name() << endl; + Pout<< " Destroying " << item.name() << endl; } - obr.checkOut(*iter); + obr.checkOut(item); } } @@ -263,30 +345,30 @@ template > void Foam::meshObject::clearUpto(objectRegistry& obr) { - HashTable<FromType<Mesh>*> meshObjects + UPtrList<FromType<Mesh>> meshObjects ( - obr.lookupClass<FromType<Mesh>>() + obr.sorted<FromType<Mesh>>() ); if (meshObject::debug) { - Pout<< "meshObject::clearUpto(objectRegistry&) :" - << " clearing " << Mesh::typeName - << " meshObjects for region " << obr.name() << endl; + Pout<< "meshObject::clearUpto() : clearing " + << meshObjects.size() << " <" << Mesh::typeName + << "> meshObjects, region=" << obr.name() << endl; } - forAllIters(meshObjects, iter) + for (auto& item : meshObjects) { - // isA<ToType<Mesh>> - auto* objectPtr = dynamic_cast<ToType<Mesh>*>(*iter); + // isA_constCast<ToType<Mesh>> + auto* objectPtr = dynamic_cast<ToType<Mesh>*>(&item); if (!objectPtr) { if (meshObject::debug) { - Pout<< " Destroying " << (*iter)->name() << endl; + Pout<< " Destroying " << item.name() << endl; } - obr.checkOut(*iter); + obr.checkOut(item); } } } diff --git a/src/OpenFOAM/meshes/MeshObject/MeshObject.H b/src/OpenFOAM/meshes/MeshObject/MeshObject.H index 11554ee3dac86bd40a6546bffa2014678d6988b3..a5d0577ade925e35af888515c04c54f073a247c5 100644 --- a/src/OpenFOAM/meshes/MeshObject/MeshObject.H +++ b/src/OpenFOAM/meshes/MeshObject/MeshObject.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2018-2023 OpenCFD Ltd. + Copyright (C) 2018-2024 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -34,8 +34,9 @@ Description MeshObject is templated on the type of mesh it is allocated to, the type of the mesh object (TopologicalMeshObject, GeometricMeshObject, MoveableMeshObject, UpdateableMeshObject) and the type of the actual object - it is created for example: + it is created for. + Example usage, \verbatim class leastSquaresVectors : @@ -49,13 +50,15 @@ Description }; \endverbatim - MeshObject types: - - - TopologicalMeshObject: mesh object to be deleted on topology change - - GeometricMeshObject: mesh object to be deleted on geometry change - - MoveableMeshObject: mesh object to be updated in movePoints - - UpdateableMeshObject: mesh object to be updated in updateMesh or - movePoints + The MeshObject types: + - TopologicalMeshObject: + mesh object to be deleted on topology change + - GeometricMeshObject: + mesh object to be deleted on geometry change + - MoveableMeshObject: + mesh object to be updated in movePoints + - UpdateableMeshObject: + mesh object to be updated in movePoints or updateMesh Note movePoints must be provided for MeshObjects of type MoveableMeshObject @@ -82,6 +85,55 @@ namespace Foam // Forward Declarations class mapPolyMesh; +/*---------------------------------------------------------------------------*\ + Class meshObject Declaration +\*---------------------------------------------------------------------------*/ + +//- The meshObject is a concrete regIOobject to register MeshObject items +class meshObject +: + public regIOobject +{ +public: + + //- Runtime declaration and debug switch + ClassName("meshObject"); + + + // Constructors + + //- Construct with given object name on a registry + meshObject(const word& objName, const objectRegistry& obr); + + + // Static Member Functions + + //- Update for mesh motion + template<class Mesh> + static void movePoints(objectRegistry& obr); + + //- Update topology using the given map + template<class Mesh> + static void updateMesh(objectRegistry& obr, const mapPolyMesh& mpm); + + //- Clear/remove all meshObject of MeshObjectType + //- via objectRegistry::checkOut() + template<class Mesh, template<class> class MeshObjectType> + static void clear(objectRegistry& obr); + + //- Clear all meshObject derived from FromType up to + //- (but not including) ToType. + // Used to clear e.g. all non-updateable meshObjects + template + < + class Mesh, + template<class> class FromType, + template<class> class ToType + > + static void clearUpto(objectRegistry& obr); +}; + + /*---------------------------------------------------------------------------*\ Class MeshObject Declaration \*---------------------------------------------------------------------------*/ @@ -108,14 +160,17 @@ public: MeshObject(const word& objName, const Mesh& mesh); + //- Destructor + virtual ~MeshObject() = default; + + // Factory Methods - //- Get existing or create a new MeshObject. Registered with typeName + //- Get existing or create MeshObject registered with typeName template<class... Args> static const Type& New(const Mesh& mesh, Args&&... args); - //- Get existing or create a new MeshObject using supplied - //- registration name + //- Get existing or create MeshObject with given registration name template<class... Args> static const Type& New ( @@ -124,11 +179,10 @@ public: Args&&... args ); + //- Transfer ownership of meshObject to registry. + static bool Store(std::unique_ptr<Type>&& ptr); - //- Destructor - virtual ~MeshObject() = default; - - //- Static destructor using supplied registration name + //- Static destructor using given registration name static bool Delete(const word& objName, const Mesh& mesh); //- Static destructor using Type::typeName @@ -137,6 +191,29 @@ public: return Delete(Type::typeName, mesh); } + //- Release ownership of meshObject (with given registration name) + //- from registry. Returns nullptr if not found or not owned. + static std::unique_ptr<Type> Release + ( + const word& objName, + const Mesh& mesh, + //! optionally perform checkOut() from the registry + const bool checkout = false + ); + + + //- Release ownership of meshObject (with Type::typeName name) + //- from registry. + static std::unique_ptr<Type> Release + ( + const Mesh& mesh, + //! optionally perform checkOut() from the registry + const bool checkout = false + ) + { + return Release(Type::typeName, mesh, checkout); + } + // Member Functions @@ -154,51 +231,6 @@ public: }; -/*---------------------------------------------------------------------------*\ - Class meshObject Declaration -\*---------------------------------------------------------------------------*/ - -//- The meshObject is a concrete regIOobject -class meshObject -: - public regIOobject -{ -public: - - //- Runtime declaration and debug switch - ClassName("meshObject"); - - - // Constructors - - //- Construct with given object name on a registry - meshObject(const word& objName, const objectRegistry& obr); - - - // Static Member Functions - - template<class Mesh> - static void movePoints(objectRegistry& obr); - - template<class Mesh> - static void updateMesh(objectRegistry& obr, const mapPolyMesh& mpm); - - template<class Mesh, template<class> class MeshObjectType> - static void clear(objectRegistry& obr); - - //- Clear all meshObject derived from FromType up to - //- (but not including) ToType. - // Used to clear e.g. all non-updateable meshObjects - template - < - class Mesh, - template<class> class FromType, - template<class> class ToType - > - static void clearUpto(objectRegistry& obr); -}; - - /*---------------------------------------------------------------------------*\ Class TopologicalMeshObject Declaration \*---------------------------------------------------------------------------*/ @@ -254,6 +286,7 @@ public: GeometricMeshObject<Mesh>(objName, obr) {} + //- Update for mesh motion virtual bool movePoints() = 0; }; @@ -275,6 +308,7 @@ public: MoveableMeshObject<Mesh>(objName, obr) {} + //- Update topology using the given map virtual void updateMesh(const mapPolyMesh& mpm) = 0; };