diff --git a/src/dynamicMesh/clearCodedRedirects.H b/src/dynamicMesh/clearCodedRedirects.H new file mode 100644 index 0000000..eec857e --- /dev/null +++ b/src/dynamicMesh/clearCodedRedirects.H @@ -0,0 +1,79 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is a derivative work 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. + +\*---------------------------------------------------------------------------*/ + +#ifndef Foam_blastAMR_clearCodedRedirects_H +#define Foam_blastAMR_clearCodedRedirects_H + +#include "fvMesh.H" +#include "codedFixedValueFvPatchField.H" +#include "codedMixedFvPatchField.H" + +namespace Foam +{ + +// Reset cached redirect patch fields on coded BCs (codedFixedValue, +// codedMixed) after any topology change (refine, unrefine, redistribute). +// +// OpenFOAM does not override autoMap/rmap on these BCs to clear the cached +// redirectPatchFieldPtr_, so it keeps a pointer at the pre-change patch field +// memory. After autoMap reallocates the parent buffer, the redirect dangles; +// any user "code" block that writes per-face data buffer-overruns the new +// patch field, and destruction of the redirect later double-frees / hits an +// invalid pointer. +// +// Workaround: replace each affected patch field with its clone. The +// codedFixedValueFvPatchField/codedMixedFvPatchField copy constructors +// initialise redirectPatchFieldPtr_ to null, so the clone has a fresh redirect +// that is rebuilt lazily on the next updateCoeffs at the correct post-change +// size. +template +void clearCodedRedirects(fvMesh& mesh) +{ + using ValueType = typename GeoField::value_type; + using FixedT = codedFixedValueFvPatchField; + using MixedT = codedMixedFvPatchField; + + HashTable flds(mesh.template lookupClass()); + forAllIter(typename HashTable, flds, iter) + { + GeoField& fld = *iter(); + auto& bfld = fld.boundaryFieldRef(); + forAll(bfld, patchi) + { + const auto& pf = bfld[patchi]; + if (isA(pf) || isA(pf)) + { + bfld.set(patchi, pf.clone(fld.internalField()).ptr()); + } + } + } +} + + +// Convenience: clear coded redirects on all common volField types. +inline void clearCodedRedirectsAllVol(fvMesh& mesh) +{ + clearCodedRedirects(mesh); + clearCodedRedirects(mesh); + clearCodedRedirects(mesh); + clearCodedRedirects(mesh); + clearCodedRedirects(mesh); +} + +} // End namespace Foam + +#endif diff --git a/src/dynamicMesh/fvMeshBalance/fvMeshBalance.C b/src/dynamicMesh/fvMeshBalance/fvMeshBalance.C index 3e7ecff..6182621 100644 --- a/src/dynamicMesh/fvMeshBalance/fvMeshBalance.C +++ b/src/dynamicMesh/fvMeshBalance/fvMeshBalance.C @@ -33,6 +33,7 @@ License #include "preservePatchesConstraint.H" #include "preserveBafflesConstraint.H" #include "sampledSurfaceWorkaround.H" +#include "clearCodedRedirects.H" #include "dynamicMotionSolverFvMesh.H" #include "pointIOField.H" @@ -639,6 +640,10 @@ Foam::fvMeshBalance::distribute() blastMeshObject::distribute(mesh_, map()); + // Reset stale codedFixedValue/codedMixed redirects after autoMap. + // See clearCodedRedirects.H for rationale. + clearCodedRedirectsAllVol(mesh_); + // Expire sampled surfaces in surfaceFieldValue function objects. // OpenFOAM's surfaceFieldValue::updateMesh() doesn't properly expire // its internal sampledPtr_ cache, leading to stale face indices after diff --git a/src/dynamicMesh/fvMeshRefiner/fvMeshHexRefiner/fvMeshHexRefiner.C b/src/dynamicMesh/fvMeshRefiner/fvMeshHexRefiner/fvMeshHexRefiner.C index 9856dfb..b686b7a 100644 --- a/src/dynamicMesh/fvMeshRefiner/fvMeshHexRefiner/fvMeshHexRefiner.C +++ b/src/dynamicMesh/fvMeshRefiner/fvMeshHexRefiner/fvMeshHexRefiner.C @@ -30,6 +30,7 @@ License #include "fvMeshHexRefiner.H" #include "addToRunTimeSelectionTable.H" +#include "clearCodedRedirects.H" #include "surfaceInterpolate.H" #include "volFields.H" #include "polyTopoChange.H" @@ -229,6 +230,10 @@ Foam::fvMeshHexRefiner::refine // would result in double cloud remapping. mesh_.updateMesh(map); + // Reset stale codedFixedValue/codedMixed redirects after autoMap. + // See clearCodedRedirects.H for rationale. + clearCodedRedirectsAllVol(mesh_); + // Update numbering of protectedCell_ if (protectedCell_.size()) { @@ -322,6 +327,10 @@ Foam::fvMeshHexRefiner::unrefine // would result in double cloud remapping. mesh_.updateMesh(map); + // Reset stale codedFixedValue/codedMixed redirects after autoMap. + // See clearCodedRedirects.H for rationale. + clearCodedRedirectsAllVol(mesh_); + // Update numbering of protectedCell_ if (protectedCell_.size()) { diff --git a/src/dynamicMesh/fvMeshRefiner/fvMeshPolyRefiner/refinement/refinement.C b/src/dynamicMesh/fvMeshRefiner/fvMeshPolyRefiner/refinement/refinement.C index fb29c56..736fb31 100644 --- a/src/dynamicMesh/fvMeshRefiner/fvMeshPolyRefiner/refinement/refinement.C +++ b/src/dynamicMesh/fvMeshRefiner/fvMeshPolyRefiner/refinement/refinement.C @@ -25,6 +25,8 @@ License #include "refinement.H" #include "polyTopoChanger.H" +#include "clearCodedRedirects.H" +#include "fvMesh.H" #include "polyAddFace.H" #include "polyAddPoint.H" #include "polyModifyFace.H" @@ -908,6 +910,11 @@ Foam::autoPtr Foam::refinement::refine autoPtr map = meshMod.changeMesh(mesh, false); mesh.updateMesh(map()); + if (auto* fvm = dynamic_cast(&mesh)) + { + clearCodedRedirectsAllVol(*fvm); + } + Info<< "Refined from " << returnReduce(map().nOldCells(), sumOp