diff --git a/src/dynamicMesh/dynamicMesh/Make/files b/src/dynamicMesh/dynamicMesh/Make/files index 25faf6db0..0ec6268cc 100644 --- a/src/dynamicMesh/dynamicMesh/Make/files +++ b/src/dynamicMesh/dynamicMesh/Make/files @@ -34,6 +34,9 @@ $(slidingInterface)/slidingInterfaceAttachedAddressing.C $(slidingInterface)/slidingInterfaceClearCouple.C $(slidingInterface)/decoupleSlidingInterface.C +repatchCoverage = $(polyMeshModifiers)/repatchCoverage +$(repatchCoverage)/repatchCoverage.C + polyTopoChange/polyTopoChange/polyTopoChange.C polyTopoChange/polyTopoChange/actions/topoAction/topoActions.C diff --git a/src/dynamicMesh/dynamicMesh/polyMeshModifiers/repatchCoverage/repatchCoverage.C b/src/dynamicMesh/dynamicMesh/polyMeshModifiers/repatchCoverage/repatchCoverage.C new file mode 100644 index 000000000..31453d800 --- /dev/null +++ b/src/dynamicMesh/dynamicMesh/polyMeshModifiers/repatchCoverage/repatchCoverage.C @@ -0,0 +1,664 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | foam-extend: Open Source CFD + \\ / O peration | + \\ / A nd | For copyright notice see file Copyright + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of foam-extend. + + foam-extend 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. + + foam-extend 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 foam-extend. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "repatchCoverage.H" +#include "polyTopoChanger.H" +#include "polyMesh.H" +#include "Time.H" +#include "primitiveMesh.H" +#include "polyTopoChange.H" +#include "primitiveFacePatch.H" +#include "GGIInterpolation.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + defineTypeNameAndDebug(repatchCoverage, 0); + addToRunTimeSelectionTable + ( + polyMeshModifier, + repatchCoverage, + dictionary + ); +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::repatchCoverage::checkDefinition() +{ + if + ( + !masterCoveredPatchID_.active() + || !masterUncoveredPatchID_.active() + || !slaveCoveredPatchID_.active() + || !slaveUncoveredPatchID_.active() + || repatchThreshold_ < 0 || repatchThreshold_ > 1 + ) + { + FatalErrorIn + ( + "void Foam::repatchCoverage::checkDefinition()" + ) << "Not all zones and patches needed in the definition " + << "have been found. Please check your mesh definition." + << abort(FatalError); + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Construct from components +Foam::repatchCoverage::repatchCoverage +( + const word& name, + const label index, + const polyTopoChanger& mme, + const word& masterCoveredPatchName, + const word& masterUncoveredPatchName, + const word& slaveCoveredPatchName, + const word& slaveUncoveredPatchName, + const scalar repatchThreshold +) +: + polyMeshModifier(name, index, mme, true), + masterCoveredPatchID_(masterCoveredPatchName, mme.mesh().boundaryMesh()), + masterUncoveredPatchID_ + ( + masterUncoveredPatchName, + mme.mesh().boundaryMesh() + ), + slaveCoveredPatchID_(slaveCoveredPatchName, mme.mesh().boundaryMesh()), + slaveUncoveredPatchID_ + ( + slaveUncoveredPatchName, + mme.mesh().boundaryMesh() + ), + repatchThreshold_ + ( + Foam::max(SMALL, Foam::min(repatchThreshold, 1 - SMALL)) + ), + uncMaster_(), + uncSlave_() +{ + checkDefinition(); +} + + +// Construct from components +Foam::repatchCoverage::repatchCoverage +( + const word& name, + const dictionary& dict, + const label index, + const polyTopoChanger& mme +) +: + polyMeshModifier(name, index, mme, Switch(dict.lookup("active"))), + masterCoveredPatchID_ + ( + dict.lookup("masterCoveredPatchName"), + mme.mesh().boundaryMesh() + ), + masterUncoveredPatchID_ + ( + dict.lookup("masterUncoveredPatchName"), + mme.mesh().boundaryMesh() + ), + slaveCoveredPatchID_ + ( + dict.lookup("slaveCoveredPatchName"), + mme.mesh().boundaryMesh() + ), + slaveUncoveredPatchID_ + ( + dict.lookup("slaveUncoveredPatchName"), + mme.mesh().boundaryMesh() + ), + repatchThreshold_ + ( + Foam::max + ( + SMALL, + Foam::min(readScalar(dict.lookup("repatchThreshold")), 1 - SMALL) + ) + ), + uncMaster_(), + uncSlave_() +{ + checkDefinition(); +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::repatchCoverage::~repatchCoverage() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::repatchCoverage::changeTopology() const +{ + // Check that masks are empty + if (!uncMaster_.empty() || !uncSlave_.empty()) + { + FatalErrorIn("bool repatchCoverage::changeTopology() const") + << "Uncovered masks are not empty. Topo change is out of sync" + << abort(FatalError); + } + + // Get mesh reference + const polyMesh& mesh = topoChanger().mesh(); + + const pointField& allPoints = mesh.allPoints(); + const faceList& allFaces = mesh.allFaces(); + + // Collect all faces for interpolation + + // Master side + const polyPatch& masterCoveredPatch = + mesh.boundaryMesh()[masterCoveredPatchID_.index()]; + + const polyPatch& masterUncoveredPatch = + mesh.boundaryMesh()[masterUncoveredPatchID_.index()]; + + faceList masterSide + ( + masterCoveredPatch.size() + + masterUncoveredPatch.size() + ); + + { + label nFaces = 0; + + // Insert covered faces + for + ( + label faceI = masterCoveredPatch.start(); + faceI < masterCoveredPatch.start() + masterCoveredPatch.size(); + faceI++ + ) + { + masterSide[nFaces] = allFaces[faceI]; + nFaces++; + } + + // Insert uncovered faces + for + ( + label faceI = masterUncoveredPatch.start(); + faceI < masterUncoveredPatch.start() + masterUncoveredPatch.size(); + faceI++ + ) + { + masterSide[nFaces] = allFaces[faceI]; + nFaces++; + } + } + + // Slave side + const polyPatch& slaveCoveredPatch = + mesh.boundaryMesh()[slaveCoveredPatchID_.index()]; + + const polyPatch& slaveUncoveredPatch = + mesh.boundaryMesh()[slaveUncoveredPatchID_.index()]; + + faceList slaveSide + ( + slaveCoveredPatch.size() + + slaveUncoveredPatch.size() + ); + + { + label nFaces = 0; + + // Insert covered faces + for + ( + label faceI = slaveCoveredPatch.start(); + faceI < slaveCoveredPatch.start() + slaveCoveredPatch.size(); + faceI++ + ) + { + slaveSide[nFaces] = allFaces[faceI]; + nFaces++; + } + + // Insert uncovered faces + for + ( + label faceI = slaveUncoveredPatch.start(); + faceI < slaveUncoveredPatch.start() + slaveUncoveredPatch.size(); + faceI++ + ) + { + slaveSide[nFaces] = allFaces[faceI]; + nFaces++; + } + } + + // Create interpolator + primitiveFacePatch master(masterSide, allPoints); + primitiveFacePatch slave(slaveSide, allPoints); + + if + ( + Pstream::parRun + && ( + (masterSide.empty() && !slaveSide.empty()) + || (!masterSide.empty() && slaveSide.empty()) + ) + ) + { + FatalErrorIn("bool repatchCoverage::changeTopology() const") + << "Parallel run with partial visibility" + << abort(FatalError); + } + + if (masterSide.empty() && slaveSide.empty()) + { + // Empty master and slave patches. No local topo change + return false; + } + + GGIInterpolation patchToPatch + ( + master, + slave, + tensorField::zero, // forwardT + tensorField::zero, // reverseT + vectorField::zero // separation + ); + + // Check uncovered master and slave faces + + // Check uncovered master faces + // All faces between 0 and masterCoveredPatch.size() - 1 should be covered + // All faces between masterCoveredPatch.size() - 1 and + // uncoveredMaster.size() - 1 should be uncovered + // If this is not the case, faces should be changed + + // Master side + label nMasterChanges = 0; + + { + // Set size of uncovered master mask. This indicates a topo change + // is in preparation + uncMaster_.setSize(master.size(), false); + + const labelList& umf = patchToPatch.uncoveredMasterFaces(); + + forAll(umf, umfI) + { + uncMaster_[umf[umfI]] = true; + } + + // Check coverage + forAll (uncMaster_, mfI) + { + if (uncMaster_[mfI] && mfI < masterCoveredPatch.size()) + { + // Found uncovered master in covered section + nMasterChanges++; + } + + if (!uncMaster_[mfI] && mfI >= masterCoveredPatch.size()) + { + // Found covered master in uncovered section + nMasterChanges++; + } + } + } + + // Slave side + label nSlaveChanges = 0; + + { + // Set size of uncovered master mask. This indicates a topo change + // is in preparation + uncSlave_.setSize(slave.size(), false); + + const labelList& umf = patchToPatch.uncoveredSlaveFaces(); + + forAll(umf, umfI) + { + uncSlave_[umf[umfI]] = true; + } + + // Check coverage + forAll (uncSlave_, mfI) + { + if (uncSlave_[mfI] && mfI < slaveCoveredPatch.size()) + { + // Found uncovered slave in covered section + nSlaveChanges++; + } + + if (!uncSlave_[mfI] && mfI >= slaveCoveredPatch.size()) + { + // Found covered slave in uncovered section + nSlaveChanges++; + } + } + } + + if (nMasterChanges > 0 || nSlaveChanges > 0) + { + InfoIn("bool repatchCoverage::changeTopology() const") + << "Changing " << nMasterChanges << " master and " + << nSlaveChanges << " slave faces" + << endl; + + return true; + } + else + { + // Clear uncovered masks to indicate that the topological change + // is not required + uncMaster_.clear(); + uncSlave_.clear(); + + return false; + } +} + + +void Foam::repatchCoverage::setRefinement(polyTopoChange& ref) const +{ + // Get mesh reference + const polyMesh& mesh = topoChanger().mesh(); + + const faceList& allFaces = mesh.allFaces(); + const faceZoneMesh& faceZones = mesh.faceZones(); + + const labelList& owner = mesh.faceOwner(); + + // Master side + { + // Get master patches + + const polyPatch& masterCoveredPatch = + mesh.boundaryMesh()[masterCoveredPatchID_.index()]; + + const label cStart = masterCoveredPatch.start(); + const label cSize = masterCoveredPatch.size(); + + const polyPatch& masterUncoveredPatch = + mesh.boundaryMesh()[masterUncoveredPatchID_.index()]; + + const label uncStart = masterUncoveredPatch.start(); + + // Adjust coverage + forAll (uncMaster_, faceI) + { + if (uncMaster_[faceI] && faceI < masterCoveredPatch.size()) + { + // Found uncovered face in covered section + + // Get face index + const label faceIndex = cStart + faceI; + + // Find zone index + const label faceZoneIndex = faceZones.whichZone(faceIndex); + + // Face flip + bool faceZoneFlip = false; + + if (faceZoneIndex > -1) + { + // Find face in zone + const label fizIndex = + faceZones[faceZoneIndex].whichFace(faceIndex); + + faceZoneFlip = + faceZones[faceZoneIndex].flipMap()[fizIndex]; + } + + // Found uncovered master in covered section + // Move to uncovered patch + ref.setAction + ( + polyModifyFace + ( + allFaces[faceIndex], // modified face + faceIndex, // modified face index + owner[faceIndex], // owner + -1, // neighbour + false, // face flip + masterUncoveredPatch.index(), // patch for face + false, // remove from zone + faceZoneIndex, // zone for face + faceZoneFlip // face flip in zone + ) + ); + } + + if (!uncMaster_[faceI] && faceI >= masterCoveredPatch.size()) + { + // Found covered face in uncovered section + + // Get face index + const label faceIndex = uncStart - cSize + faceI; + + // Find zone index + const label faceZoneIndex = faceZones.whichZone(faceIndex); + + // Face flip + bool faceZoneFlip = false; + + if (faceZoneIndex > -1) + { + // Find face in zone + const label fizIndex = + faceZones[faceZoneIndex].whichFace(faceIndex); + + faceZoneFlip = + faceZones[faceZoneIndex].flipMap()[fizIndex]; + } + + // Found uncovered master in covered section + // Move to uncovered patch + ref.setAction + ( + polyModifyFace + ( + allFaces[faceIndex], // modified face + faceIndex, // modified face index + owner[faceIndex], // owner + -1, // neighbour + false, // face flip + masterCoveredPatch.index(), // patch for face + false, // remove from zone + faceZoneIndex, // zone for face + faceZoneFlip // face flip in zone + ) + ); + } + } + } + + { + // Get slave patches + + const polyPatch& slaveCoveredPatch = + mesh.boundaryMesh()[slaveCoveredPatchID_.index()]; + + const label cStart = slaveCoveredPatch.start(); + const label cSize = slaveCoveredPatch.size(); + + const polyPatch& slaveUncoveredPatch = + mesh.boundaryMesh()[slaveUncoveredPatchID_.index()]; + + const label uncStart = slaveUncoveredPatch.start(); + + // Check coverage + forAll (uncSlave_, faceI) + { + if (uncSlave_[faceI] && faceI < slaveCoveredPatch.size()) + { + // Found uncovered face in covered section + + // Get face index + const label faceIndex = cStart + faceI; + + // Find zone index + const label faceZoneIndex = faceZones.whichZone(faceIndex); + + // Face flip + bool faceZoneFlip = false; + + if (faceZoneIndex > -1) + { + // Find face in zone + const label fizIndex = + faceZones[faceZoneIndex].whichFace(faceIndex); + + faceZoneFlip = + faceZones[faceZoneIndex].flipMap()[fizIndex]; + } + + // Found uncovered slave in covered section + // Move to uncovered patch + ref.setAction + ( + polyModifyFace + ( + allFaces[faceIndex], // modified face + faceIndex, // modified face index + owner[faceIndex], // owner + -1, // neighbour + false, // face flip + slaveUncoveredPatch.index(), // patch for face + false, // remove from zone + faceZoneIndex, // zone for face + faceZoneFlip // face flip in zone + ) + ); + } + + if (!uncSlave_[faceI] && faceI >= slaveCoveredPatch.size()) + { + // Found covered face in uncovered section + + // Get face index + const label faceIndex = uncStart - cSize + faceI; + + // Find zone index + const label faceZoneIndex = faceZones.whichZone(faceIndex); + + // Face flip + bool faceZoneFlip = false; + + if (faceZoneIndex > -1) + { + // Find face in zone + const label fizIndex = + faceZones[faceZoneIndex].whichFace(faceIndex); + + faceZoneFlip = + faceZones[faceZoneIndex].flipMap()[fizIndex]; + } + + // Found uncovered slave in covered section + // Move to uncovered patch + ref.setAction + ( + polyModifyFace + ( + allFaces[faceIndex], // modified face + faceIndex, // modified face index + owner[faceIndex], // owner + -1, // neighbour + false, // face flip + slaveCoveredPatch.index(), // patch for face + false, // remove from zone + faceZoneIndex, // zone for face + faceZoneFlip // face flip in zone + ) + ); + } + } + } + + + // Clear uncovered masks to indicate that the topological change + // has been performed + uncMaster_.clear(); + uncSlave_.clear(); +} + + +void Foam::repatchCoverage::modifyMotionPoints(pointField& motionPoints) const +{} + + +void Foam::repatchCoverage::updateMesh(const mapPolyMesh&) +{ + // Mesh has changed topologically. Update local topological data + const polyMesh& mesh = topoChanger().mesh(); + + masterCoveredPatchID_.update(mesh.boundaryMesh()); + masterUncoveredPatchID_.update(mesh.boundaryMesh()); + slaveCoveredPatchID_.update(mesh.boundaryMesh()); + slaveUncoveredPatchID_.update(mesh.boundaryMesh()); +} + + +void Foam::repatchCoverage::write(Ostream& os) const +{ + os << nl << type() << nl + << name() << nl + << masterCoveredPatchID_.name() << nl + << masterUncoveredPatchID_.name() << nl + << slaveCoveredPatchID_.name() << nl + << slaveUncoveredPatchID_.name() << endl; +} + + +void Foam::repatchCoverage::writeDict(Ostream& os) const +{ + os << nl << name() << nl << token::BEGIN_BLOCK << nl + << " type " << type() + << token::END_STATEMENT << nl + << " masterCoveredPatchName " << masterCoveredPatchID_.name() + << token::END_STATEMENT << nl + << " masterUncoveredPatchName " << masterUncoveredPatchID_.name() + << token::END_STATEMENT << nl + << " slaveCoveredPatchName " << slaveCoveredPatchID_.name() + << token::END_STATEMENT << nl + << " slaveUncoveredPatchName " << slaveUncoveredPatchID_.name() + << token::END_STATEMENT << nl + << " repatchThreshold " << repatchThreshold_ + << token::END_STATEMENT << nl + << " active " << active() + << token::END_STATEMENT << nl + << token::END_BLOCK << endl; +} + + +// ************************************************************************* // diff --git a/src/dynamicMesh/dynamicMesh/polyMeshModifiers/repatchCoverage/repatchCoverage.H b/src/dynamicMesh/dynamicMesh/polyMeshModifiers/repatchCoverage/repatchCoverage.H new file mode 100644 index 000000000..c2ab6be4f --- /dev/null +++ b/src/dynamicMesh/dynamicMesh/polyMeshModifiers/repatchCoverage/repatchCoverage.H @@ -0,0 +1,168 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | foam-extend: Open Source CFD + \\ / O peration | + \\ / A nd | For copyright notice see file Copyright + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of foam-extend. + + foam-extend 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. + + foam-extend 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 foam-extend. If not, see . + +Class + Foam::repatchCoverage + +Description + Repatch boundary mesh modifier. This modifier is used to move uncovered + faces of a partially covered patch pair into a separate patch for + master and slave side separately. + +SourceFiles + repatchCoverage.C + +\*---------------------------------------------------------------------------*/ + +#ifndef repatchCoverage_H +#define repatchCoverage_H + +#include "polyMeshModifier.H" +#include "polyPatchID.H" +#include "ZoneIDs.H" +#include "ggiInterpolation.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class repatchCoverage Declaration +\*---------------------------------------------------------------------------*/ + +class repatchCoverage +: + public polyMeshModifier +{ + // Private data + + //- Master covered patch ID + polyPatchID masterCoveredPatchID_; + + //- Master uncovered patch ID + polyPatchID masterUncoveredPatchID_; + + //- Slave covered patch ID + polyPatchID slaveCoveredPatchID_; + + //- Slave uncovered patch ID + polyPatchID slaveUncoveredPatchID_; + + //- Repatch threshold + scalar repatchThreshold_; + + + //- Demand-driven data + + //- Uncovered master face indicator + mutable boolList uncMaster_; + + //- Uncovered slave face indicator + mutable boolList uncSlave_; + + + // Private Member Functions + + //- Disallow default bitwise copy construct + repatchCoverage(const repatchCoverage&); + + //- Disallow default bitwise assignment + void operator=(const repatchCoverage&); + + + // Helper functions + + //- Check validity of construction data + void checkDefinition(); + + +public: + + //- Runtime type information + TypeName("repatchCoverage"); + + + // Constructors + + //- Construct from components + repatchCoverage + ( + const word& name, + const label index, + const polyTopoChanger& mme, + const word& masterCoveredPatchName, + const word& masterUncoveredPatchName, + const word& slaveCoveredPatchName, + const word& slaveUncoveredPatchName, + const scalar repatchThreshold + ); + + //- Construct from dictionary + repatchCoverage + ( + const word& name, + const dictionary& dict, + const label index, + const polyTopoChanger& mme + ); + + + // Destructor + + virtual ~repatchCoverage(); + + + // Member Functions + + //- Check for topology change + virtual bool changeTopology() const; + + //- Insert the layer addition/removal instructions + // into the topological change + virtual void setRefinement(polyTopoChange&) const; + + //- Modify motion points to comply with the topological change + virtual void modifyMotionPoints(pointField& motionPoints) const; + + //- Force recalculation of locally stored data on topological change + virtual void updateMesh(const mapPolyMesh&); + + + //- Write + virtual void write(Ostream&) const; + + //- Write dictionary + virtual void writeDict(Ostream&) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* //