Add the OpenFOAM source tree

This commit is contained in:
Henry
2014-12-10 22:40:10 +00:00
parent ee487c860d
commit 446e5777f0
13379 changed files with 3983377 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,430 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "slidingInterface.H"
#include "polyMesh.H"
#include "primitiveMesh.H"
#include "polyTopoChange.H"
#include "polyTopoChanger.H"
#include "polyModifyFace.H"
#include "polyModifyPoint.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::slidingInterface::decoupleInterface
(
polyTopoChange& ref
) const
{
if (debug)
{
Pout<< "void slidingInterface::decoupleInterface("
<< "polyTopoChange& ref) const : "
<< "Decoupling sliding interface " << name() << endl;
}
if (!attached_)
{
if (debug)
{
Pout<< "void slidingInterface::decoupleInterface("
<< "polyTopoChange& ref) const : "
<< "Interface already decoupled." << endl;
}
return;
}
// Clear previous couple
clearCouple(ref);
const polyMesh& mesh = topoChanger().mesh();
const faceList& faces = mesh.faces();
const cellList& cells = mesh.cells();
const labelList& own = mesh.faceOwner();
const labelList& nei = mesh.faceNeighbour();
// Master side
const primitiveFacePatch& masterPatch =
mesh.faceZones()[masterFaceZoneID_.index()]();
const labelList& masterPatchAddr =
mesh.faceZones()[masterFaceZoneID_.index()];
const boolList& masterPatchFlip =
mesh.faceZones()[masterFaceZoneID_.index()].flipMap();
const labelList& masterFc = masterFaceCells();
// Recover faces in master patch
forAll(masterPatchAddr, faceI)
{
// Make a copy of the face and turn it if necessary
face newFace = faces[masterPatchAddr[faceI]];
if (masterPatchFlip[faceI])
{
newFace.flip();
}
ref.setAction
(
polyModifyFace
(
newFace, // new face
masterPatchAddr[faceI], // master face index
masterFc[faceI], // owner
-1, // neighbour
false, // flux flip
masterPatchID_.index(), // patch ID
false, // remove from zone
masterFaceZoneID_.index(), // zone ID
false // zone flip. Face corrected
)
);
// Pout<< "Modifying master patch face no "
// << masterPatchAddr[faceI]
// << " face: " << faces[masterPatchAddr[faceI]]
// << " old owner: " << own[masterPatchAddr[faceI]]
// << " new owner: " << masterFc[faceI]
// << endl;
}
// Slave side
const primitiveFacePatch& slavePatch =
mesh.faceZones()[slaveFaceZoneID_.index()]();
const labelList& slavePatchAddr =
mesh.faceZones()[slaveFaceZoneID_.index()];
const boolList& slavePatchFlip =
mesh.faceZones()[slaveFaceZoneID_.index()].flipMap();
const labelList& slaveFc = slaveFaceCells();
// Grab retired point mapping
const Map<label>& rpm = retiredPointMap();
// Recover faces in slave patch
forAll(slavePatchAddr, faceI)
{
// Make a copy of face and turn it if necessary
face newFace = faces[slavePatchAddr[faceI]];
if (slavePatchFlip[faceI])
{
newFace.flip();
}
// Recover retired points on the slave side
forAll(newFace, pointI)
{
Map<label>::const_iterator rpmIter = rpm.find(newFace[pointI]);
if (rpmIter != rpm.end())
{
// Master of retired point; grab its original
// Pout<< "Reinstating retired point: " << newFace[pointI]
// << " with old: " << rpm.find(newFace[pointI])()
// << endl;
newFace[pointI] = rpmIter();
}
}
ref.setAction
(
polyModifyFace
(
newFace, // new face
slavePatchAddr[faceI], // master face index
slaveFc[faceI], // owner
-1, // neighbour
false, // flux flip
slavePatchID_.index(), // patch ID
false, // remove from zone
slaveFaceZoneID_.index(), // zone ID
false // zone flip. Face corrected
)
);
}
// Re-create the master stick-out faces
// Grab the list of faces in the layer
const labelList& masterStickOuts = masterStickOutFaces();
forAll(masterStickOuts, faceI)
{
// Renumber the face and remove additional points
const label curFaceID = masterStickOuts[faceI];
const face& oldFace = faces[curFaceID];
DynamicList<label> newFaceLabels(oldFace.size());
bool changed = false;
forAll(oldFace, pointI)
{
// Check if the point is removed
if (ref.pointRemoved(oldFace[pointI]))
{
// Point removed; skip it
changed = true;
}
else
{
newFaceLabels.append(oldFace[pointI]);
}
}
if (changed)
{
if (newFaceLabels.size() < 3)
{
FatalErrorIn
(
"void slidingInterface::decoupleInterface("
"polyTopoChange& ref) const"
) << "Face " << curFaceID << " reduced to less than "
<< "3 points. Topological/cutting error." << nl
<< "Old face: " << oldFace << " new face: " << newFaceLabels
<< abort(FatalError);
}
// Get face zone and its flip
label modifiedFaceZone = mesh.faceZones().whichZone(curFaceID);
bool modifiedFaceZoneFlip = false;
if (modifiedFaceZone >= 0)
{
modifiedFaceZoneFlip =
mesh.faceZones()[modifiedFaceZone].flipMap()
[
mesh.faceZones()[modifiedFaceZone].whichFace(curFaceID)
];
}
face newFace;
newFace.transfer(newFaceLabels);
// Pout<< "Modifying master stick-out face " << curFaceID
// << " old face: " << oldFace
// << " new face: " << newFace
// << endl;
// Modify the face
ref.setAction
(
polyModifyFace
(
newFace, // modified face
curFaceID, // label of face being modified
own[curFaceID], // owner
nei[curFaceID], // neighbour
false, // face flip
mesh.boundaryMesh().whichPatch(curFaceID), // patch for face
false, // remove from zone
modifiedFaceZone, // zone for face
modifiedFaceZoneFlip // face flip in zone
)
);
}
}
// Re-create the slave stick-out faces
labelHashSet slaveLayerCellFaceMap
(
primitiveMesh::facesPerCell_*(masterPatch.size() + slavePatch.size())
);
forAll(slaveFc, faceI)
{
const labelList& curFaces = cells[slaveFc[faceI]];
forAll(curFaces, faceI)
{
// Check if the face belongs to the slave face zone; and
// if it has been removed; if not add it
if
(
mesh.faceZones().whichZone(curFaces[faceI])
!= slaveFaceZoneID_.index()
&& !ref.faceRemoved(curFaces[faceI])
)
{
slaveLayerCellFaceMap.insert(curFaces[faceI]);
}
}
}
// Grab the list of faces in the layer
const labelList& slaveStickOuts = slaveStickOutFaces();
// Grab master point mapping
const Map<label>& masterPm = masterPatch.meshPointMap();
forAll(slaveStickOuts, faceI)
{
// Renumber the face and remove additional points
const label curFaceID = slaveStickOuts[faceI];
const face& oldFace = faces[curFaceID];
DynamicList<label> newFaceLabels(oldFace.size());
bool changed = false;
forAll(oldFace, pointI)
{
// Check if the point is removed or retired
if (rpm.found(oldFace[pointI]))
{
// Master of retired point; grab its original
changed = true;
// Pout<< "Reinstating retired point: " << oldFace[pointI]
// << " with old: " << rpm.find(oldFace[pointI])()
// << endl;
newFaceLabels.append(rpm.find(oldFace[pointI])());
}
else if (ref.pointRemoved(oldFace[pointI]))
{
// Point removed; skip it
changed = true;
}
else if (masterPm.found(oldFace[pointI]))
{
// Point from master patch only; skip it
changed = true;
}
else
{
newFaceLabels.append(oldFace[pointI]);
}
}
if (changed)
{
if (newFaceLabels.size() < 3)
{
FatalErrorIn
(
"void slidingInterface::decoupleInterface("
"polyTopoChange& ref) const"
) << "Face " << curFaceID << " reduced to less than "
<< "3 points. Topological/cutting error." << nl
<< "Old face: " << oldFace << " new face: " << newFaceLabels
<< abort(FatalError);
}
// Get face zone and its flip
label modifiedFaceZone = mesh.faceZones().whichZone(curFaceID);
bool modifiedFaceZoneFlip = false;
if (modifiedFaceZone >= 0)
{
modifiedFaceZoneFlip =
mesh.faceZones()[modifiedFaceZone].flipMap()
[
mesh.faceZones()[modifiedFaceZone].whichFace(curFaceID)
];
}
face newFace;
newFace.transfer(newFaceLabels);
// Pout<< "Modifying slave stick-out face " << curFaceID
// << " old face: " << oldFace
// << " new face: " << newFace
// << endl;
// Modify the face
ref.setAction
(
polyModifyFace
(
newFace, // modified face
curFaceID, // label of face being modified
own[curFaceID], // owner
nei[curFaceID], // neighbour
false, // face flip
mesh.boundaryMesh().whichPatch(curFaceID), // patch for face
false, // remove from zone
modifiedFaceZone, // zone for face
modifiedFaceZoneFlip // face flip in zone
)
);
}
}
// Bring all slave patch points back to life
const pointField& points = mesh.points();
const labelList& slaveMeshPoints =
mesh.faceZones()[slaveFaceZoneID_.index()]().meshPoints();
forAll(slaveMeshPoints, pointI)
{
ref.setAction
(
polyModifyPoint
(
slaveMeshPoints[pointI], // point ID
points[slaveMeshPoints[pointI]], // point
false, // remove from zone
mesh.pointZones().whichZone(slaveMeshPoints[pointI]), // zone
true // in a cell
)
);
}
// Clear the retired point numbering
retiredPointMapPtr_->clear();
// Finished decoupling
attached_ = false;
if (debug)
{
Pout<< "void slidingInterface::coupleInterface("
<< "polyTopoChange& ref) const : "
<< "Finished decoupling sliding interface " << name() << endl;
}
}
// ************************************************************************* //

View File

@ -0,0 +1,287 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "enrichedPatch.H"
#include "demandDrivenData.H"
#include "OFstream.H"
#include "meshTools.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(enrichedPatch, 0);
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::enrichedPatch::calcMeshPoints() const
{
if (meshPointsPtr_)
{
FatalErrorIn("void enrichedPatch::calcMeshPoints() const")
<< "Mesh points already calculated."
<< abort(FatalError);
}
meshPointsPtr_ = new labelList(pointMap().toc());
labelList& mp = *meshPointsPtr_;
sort(mp);
}
void Foam::enrichedPatch::calcLocalFaces() const
{
if (localFacesPtr_)
{
FatalErrorIn("void enrichedPatch::calcLocalFaces() const")
<< "Local faces already calculated."
<< abort(FatalError);
}
// Invert mesh points and renumber faces using it
const labelList& mp = meshPoints();
Map<label> mpLookup(2*mp.size());
forAll(mp, mpI)
{
mpLookup.insert(mp[mpI], mpI);
}
const faceList& faces = enrichedFaces();
localFacesPtr_ = new faceList(faces.size());
faceList& lf = *localFacesPtr_;
forAll(faces, faceI)
{
const face& f = faces[faceI];
face& curlf = lf[faceI];
curlf.setSize(f.size());
forAll(f, pointI)
{
curlf[pointI] = mpLookup.find(f[pointI])();
}
}
}
void Foam::enrichedPatch::calcLocalPoints() const
{
if (localPointsPtr_)
{
FatalErrorIn("void enrichedPatch::calcLocalPoints() const")
<< "Local points already calculated."
<< abort(FatalError);
}
const labelList& mp = meshPoints();
localPointsPtr_ = new pointField(mp.size());
pointField& lp = *localPointsPtr_;
forAll(lp, i)
{
lp[i] = pointMap().find(mp[i])();
}
}
void Foam::enrichedPatch::clearOut()
{
deleteDemandDrivenData(enrichedFacesPtr_);
deleteDemandDrivenData(meshPointsPtr_);
deleteDemandDrivenData(localFacesPtr_);
deleteDemandDrivenData(localPointsPtr_);
deleteDemandDrivenData(pointPointsPtr_);
deleteDemandDrivenData(masterPointFacesPtr_);
clearCutFaces();
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// Construct from components
Foam::enrichedPatch::enrichedPatch
(
const primitiveFacePatch& masterPatch,
const primitiveFacePatch& slavePatch,
const labelList& slavePointPointHits,
const labelList& slavePointEdgeHits,
const List<objectHit>& slavePointFaceHits
)
:
masterPatch_(masterPatch),
slavePatch_(slavePatch),
pointMap_
(
masterPatch_.meshPoints().size()
+ slavePatch_.meshPoints().size()
),
pointMapComplete_(false),
pointMergeMap_(2*slavePatch_.meshPoints().size()),
slavePointPointHits_(slavePointPointHits),
slavePointEdgeHits_(slavePointEdgeHits),
slavePointFaceHits_(slavePointFaceHits),
enrichedFacesPtr_(NULL),
meshPointsPtr_(NULL),
localFacesPtr_(NULL),
localPointsPtr_(NULL),
pointPointsPtr_(NULL),
masterPointFacesPtr_(NULL),
cutFacesPtr_(NULL),
cutFaceMasterPtr_(NULL),
cutFaceSlavePtr_(NULL)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::enrichedPatch::~enrichedPatch()
{
clearOut();
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::labelList& Foam::enrichedPatch::meshPoints() const
{
if (!meshPointsPtr_)
{
calcMeshPoints();
}
return *meshPointsPtr_;
}
const Foam::faceList& Foam::enrichedPatch::localFaces() const
{
if (!localFacesPtr_)
{
calcLocalFaces();
}
return *localFacesPtr_;
}
const Foam::pointField& Foam::enrichedPatch::localPoints() const
{
if (!localPointsPtr_)
{
calcLocalPoints();
}
return *localPointsPtr_;
}
const Foam::labelListList& Foam::enrichedPatch::pointPoints() const
{
if (!pointPointsPtr_)
{
calcPointPoints();
}
return *pointPointsPtr_;
}
bool Foam::enrichedPatch::checkSupport() const
{
const faceList& faces = enrichedFaces();
bool error = false;
forAll(faces, faceI)
{
const face& curFace = faces[faceI];
forAll(curFace, pointI)
{
if (!pointMap().found(curFace[pointI]))
{
WarningIn("void enrichedPatch::checkSupport()")
<< "Point " << pointI << " of face " << faceI
<< " global point index: " << curFace[pointI]
<< " not supported in point map. This is not allowed."
<< endl;
error = true;
}
}
}
return error;
}
void Foam::enrichedPatch::writeOBJ(const fileName& fName) const
{
OFstream str(fName);
const pointField& lp = localPoints();
forAll(lp, pointI)
{
meshTools::writeOBJ(str, lp[pointI]);
}
const faceList& faces = localFaces();
forAll(faces, faceI)
{
const face& f = faces[faceI];
str << 'f';
forAll(f, fp)
{
str << ' ' << f[fp]+1;
}
str << nl;
}
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -0,0 +1,293 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
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 <http://www.gnu.org/licenses/>.
Class
Foam::enrichedPatch
Description
The enriched patch contains a double set of faces from the two
sides of the sliding interface before the cutting.
The patch basically consists of two over-lapping sets of faces sitting
on a common point support, where every edge may be shared by more than
2 faces. The patch points are collected in a map. Additional
information needed for cutting is the point insertion into every edge
of master and slave.
Note:
If new points are created during master-slave edge cutting, they
should be registred with the pointMap.
SourceFiles
enrichedPatch.C
enrichedPatchCutFaces.C
enrichedPatchFaces.C
enrichedPatchPointMap.C
enrichedPatchPointMergeMap.C
enrichedPatchPointPoints.C
\*---------------------------------------------------------------------------*/
#ifndef enrichedPatch_H
#define enrichedPatch_H
#include "primitiveFacePatch.H"
#include "Map.H"
#include "point.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class enrichedPatch Declaration
\*---------------------------------------------------------------------------*/
class enrichedPatch
{
// Private data
//- Reference to master patch
const primitiveFacePatch& masterPatch_;
//- Reference to slave patch
const primitiveFacePatch& slavePatch_;
//- Map of points supporting patch faces
mutable Map<point> pointMap_;
//- Has the point map been completed?
mutable bool pointMapComplete_;
//- Map of point merges
mutable Map<label> pointMergeMap_;
//- Slave point point hits
const labelList& slavePointPointHits_;
//- Slave point edge hits
const labelList& slavePointEdgeHits_;
//- Slave point face hits
const List<objectHit>& slavePointFaceHits_;
// Demand-driven private data
//- Enriched patch
mutable faceList* enrichedFacesPtr_;
//- Mesh points
mutable labelList* meshPointsPtr_;
//- Local faces
mutable faceList* localFacesPtr_;
//- Local points
mutable pointField* localPointsPtr_;
//- Point-point addressing
mutable labelListList* pointPointsPtr_;
// Master point addressing
mutable Map<labelList>* masterPointFacesPtr_;
// Cut faces and addressing
//- Cut faces
mutable faceList* cutFacesPtr_;
//- Cut face master
// - the face on the master patch for internal faces
// - the creator face for boundary face
mutable labelList* cutFaceMasterPtr_;
//- Cut face slave
// - the face on the slave patch for internal faces
// - -1 for boundary face
mutable labelList* cutFaceSlavePtr_;
// Private Member Functions
//- Disallow default bitwise copy construct
enrichedPatch(const enrichedPatch&);
//- Disallow default bitwise assignment
void operator=(const enrichedPatch&);
// Creation of demand-driven private data
//- Calculate point merge map
void calcPointMergeMap() const;
//- Complete point map
void completePointMap() const;
//- Calculate mesh points
void calcMeshPoints() const;
//- Calculate local points
void calcLocalPoints() const;
//- Calculate local faces
void calcLocalFaces() const;
//- Calculate point-point addressing
void calcPointPoints() const;
//- Calculate master point addressing
void calcMasterPointFaces() const;
//- Calculate cut faces
void calcCutFaces() const;
//- Clear cut faces
void clearCutFaces();
//- Clear out demand-driven data
void clearOut();
// Static data members
//- Estimated ratio of original-to-enriched face size
static const label enrichedFaceRatio_;
//- Estimated number of master face hits by slave points
static const label nFaceHits_;
//- Size of face on which the check is forced
static const label maxFaceSizeDebug_;
public:
// Static data members
ClassName("enrichedPatch");
// Constructors
//- Construct from components
enrichedPatch
(
const primitiveFacePatch& masterPatch,
const primitiveFacePatch& slavePatch,
const labelList& slavePointPointHits,
// -1 or common point snapped to
const labelList& slavePointEdgeHits,
// -1 or common edge snapped to
const List<objectHit>& slavePointFaceHits
// master face snapped to
);
//- Destructor
~enrichedPatch();
// Member Functions
// Access
//- Return non-const access to point map to add points
Map<point>& pointMap();
//- Return map of points
const Map<point>& pointMap() const;
//- Return map of point merges
Map<label>& pointMergeMap()
{
return pointMergeMap_;
}
//- Return map of point merges
const Map<label>& pointMergeMap() const
{
return pointMergeMap_;
}
// Topological data
//- Calculate enriched faces
void calcEnrichedFaces
(
const labelListList& pointsIntoMasterEdges,
const labelListList& pointsIntoSlaveEdges,
const pointField& projectedSlavePoints
);
//- Return enriched faces
const faceList& enrichedFaces() const;
//- Return mesh points
const labelList& meshPoints() const;
//- Return local faces
const faceList& localFaces() const;
//- Return local points
const pointField& localPoints() const;
//- Return point-point addressing
const labelListList& pointPoints() const;
//- Master point face addressing
const Map<labelList>& masterPointFaces() const;
// Cut faces
//- Return list of cut faces
const faceList& cutFaces() const;
//- Return cut face master list
const labelList& cutFaceMaster() const;
//- Return cut face slave list
const labelList& cutFaceSlave() const;
//- Check if the patch is fully supported
bool checkSupport() const;
//- Debugging: dump graphical representation to obj format file
void writeOBJ(const fileName&) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,709 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
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 <http://www.gnu.org/licenses/>.
Description
Calculating cut faces of the enriched patch, together with the addressing
into master and slave patch.
\*---------------------------------------------------------------------------*/
#include "enrichedPatch.H"
#include "boolList.H"
#include "DynamicList.H"
#include "labelPair.H"
#include "primitiveMesh.H"
#include "HashSet.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
// If the cut face gets more than this number of points, it will be checked
const Foam::label Foam::enrichedPatch::maxFaceSizeDebug_ = 100;
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// Index of debug signs:
// x - skip a point
// l - left turn
// r - right turn
void Foam::enrichedPatch::calcCutFaces() const
{
if (cutFacesPtr_ || cutFaceMasterPtr_ || cutFaceSlavePtr_)
{
FatalErrorIn("void enrichedPatch::calcCutFaces() const")
<< "Cut faces addressing already calculated."
<< abort(FatalError);
}
const faceList& enFaces = enrichedFaces();
const labelList& mp = meshPoints();
const faceList& lf = localFaces();
const pointField& lp = localPoints();
const labelListList& pp = pointPoints();
// Pout<< "enFaces: " << enFaces << endl;
// Pout<< "lf: " << lf << endl;
// Pout<< "lp: " << lp << endl;
// Pout<< "pp: " << pp << endl;
const Map<labelList>& masterPointFaceAddr = masterPointFaces();
// Prepare the storage
DynamicList<face> cf(2*lf.size());
DynamicList<label> cfMaster(2*lf.size());
DynamicList<label> cfSlave(2*lf.size());
// Algorithm
// Go through all the faces
// 1) For each face, start at point zero and grab the edge zero.
// Both points are added into the cut face. Mark the first edge
// as used and position the current point as the end of the first
// edge and previous point as point zero.
// 2) Grab all possible points from the current point. Excluding
// the previous point find the point giving the biggest right
// turn. Add the point to the face and mark the edges as used.
// Continue doing this until the face is complete, i.e. the next point
// to add is the first point of the face.
// 3) Once the facet is completed, register its owner from the face
// it has been created from (remember that the first lot of faces
// inserted into the enriched faces list are the slaves, to allow
// matching of the other side).
// 4) If the facet is created from an original slave face, go
// through the master patch and try to identify the master face
// this facet belongs to. This is recognised by the fact that the
// faces consists exclusively of the points of the master face and
// the points projected onto the face.
// Create a set of edge usage parameters
HashSet<edge, Hash<edge> > edgesUsedOnce(pp.size());
HashSet<edge, Hash<edge> > edgesUsedTwice
(pp.size()*primitiveMesh::edgesPerPoint_);
forAll(lf, faceI)
{
const face& curLocalFace = lf[faceI];
const face& curGlobalFace = enFaces[faceI];
// Pout<< "Doing face " << faceI
// << " local: " << curLocalFace
// << " or " << curGlobalFace
// << endl;
// if (faceI < slavePatch_.size())
// {
// Pout<< "original slave: " << slavePatch_[faceI]
// << " local: " << slavePatch_.localFaces()[faceI] << endl;
// }
// else
// {
// Pout<< "original master: "
// << masterPatch_[faceI - slavePatch_.size()] << " "
// << masterPatch_.localFaces()[faceI - slavePatch_.size()]
// << endl;
// }
// {
// pointField facePoints = curLocalFace.points(lp);
// forAll(curLocalFace, pointI)
// {
// Pout<< "v " << facePoints[pointI].x() << " "
// << facePoints[pointI].y() << " "
// << facePoints[pointI].z() << endl;
// }
// }
// Track the usage of face edges. When all edges are used, the
// face decomposition is complete.
// The seed edges include all the edges of the original face + all edges
// of other faces that have been used in the construction of the
// facet. Edges from other faces can be considered as
// internal to the current face if used only once.
// Track the edge usage to avoid duplicate faces and reset it to unused
boolList usedFaceEdges(curLocalFace.size(), false);
SLList<edge> edgeSeeds;
// Insert the edges of current face into the seed list.
edgeList cfe = curLocalFace.edges();
forAll(curLocalFace, edgeI)
{
edgeSeeds.append(cfe[edgeI]);
}
// Grab face normal
vector normal = curLocalFace.normal(lp);
normal /= mag(normal);
while (edgeSeeds.size())
{
// Pout<< "edgeSeeds.size(): "
// << edgeSeeds.size()
// << endl;
const edge curEdge = edgeSeeds.removeHead();
// Locate the edge in current face
const label curEdgeWhich = curLocalFace.which(curEdge.start());
// Check if the edge is in current face and if it has been
// used already. If so, skip it
if
(
curEdgeWhich > -1
&& curLocalFace.nextLabel(curEdgeWhich) == curEdge.end()
)
{
// Edge is in the starting face.
// If unused, mark it as used; if used, skip it
if (usedFaceEdges[curEdgeWhich]) continue;
usedFaceEdges[curEdgeWhich] = true;
}
// If the edge has already been used twice, skip it
if (edgesUsedTwice.found(curEdge)) continue;
// Pout<< "Trying new edge (" << mp[curEdge.start()]
// << ", " << mp[curEdge.end()]
// << ") seed: " << curEdge
// << " used: " << edgesUsedTwice.found(curEdge)
// << endl;
// Estimate the size of cut face as twice the size of original face
DynamicList<label> cutFaceGlobalPoints(2*curLocalFace.size());
DynamicList<label> cutFaceLocalPoints(2*curLocalFace.size());
// Found unused edge.
label prevPointLabel = curEdge.start();
cutFaceGlobalPoints.append(mp[prevPointLabel]);
cutFaceLocalPoints.append(prevPointLabel);
// Pout<< "prevPointLabel: " << mp[prevPointLabel] << endl;
// Grab current point and append it to the list
label curPointLabel = curEdge.end();
point curPoint = lp[curPointLabel];
cutFaceGlobalPoints.append(mp[curPointLabel]);
cutFaceLocalPoints.append(curPointLabel);
bool completedCutFace = false;
label faceSizeDebug = maxFaceSizeDebug_;
do
{
// Grab the next point options
// Pout<< "curPointLabel: " << mp[curPointLabel] << endl;
const labelList& nextPoints = pp[curPointLabel];
// Pout<< "nextPoints: "
// << UIndirectList<label>(mp, nextPoints)
// << endl;
// Get the vector along the edge and the right vector
vector ahead = curPoint - lp[prevPointLabel];
ahead -= normal*(normal & ahead);
ahead /= mag(ahead);
vector right = normal ^ ahead;
right /= mag(right);
// Pout<< "normal: " << normal
// << " ahead: " << ahead
// << " right: " << right
// << endl;
scalar atanTurn = -GREAT;
label bestAtanPoint = -1;
forAll(nextPoints, nextI)
{
// Exclude the point we are coming from; there will always
// be more than one edge, so this is safe
if (nextPoints[nextI] != prevPointLabel)
{
// Pout<< "cur point: " << curPoint
// << " trying for point: "
// << mp[nextPoints[nextI]]
// << " " << lp[nextPoints[nextI]];
vector newDir = lp[nextPoints[nextI]] - curPoint;
// Pout<< " newDir: " << newDir
// << " mag: " << mag(newDir) << flush;
newDir -= normal*(normal & newDir);
scalar magNewDir = mag(newDir);
// Pout<< " corrected: " << newDir
// << " mag: " << mag(newDir) << flush;
if (magNewDir < SMALL)
{
FatalErrorIn
(
"void enrichedPatch::"
"calcCutFaces() const"
) << "Zero length edge detected. Probable "
<< "projection error: slave patch probably "
<< "does not project onto master. "
<< "Please switch on "
<< "enriched patch debug for more info"
<< abort(FatalError);
}
newDir /= magNewDir;
scalar curAtanTurn =
atan2(newDir & right, newDir & ahead);
// Pout<< " atan: " << curAtanTurn << endl;
if (curAtanTurn > atanTurn)
{
bestAtanPoint = nextPoints[nextI];
atanTurn = curAtanTurn;
}
} // end of prev point skip
} // end of next point selection
// Pout<< " bestAtanPoint: " << bestAtanPoint << " or "
// << mp[bestAtanPoint]
// << endl;
// Selected next best point.
// Pout<< "cutFaceGlobalPoints: "
// << cutFaceGlobalPoints
// << endl;
// Check if the edge about to be added has been used
// in the current face or twice in other faces. If
// so, the face is bad.
const label whichNextPoint = curLocalFace.which(curPointLabel);
if
(
whichNextPoint > -1
&& curLocalFace.nextLabel(whichNextPoint) == bestAtanPoint
&& usedFaceEdges[whichNextPoint]
)
{
// This edge is already used in current face
// face cannot be good; start on a new one
// Pout<< "Double usage in current face, cannot be good"
// << endl;
completedCutFace = true;
}
if (edgesUsedTwice.found(edge(curPointLabel, bestAtanPoint)))
{
// This edge is already used -
// face cannot be good; start on a new one
completedCutFace = true;
// Pout<< "Double usage elsewhere, cannot be good" << endl;
}
if (completedCutFace) continue;
// Insert the next best point into the list
if (mp[bestAtanPoint] == cutFaceGlobalPoints[0])
{
// Face is completed. Save it and move on to the next
// available edge
completedCutFace = true;
if (debug)
{
Pout<< " local: " << cutFaceLocalPoints
<< " one side: " << faceI;
}
// Append the face
face cutFaceGlobal;
cutFaceGlobal.transfer(cutFaceGlobalPoints);
cf.append(cutFaceGlobal);
face cutFaceLocal;
cutFaceLocal.transfer(cutFaceLocalPoints);
// Pout<< "\ncutFaceLocal: "
// << cutFaceLocal.points(lp)
// << endl;
// Go through all edges of the cut faces.
// If the edge corresponds to a starting face edge,
// mark the starting face edge as true
forAll(cutFaceLocal, cutI)
{
const edge curCutFaceEdge
(
cutFaceLocal[cutI],
cutFaceLocal.nextLabel(cutI)
);
// Increment the usage count using two hash sets
HashSet<edge, Hash<edge> >::iterator euoIter =
edgesUsedOnce.find(curCutFaceEdge);
if (euoIter == edgesUsedOnce.end())
{
// Pout<< "Found edge not used before: "
// << curCutFaceEdge
// << endl;
edgesUsedOnce.insert(curCutFaceEdge);
}
else
{
// Pout<< "Found edge used once: "
// << curCutFaceEdge
// << endl;
edgesUsedOnce.erase(euoIter);
edgesUsedTwice.insert(curCutFaceEdge);
}
const label curCutFaceEdgeWhich = curLocalFace.which
(
curCutFaceEdge.start()
);
if
(
curCutFaceEdgeWhich > -1
&& curLocalFace.nextLabel(curCutFaceEdgeWhich)
== curCutFaceEdge.end()
)
{
// Found edge in original face
// Pout<< "Found edge in orig face: "
// << curCutFaceEdge << ": "
// << curCutFaceEdgeWhich
// << endl;
usedFaceEdges[curCutFaceEdgeWhich] = true;
}
else
{
// Edge not in original face. Add it to seeds
// Pout<< "Found new edge seed: "
// << curCutFaceEdge
// << endl;
edgeSeeds.append(curCutFaceEdge.reverseEdge());
}
}
// Find out what the other side is
// Algorithm
// If the face is in the slave half of the
// enrichedFaces lists, it may be matched against
// the master face. It can be recognised by the
// fact that all its points belong to one master
// face. For this purpose:
// 1) Grab the master faces around the point zero
// of the cut face and collect all master faces
// around it.
// 2) Loop through the rest of cut face points and
// if the point refers to one of the faces marked
// by point zero, increment its count.
// 3) When completed, the face whose count is
// equal to the number of points in the cut face
// is the other side. If this is not the case, there is no
// face on the other side.
if (faceI < slavePatch_.size())
{
Map<labelList>::const_iterator mpfAddrIter =
masterPointFaceAddr.find(cutFaceGlobal[0]);
bool otherSideFound = false;
if (mpfAddrIter != masterPointFaceAddr.end())
{
bool miss = false;
// Create the label count using point zero
const labelList& masterFacesOfPZero = mpfAddrIter();
labelList hits(masterFacesOfPZero.size(), 1);
for
(
label pointI = 1;
pointI < cutFaceGlobal.size();
pointI++
)
{
Map<labelList>::const_iterator
mpfAddrPointIter =
masterPointFaceAddr.find
(
cutFaceGlobal[pointI]
);
if
(
mpfAddrPointIter
== masterPointFaceAddr.end()
)
{
// Point is off the master patch. Skip
miss = true;
break;
}
const labelList& curMasterFaces =
mpfAddrPointIter();
// For every current face, try to find it in the
// zero-list
forAll(curMasterFaces, i)
{
forAll(masterFacesOfPZero, j)
{
if
(
curMasterFaces[i]
== masterFacesOfPZero[j]
)
{
hits[j]++;
break;
}
}
}
}
// If all point are found attempt matching
if (!miss)
{
forAll(hits, pointI)
{
if (hits[pointI] == cutFaceGlobal.size())
{
// Found other side.
otherSideFound = true;
cfMaster.append
(
masterFacesOfPZero[pointI]
);
cfSlave.append(faceI);
// Reverse the face such that it
// points out of the master patch
cf.last().flip();
if (debug)
{
Pout<< " other side: "
<< masterFacesOfPZero[pointI]
<< endl;
}
} // end of hits
} // end of for all hits
} // end of not miss
if (!otherSideFound || miss)
{
if (debug)
{
Pout<< " solo slave A" << endl;
}
cfMaster.append(-1);
cfSlave.append(faceI);
}
}
else
{
// First point not in master patch
if (debug)
{
Pout<< " solo slave B" << endl;
}
cfMaster.append(-1);
cfSlave.append(faceI);
}
}
else
{
if (debug)
{
Pout<< " master side" << endl;
}
cfMaster.append(faceI - slavePatch_.size());
cfSlave.append(-1);
}
}
else
{
// Face not completed. Prepare for the next point search
prevPointLabel = curPointLabel;
curPointLabel = bestAtanPoint;
curPoint = lp[curPointLabel];
cutFaceGlobalPoints.append(mp[curPointLabel]);
cutFaceLocalPoints.append(curPointLabel);
if (debug || cutFaceGlobalPoints.size() > faceSizeDebug)
{
faceSizeDebug *= 2;
// Check for duplicate points in the face
forAll(cutFaceGlobalPoints, checkI)
{
for
(
label checkJ = checkI + 1;
checkJ < cutFaceGlobalPoints.size();
checkJ++
)
{
if
(
cutFaceGlobalPoints[checkI]
== cutFaceGlobalPoints[checkJ]
)
{
// Shrink local points for debugging
cutFaceLocalPoints.shrink();
face origFace;
face origFaceLocal;
if (faceI < slavePatch_.size())
{
origFace = slavePatch_[faceI];
origFaceLocal =
slavePatch_.localFaces()[faceI];
}
else
{
origFace =
masterPatch_
[faceI - slavePatch_.size()];
origFaceLocal =
masterPatch_.localFaces()
[faceI - slavePatch_.size()];
}
FatalErrorIn
(
"void enrichedPatch::"
"calcCutFaces() const"
) << "Duplicate point found in cut face. "
<< "Error in the face cutting "
<< "algorithm for global face "
<< origFace << " local face "
<< origFaceLocal << nl
<< "Slave size: " << slavePatch_.size()
<< " Master size: "
<< masterPatch_.size()
<< " index: " << faceI << ".\n"
<< "Face: " << curGlobalFace << nl
<< "Cut face: " << cutFaceGlobalPoints
<< " local: " << cutFaceLocalPoints
<< nl << "Points: "
<< face(cutFaceLocalPoints).points(lp)
<< abort(FatalError);
}
}
}
} // end of debug
}
} while (!completedCutFace);
} // end of used edges
if (debug)
{
Pout<< " Finished face " << faceI << endl;
}
} // end of local faces
// Re-pack the list into compact storage
cutFacesPtr_ = new faceList();
cutFacesPtr_->transfer(cf);
cutFaceMasterPtr_ = new labelList();
cutFaceMasterPtr_->transfer(cfMaster);
cutFaceSlavePtr_ = new labelList();
cutFaceSlavePtr_->transfer(cfSlave);
}
void Foam::enrichedPatch::clearCutFaces()
{
deleteDemandDrivenData(cutFacesPtr_);
deleteDemandDrivenData(cutFaceMasterPtr_);
deleteDemandDrivenData(cutFaceSlavePtr_);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::faceList& Foam::enrichedPatch::cutFaces() const
{
if (!cutFacesPtr_)
{
calcCutFaces();
}
return *cutFacesPtr_;
}
const Foam::labelList& Foam::enrichedPatch::cutFaceMaster() const
{
if (!cutFaceMasterPtr_)
{
calcCutFaces();
}
return *cutFaceMasterPtr_;
}
const Foam::labelList& Foam::enrichedPatch::cutFaceSlave() const
{
if (!cutFaceSlavePtr_)
{
calcCutFaces();
}
return *cutFaceSlavePtr_;
}
// ************************************************************************* //

View File

@ -0,0 +1,443 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "enrichedPatch.H"
#include "DynamicList.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
const Foam::label Foam::enrichedPatch::enrichedFaceRatio_ = 3;
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::enrichedPatch::calcEnrichedFaces
(
const labelListList& pointsIntoMasterEdges,
const labelListList& pointsIntoSlaveEdges,
const pointField& projectedSlavePoints
)
{
if (enrichedFacesPtr_)
{
FatalErrorIn
(
"void enrichedPatch::calcEnrichedFaces\n"
"(\n"
" const labelListList& pointsIntoMasterEdges,\n"
" const labelListList& pointsIntoSlaveEdges,\n"
" const pointField& projectedSlavePoints\n"
")"
) << "Enriched faces already calculated."
<< abort(FatalError);
}
// Create a list of enriched faces
// Algorithm:
// 1) Grab the original face and start from point zero.
// 2) If the point has been merged away, grab the merge label;
// otherwise, keep the original label.
// 3) Go to the next edge. Collect all the points to be added along
// the edge; order them in the necessary direction and insert onto the
// face.
// 4) Grab the next point and return on step 2.
enrichedFacesPtr_ = new faceList(masterPatch_.size() + slavePatch_.size());
faceList& enrichedFaces = *enrichedFacesPtr_;
label nEnrichedFaces = 0;
const pointField& masterLocalPoints = masterPatch_.localPoints();
const faceList& masterLocalFaces = masterPatch_.localFaces();
const labelListList& masterFaceEdges = masterPatch_.faceEdges();
const faceList& slaveLocalFaces = slavePatch_.localFaces();
const labelListList& slaveFaceEdges = slavePatch_.faceEdges();
// For correct functioning of the enrichedPatch class, the slave
// faces need to be inserted first. See comments in
// enrichedPatch.H
// Get reference to the point merge map
const Map<label>& pmm = pointMergeMap();
// Add slave faces into the enriched faces list
forAll(slavePatch_, faceI)
{
const face oldFace = slavePatch_[faceI];
const face oldLocalFace = slaveLocalFaces[faceI];
// Info<< "old slave face " << faceI << ": " << oldFace << endl;
const labelList& curEdges = slaveFaceEdges[faceI];
DynamicList<label> newFace(oldFace.size()*enrichedFaceRatio_);
// Note: The number of points and edges in a face is always identical
// so both can be done is the same loop
forAll(oldFace, i)
{
// Add the point
Map<label>::const_iterator mpIter =
pmm.find(oldFace[i]);
if (mpIter == pmm.end())
{
// Point not mapped
newFace.append(oldFace[i]);
// Add the projected point into the patch support
pointMap().insert
(
oldFace[i], // Global label of point
projectedSlavePoints[oldLocalFace[i]] // Projected position
);
}
else
{
// Point mapped
newFace.append(mpIter());
// Add the projected point into the patch support
pointMap().insert
(
mpIter(), // Merged global label of point
projectedSlavePoints[oldLocalFace[i]] // Projected position
);
}
// Grab the edge points
const labelList& slavePointsOnEdge =
pointsIntoSlaveEdges[curEdges[i]];
// Info<< "slavePointsOnEdge for "
// << curEdges[i] << ": " << slavePointsOnEdge
// << endl;
// If there are no points on the edge, skip everything
// If there is only one point, no need for sorting
if (slavePointsOnEdge.size())
{
// Sort edge points in order
scalarField edgePointWeights(slavePointsOnEdge.size());
const point& startPoint = projectedSlavePoints[oldLocalFace[i]];
vector e =
projectedSlavePoints[oldLocalFace.nextLabel(i)]
- startPoint;
scalar magSqrE = magSqr(e);
if (magSqrE > SMALL)
{
e /= magSqrE;
}
else
{
FatalErrorIn
(
"void enrichedPatch::calcEnrichedFaces\n"
"(\n"
" const labelListList& pointsIntoMasterEdges,\n"
" const labelListList& pointsIntoSlaveEdges,\n"
" const pointField& projectedSlavePoints\n"
")"
) << "Zero length edge in slave patch for face " << i
<< ". This is not allowed."
<< abort(FatalError);
}
pointField slavePosOnEdge(slavePointsOnEdge.size());
forAll(slavePointsOnEdge, edgePointI)
{
slavePosOnEdge[edgePointI] =
pointMap().find(slavePointsOnEdge[edgePointI])();
edgePointWeights[edgePointI] =
(e & (slavePosOnEdge[edgePointI] - startPoint));
}
if (debug)
{
// Check weights: all new points should be on the edge
if (min(edgePointWeights) < 0 || max(edgePointWeights) > 1)
{
FatalErrorIn
(
"void enrichedPatch::calcEnrichedFaces\n"
"(\n"
" const labelListList& pointsIntoMasterEdges,\n"
" const labelListList& pointsIntoSlaveEdges,\n"
" const pointField& projectedSlavePoints\n"
")"
) << "Invalid point edge weights. Some of points are"
<< " not on the edge for edge " << curEdges[i]
<< " of face " << faceI << " in slave patch." << nl
<< "Min weight: " << min(edgePointWeights)
<< " Max weight: " << max(edgePointWeights)
<< abort(FatalError);
}
}
// Go through the points and collect them based on
// weights from lower to higher. This gives the
// correct order of points along the edge.
forAll(edgePointWeights, passI)
{
// Max weight can only be one, so the sorting is
// done by elimination.
label nextPoint = -1;
scalar dist = 2;
forAll(edgePointWeights, wI)
{
if (edgePointWeights[wI] < dist)
{
dist = edgePointWeights[wI];
nextPoint = wI;
}
}
// Insert the next point and reset its weight to exclude it
// from future picks
newFace.append(slavePointsOnEdge[nextPoint]);
edgePointWeights[nextPoint] = GREAT;
// Add the point into patch support
pointMap().insert
(
slavePointsOnEdge[nextPoint],
slavePosOnEdge[nextPoint]
);
}
}
}
// Info<< "New slave face " << faceI << ": " << newFace << endl;
// Add the new face to the list
enrichedFaces[nEnrichedFaces].transfer(newFace);
nEnrichedFaces++;
}
// Add master faces into the enriched faces list
forAll(masterPatch_, faceI)
{
const face& oldFace = masterPatch_[faceI];
const face& oldLocalFace = masterLocalFaces[faceI];
// Info<< "old master face: " << oldFace << endl;
const labelList& curEdges = masterFaceEdges[faceI];
DynamicList<label> newFace(oldFace.size()*enrichedFaceRatio_);
// Note: The number of points and edges in a face is always identical
// so both can be done is the same loop
forAll(oldFace, i)
{
// Add the point
Map<label>::const_iterator mpIter =
pmm.find(oldFace[i]);
if (mpIter == pmm.end())
{
// Point not mapped
newFace.append(oldFace[i]);
// Add the point into patch support
pointMap().insert
(
oldFace[i],
masterLocalPoints[oldLocalFace[i]]
);
}
else
{
// Point mapped
newFace.append(mpIter());
// Add the point into support
pointMap().insert(mpIter(), masterLocalPoints[oldLocalFace[i]]);
}
// Grab the edge points
const labelList& masterPointsOnEdge =
pointsIntoMasterEdges[curEdges[i]];
// If there are no points on the edge, skip everything
// If there is only one point, no need for sorting
if (masterPointsOnEdge.size())
{
// Sort edge points in order
scalarField edgePointWeights(masterPointsOnEdge.size());
const point& startPoint = masterLocalPoints[oldLocalFace[i]];
vector e =
masterLocalPoints[oldLocalFace.nextLabel(i)]
- startPoint;
scalar magSqrE = magSqr(e);
if (magSqrE > SMALL)
{
e /= magSqrE;
}
else
{
FatalErrorIn
(
"void enrichedPatch::calcEnrichedFaces\n"
"(\n"
" const labelListList& pointsIntoMasterEdges,\n"
" const labelListList& pointsIntoSlaveEdges,\n"
" const pointField& projectedSlavePoints\n"
")"
) << "Zero length edge in master patch for face " << i
<< ". This is not allowed."
<< abort(FatalError);
}
pointField masterPosOnEdge(masterPointsOnEdge.size());
forAll(masterPointsOnEdge, edgePointI)
{
masterPosOnEdge[edgePointI] =
pointMap().find(masterPointsOnEdge[edgePointI])();
edgePointWeights[edgePointI] =
(e & (masterPosOnEdge[edgePointI] - startPoint));
}
if (debug)
{
// Check weights: all new points should be on the edge
if (min(edgePointWeights) < 0 || max(edgePointWeights) > 1)
{
FatalErrorIn
(
"void enrichedPatch::calcEnrichedFaces\n"
"(\n"
" const labelListList& pointsIntoMasterEdges,\n"
" const labelListList& pointsIntoSlaveEdges,\n"
" const pointField& projectedSlavePoints\n"
")"
) << "Invalid point edge weights. Some of points are"
<< " not on the edge for edge " << curEdges[i]
<< " of face " << faceI << " in master patch." << nl
<< "Min weight: " << min(edgePointWeights)
<< " Max weight: " << max(edgePointWeights)
<< abort(FatalError);
}
}
// Go through the points and collect them based on
// weights from lower to higher. This gives the
// correct order of points along the edge.
forAll(edgePointWeights, passI)
{
// Max weight can only be one, so the sorting is
// done by elimination.
label nextPoint = -1;
scalar dist = 2;
forAll(edgePointWeights, wI)
{
if (edgePointWeights[wI] < dist)
{
dist = edgePointWeights[wI];
nextPoint = wI;
}
}
// Insert the next point and reset its weight to exclude it
// from future picks
newFace.append(masterPointsOnEdge[nextPoint]);
edgePointWeights[nextPoint] = GREAT;
// Add the point into patch support
pointMap().insert
(
masterPointsOnEdge[nextPoint],
masterPosOnEdge[nextPoint]
);
}
}
}
// Info<< "New master face: " << newFace << endl;
// Add the new face to the list
enrichedFaces[nEnrichedFaces].transfer(newFace);
nEnrichedFaces++;
}
// Check the support for the enriched patch
if (debug)
{
if (!checkSupport())
{
Info<< "Enriched patch support OK. Slave faces: "
<< slavePatch_.size() << " Master faces: "
<< masterPatch_.size() << endl;
}
else
{
FatalErrorIn
(
"void enrichedPatch::calcEnrichedFaces\n"
"(\n"
" const labelListList& pointsIntoMasterEdges,\n"
" const labelListList& pointsIntoSlaveEdges,\n"
" const pointField& projectedSlavePoints\n"
")"
) << "Error in enriched patch support"
<< abort(FatalError);
}
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::faceList& Foam::enrichedPatch::enrichedFaces() const
{
if (!enrichedFacesPtr_)
{
FatalErrorIn("const faceList& enrichedPatch::enrichedFaces() const")
<< "Enriched faces not available yet. Please use "
<< "void enrichedPatch::calcEnrichedFaces\n"
<< "(\n"
<< " const labelListList& pointsIntoMasterEdges,\n"
<< " const labelListList& pointsIntoSlaveEdges,\n"
<< " const pointField& projectedSlavePoints\n"
<< ")"
<< " before trying to access faces."
<< abort(FatalError);
}
return *enrichedFacesPtr_;
}
// ************************************************************************* //

View File

@ -0,0 +1,159 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "enrichedPatch.H"
#include "primitiveMesh.H"
#include "demandDrivenData.H"
#include "DynamicList.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
const Foam::label Foam::enrichedPatch::nFaceHits_ = 4;
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::enrichedPatch::calcMasterPointFaces() const
{
if (masterPointFacesPtr_)
{
FatalErrorIn("void enrichedPatch::calcMasterPointFaces() const")
<< "Master point face addressing already calculated."
<< abort(FatalError);
}
// Note:
// Master point face addressing lists the master faces for all points
// in the enriched patch support (if there are no master faces, which is
// normal, the list will be empty). The index represents the index of
// the master face rather than the index from the enriched patch
// Master face points lists the points of the enriched master face plus
// points projected into the master face
Map<DynamicList<label> > mpf(meshPoints().size());
const faceList& ef = enrichedFaces();
// Add the original face points
forAll(masterPatch_, faceI)
{
const face& curFace = ef[faceI + slavePatch_.size()];
// Pout<< "Cur face in pfAddr: " << curFace << endl;
forAll(curFace, pointI)
{
Map<DynamicList<label> >::iterator mpfIter =
mpf.find(curFace[pointI]);
if (mpfIter == mpf.end())
{
// Not found, add new dynamic list
mpf.insert
(
curFace[pointI],
DynamicList<label>(primitiveMesh::facesPerPoint_)
);
// Iterator is invalidated - have to find again
mpf.find(curFace[pointI])().append(faceI);
}
else
{
mpfIter().append(faceI);
}
}
}
// Add the projected points which hit the face
const labelList& slaveMeshPoints = slavePatch_.meshPoints();
forAll(slavePointFaceHits_, pointI)
{
if
(
slavePointPointHits_[pointI] < 0
&& slavePointEdgeHits_[pointI] < 0
&& slavePointFaceHits_[pointI].hit()
)
{
// Get the index of projected point corresponding to this slave
// point
const label mergedSmp =
pointMergeMap().find(slaveMeshPoints[pointI])();
Map<DynamicList<label> >::iterator mpfIter =
mpf.find(mergedSmp);
if (mpfIter == mpf.end())
{
// Not found, add new dynamic list
mpf.insert
(
mergedSmp,
DynamicList<label>(primitiveMesh::facesPerPoint_)
);
// Iterator is invalidated - have to find again
mpf.find(mergedSmp)().append
(
slavePointFaceHits_[pointI].hitObject()
);
}
else
{
mpfIter().append(slavePointFaceHits_[pointI].hitObject());
}
}
}
// Re-pack dynamic lists into normal lists
const labelList mpfToc = mpf.toc();
masterPointFacesPtr_ = new Map<labelList>(2*mpfToc.size());
Map<labelList>& masterPointFaceAddr = *masterPointFacesPtr_;
forAll(mpfToc, mpfTocI)
{
labelList l;
l.transfer(mpf.find(mpfToc[mpfTocI])());
masterPointFaceAddr.insert(mpfToc[mpfTocI], l);
}
// Pout<< "masterPointFaceAddr: " << masterPointFaceAddr << endl;
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::Map<Foam::labelList>& Foam::enrichedPatch::masterPointFaces() const
{
if (!masterPointFacesPtr_)
{
calcMasterPointFaces();
}
return *masterPointFacesPtr_;
}
// ************************************************************************* //

View File

@ -0,0 +1,105 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "enrichedPatch.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::enrichedPatch::completePointMap() const
{
if (pointMapComplete_)
{
FatalErrorIn("void enrichedPatch::completePointMap() const")
<< "Point map already completed"
<< abort(FatalError);
}
pointMapComplete_ = true;
const Map<label>& pmm = pointMergeMap();
// Get the mesh points for both patches. If the point has not been
// merged away, add it to the map
// Do master patch
const labelList& masterMeshPoints = masterPatch_.meshPoints();
const pointField& masterLocalPoints = masterPatch_.localPoints();
forAll(masterMeshPoints, pointI)
{
if (!pmm.found(masterMeshPoints[pointI]))
{
pointMap_.insert
(
masterMeshPoints[pointI],
masterLocalPoints[pointI]
);
}
}
// Do slave patch
const labelList& slaveMeshPoints = slavePatch_.meshPoints();
const pointField& slaveLocalPoints = slavePatch_.localPoints();
forAll(slaveMeshPoints, pointI)
{
if (!pmm.found(slaveMeshPoints[pointI]))
{
pointMap_.insert
(
slaveMeshPoints[pointI],
slaveLocalPoints[pointI]
);
}
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::Map<Foam::point>& Foam::enrichedPatch::pointMap()
{
if (!pointMapComplete_)
{
completePointMap();
}
return pointMap_;
}
const Foam::Map<Foam::point>& Foam::enrichedPatch::pointMap() const
{
if (!pointMapComplete_)
{
completePointMap();
}
return pointMap_;
}
// ************************************************************************* //

View File

@ -0,0 +1,115 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "enrichedPatch.H"
#include "primitiveMesh.H"
#include "DynamicList.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::enrichedPatch::calcPointPoints() const
{
// Calculate point-point addressing
if (pointPointsPtr_)
{
FatalErrorIn("void enrichedPatch::calcPointPoints() const")
<< "Point-point addressing already calculated."
<< abort(FatalError);
}
// Algorithm:
// Go through all faces and add the previous and next point as the
// neighbour for each point. While inserting points, reject the
// duplicates (as every internal edge will be visited twice).
List<DynamicList<label, primitiveMesh::edgesPerPoint_> >
pp(meshPoints().size());
const faceList& lf = localFaces();
register bool found = false;
forAll(lf, faceI)
{
const face& curFace = lf[faceI];
forAll(curFace, pointI)
{
DynamicList<label, primitiveMesh::edgesPerPoint_>&
curPp = pp[curFace[pointI]];
// Do next label
label next = curFace.nextLabel(pointI);
found = false;
forAll(curPp, i)
{
if (curPp[i] == next)
{
found = true;
break;
}
}
if (!found)
{
curPp.append(next);
}
// Do previous label
label prev = curFace.prevLabel(pointI);
found = false;
forAll(curPp, i)
{
if (curPp[i] == prev)
{
found = true;
break;
}
}
if (!found)
{
curPp.append(prev);
}
}
}
// Re-pack the list
pointPointsPtr_ = new labelListList(pp.size());
labelListList& ppAddr = *pointPointsPtr_;
forAll(pp, pointI)
{
ppAddr[pointI].transfer(pp[pointI]);
}
}
// ************************************************************************* //

View File

@ -0,0 +1,844 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "slidingInterface.H"
#include "polyTopoChanger.H"
#include "polyMesh.H"
#include "polyTopoChange.H"
#include "addToRunTimeSelectionTable.H"
#include "plane.H"
// Index of debug signs:
// p - adjusting a projection point
// * - adjusting edge intersection
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(slidingInterface, 0);
addToRunTimeSelectionTable
(
polyMeshModifier,
slidingInterface,
dictionary
);
template<>
const char* Foam::NamedEnum
<
Foam::slidingInterface::typeOfMatch,
2
>::names[] =
{
"integral",
"partial"
};
}
const Foam::NamedEnum<Foam::slidingInterface::typeOfMatch, 2>
Foam::slidingInterface::typeOfMatchNames_;
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::slidingInterface::checkDefinition()
{
const polyMesh& mesh = topoChanger().mesh();
if
(
!masterFaceZoneID_.active()
|| !slaveFaceZoneID_.active()
|| !cutPointZoneID_.active()
|| !cutFaceZoneID_.active()
|| !masterPatchID_.active()
|| !slavePatchID_.active()
)
{
FatalErrorIn
(
"void slidingInterface::checkDefinition()"
) << "Not all zones and patches needed in the definition "
<< "have been found. Please check your mesh definition."
<< abort(FatalError);
}
// Check the sizes and set up state
if
(
mesh.faceZones()[masterFaceZoneID_.index()].empty()
|| mesh.faceZones()[slaveFaceZoneID_.index()].empty()
)
{
FatalErrorIn("void slidingInterface::checkDefinition()")
<< "Master or slave face zone contain no faces. "
<< "Please check your mesh definition."
<< abort(FatalError);
}
if (debug)
{
Pout<< "Sliding interface object " << name() << " :" << nl
<< " master face zone: " << masterFaceZoneID_.index() << nl
<< " slave face zone: " << slaveFaceZoneID_.index() << endl;
}
}
void Foam::slidingInterface::clearOut() const
{
clearPointProjection();
clearAttachedAddressing();
clearAddressing();
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// Construct from components
Foam::slidingInterface::slidingInterface
(
const word& name,
const label index,
const polyTopoChanger& mme,
const word& masterFaceZoneName,
const word& slaveFaceZoneName,
const word& cutPointZoneName,
const word& cutFaceZoneName,
const word& masterPatchName,
const word& slavePatchName,
const typeOfMatch tom,
const bool coupleDecouple,
const intersection::algorithm algo
)
:
polyMeshModifier(name, index, mme, true),
masterFaceZoneID_
(
masterFaceZoneName,
mme.mesh().faceZones()
),
slaveFaceZoneID_
(
slaveFaceZoneName,
mme.mesh().faceZones()
),
cutPointZoneID_
(
cutPointZoneName,
mme.mesh().pointZones()
),
cutFaceZoneID_
(
cutFaceZoneName,
mme.mesh().faceZones()
),
masterPatchID_
(
masterPatchName,
mme.mesh().boundaryMesh()
),
slavePatchID_
(
slavePatchName,
mme.mesh().boundaryMesh()
),
matchType_(tom),
coupleDecouple_(coupleDecouple),
attached_(false),
projectionAlgo_(algo),
trigger_(false),
pointMergeTol_(pointMergeTolDefault_),
edgeMergeTol_(edgeMergeTolDefault_),
nFacesPerSlaveEdge_(nFacesPerSlaveEdgeDefault_),
edgeFaceEscapeLimit_(edgeFaceEscapeLimitDefault_),
integralAdjTol_(integralAdjTolDefault_),
edgeMasterCatchFraction_(edgeMasterCatchFractionDefault_),
edgeCoPlanarTol_(edgeCoPlanarTolDefault_),
edgeEndCutoffTol_(edgeEndCutoffTolDefault_),
cutFaceMasterPtr_(NULL),
cutFaceSlavePtr_(NULL),
masterFaceCellsPtr_(NULL),
slaveFaceCellsPtr_(NULL),
masterStickOutFacesPtr_(NULL),
slaveStickOutFacesPtr_(NULL),
retiredPointMapPtr_(NULL),
cutPointEdgePairMapPtr_(NULL),
slavePointPointHitsPtr_(NULL),
slavePointEdgeHitsPtr_(NULL),
slavePointFaceHitsPtr_(NULL),
masterPointEdgeHitsPtr_(NULL),
projectedSlavePointsPtr_(NULL)
{
checkDefinition();
if (attached_)
{
FatalErrorIn
(
"Foam::slidingInterface::slidingInterface\n"
"(\n"
" const word& name,\n"
" const label index,\n"
" const polyTopoChanger& mme,\n"
" const word& masterFaceZoneName,\n"
" const word& slaveFaceZoneName,\n"
" const word& cutFaceZoneName,\n"
" const word& cutPointZoneName,\n"
" const word& masterPatchName,\n"
" const word& slavePatchName,\n"
" const typeOfMatch tom,\n"
" const bool coupleDecouple\n"
")"
) << "Creation of a sliding interface from components "
<< "in attached state not supported."
<< abort(FatalError);
}
else
{
calcAttachedAddressing();
}
}
// Construct from components
Foam::slidingInterface::slidingInterface
(
const word& name,
const dictionary& dict,
const label index,
const polyTopoChanger& mme
)
:
polyMeshModifier(name, index, mme, Switch(dict.lookup("active"))),
masterFaceZoneID_
(
dict.lookup("masterFaceZoneName"),
mme.mesh().faceZones()
),
slaveFaceZoneID_
(
dict.lookup("slaveFaceZoneName"),
mme.mesh().faceZones()
),
cutPointZoneID_
(
dict.lookup("cutPointZoneName"),
mme.mesh().pointZones()
),
cutFaceZoneID_
(
dict.lookup("cutFaceZoneName"),
mme.mesh().faceZones()
),
masterPatchID_
(
dict.lookup("masterPatchName"),
mme.mesh().boundaryMesh()
),
slavePatchID_
(
dict.lookup("slavePatchName"),
mme.mesh().boundaryMesh()
),
matchType_(typeOfMatchNames_.read((dict.lookup("typeOfMatch")))),
coupleDecouple_(dict.lookup("coupleDecouple")),
attached_(dict.lookup("attached")),
projectionAlgo_
(
intersection::algorithmNames_.read(dict.lookup("projection"))
),
trigger_(false),
cutFaceMasterPtr_(NULL),
cutFaceSlavePtr_(NULL),
masterFaceCellsPtr_(NULL),
slaveFaceCellsPtr_(NULL),
masterStickOutFacesPtr_(NULL),
slaveStickOutFacesPtr_(NULL),
retiredPointMapPtr_(NULL),
cutPointEdgePairMapPtr_(NULL),
slavePointPointHitsPtr_(NULL),
slavePointEdgeHitsPtr_(NULL),
slavePointFaceHitsPtr_(NULL),
masterPointEdgeHitsPtr_(NULL),
projectedSlavePointsPtr_(NULL)
{
// Optionally default tolerances from dictionary
setTolerances(dict);
checkDefinition();
// If the interface is attached, the master and slave face zone addressing
// needs to be read in; otherwise it will be created
if (attached_)
{
if (debug)
{
Pout<< "slidingInterface::slidingInterface(...) "
<< " for object " << name << " : "
<< "Interface attached. Reading master and slave face zones "
<< "and retired point lookup." << endl;
}
// The face zone addressing is written out in the definition dictionary
masterFaceCellsPtr_ = new labelList(dict.lookup("masterFaceCells"));
slaveFaceCellsPtr_ = new labelList(dict.lookup("slaveFaceCells"));
masterStickOutFacesPtr_ =
new labelList(dict.lookup("masterStickOutFaces"));
slaveStickOutFacesPtr_ =
new labelList(dict.lookup("slaveStickOutFaces"));
retiredPointMapPtr_ = new Map<label>(dict.lookup("retiredPointMap"));
cutPointEdgePairMapPtr_ =
new Map<Pair<edge> >(dict.lookup("cutPointEdgePairMap"));
}
else
{
calcAttachedAddressing();
}
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::slidingInterface::~slidingInterface()
{
clearOut();
}
void Foam::slidingInterface::clearAddressing() const
{
deleteDemandDrivenData(cutFaceMasterPtr_);
deleteDemandDrivenData(cutFaceSlavePtr_);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::faceZoneID& Foam::slidingInterface::masterFaceZoneID() const
{
return masterFaceZoneID_;
}
const Foam::faceZoneID& Foam::slidingInterface::slaveFaceZoneID() const
{
return slaveFaceZoneID_;
}
bool Foam::slidingInterface::changeTopology() const
{
if (coupleDecouple_)
{
// Always changes. If not attached, project points
if (debug)
{
Pout<< "bool slidingInterface::changeTopology() const "
<< "for object " << name() << " : "
<< "Couple-decouple mode." << endl;
}
if (!attached_)
{
projectPoints();
}
else
{
}
return true;
}
if
(
attached_
&& !topoChanger().mesh().changing()
)
{
// If the mesh is not moving or morphing and the interface is
// already attached, the topology will not change
return false;
}
else
{
// Check if the motion changes point projection
return projectPoints();
}
}
void Foam::slidingInterface::setRefinement(polyTopoChange& ref) const
{
if (coupleDecouple_)
{
if (attached_)
{
// Attached, coupling
decoupleInterface(ref);
}
else
{
// Detached, coupling
coupleInterface(ref);
}
return;
}
if (trigger_)
{
if (attached_)
{
// Clear old coupling data
clearCouple(ref);
}
coupleInterface(ref);
trigger_ = false;
}
}
void Foam::slidingInterface::modifyMotionPoints(pointField& motionPoints) const
{
if (debug)
{
Pout<< "void slidingInterface::modifyMotionPoints("
<< "pointField& motionPoints) const for object " << name() << " : "
<< "Adjusting motion points." << endl;
}
const polyMesh& mesh = topoChanger().mesh();
// Get point from the cut zone
const labelList& cutPoints = mesh.pointZones()[cutPointZoneID_.index()];
if (cutPoints.size() && !projectedSlavePointsPtr_)
{
return;
}
else
{
const pointField& projectedSlavePoints = *projectedSlavePointsPtr_;
const Map<label>& rpm = retiredPointMap();
const Map<Pair<edge> >& cpepm = cutPointEdgePairMap();
const Map<label>& slaveZonePointMap =
mesh.faceZones()[slaveFaceZoneID_.index()]().meshPointMap();
const primitiveFacePatch& masterPatch =
mesh.faceZones()[masterFaceZoneID_.index()]();
const edgeList& masterEdges = masterPatch.edges();
const pointField& masterLocalPoints = masterPatch.localPoints();
const primitiveFacePatch& slavePatch =
mesh.faceZones()[slaveFaceZoneID_.index()]();
const edgeList& slaveEdges = slavePatch.edges();
const pointField& slaveLocalPoints = slavePatch.localPoints();
const vectorField& slavePointNormals = slavePatch.pointNormals();
forAll(cutPoints, pointI)
{
// Try to find the cut point in retired points
Map<label>::const_iterator rpmIter = rpm.find(cutPoints[pointI]);
if (rpmIter != rpm.end())
{
if (debug)
{
Pout<< "p";
}
// Cut point is a retired point
motionPoints[cutPoints[pointI]] =
projectedSlavePoints[slaveZonePointMap.find(rpmIter())()];
}
else
{
// A cut point is not a projected slave point. Therefore, it
// must be an edge-to-edge intersection.
Map<Pair<edge> >::const_iterator cpepmIter =
cpepm.find(cutPoints[pointI]);
if (cpepmIter != cpepm.end())
{
// Pout<< "Need to re-create hit for point "
// << cutPoints[pointI]
// << " lookup: " << cpepmIter()
// << endl;
// Note.
// The edge cutting code is repeated in
// slidingInterface::coupleInterface. This is done for
// efficiency reasons and avoids multiple creation of
// cutting planes. Please update both simultaneously.
//
const edge& globalMasterEdge = cpepmIter().first();
const label curMasterEdgeIndex =
masterPatch.whichEdge
(
edge
(
masterPatch.whichPoint
(
globalMasterEdge.start()
),
masterPatch.whichPoint
(
globalMasterEdge.end()
)
)
);
const edge& cme = masterEdges[curMasterEdgeIndex];
// Pout<< "curMasterEdgeIndex: " << curMasterEdgeIndex
// << " cme: " << cme
// << endl;
const edge& globalSlaveEdge = cpepmIter().second();
const label curSlaveEdgeIndex =
slavePatch.whichEdge
(
edge
(
slavePatch.whichPoint
(
globalSlaveEdge.start()
),
slavePatch.whichPoint
(
globalSlaveEdge.end()
)
)
);
const edge& curSlaveEdge = slaveEdges[curSlaveEdgeIndex];
// Pout<< "curSlaveEdgeIndex: " << curSlaveEdgeIndex
// << " curSlaveEdge: " << curSlaveEdge
// << endl;
const point& a = projectedSlavePoints[curSlaveEdge.start()];
const point& b = projectedSlavePoints[curSlaveEdge.end()];
point c =
0.5*
(
slaveLocalPoints[curSlaveEdge.start()]
+ slavePointNormals[curSlaveEdge.start()]
+ slaveLocalPoints[curSlaveEdge.end()]
+ slavePointNormals[curSlaveEdge.end()]
);
// Create the plane
plane cutPlane(a, b, c);
linePointRef curSlaveLine =
curSlaveEdge.line(slaveLocalPoints);
const scalar curSlaveLineMag = curSlaveLine.mag();
scalar cutOnMaster =
cutPlane.lineIntersect
(
cme.line(masterLocalPoints)
);
if
(
cutOnMaster > edgeEndCutoffTol_
&& cutOnMaster < 1.0 - edgeEndCutoffTol_
)
{
// Master is cut, check the slave
point masterCutPoint =
masterLocalPoints[cme.start()]
+ cutOnMaster*cme.vec(masterLocalPoints);
pointHit slaveCut =
curSlaveLine.nearestDist(masterCutPoint);
if (slaveCut.hit())
{
// Strict checking of slave cut to avoid capturing
// end points.
scalar cutOnSlave =
(
(
slaveCut.hitPoint()
- curSlaveLine.start()
) & curSlaveLine.vec()
)/sqr(curSlaveLineMag);
// Calculate merge tolerance from the
// target edge length
scalar mergeTol =
edgeCoPlanarTol_*mag(b - a);
if
(
cutOnSlave > edgeEndCutoffTol_
&& cutOnSlave < 1.0 - edgeEndCutoffTol_
&& slaveCut.distance() < mergeTol
)
{
// Cut both master and slave.
motionPoints[cutPoints[pointI]] =
masterCutPoint;
}
}
else
{
Pout<< "Missed slave edge!!! This is an error. "
<< "Master edge: "
<< cme.line(masterLocalPoints)
<< " slave edge: " << curSlaveLine
<< " point: " << masterCutPoint
<< " weight: " <<
(
(
slaveCut.missPoint()
- curSlaveLine.start()
) & curSlaveLine.vec()
)/sqr(curSlaveLineMag)
<< endl;
}
}
else
{
Pout<< "Missed master edge!!! This is an error"
<< endl;
}
}
else
{
FatalErrorIn
(
"void slidingInterface::modifyMotionPoints"
"(pointField&) const"
) << "Cut point " << cutPoints[pointI]
<< " not recognised as either the projected "
<< "or as intersection point. Error in point "
<< "projection or data mapping"
<< abort(FatalError);
}
}
}
if (debug)
{
Pout<< endl;
}
}
}
void Foam::slidingInterface::updateMesh(const mapPolyMesh& m)
{
if (debug)
{
Pout<< "void slidingInterface::updateMesh(const mapPolyMesh& m)"
<< " const for object " << name() << " : "
<< "Updating topology." << endl;
}
// Mesh has changed topologically. Update local topological data
const polyMesh& mesh = topoChanger().mesh();
masterFaceZoneID_.update(mesh.faceZones());
slaveFaceZoneID_.update(mesh.faceZones());
cutPointZoneID_.update(mesh.pointZones());
cutFaceZoneID_.update(mesh.faceZones());
masterPatchID_.update(mesh.boundaryMesh());
slavePatchID_.update(mesh.boundaryMesh());
//MJ:Disabled updating
// if (!attached())
// {
// calcAttachedAddressing();
// }
// else
// {
// renumberAttachedAddressing(m);
// }
}
const Foam::pointField& Foam::slidingInterface::pointProjection() const
{
if (!projectedSlavePointsPtr_)
{
projectPoints();
}
return *projectedSlavePointsPtr_;
}
void Foam::slidingInterface::setTolerances(const dictionary&dict, bool report)
{
pointMergeTol_ = dict.lookupOrDefault<scalar>
(
"pointMergeTol",
pointMergeTol_
);
edgeMergeTol_ = dict.lookupOrDefault<scalar>
(
"edgeMergeTol",
edgeMergeTol_
);
nFacesPerSlaveEdge_ = dict.lookupOrDefault<label>
(
"nFacesPerSlaveEdge",
nFacesPerSlaveEdge_
);
edgeFaceEscapeLimit_ = dict.lookupOrDefault<label>
(
"edgeFaceEscapeLimit",
edgeFaceEscapeLimit_
);
integralAdjTol_ = dict.lookupOrDefault<scalar>
(
"integralAdjTol",
integralAdjTol_
);
edgeMasterCatchFraction_ = dict.lookupOrDefault<scalar>
(
"edgeMasterCatchFraction",
edgeMasterCatchFraction_
);
edgeCoPlanarTol_ = dict.lookupOrDefault<scalar>
(
"edgeCoPlanarTol",
edgeCoPlanarTol_
);
edgeEndCutoffTol_ = dict.lookupOrDefault<scalar>
(
"edgeEndCutoffTol",
edgeEndCutoffTol_
);
if (report)
{
Info<< "Sliding interface parameters:" << nl
<< "pointMergeTol : " << pointMergeTol_ << nl
<< "edgeMergeTol : " << edgeMergeTol_ << nl
<< "nFacesPerSlaveEdge : " << nFacesPerSlaveEdge_ << nl
<< "edgeFaceEscapeLimit : " << edgeFaceEscapeLimit_ << nl
<< "integralAdjTol : " << integralAdjTol_ << nl
<< "edgeMasterCatchFraction : " << edgeMasterCatchFraction_ << nl
<< "edgeCoPlanarTol : " << edgeCoPlanarTol_ << nl
<< "edgeEndCutoffTol : " << edgeEndCutoffTol_ << endl;
}
}
void Foam::slidingInterface::write(Ostream& os) const
{
os << nl << type() << nl
<< name()<< nl
<< masterFaceZoneID_.name() << nl
<< slaveFaceZoneID_.name() << nl
<< cutPointZoneID_.name() << nl
<< cutFaceZoneID_.name() << nl
<< masterPatchID_.name() << nl
<< slavePatchID_.name() << nl
<< typeOfMatchNames_[matchType_] << nl
<< coupleDecouple_ << nl
<< attached_ << endl;
}
// To write out all those tolerances
#define WRITE_NON_DEFAULT(name) \
if ( name ## _ != name ## Default_ )\
{ \
os << " " #name " " << name ## _ << token::END_STATEMENT << nl; \
}
void Foam::slidingInterface::writeDict(Ostream& os) const
{
os << nl << name() << nl << token::BEGIN_BLOCK << nl
<< " type " << type() << token::END_STATEMENT << nl
<< " masterFaceZoneName " << masterFaceZoneID_.name()
<< token::END_STATEMENT << nl
<< " slaveFaceZoneName " << slaveFaceZoneID_.name()
<< token::END_STATEMENT << nl
<< " cutPointZoneName " << cutPointZoneID_.name()
<< token::END_STATEMENT << nl
<< " cutFaceZoneName " << cutFaceZoneID_.name()
<< token::END_STATEMENT << nl
<< " masterPatchName " << masterPatchID_.name()
<< token::END_STATEMENT << nl
<< " slavePatchName " << slavePatchID_.name()
<< token::END_STATEMENT << nl
<< " typeOfMatch " << typeOfMatchNames_[matchType_]
<< token::END_STATEMENT << nl
<< " coupleDecouple " << coupleDecouple_
<< token::END_STATEMENT << nl
<< " projection " << intersection::algorithmNames_[projectionAlgo_]
<< token::END_STATEMENT << nl
<< " attached " << attached_
<< token::END_STATEMENT << nl
<< " active " << active()
<< token::END_STATEMENT << nl;
if (attached_)
{
masterFaceCellsPtr_->writeEntry("masterFaceCells", os);
slaveFaceCellsPtr_->writeEntry("slaveFaceCells", os);
masterStickOutFacesPtr_->writeEntry("masterStickOutFaces", os);
slaveStickOutFacesPtr_->writeEntry("slaveStickOutFaces", os);
os << " retiredPointMap " << retiredPointMap()
<< token::END_STATEMENT << nl
<< " cutPointEdgePairMap " << cutPointEdgePairMap()
<< token::END_STATEMENT << nl;
}
WRITE_NON_DEFAULT(pointMergeTol)
WRITE_NON_DEFAULT(edgeMergeTol)
WRITE_NON_DEFAULT(nFacesPerSlaveEdge)
WRITE_NON_DEFAULT(edgeFaceEscapeLimit)
WRITE_NON_DEFAULT(integralAdjTol)
WRITE_NON_DEFAULT(edgeMasterCatchFraction)
WRITE_NON_DEFAULT(edgeCoPlanarTol)
WRITE_NON_DEFAULT(edgeEndCutoffTol)
os << token::END_BLOCK << endl;
}
// ************************************************************************* //

View File

@ -0,0 +1,394 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
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 <http://www.gnu.org/licenses/>.
Class
Foam::slidingInterface
Description
Sliding interface mesh modifier. Given two face zones, couple the
master and slave side using a cutting procedure.
The coupled faces are collected into the "coupled" zone and can become
either internal or placed into a master and slave coupled zone. The
remaining faces (uncovered master or slave) are placed into the master
and slave patch.
The definition of the sliding interface can be either integral or partial.
Integral interface implies that the slave side completely covers
the master (i.e. no faces are uncovered); partial interface
implies that the uncovered part of master/slave face zone should
become boundary faces.
SourceFiles
slidingInterface.C
coupleSlidingInterface.C
decoupleSlidingInterface.C
slidingInterfaceProjectPoints.C
slidingInterfaceAttachedAddressing.C
slidingInterfaceClearCouple.C
\*---------------------------------------------------------------------------*/
#ifndef slidingInterface_H
#define slidingInterface_H
#include "polyMeshModifier.H"
#include "primitiveFacePatch.H"
#include "polyPatchID.H"
#include "ZoneIDs.H"
#include "intersection.H"
#include "Pair.H"
#include "objectHit.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class slidingInterface Declaration
\*---------------------------------------------------------------------------*/
class slidingInterface
:
public polyMeshModifier
{
public:
// Public enumerations
//- Type of match
enum typeOfMatch
{
INTEGRAL,
PARTIAL
};
//- Direction names
static const NamedEnum<typeOfMatch, 2> typeOfMatchNames_;
private:
// Private data
//- Master face zone ID
faceZoneID masterFaceZoneID_;
//- Slave face zone ID
faceZoneID slaveFaceZoneID_;
//- Cut point zone ID
pointZoneID cutPointZoneID_;
//- Cut face zone ID
faceZoneID cutFaceZoneID_;
//- Master patch ID
polyPatchID masterPatchID_;
//- Slave patch ID
polyPatchID slavePatchID_;
//- Type of match
const typeOfMatch matchType_;
//- Couple-decouple operation.
// If the interface is coupled, decouple it and vice versa.
// Used in conjuction with automatic mesh motion
mutable Switch coupleDecouple_;
//- State of the modifier
mutable Switch attached_;
//- Point projection algorithm
intersection::algorithm projectionAlgo_;
//- Trigger topological change
mutable bool trigger_;
// Tolerances. Initialised to static ones below.
//- Point merge tolerance
scalar pointMergeTol_;
//- Edge merge tolerance
scalar edgeMergeTol_;
//- Estimated number of faces an edge goes through
label nFacesPerSlaveEdge_;
//- Edge-face interaction escape limit
label edgeFaceEscapeLimit_;
//- Integral match point adjustment tolerance
scalar integralAdjTol_;
//- Edge intersection master catch fraction
scalar edgeMasterCatchFraction_;
//- Edge intersection co-planar tolerance
scalar edgeCoPlanarTol_;
//- Edge end cut-off tolerance
scalar edgeEndCutoffTol_;
// Private addressing data.
//- Cut face master face. Gives the index of face in master patch
// the cut face has been created from. For a slave-only face
// this will be -1
mutable labelList* cutFaceMasterPtr_;
//- Cut face slave face. Gives the index of face in slave patch
// the cut face has been created from. For a master-only face
// this will be -1
mutable labelList* cutFaceSlavePtr_;
//- Master zone faceCells
mutable labelList* masterFaceCellsPtr_;
//- Slave zone faceCells
mutable labelList* slaveFaceCellsPtr_;
//- Master stick-out faces
mutable labelList* masterStickOutFacesPtr_;
//- Slave stick-out faces
mutable labelList* slaveStickOutFacesPtr_;
//- Retired point mapping.
// For every retired slave side point, gives the label of the
// master point that replaces it
mutable Map<label>* retiredPointMapPtr_;
//- Cut edge pairs
// For cut points created by intersection two edges,
// store the master-slave edge pair used in creation
mutable Map<Pair<edge> >* cutPointEdgePairMapPtr_;
//- Slave point hit. The index of master point hit by the
// slave point in projection. For no point hit, set to -1
mutable labelList* slavePointPointHitsPtr_;
//- Slave edge hit. The index of master edge hit by the
// slave point in projection. For point or no edge hit, set to -1
mutable labelList* slavePointEdgeHitsPtr_;
//- Slave face hit. The index of master face hit by the
// slave point in projection.
mutable List<objectHit>* slavePointFaceHitsPtr_;
//- Master point edge hit. The index of slave edge hit by
// a master point. For no hit set to -1
mutable labelList* masterPointEdgeHitsPtr_;
//- Projected slave points
mutable pointField* projectedSlavePointsPtr_;
// Private Member Functions
//- Disallow default bitwise copy construct
slidingInterface(const slidingInterface&);
//- Disallow default bitwise assignment
void operator=(const slidingInterface&);
//- Clear out
void clearOut() const;
//- Check validity of construction data
void checkDefinition();
//- Calculate attached addressing
void calcAttachedAddressing() const;
//- Calculate decoupled zone face-cell addressing
void renumberAttachedAddressing(const mapPolyMesh&) const;
//- Clear attached addressing
void clearAttachedAddressing() const;
// Topological changes
//- Master faceCells
const labelList& masterFaceCells() const;
//- Slave faceCells
const labelList& slaveFaceCells() const;
//- Master stick-out faces
const labelList& masterStickOutFaces() const;
//- Slave stick-out faces
const labelList& slaveStickOutFaces() const;
//- Retired point map
const Map<label>& retiredPointMap() const;
//- Cut point edge pair map
const Map<Pair<edge> >& cutPointEdgePairMap() const;
//- Clear addressing
void clearAddressing() const;
//- Project slave points and compare with the current projection.
// If the projection has changed, the sliding interface
// changes topologically
bool projectPoints() const;
//- Couple sliding interface
void coupleInterface(polyTopoChange& ref) const;
//- Clear projection
void clearPointProjection() const;
//- Clear old couple
void clearCouple(polyTopoChange& ref) const;
//- Decouple interface (returns it to decoupled state)
// Note: this should not be used in normal operation of the
// sliding mesh, but only to return the mesh to its
// original state
void decoupleInterface(polyTopoChange& ref) const;
// Static data members
//- Point merge tolerance
static const scalar pointMergeTolDefault_;
//- Edge merge tolerance
static const scalar edgeMergeTolDefault_;
//- Estimated number of faces an edge goes through
static const label nFacesPerSlaveEdgeDefault_;
//- Edge-face interaction escape limit
static const label edgeFaceEscapeLimitDefault_;
//- Integral match point adjustment tolerance
static const scalar integralAdjTolDefault_;
//- Edge intersection master catch fraction
static const scalar edgeMasterCatchFractionDefault_;
//- Edge intersection co-planar tolerance
static const scalar edgeCoPlanarTolDefault_;
//- Edge end cut-off tolerance
static const scalar edgeEndCutoffTolDefault_;
public:
//- Runtime type information
TypeName("slidingInterface");
// Constructors
//- Construct from components
slidingInterface
(
const word& name,
const label index,
const polyTopoChanger& mme,
const word& masterFaceZoneName,
const word& slaveFaceZoneName,
const word& cutPointZoneName,
const word& cutFaceZoneName,
const word& masterPatchName,
const word& slavePatchName,
const typeOfMatch tom,
const bool coupleDecouple = false,
const intersection::algorithm algo = intersection::VISIBLE
);
//- Construct from dictionary
slidingInterface
(
const word& name,
const dictionary& dict,
const label index,
const polyTopoChanger& mme
);
//- Destructor
virtual ~slidingInterface();
// Member Functions
//- Return master face zone ID
const faceZoneID& masterFaceZoneID() const;
//- Return slave face zone ID
const faceZoneID& slaveFaceZoneID() const;
//- Return true if attached
bool attached() const
{
return attached_;
}
//- 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&);
//- Return projected points for a slave patch
const pointField& pointProjection() const;
//- Set the tolerances from the values in a dictionary
void setTolerances(const dictionary&, bool report=false);
//- Write
virtual void write(Ostream&) const;
//- Write dictionary
virtual void writeDict(Ostream&) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,591 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "slidingInterface.H"
#include "polyMesh.H"
#include "mapPolyMesh.H"
#include "polyTopoChanger.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::slidingInterface::calcAttachedAddressing() const
{
if (debug)
{
Pout<< "void Foam::slidingInterface::calcAttachedAddressing() const "
<< " for object " << name() << " : "
<< "Calculating zone face-cell addressing."
<< endl;
}
if (!attached_)
{
// Clear existing addressing
clearAttachedAddressing();
const polyMesh& mesh = topoChanger().mesh();
const labelList& own = mesh.faceOwner();
const labelList& nei = mesh.faceNeighbour();
const faceZoneMesh& faceZones = mesh.faceZones();
// Master side
const primitiveFacePatch& masterPatch =
faceZones[masterFaceZoneID_.index()]();
const labelList& masterPatchFaces =
faceZones[masterFaceZoneID_.index()];
const boolList& masterFlip =
faceZones[masterFaceZoneID_.index()].flipMap();
masterFaceCellsPtr_ = new labelList(masterPatchFaces.size());
labelList& mfc = *masterFaceCellsPtr_;
forAll(masterPatchFaces, faceI)
{
if (masterFlip[faceI])
{
mfc[faceI] = nei[masterPatchFaces[faceI]];
}
else
{
mfc[faceI] = own[masterPatchFaces[faceI]];
}
}
// Slave side
const primitiveFacePatch& slavePatch =
faceZones[slaveFaceZoneID_.index()]();
const labelList& slavePatchFaces =
faceZones[slaveFaceZoneID_.index()];
const boolList& slaveFlip =
faceZones[slaveFaceZoneID_.index()].flipMap();
slaveFaceCellsPtr_ = new labelList(slavePatchFaces.size());
labelList& sfc = *slaveFaceCellsPtr_;
forAll(slavePatchFaces, faceI)
{
if (slaveFlip[faceI])
{
sfc[faceI] = nei[slavePatchFaces[faceI]];
}
else
{
sfc[faceI] = own[slavePatchFaces[faceI]];
}
}
// Check that the addressing is valid
if (min(mfc) < 0 || min(sfc) < 0)
{
if (debug)
{
forAll(mfc, faceI)
{
if (mfc[faceI] < 0)
{
Pout<< "No cell next to master patch face " << faceI
<< ". Global face no: " << mfc[faceI]
<< " own: " << own[masterPatchFaces[faceI]]
<< " nei: " << nei[masterPatchFaces[faceI]]
<< " flip: " << masterFlip[faceI] << endl;
}
}
forAll(sfc, faceI)
{
if (sfc[faceI] < 0)
{
Pout<< "No cell next to slave patch face " << faceI
<< ". Global face no: " << sfc[faceI]
<< " own: " << own[slavePatchFaces[faceI]]
<< " nei: " << nei[slavePatchFaces[faceI]]
<< " flip: " << slaveFlip[faceI] << endl;
}
}
}
FatalErrorIn
(
"void slidingInterface::calcAttachedAddressing()"
"const"
) << "Error is zone face-cell addressing. Probable error in "
<< "decoupled mesh or sliding interface definition."
<< abort(FatalError);
}
// Calculate stick-out faces
const labelListList& pointFaces = mesh.pointFaces();
// Master side
labelHashSet masterStickOutFaceMap
(
primitiveMesh::facesPerCell_*(masterPatch.size())
);
const labelList& masterMeshPoints = masterPatch.meshPoints();
forAll(masterMeshPoints, pointI)
{
const labelList& curFaces = pointFaces[masterMeshPoints[pointI]];
forAll(curFaces, faceI)
{
// Check if the face belongs to the master face zone;
// if not add it
if
(
faceZones.whichZone(curFaces[faceI])
!= masterFaceZoneID_.index()
)
{
masterStickOutFaceMap.insert(curFaces[faceI]);
}
}
}
masterStickOutFacesPtr_ = new labelList(masterStickOutFaceMap.toc());
// Slave side
labelHashSet slaveStickOutFaceMap
(
primitiveMesh::facesPerCell_*(slavePatch.size())
);
const labelList& slaveMeshPoints = slavePatch.meshPoints();
forAll(slaveMeshPoints, pointI)
{
const labelList& curFaces = pointFaces[slaveMeshPoints[pointI]];
forAll(curFaces, faceI)
{
// Check if the face belongs to the slave face zone;
// if not add it
if
(
faceZones.whichZone(curFaces[faceI])
!= slaveFaceZoneID_.index()
)
{
slaveStickOutFaceMap.insert(curFaces[faceI]);
}
}
}
slaveStickOutFacesPtr_ = new labelList(slaveStickOutFaceMap.toc());
// Retired point addressing does not exist at this stage.
// It will be filled when the interface is coupled.
retiredPointMapPtr_ =
new Map<label>
(
2*faceZones[slaveFaceZoneID_.index()]().nPoints()
);
// Ditto for cut point edge map. This is a rough guess of its size
//
cutPointEdgePairMapPtr_ =
new Map<Pair<edge> >
(
faceZones[slaveFaceZoneID_.index()]().nEdges()
);
}
else
{
FatalErrorIn
(
"void slidingInterface::calcAttachedAddressing() const"
) << "The interface is attached. The zone face-cell addressing "
<< "cannot be assembled for object " << name()
<< abort(FatalError);
}
if (debug)
{
Pout<< "void Foam::slidingInterface::calcAttachedAddressing() const "
<< " for object " << name() << " : "
<< "Finished calculating zone face-cell addressing."
<< endl;
}
}
void Foam::slidingInterface::clearAttachedAddressing() const
{
deleteDemandDrivenData(masterFaceCellsPtr_);
deleteDemandDrivenData(slaveFaceCellsPtr_);
deleteDemandDrivenData(masterStickOutFacesPtr_);
deleteDemandDrivenData(slaveStickOutFacesPtr_);
deleteDemandDrivenData(retiredPointMapPtr_);
deleteDemandDrivenData(cutPointEdgePairMapPtr_);
}
void Foam::slidingInterface::renumberAttachedAddressing
(
const mapPolyMesh& m
) const
{
// Get reference to reverse cell renumbering
// The renumbering map is needed the other way around, i.e. giving
// the new cell number for every old cell next to the interface.
const labelList& reverseCellMap = m.reverseCellMap();
const labelList& mfc = masterFaceCells();
const labelList& sfc = slaveFaceCells();
// Master side
labelList* newMfcPtr = new labelList(mfc.size(), -1);
labelList& newMfc = *newMfcPtr;
const labelList& mfzRenumber =
m.faceZoneFaceMap()[masterFaceZoneID_.index()];
forAll(mfc, faceI)
{
label newCellI = reverseCellMap[mfc[mfzRenumber[faceI]]];
if (newCellI >= 0)
{
newMfc[faceI] = newCellI;
}
}
// Slave side
labelList* newSfcPtr = new labelList(sfc.size(), -1);
labelList& newSfc = *newSfcPtr;
const labelList& sfzRenumber =
m.faceZoneFaceMap()[slaveFaceZoneID_.index()];
forAll(sfc, faceI)
{
label newCellI = reverseCellMap[sfc[sfzRenumber[faceI]]];
if (newCellI >= 0)
{
newSfc[faceI] = newCellI;
}
}
if (debug)
{
// Check if all the mapped cells are live
if (min(newMfc) < 0 || min(newSfc) < 0)
{
FatalErrorIn
(
"void slidingInterface::renumberAttachedAddressing("
"const mapPolyMesh& m) const"
) << "Error in cell renumbering for object " << name()
<< ". Some of master cells next "
<< "to the interface have been removed."
<< abort(FatalError);
}
}
// Renumber stick-out faces
const labelList& reverseFaceMap = m.reverseFaceMap();
// Master side
const labelList& msof = masterStickOutFaces();
labelList* newMsofPtr = new labelList(msof.size(), -1);
labelList& newMsof = *newMsofPtr;
forAll(msof, faceI)
{
label newFaceI = reverseFaceMap[msof[faceI]];
if (newFaceI >= 0)
{
newMsof[faceI] = newFaceI;
}
}
// Pout<< "newMsof: " << newMsof << endl;
// Slave side
const labelList& ssof = slaveStickOutFaces();
labelList* newSsofPtr = new labelList(ssof.size(), -1);
labelList& newSsof = *newSsofPtr;
forAll(ssof, faceI)
{
label newFaceI = reverseFaceMap[ssof[faceI]];
if (newFaceI >= 0)
{
newSsof[faceI] = newFaceI;
}
}
// Pout<< "newSsof: " << newSsof << endl;
if (debug)
{
// Check if all the mapped cells are live
if (min(newMsof) < 0 || min(newSsof) < 0)
{
FatalErrorIn
(
"void slidingInterface::renumberAttachedAddressing("
"const mapPolyMesh& m) const"
) << "Error in face renumbering for object " << name()
<< ". Some of stick-out next "
<< "to the interface have been removed."
<< abort(FatalError);
}
}
// Renumber the retired point map. Need to take a copy!
const Map<label> rpm = retiredPointMap();
Map<label>* newRpmPtr = new Map<label>(rpm.size());
Map<label>& newRpm = *newRpmPtr;
const labelList rpmToc = rpm.toc();
// Get reference to point renumbering
const labelList& reversePointMap = m.reversePointMap();
label key, value;
forAll(rpmToc, rpmTocI)
{
key = reversePointMap[rpmToc[rpmTocI]];
value = reversePointMap[rpm.find(rpmToc[rpmTocI])()];
if (debug)
{
// Check if all the mapped cells are live
if (key < 0 || value < 0)
{
FatalErrorIn
(
"void slidingInterface::renumberAttachedAddressing("
"const mapPolyMesh& m) const"
) << "Error in retired point numbering for object "
<< name() << ". Some of master "
<< "points have been removed."
<< abort(FatalError);
}
}
newRpm.insert(key, value);
}
// Renumber the cut point edge pair map. Need to take a copy!
const Map<Pair<edge> > cpepm = cutPointEdgePairMap();
Map<Pair<edge> >* newCpepmPtr = new Map<Pair<edge> >(cpepm.size());
Map<Pair<edge> >& newCpepm = *newCpepmPtr;
const labelList cpepmToc = cpepm.toc();
forAll(cpepmToc, cpepmTocI)
{
key = reversePointMap[cpepmToc[cpepmTocI]];
const Pair<edge>& oldPe = cpepm.find(cpepmToc[cpepmTocI])();
// Re-do the edges in global addressing
const label ms = reversePointMap[oldPe.first().start()];
const label me = reversePointMap[oldPe.first().end()];
const label ss = reversePointMap[oldPe.second().start()];
const label se = reversePointMap[oldPe.second().end()];
if (debug)
{
// Check if all the mapped cells are live
if (key < 0 || ms < 0 || me < 0 || ss < 0 || se < 0)
{
FatalErrorIn
(
"void slidingInterface::renumberAttachedAddressing("
"const mapPolyMesh& m) const"
) << "Error in cut point edge pair map numbering for object "
<< name() << ". Some of master points have been removed."
<< abort(FatalError);
}
}
newCpepm.insert(key, Pair<edge>(edge(ms, me), edge(ss, se)));
}
if (!projectedSlavePointsPtr_)
{
FatalErrorIn
(
"void slidingInterface::renumberAttachedAddressing("
"const mapPolyMesh& m) const"
) << "Error in projected point numbering for object " << name()
<< abort(FatalError);
}
// Renumber the projected slave zone points
const pointField& projectedSlavePoints = *projectedSlavePointsPtr_;
pointField* newProjectedSlavePointsPtr
(
new pointField(projectedSlavePoints.size())
);
pointField& newProjectedSlavePoints = *newProjectedSlavePointsPtr;
const labelList& sfzPointRenumber =
m.faceZonePointMap()[slaveFaceZoneID_.index()];
forAll(newProjectedSlavePoints, pointI)
{
if (sfzPointRenumber[pointI] > -1)
{
newProjectedSlavePoints[pointI] =
projectedSlavePoints[sfzPointRenumber[pointI]];
}
}
// Re-set the lists
clearAttachedAddressing();
deleteDemandDrivenData(projectedSlavePointsPtr_);
masterFaceCellsPtr_ = newMfcPtr;
slaveFaceCellsPtr_ = newSfcPtr;
masterStickOutFacesPtr_ = newMsofPtr;
slaveStickOutFacesPtr_ = newSsofPtr;
retiredPointMapPtr_ = newRpmPtr;
cutPointEdgePairMapPtr_ = newCpepmPtr;
projectedSlavePointsPtr_ = newProjectedSlavePointsPtr;
}
const Foam::labelList& Foam::slidingInterface::masterFaceCells() const
{
if (!masterFaceCellsPtr_)
{
FatalErrorIn
(
"const labelList& slidingInterface::masterFaceCells() const"
) << "Master zone face-cell addressing not available for object "
<< name()
<< abort(FatalError);
}
return *masterFaceCellsPtr_;
}
const Foam::labelList& Foam::slidingInterface::slaveFaceCells() const
{
if (!slaveFaceCellsPtr_)
{
FatalErrorIn
(
"const labelList& slidingInterface::slaveFaceCells() const"
) << "Slave zone face-cell addressing not available for object "
<< name()
<< abort(FatalError);
}
return *slaveFaceCellsPtr_;
}
const Foam::labelList& Foam::slidingInterface::masterStickOutFaces() const
{
if (!masterStickOutFacesPtr_)
{
FatalErrorIn
(
"const labelList& slidingInterface::masterStickOutFaces() const"
) << "Master zone stick-out face addressing not available for object "
<< name()
<< abort(FatalError);
}
return *masterStickOutFacesPtr_;
}
const Foam::labelList& Foam::slidingInterface::slaveStickOutFaces() const
{
if (!slaveStickOutFacesPtr_)
{
FatalErrorIn
(
"const labelList& slidingInterface::slaveStickOutFaces() const"
) << "Slave zone stick-out face addressing not available for object "
<< name()
<< abort(FatalError);
}
return *slaveStickOutFacesPtr_;
}
const Foam::Map<Foam::label>& Foam::slidingInterface::retiredPointMap() const
{
if (!retiredPointMapPtr_)
{
FatalErrorIn
(
"const Map<label>& slidingInterface::retiredPointMap() const"
) << "Retired point map not available for object " << name()
<< abort(FatalError);
}
return *retiredPointMapPtr_;
}
const Foam::Map<Foam::Pair<Foam::edge> >&
Foam::slidingInterface::cutPointEdgePairMap() const
{
if (!cutPointEdgePairMapPtr_)
{
FatalErrorIn
(
"const Map<Pair<edge> >& slidingInterface::"
"cutPointEdgePairMap() const"
) << "Retired point map not available for object " << name()
<< abort(FatalError);
}
return *cutPointEdgePairMapPtr_;
}
// ************************************************************************* //

View File

@ -0,0 +1,77 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "slidingInterface.H"
#include "polyTopoChange.H"
#include "polyMesh.H"
#include "polyTopoChanger.H"
#include "polyRemovePoint.H"
#include "polyRemoveFace.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::slidingInterface::clearCouple
(
polyTopoChange& ref
) const
{
if (debug)
{
Pout<< "void slidingInterface::clearCouple("
<< "polyTopoChange& ref) const for object " << name() << " : "
<< "Clearing old couple points and faces." << endl;
}
// Remove all points from the point zone
const polyMesh& mesh = topoChanger().mesh();
const labelList& cutPointZoneLabels =
mesh.pointZones()[cutPointZoneID_.index()];
forAll(cutPointZoneLabels, pointI)
{
ref.setAction(polyRemovePoint(cutPointZoneLabels[pointI]));
}
// Remove all faces from the face zone
const labelList& cutFaceZoneLabels =
mesh.faceZones()[cutFaceZoneID_.index()];
forAll(cutFaceZoneLabels, faceI)
{
ref.setAction(polyRemoveFace(cutFaceZoneLabels[faceI]));
}
if (debug)
{
Pout<< "void slidingInterface::clearCouple("
<< "polyTopoChange& ref) const for object " << name() << " : "
<< "Finished clearing old couple points and faces." << endl;
}
}
// ************************************************************************* //

File diff suppressed because it is too large Load Diff