Manually merged Henrik's DLB and some other stuff
This commit is contained in:
parent
75a6813d3a
commit
920ff7bcc4
58 changed files with 1225 additions and 209 deletions
|
@ -34,6 +34,7 @@ License
|
||||||
#include "OSspecific.H"
|
#include "OSspecific.H"
|
||||||
#include "Map.H"
|
#include "Map.H"
|
||||||
#include "DynamicList.H"
|
#include "DynamicList.H"
|
||||||
|
#include "globalMeshData.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
@ -53,6 +54,7 @@ Foam::domainDecomposition::domainDecomposition
|
||||||
nProcs_(readInt(decompositionDict_.lookup("numberOfSubdomains"))),
|
nProcs_(readInt(decompositionDict_.lookup("numberOfSubdomains"))),
|
||||||
distributed_(false),
|
distributed_(false),
|
||||||
gfIndex_(mesh_),
|
gfIndex_(mesh_),
|
||||||
|
gpIndex_(mesh_),
|
||||||
cellToProc_(mesh_.nCells()),
|
cellToProc_(mesh_.nCells()),
|
||||||
patchNbrCellToProc_(mesh_.boundaryMesh().size()),
|
patchNbrCellToProc_(mesh_.boundaryMesh().size()),
|
||||||
procPointAddressing_(nProcs_),
|
procPointAddressing_(nProcs_),
|
||||||
|
@ -503,6 +505,24 @@ Foam::autoPtr<Foam::fvMesh> Foam::domainDecomposition::processorMesh
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::labelList Foam::domainDecomposition::globalPointIndex
|
||||||
|
(
|
||||||
|
const label procI
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
const labelList& gppi = gpIndex_.globalLabel();
|
||||||
|
const labelList& ppAddr = procPointAddressing_[procI];
|
||||||
|
labelList globalPointIndex(ppAddr.size());
|
||||||
|
|
||||||
|
forAll (globalPointIndex, gpI)
|
||||||
|
{
|
||||||
|
globalPointIndex[gpI] = gppi[ppAddr[gpI]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return globalPointIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Foam::domainDecomposition::writeDecomposition()
|
bool Foam::domainDecomposition::writeDecomposition()
|
||||||
{
|
{
|
||||||
Info<< "\nConstructing processor meshes" << endl;
|
Info<< "\nConstructing processor meshes" << endl;
|
||||||
|
|
|
@ -43,6 +43,7 @@ SourceFiles
|
||||||
#include "PtrList.H"
|
#include "PtrList.H"
|
||||||
#include "point.H"
|
#include "point.H"
|
||||||
#include "globalProcFaceIndex.H"
|
#include "globalProcFaceIndex.H"
|
||||||
|
#include "globalProcPointIndex.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
@ -72,6 +73,9 @@ class domainDecomposition
|
||||||
//- Global face index
|
//- Global face index
|
||||||
globalProcFaceIndex gfIndex_;
|
globalProcFaceIndex gfIndex_;
|
||||||
|
|
||||||
|
//- Global face index
|
||||||
|
globalProcPointIndex gpIndex_;
|
||||||
|
|
||||||
//- Processor label for each cell
|
//- Processor label for each cell
|
||||||
labelList cellToProc_;
|
labelList cellToProc_;
|
||||||
|
|
||||||
|
@ -205,6 +209,9 @@ public:
|
||||||
const bool createPassiveProcPatches = false
|
const bool createPassiveProcPatches = false
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
|
//- Create and return global point index
|
||||||
|
labelList globalPointIndex(const label procI) const;
|
||||||
|
|
||||||
//- Return processor point addressing
|
//- Return processor point addressing
|
||||||
const labelListList& procPointAddressing() const
|
const labelListList& procPointAddressing() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -44,10 +44,10 @@ void Foam::fvFieldReconstructor::reconstructField
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
// Get references to internal and boundary field
|
// Get references to internal and boundary field
|
||||||
Field<Type>& iField = reconField.internalField();
|
Field<Type>& iField = reconField;
|
||||||
|
|
||||||
typename GeometricField<Type, fvPatchField, volMesh>::
|
typename GeometricField<Type, fvPatchField, volMesh>::
|
||||||
GeometricBoundaryField& bouField = reconField.boundaryField();
|
GeometricBoundaryField& bouField = reconField.boundaryFieldNoStoreOldTimes();
|
||||||
|
|
||||||
forAll (procFields, procI)
|
forAll (procFields, procI)
|
||||||
{
|
{
|
||||||
|
@ -143,10 +143,10 @@ void Foam::fvFieldReconstructor::reconstructField
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
// Create the internalField
|
// Create the internalField
|
||||||
Field<Type>& iField = reconField.internalField();
|
Field<Type>& iField = reconField;
|
||||||
|
|
||||||
typename GeometricField<Type, fvsPatchField, surfaceMesh>::
|
typename GeometricField<Type, fvsPatchField, surfaceMesh>::
|
||||||
GeometricBoundaryField& bouField = reconField.boundaryField();
|
GeometricBoundaryField& bouField = reconField.boundaryFieldNoStoreOldTimes();
|
||||||
|
|
||||||
forAll (procFields, procI)
|
forAll (procFields, procI)
|
||||||
{
|
{
|
||||||
|
|
|
@ -652,10 +652,30 @@ Foam::processorMeshesReconstructor::reconstructMesh(const Time& db)
|
||||||
|
|
||||||
reconPatchSizes = 0;
|
reconPatchSizes = 0;
|
||||||
|
|
||||||
|
// HR 21.12.18 : A bit of a hack for the moment in order to support the new
|
||||||
|
// method (using global point addressing) and old method (syncing across
|
||||||
|
// processor BCs) of constructing the shared points. The old method is still
|
||||||
|
// needed since global point addressing does not exist when the sharedPoint
|
||||||
|
// object is constructed from reconstructParMesh.
|
||||||
|
//
|
||||||
|
// TODO: Unify the methods by constructing global point addressing from the
|
||||||
|
// mesh pieces when. Or even better, calculate procPointAddressing directly
|
||||||
|
// which will simplify the mesh merging immensely.
|
||||||
|
autoPtr<sharedPoints> sharedDataPtr;
|
||||||
|
if(globalPointIndex_.size())
|
||||||
|
{
|
||||||
|
// Determine globally shared points using global point
|
||||||
|
// adressing
|
||||||
|
sharedDataPtr.set(new sharedPoints(meshes_, globalPointIndex_));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Prepare handling for globally shared points. This is equivalent
|
// Prepare handling for globally shared points. This is equivalent
|
||||||
// to parallel processor points, but working on a PtrList of meshes
|
// to parallel processor points, but working on a PtrList of meshes
|
||||||
// on the same processor
|
// on the same processor
|
||||||
sharedPoints sharedData(meshes_);
|
sharedDataPtr.set(new sharedPoints(meshes_));
|
||||||
|
}
|
||||||
|
sharedPoints& sharedData = sharedDataPtr();
|
||||||
|
|
||||||
// Record global point index for shared points
|
// Record global point index for shared points
|
||||||
labelList globalPointMapping(sharedData.nGlobalPoints(), -1);
|
labelList globalPointMapping(sharedData.nGlobalPoints(), -1);
|
||||||
|
|
|
@ -71,6 +71,7 @@ Foam::processorMeshesReconstructor::processorMeshesReconstructor
|
||||||
:
|
:
|
||||||
meshName_(meshName),
|
meshName_(meshName),
|
||||||
meshes_(),
|
meshes_(),
|
||||||
|
globalPointIndex_(),
|
||||||
pointProcAddressing_(),
|
pointProcAddressing_(),
|
||||||
faceProcAddressing_(),
|
faceProcAddressing_(),
|
||||||
cellProcAddressing_(),
|
cellProcAddressing_(),
|
||||||
|
@ -86,6 +87,7 @@ Foam::processorMeshesReconstructor::processorMeshesReconstructor
|
||||||
:
|
:
|
||||||
meshName_(meshName),
|
meshName_(meshName),
|
||||||
meshes_(databases.size()),
|
meshes_(databases.size()),
|
||||||
|
globalPointIndex_(),
|
||||||
pointProcAddressing_(),
|
pointProcAddressing_(),
|
||||||
faceProcAddressing_(),
|
faceProcAddressing_(),
|
||||||
cellProcAddressing_(),
|
cellProcAddressing_(),
|
||||||
|
|
|
@ -72,6 +72,9 @@ class processorMeshesReconstructor
|
||||||
//- List of processor meshes
|
//- List of processor meshes
|
||||||
PtrList<fvMesh> meshes_;
|
PtrList<fvMesh> meshes_;
|
||||||
|
|
||||||
|
//- global point index per sub-mesh
|
||||||
|
labelListList globalPointIndex_;
|
||||||
|
|
||||||
//- List of processor point addressing lists
|
//- List of processor point addressing lists
|
||||||
PtrList<labelIOList> pointProcAddressing_;
|
PtrList<labelIOList> pointProcAddressing_;
|
||||||
|
|
||||||
|
@ -161,6 +164,12 @@ public:
|
||||||
return meshes_;
|
return meshes_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- Return access to meshes
|
||||||
|
labelListList& globalPointIndex()
|
||||||
|
{
|
||||||
|
return globalPointIndex_;
|
||||||
|
}
|
||||||
|
|
||||||
//- Return point-processor addressing arrays
|
//- Return point-processor addressing arrays
|
||||||
const PtrList<labelIOList>& pointProcAddressing() const;
|
const PtrList<labelIOList>& pointProcAddressing() const;
|
||||||
|
|
||||||
|
|
|
@ -451,9 +451,160 @@ void Foam::sharedPoints::calcSharedPoints()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::sharedPoints::calcSharedPoints
|
||||||
|
(
|
||||||
|
const labelListList& globalPointIndex
|
||||||
|
)
|
||||||
|
{
|
||||||
|
typedef HashTable<Pair<label>, label, Hash<label> > markTable;
|
||||||
|
markTable marker;
|
||||||
|
|
||||||
|
List<labelHashSet> procSharedPoints(meshes_.size());
|
||||||
|
|
||||||
|
// Mark up points for the first time
|
||||||
|
forAll (meshes_, meshI)
|
||||||
|
{
|
||||||
|
if (meshes_.set(meshI))
|
||||||
|
{
|
||||||
|
const labelList& curGlobalPointIndex = globalPointIndex[meshI];
|
||||||
|
|
||||||
|
labelHashSet& sharedPoints = procSharedPoints[meshI];
|
||||||
|
|
||||||
|
forAll (curGlobalPointIndex, pI)
|
||||||
|
{
|
||||||
|
const label gpi = curGlobalPointIndex[pI];
|
||||||
|
|
||||||
|
markTable::iterator iter = marker.find(gpi);
|
||||||
|
if (iter == Map<label>::end())
|
||||||
|
{
|
||||||
|
// Record meshI and pI
|
||||||
|
marker.insert(gpi, Pair<label>(-meshI - 1, pI));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (iter().first() < 0)
|
||||||
|
{
|
||||||
|
if(iter().first() != -meshI - 1)
|
||||||
|
{
|
||||||
|
// Shared point detected. Add for both meshes
|
||||||
|
|
||||||
|
// Add for first mesh
|
||||||
|
const label firstMesh = -iter().first() - 1;
|
||||||
|
const label firstPointI = iter().second();
|
||||||
|
procSharedPoints[firstMesh].insert(firstPointI);
|
||||||
|
|
||||||
|
// Add for current mesh
|
||||||
|
sharedPoints.insert(pI);
|
||||||
|
|
||||||
|
// Count shared points and update bookkeeping
|
||||||
|
iter().first() = nGlobalPoints_;
|
||||||
|
nGlobalPoints_++;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Existing shared point. Add for current mesh
|
||||||
|
sharedPoints.insert(pI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
forAll (meshes_, meshI)
|
||||||
|
{
|
||||||
|
if (meshes_.set(meshI))
|
||||||
|
{
|
||||||
|
const labelList& curGlobalPointIndex = globalPointIndex[meshI];
|
||||||
|
|
||||||
|
labelList& curSharedPoints = sharedPointLabels_[meshI];
|
||||||
|
curSharedPoints = procSharedPoints[meshI].toc();
|
||||||
|
|
||||||
|
labelList& curSharedAddr = sharedPointAddr_[meshI];
|
||||||
|
curSharedAddr.setSize(curSharedPoints.size());
|
||||||
|
|
||||||
|
forAll(curSharedPoints, i)
|
||||||
|
{
|
||||||
|
const label gpi = curSharedPoints[i];
|
||||||
|
curSharedAddr[i] = marker.find(curGlobalPointIndex[gpi])().first();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// debug
|
||||||
|
{
|
||||||
|
pointField gp(nGlobalPoints_);
|
||||||
|
boolList gpSet(nGlobalPoints_, false);
|
||||||
|
|
||||||
|
forAll (meshes_, meshI)
|
||||||
|
{
|
||||||
|
if (meshes_.set(meshI))
|
||||||
|
{
|
||||||
|
// Get points
|
||||||
|
const pointField& P = meshes_[meshI].points();
|
||||||
|
|
||||||
|
// Get list of local point labels that are globally shared
|
||||||
|
const labelList& curShared = sharedPointLabels_[meshI];
|
||||||
|
|
||||||
|
// Get index in global point list
|
||||||
|
const labelList& curAddr = sharedPointAddr_[meshI];
|
||||||
|
|
||||||
|
// Loop through all local points
|
||||||
|
forAll (curShared, i)
|
||||||
|
{
|
||||||
|
if (!gpSet[curAddr[i]])
|
||||||
|
{
|
||||||
|
// Point not set: set it
|
||||||
|
gp[curAddr[i]] = P[curShared[i]];
|
||||||
|
gpSet[curAddr[i]] = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Point already set: check location
|
||||||
|
if (mag(gp[curAddr[i]] - P[curShared[i]]) > SMALL)
|
||||||
|
{
|
||||||
|
Info<< "MERGE MISMATCH: mesh" << meshI
|
||||||
|
<< " point: " << curShared[i]
|
||||||
|
<< " dist: " << gp[curAddr[i]] << " "
|
||||||
|
<< P[curShared[i]]
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Grab marked points
|
||||||
|
OFstream ppp("points.vtk");
|
||||||
|
ppp << "# vtk DataFile Version 2.0" << nl
|
||||||
|
<< "points.vtk" << nl
|
||||||
|
<< "ASCII" << nl
|
||||||
|
<< "DATASET POLYDATA" << nl
|
||||||
|
<< "POINTS " << nGlobalPoints_ << " float" << nl;
|
||||||
|
|
||||||
|
Pout << "Global marking " << nGlobalPoints_ << endl;
|
||||||
|
forAll (gp, i)
|
||||||
|
{
|
||||||
|
ppp << float(gp[i].x()) << ' '
|
||||||
|
<< float(gp[i].y()) << ' '
|
||||||
|
<< float(gp[i].z())
|
||||||
|
<< nl;
|
||||||
|
|
||||||
|
Pout << gp[i] << endl;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::sharedPoints::sharedPoints(const PtrList<fvMesh>& meshes)
|
Foam::sharedPoints::sharedPoints
|
||||||
|
(
|
||||||
|
const PtrList<fvMesh>& meshes
|
||||||
|
)
|
||||||
:
|
:
|
||||||
meshes_(meshes),
|
meshes_(meshes),
|
||||||
sharedPointAddr_(meshes_.size()),
|
sharedPointAddr_(meshes_.size()),
|
||||||
|
@ -463,11 +614,19 @@ Foam::sharedPoints::sharedPoints(const PtrList<fvMesh>& meshes)
|
||||||
calcSharedPoints();
|
calcSharedPoints();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Foam::sharedPoints::sharedPoints
|
||||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
(
|
||||||
|
const PtrList<fvMesh>& meshes,
|
||||||
// Foam::sharedPoints::~sharedPoints()
|
const labelListList& globalPointIndex
|
||||||
// {}
|
)
|
||||||
|
:
|
||||||
|
meshes_(meshes),
|
||||||
|
sharedPointAddr_(meshes_.size()),
|
||||||
|
sharedPointLabels_(meshes_.size()),
|
||||||
|
nGlobalPoints_(0)
|
||||||
|
{
|
||||||
|
calcSharedPoints(globalPointIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|
|
@ -117,13 +117,26 @@ class sharedPoints
|
||||||
//- Calculate shared points
|
//- Calculate shared points
|
||||||
void calcSharedPoints();
|
void calcSharedPoints();
|
||||||
|
|
||||||
|
//- Calculate shared points
|
||||||
|
void calcSharedPoints(const labelListList& globalPointIndex);
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
//- Construct from the list of meshes
|
//- Construct from the list of meshes
|
||||||
sharedPoints(const PtrList<fvMesh>& meshes);
|
sharedPoints
|
||||||
|
(
|
||||||
|
const PtrList<fvMesh>& meshes
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Construct from the list of meshes and global point addressing
|
||||||
|
sharedPoints
|
||||||
|
(
|
||||||
|
const PtrList<fvMesh>& meshes,
|
||||||
|
const labelListList& globalPointIndex
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
//- Destructor
|
//- Destructor
|
||||||
|
|
|
@ -271,13 +271,13 @@ bool Foam::dynamicPolyRefinementFvMesh::update()
|
||||||
(
|
(
|
||||||
refinementSelectionPtr_->refinementCellCandidates()()
|
refinementSelectionPtr_->refinementCellCandidates()()
|
||||||
);
|
);
|
||||||
Pout<< "Selected " << refCandidates.size()
|
Info<< "Selected " << refCandidates.size()
|
||||||
<< " refinement candidates."
|
<< " refinement candidates."
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Pout<< "Skipping refinement for this time-step..." << endl;
|
Info<< "Skipping refinement for this time-step..." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set cells to refine. Note: refinement needs to make sure that face
|
// Set cells to refine. Note: refinement needs to make sure that face
|
||||||
|
@ -297,13 +297,13 @@ bool Foam::dynamicPolyRefinementFvMesh::update()
|
||||||
(
|
(
|
||||||
refinementSelectionPtr_->unrefinementPointCandidates()()
|
refinementSelectionPtr_->unrefinementPointCandidates()()
|
||||||
);
|
);
|
||||||
Pout<< "Selected " << unrefCandidates.size()
|
Info<< "Selected " << unrefCandidates.size()
|
||||||
<< " unrefinement candidates."
|
<< " unrefinement candidates."
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Pout<< "Skipping unrefinement for this time-step..." << endl;
|
Info<< "Skipping unrefinement for this time-step..." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set split points to unrefine around.
|
// Set split points to unrefine around.
|
||||||
|
@ -344,13 +344,13 @@ bool Foam::dynamicPolyRefinementFvMesh::update()
|
||||||
// some topo changes
|
// some topo changes
|
||||||
if (sizeCellMap)
|
if (sizeCellMap)
|
||||||
{
|
{
|
||||||
Pout<< "Successfully performed polyhedral refinement. "
|
Info<< "Successfully performed polyhedral refinement. "
|
||||||
<< "Changed from " << nOldCells << " to " << sizeCellMap
|
<< "Changed from " << nOldCells << " to " << sizeCellMap
|
||||||
<< " cells." << endl;
|
<< " cells." << endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Pout<< "Refinement/unrefinement not performed in this time step "
|
Info<< "Refinement/unrefinement not performed in this time step "
|
||||||
<< "since no cells were selected." << endl;
|
<< "since no cells were selected." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,7 +363,7 @@ bool Foam::dynamicPolyRefinementFvMesh::update()
|
||||||
curTimeIndex_ = time().timeIndex();
|
curTimeIndex_ = time().timeIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
Pout<< "No refinement/unrefinement" << endl;
|
Info<< "No refinement/unrefinement" << endl;
|
||||||
|
|
||||||
// No refinement/unrefinement at this time step. Return false
|
// No refinement/unrefinement at this time step. Return false
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -33,6 +33,7 @@ License
|
||||||
#include "addToRunTimeSelectionTable.H"
|
#include "addToRunTimeSelectionTable.H"
|
||||||
#include "cloud.H"
|
#include "cloud.H"
|
||||||
#include "cloudDistribute.H"
|
#include "cloudDistribute.H"
|
||||||
|
#include "meshObjectBase.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
@ -138,10 +139,14 @@ bool Foam::topoChangerFvMesh::loadBalance(const dictionary& decompDict)
|
||||||
// Prepare receiving side
|
// Prepare receiving side
|
||||||
|
|
||||||
// Create the reconstructor
|
// Create the reconstructor
|
||||||
processorMeshesReconstructor meshRecon("reconstructed");
|
//
|
||||||
|
// HR 21.12.18 : Use empty domainname to avoid auto-created of
|
||||||
|
// fvSchemes/fvSolution
|
||||||
|
processorMeshesReconstructor meshRecon("");
|
||||||
|
|
||||||
PtrList<fvMesh>& procMeshes = meshRecon.meshes();
|
PtrList<fvMesh>& procMeshes = meshRecon.meshes();
|
||||||
procMeshes.setSize(meshDecomp.nProcs());
|
procMeshes.setSize(meshDecomp.nProcs());
|
||||||
|
meshRecon.globalPointIndex().setSize(meshDecomp.nProcs());
|
||||||
|
|
||||||
// Collect local fields for decomposition
|
// Collect local fields for decomposition
|
||||||
clearOut();
|
clearOut();
|
||||||
|
@ -242,6 +247,29 @@ bool Foam::topoChangerFvMesh::loadBalance(const dictionary& decompDict)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HR 14.12.18: Create dummy database pointing into the non-parallel case
|
||||||
|
// directory and disable the runTimeModifiable switch. dummyTime is used
|
||||||
|
// for decomposed, received and reconstructed fvMeshes (ie. before its data
|
||||||
|
// is moved into *this).
|
||||||
|
//
|
||||||
|
// The pointing into the non-parallel case directory is somewhat a hack to
|
||||||
|
// prevent auto-creation of fvSchemes and fvSolution (they exist in the root
|
||||||
|
// case). This is potentially dangerous if we write anything, but fvMeshes
|
||||||
|
// derived from this database are NO_WRITE so we should be fine. Making if
|
||||||
|
// non-runTimeModifiable prevents registration of fvSolution with the
|
||||||
|
// fileMonitor (addWatch). Not all processors will necessarily receive a
|
||||||
|
// mesh and watches will then cause dead-locks!
|
||||||
|
Time dummyTime
|
||||||
|
(
|
||||||
|
time().rootPath(),
|
||||||
|
time().globalCaseName(),
|
||||||
|
"system",
|
||||||
|
"constant",
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
const_cast<Switch&>(dummyTime.runTimeModifiable()) = false;
|
||||||
|
|
||||||
for (label procI = 0; procI < meshDecomp.nProcs(); procI++)
|
for (label procI = 0; procI < meshDecomp.nProcs(); procI++)
|
||||||
{
|
{
|
||||||
// Check if there is a mesh to send
|
// Check if there is a mesh to send
|
||||||
|
@ -253,8 +281,9 @@ bool Foam::topoChangerFvMesh::loadBalance(const dictionary& decompDict)
|
||||||
autoPtr<fvMesh> procMeshPtr = meshDecomp.processorMesh
|
autoPtr<fvMesh> procMeshPtr = meshDecomp.processorMesh
|
||||||
(
|
(
|
||||||
procI,
|
procI,
|
||||||
time(),
|
dummyTime,
|
||||||
"processorPart" + Foam::name(procI),
|
"", // HR 21.12.18 : Use empty domainname to avoid
|
||||||
|
// auto-created offvSchemes/fvSolution
|
||||||
true // Create passive processor patches
|
true // Create passive processor patches
|
||||||
);
|
);
|
||||||
fvMesh& procMesh = procMeshPtr();
|
fvMesh& procMesh = procMeshPtr();
|
||||||
|
@ -286,6 +315,7 @@ bool Foam::topoChangerFvMesh::loadBalance(const dictionary& decompDict)
|
||||||
|
|
||||||
// Send the mesh and fields to target processor
|
// Send the mesh and fields to target processor
|
||||||
toProc << procMesh << nl;
|
toProc << procMesh << nl;
|
||||||
|
toProc << meshDecomp.globalPointIndex(procI) << nl;
|
||||||
|
|
||||||
// Send fields
|
// Send fields
|
||||||
sendFields(volScalarFields, fieldDecomposer, toProc);
|
sendFields(volScalarFields, fieldDecomposer, toProc);
|
||||||
|
@ -342,6 +372,9 @@ bool Foam::topoChangerFvMesh::loadBalance(const dictionary& decompDict)
|
||||||
procMeshPtr
|
procMeshPtr
|
||||||
);
|
);
|
||||||
|
|
||||||
|
meshRecon.globalPointIndex()[procI] =
|
||||||
|
meshDecomp.globalPointIndex(procI);
|
||||||
|
|
||||||
// Set local fields
|
// Set local fields
|
||||||
// Note: first index is field index and second index is procI
|
// Note: first index is field index and second index is procI
|
||||||
insertFields
|
insertFields
|
||||||
|
@ -411,6 +444,10 @@ bool Foam::topoChangerFvMesh::loadBalance(const dictionary& decompDict)
|
||||||
}
|
}
|
||||||
|
|
||||||
//HJ Insert clouds missing. HJ, 12/Oct/2018
|
//HJ Insert clouds missing. HJ, 12/Oct/2018
|
||||||
|
//
|
||||||
|
// HR 18.11.18 - Not missing. Step is trivial and is treated in
|
||||||
|
// Cloud<ParticleType>::split which is called in the constructor
|
||||||
|
// of CloudDistibute
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -445,9 +482,9 @@ bool Foam::topoChangerFvMesh::loadBalance(const dictionary& decompDict)
|
||||||
(
|
(
|
||||||
IOobject
|
IOobject
|
||||||
(
|
(
|
||||||
"processorPart" + Foam::name(procI),
|
"", // "processorPart" + Foam::name(procI),
|
||||||
time().timeName(),
|
dummyTime.timeName(),
|
||||||
time(),
|
dummyTime,
|
||||||
IOobject::NO_READ,
|
IOobject::NO_READ,
|
||||||
IOobject::NO_WRITE
|
IOobject::NO_WRITE
|
||||||
),
|
),
|
||||||
|
@ -456,6 +493,10 @@ bool Foam::topoChangerFvMesh::loadBalance(const dictionary& decompDict)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Receive the global points addr
|
||||||
|
labelList gppi(fromProc);
|
||||||
|
meshRecon.globalPointIndex()[procI] = gppi;
|
||||||
|
|
||||||
// Receive fields
|
// Receive fields
|
||||||
// Note: first index is field index and second index is procI
|
// Note: first index is field index and second index is procI
|
||||||
receiveFields
|
receiveFields
|
||||||
|
@ -535,7 +576,7 @@ bool Foam::topoChangerFvMesh::loadBalance(const dictionary& decompDict)
|
||||||
|
|
||||||
// Create the reconstructed mesh
|
// Create the reconstructed mesh
|
||||||
autoPtr<fvMesh> reconstructedMeshPtr =
|
autoPtr<fvMesh> reconstructedMeshPtr =
|
||||||
meshRecon.reconstructMesh(time());
|
meshRecon.reconstructMesh(dummyTime);
|
||||||
fvMesh& reconMesh = reconstructedMeshPtr();
|
fvMesh& reconMesh = reconstructedMeshPtr();
|
||||||
|
|
||||||
Pout<< "Reconstructed mesh stats: "
|
Pout<< "Reconstructed mesh stats: "
|
||||||
|
@ -915,6 +956,9 @@ bool Foam::topoChangerFvMesh::loadBalance(const dictionary& decompDict)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HR 13.12.18: Update the mesh objects
|
||||||
|
meshObjectBase::allUpdateTopology<polyMesh>(*this, meshMap);
|
||||||
|
|
||||||
// Debug: remove? HJ, 22/Oct/2018
|
// Debug: remove? HJ, 22/Oct/2018
|
||||||
// checkMesh(true);
|
// checkMesh(true);
|
||||||
|
|
||||||
|
|
|
@ -263,12 +263,12 @@ void Foam::topoChangerFvMesh::rebuildFields
|
||||||
// Resize internal field
|
// Resize internal field
|
||||||
if
|
if
|
||||||
(
|
(
|
||||||
masterField.internalField().size()
|
masterField.size()
|
||||||
!= GeoField::GeoMeshType::size(masterField.mesh())
|
!= GeoField::GeoMeshType::size(masterField.mesh())
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Pout<< "Resizing internal field: old size = "
|
Pout<< "Resizing internal field: old size = "
|
||||||
<< masterField.internalField().size()
|
<< masterField.size()
|
||||||
<< " new size = "
|
<< " new size = "
|
||||||
<< GeoField::GeoMeshType::size(masterField.mesh())
|
<< GeoField::GeoMeshType::size(masterField.mesh())
|
||||||
<< endl;
|
<< endl;
|
||||||
|
@ -280,7 +280,7 @@ void Foam::topoChangerFvMesh::rebuildFields
|
||||||
|
|
||||||
// Resize boundary (number of patches)
|
// Resize boundary (number of patches)
|
||||||
typename GeoField::GeometricBoundaryField& patchFields =
|
typename GeoField::GeometricBoundaryField& patchFields =
|
||||||
masterField.boundaryField();
|
masterField.boundaryFieldNoStoreOldTimes();
|
||||||
|
|
||||||
if (patchFields.size() != masterField.mesh().boundary().size())
|
if (patchFields.size() != masterField.mesh().boundary().size())
|
||||||
{
|
{
|
||||||
|
@ -352,6 +352,22 @@ void Foam::topoChangerFvMesh::rebuildFields
|
||||||
fieldI++;
|
fieldI++;
|
||||||
Pout<< "... done" << endl;
|
Pout<< "... done" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HR 14.12.18: We create new processor boundary faces from internal
|
||||||
|
// faces. The values on these faces could be initialised by interpolation.
|
||||||
|
// Instead we choose to fix the values by evaluating the boundaries.
|
||||||
|
// I tried to execute evaluateCoupled() at the end of
|
||||||
|
// fvFieldReconstructor::reconstructField, but this fails in a strange way.
|
||||||
|
forAllConstIter
|
||||||
|
(
|
||||||
|
typename HashTable<const GeoField*>,
|
||||||
|
geoFields,
|
||||||
|
iter
|
||||||
|
)
|
||||||
|
{
|
||||||
|
GeoField& masterField = const_cast<GeoField&>(*iter());
|
||||||
|
masterField.boundaryField().evaluateCoupled();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,12 @@ scalar CoNum = 0.0;
|
||||||
scalar meanCoNum = 0.0;
|
scalar meanCoNum = 0.0;
|
||||||
scalar velMag = 0.0;
|
scalar velMag = 0.0;
|
||||||
|
|
||||||
if (mesh.nInternalFaces())
|
// HR 26.06.18: A parallel run has at least two cells and therefore at least
|
||||||
|
// one internal face in the global mesh. It may be a processor boundary, but
|
||||||
|
// this is captured by max(mag(phi)).
|
||||||
|
// Old formulation hangs on parallel cases where one partition is degenerated
|
||||||
|
// to a single cell.
|
||||||
|
if (mesh.nInternalFaces() || Pstream::parRun())
|
||||||
{
|
{
|
||||||
surfaceScalarField phiOverRho = mag(phi)/fvc::interpolate(rho);
|
surfaceScalarField phiOverRho = mag(phi)/fvc::interpolate(rho);
|
||||||
|
|
||||||
|
@ -47,6 +52,20 @@ if (mesh.nInternalFaces())
|
||||||
|
|
||||||
velMag = max(phiOverRho/mesh.magSf()).value();
|
velMag = max(phiOverRho/mesh.magSf()).value();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Single cell mesh: Co is still defined; use cell formulation
|
||||||
|
|
||||||
|
const scalar deltaT = runTime.deltaT().value();
|
||||||
|
|
||||||
|
const scalar deltaX = Foam::cbrt(mesh.V()[0]);
|
||||||
|
|
||||||
|
velMag = mag(U[0]);
|
||||||
|
|
||||||
|
CoNum = velMag*deltaT/deltaX;
|
||||||
|
|
||||||
|
meanCoNum = CoNum;
|
||||||
|
}
|
||||||
|
|
||||||
Info<< "Courant Number mean: " << meanCoNum
|
Info<< "Courant Number mean: " << meanCoNum
|
||||||
<< " max: " << CoNum
|
<< " max: " << CoNum
|
||||||
|
|
|
@ -33,7 +33,7 @@ scalar CoNum = 0.0;
|
||||||
scalar meanCoNum = 0.0;
|
scalar meanCoNum = 0.0;
|
||||||
scalar velMag = 0.0;
|
scalar velMag = 0.0;
|
||||||
|
|
||||||
// HR 26.06.28: A parallel run has at least two cells and therefore at least
|
// HR 26.06.18: A parallel run has at least two cells and therefore at least
|
||||||
// one internal face in the global mesh. It may be a processor boundary, but
|
// one internal face in the global mesh. It may be a processor boundary, but
|
||||||
// this is captured by max(mag(phi)).
|
// this is captured by max(mag(phi)).
|
||||||
// Old formulation hangs on parallel cases where one partition is degenerated
|
// Old formulation hangs on parallel cases where one partition is degenerated
|
||||||
|
|
|
@ -67,11 +67,11 @@ fixedGradientFvPatchField<Type>::fixedGradientFvPatchField
|
||||||
const dictionary& dict
|
const dictionary& dict
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
fvPatchField<Type>(p, iF, dict),
|
// HR 15.12.18: Must not call evaluate during construction. Read value
|
||||||
|
// instead. This is needed for PLB.
|
||||||
|
fvPatchField<Type>(p, iF, dict, true),
|
||||||
gradient_("gradient", dict, p.size())
|
gradient_("gradient", dict, p.size())
|
||||||
{
|
{}
|
||||||
evaluate();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
|
|
|
@ -54,13 +54,13 @@ mixedFvPatchField<Type>::mixedFvPatchField
|
||||||
const dictionary& dict
|
const dictionary& dict
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
fvPatchField<Type>(p, iF, dict),
|
// HR 15.12.18: Must not call evaluate during construction. Read value
|
||||||
|
// instead. This is needed for PLB.
|
||||||
|
fvPatchField<Type>(p, iF, dict, true),
|
||||||
refValue_("refValue", dict, p.size()),
|
refValue_("refValue", dict, p.size()),
|
||||||
refGrad_("refGradient", dict, p.size()),
|
refGrad_("refGradient", dict, p.size()),
|
||||||
valueFraction_("valueFraction", dict, p.size())
|
valueFraction_("valueFraction", dict, p.size())
|
||||||
{
|
{}
|
||||||
evaluate();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
|
|
|
@ -70,7 +70,12 @@ Foam::fvSchemes::fvSchemes(const objectRegistry& obr)
|
||||||
"fvSchemes",
|
"fvSchemes",
|
||||||
obr.time().system(),
|
obr.time().system(),
|
||||||
obr,
|
obr,
|
||||||
IOobject::READ_IF_PRESENT_IF_MODIFIED, // Allow default dictionary creation
|
(
|
||||||
|
obr.readOpt() == IOobject::MUST_READ
|
||||||
|
|| obr.readOpt() == IOobject::READ_IF_PRESENT
|
||||||
|
? IOobject::MUST_READ_IF_MODIFIED
|
||||||
|
: obr.readOpt()
|
||||||
|
),
|
||||||
IOobject::NO_WRITE
|
IOobject::NO_WRITE
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
@ -168,21 +173,17 @@ Foam::fvSchemes::fvSchemes(const objectRegistry& obr)
|
||||||
fluxRequired_(), // Do not read flux required option
|
fluxRequired_(), // Do not read flux required option
|
||||||
defaultFluxRequired_(false)
|
defaultFluxRequired_(false)
|
||||||
{
|
{
|
||||||
if (!headerOk())
|
// HR 21.12.18 : Writing a default fvSchemes is not useful in PLB. Please
|
||||||
{
|
// specify MUST_READ on obr if you need this.
|
||||||
if (debug)
|
if
|
||||||
{
|
|
||||||
InfoIn
|
|
||||||
(
|
(
|
||||||
"fvSchemes::fvSchemes(const objectRegistry& obr)"
|
readOpt() == IOobject::MUST_READ
|
||||||
) << "fvSchemes dictionary not found. Creating default."
|
|| readOpt() == IOobject::MUST_READ_IF_MODIFIED
|
||||||
<< endl;
|
|| (readOpt() == IOobject::READ_IF_PRESENT && headerOk())
|
||||||
}
|
)
|
||||||
|
{
|
||||||
regIOobject::write();
|
|
||||||
}
|
|
||||||
|
|
||||||
read();
|
read();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -424,6 +424,9 @@ void Foam::fvMesh::resetFvPrimitives
|
||||||
// Reset fvPatches HJ, 16/Apr/2018
|
// Reset fvPatches HJ, 16/Apr/2018
|
||||||
boundary_.resetFvPatches(resetFvPatchFlag);
|
boundary_.resetFvPatches(resetFvPatchFlag);
|
||||||
|
|
||||||
|
// HR 14.12.18: Indicate that the mesh is changing to e.g. nearWallDist
|
||||||
|
polyMesh::changing(true);
|
||||||
|
|
||||||
// Clear all mesh data
|
// Clear all mesh data
|
||||||
clearOut();
|
clearOut();
|
||||||
}
|
}
|
||||||
|
|
|
@ -447,6 +447,7 @@ $(globalMeshData)/globalMeshData.C
|
||||||
$(globalMeshData)/globalPoints.C
|
$(globalMeshData)/globalPoints.C
|
||||||
$(globalMeshData)/globalIndex.C
|
$(globalMeshData)/globalIndex.C
|
||||||
$(globalMeshData)/globalProcFaceIndex.C
|
$(globalMeshData)/globalProcFaceIndex.C
|
||||||
|
$(globalMeshData)/globalProcPointIndex.C
|
||||||
|
|
||||||
$(polyMesh)/syncTools/syncTools.C
|
$(polyMesh)/syncTools/syncTools.C
|
||||||
|
|
||||||
|
|
|
@ -728,6 +728,16 @@ Foam::GeometricField<Type, PatchField, GeoMesh>::boundaryField()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Return reference to GeometricBoundaryField
|
||||||
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||||
|
typename
|
||||||
|
Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricBoundaryField&
|
||||||
|
Foam::GeometricField<Type, PatchField, GeoMesh>::boundaryFieldNoStoreOldTimes()
|
||||||
|
{
|
||||||
|
return boundaryField_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Store old-time field
|
// Store old-time field
|
||||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||||
void Foam::GeometricField<Type, PatchField, GeoMesh>::storeOldTimes() const
|
void Foam::GeometricField<Type, PatchField, GeoMesh>::storeOldTimes() const
|
||||||
|
|
|
@ -447,6 +447,10 @@ public:
|
||||||
//- Return reference to GeometricBoundaryField for const field
|
//- Return reference to GeometricBoundaryField for const field
|
||||||
inline const GeometricBoundaryField& boundaryField() const;
|
inline const GeometricBoundaryField& boundaryField() const;
|
||||||
|
|
||||||
|
//- Return reference to GeometricBoundaryField without storing old
|
||||||
|
//- times
|
||||||
|
GeometricBoundaryField& boundaryFieldNoStoreOldTimes();
|
||||||
|
|
||||||
//- Return the time index of the field
|
//- Return the time index of the field
|
||||||
inline label timeIndex() const;
|
inline label timeIndex() const;
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,13 @@ Foam::autoPtr<Foam::cloudDistribute> Foam::cloud::cloudDist
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::labelList Foam::cloud::nParticlesPerCell() const
|
||||||
|
{
|
||||||
|
NotImplemented;
|
||||||
|
return labelList(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::cloud::~cloud()
|
Foam::cloud::~cloud()
|
||||||
|
|
|
@ -101,6 +101,8 @@ public:
|
||||||
//- Return size of the cloud
|
//- Return size of the cloud
|
||||||
virtual label size() const;
|
virtual label size() const;
|
||||||
|
|
||||||
|
//- Count and return number of particles per cell
|
||||||
|
virtual labelList nParticlesPerCell() const;
|
||||||
|
|
||||||
// Edit
|
// Edit
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ License
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "pointBoundaryMesh.H"
|
#include "pointBoundaryMesh.H"
|
||||||
|
#include "polyMesh.H"
|
||||||
#include "polyBoundaryMesh.H"
|
#include "polyBoundaryMesh.H"
|
||||||
#include "facePointPatch.H"
|
#include "facePointPatch.H"
|
||||||
#include "globalPointPatch.H"
|
#include "globalPointPatch.H"
|
||||||
|
@ -105,10 +106,39 @@ void Foam::pointBoundaryMesh::movePoints()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::pointBoundaryMesh::updateMesh()
|
void Foam::pointBoundaryMesh::updateMesh
|
||||||
|
(
|
||||||
|
const polyMesh& pMesh
|
||||||
|
)
|
||||||
{
|
{
|
||||||
|
const polyBoundaryMesh& pBoundary = pMesh.boundaryMesh();
|
||||||
pointPatchList& patches = *this;
|
pointPatchList& patches = *this;
|
||||||
|
|
||||||
|
// 21.1.19 HR : Patches need to be recreated in PLB
|
||||||
|
patches.clear();
|
||||||
|
patches.setSize(pBoundary.size());
|
||||||
|
|
||||||
|
forAll(patches, patchI)
|
||||||
|
{
|
||||||
|
patches.set
|
||||||
|
(
|
||||||
|
patchI,
|
||||||
|
facePointPatch::New(pBoundary[patchI], *this).ptr()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the globalPointPatch
|
||||||
|
if(pMesh.globalData().nGlobalPoints())
|
||||||
|
{
|
||||||
|
patches.setSize(pBoundary.size() + 1);
|
||||||
|
|
||||||
|
patches.set
|
||||||
|
(
|
||||||
|
patches.size() - 1,
|
||||||
|
new globalPointPatch(*this, patches.size() - 1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
forAll(patches, patchi)
|
forAll(patches, patchi)
|
||||||
{
|
{
|
||||||
patches[patchi].initUpdateMesh();
|
patches[patchi].initUpdateMesh();
|
||||||
|
|
|
@ -46,6 +46,7 @@ namespace Foam
|
||||||
class pointMesh;
|
class pointMesh;
|
||||||
class polyBoundaryMesh;
|
class polyBoundaryMesh;
|
||||||
class globalPointPatch;
|
class globalPointPatch;
|
||||||
|
class polyMesh;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class pointBoundaryMesh Declaration
|
Class pointBoundaryMesh Declaration
|
||||||
|
@ -105,7 +106,10 @@ public:
|
||||||
void movePoints();
|
void movePoints();
|
||||||
|
|
||||||
//- Correct polyBoundaryMesh after topology update
|
//- Correct polyBoundaryMesh after topology update
|
||||||
void updateMesh();
|
void updateMesh
|
||||||
|
(
|
||||||
|
const polyMesh& pMesh
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,10 @@ bool Foam::pointMesh::updateMesh(const mapPolyMesh& mpm) const
|
||||||
{
|
{
|
||||||
// Casting const-ness to answer the interface of meshObject
|
// Casting const-ness to answer the interface of meshObject
|
||||||
// HJ, 30/Aug/2010
|
// HJ, 30/Aug/2010
|
||||||
const_cast<pointBoundaryMesh&>(boundary_).updateMesh();
|
const_cast<pointBoundaryMesh&>(boundary_).updateMesh
|
||||||
|
(
|
||||||
|
GeoMesh<polyMesh>::mesh_
|
||||||
|
);
|
||||||
|
|
||||||
// Map all registered point fields
|
// Map all registered point fields
|
||||||
mapFields(mpm);
|
mapFields(mpm);
|
||||||
|
|
|
@ -118,7 +118,8 @@ void Foam::globalProcFaceIndex::calcFaceIndex()
|
||||||
|
|
||||||
OPstream toProc
|
OPstream toProc
|
||||||
(
|
(
|
||||||
Pstream::nonBlocking,
|
// HR 12.12.18: nonBlocking fails on PLB of Aachen bomb
|
||||||
|
Pstream::blocking,
|
||||||
procPatch.neighbProcNo()
|
procPatch.neighbProcNo()
|
||||||
);
|
);
|
||||||
toProc<< curFaceLabels;
|
toProc<< curFaceLabels;
|
||||||
|
@ -154,7 +155,8 @@ void Foam::globalProcFaceIndex::calcFaceIndex()
|
||||||
// Receive the data from master and insert into the list
|
// Receive the data from master and insert into the list
|
||||||
IPstream fromProc
|
IPstream fromProc
|
||||||
(
|
(
|
||||||
Pstream::nonBlocking,
|
// HR 12.12.18: nonBlocking fails on PLB of Aachen bomb
|
||||||
|
Pstream::blocking,
|
||||||
procPatch.neighbProcNo()
|
procPatch.neighbProcNo()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,7 @@ public:
|
||||||
return procFaceOffset_;
|
return procFaceOffset_;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Return lobal face label for all faces of current mesh
|
//- Return global face label for all faces of current mesh
|
||||||
// Sized to number of live faces in the mesh
|
// Sized to number of live faces in the mesh
|
||||||
const labelList globalLabel() const
|
const labelList globalLabel() const
|
||||||
{
|
{
|
||||||
|
|
319
src/foam/meshes/polyMesh/globalMeshData/globalProcPointIndex.C
Normal file
319
src/foam/meshes/polyMesh/globalMeshData/globalProcPointIndex.C
Normal file
|
@ -0,0 +1,319 @@
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | foam-extend: Open Source CFD
|
||||||
|
\\ / O peration | Version: 4.1
|
||||||
|
\\ / A nd | Web: http://www.foam-extend.org
|
||||||
|
\\/ M anipulation | For copyright notice see file Copyright
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of foam-extend.
|
||||||
|
|
||||||
|
foam-extend is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
foam-extend is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "globalProcPointIndex.H"
|
||||||
|
#include "processorPolyPatch.H"
|
||||||
|
#include "globalMeshData.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::globalProcPointIndex::calcPointIndex()
|
||||||
|
{
|
||||||
|
// Count and mark points in the following order
|
||||||
|
// 1. global points
|
||||||
|
// 2. processor patches
|
||||||
|
// 3. regular patches
|
||||||
|
// 4. anything else ("internal points")
|
||||||
|
//
|
||||||
|
// The marking is a follows
|
||||||
|
// -4 : Not visited yet
|
||||||
|
// -3 : Found in a regular patch
|
||||||
|
// -2 : Found in slave processor patch
|
||||||
|
// -1 : Found in a master processor patch
|
||||||
|
// 0 - nGlobalPoints-1 : Global point ID
|
||||||
|
|
||||||
|
// 1. Mark the global points
|
||||||
|
const labelList& spl = mesh_.globalData().sharedPointLabels();
|
||||||
|
const labelList& spa = mesh_.globalData().sharedPointAddr();
|
||||||
|
|
||||||
|
forAll(spl, spI)
|
||||||
|
{
|
||||||
|
globalLabel_[spl[spI]] = spa[spI];
|
||||||
|
}
|
||||||
|
|
||||||
|
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
|
||||||
|
|
||||||
|
labelList procPointCounter(Pstream::nProcs(), 0);
|
||||||
|
labelList patchPointCounter(patches.size(), 0);
|
||||||
|
label& nProcPoints = procPointCounter[Pstream::myProcNo()];
|
||||||
|
|
||||||
|
// Master processor patches - first pass
|
||||||
|
forAll (patches, patchI)
|
||||||
|
{
|
||||||
|
const polyPatch& pp = patches[patchI];
|
||||||
|
const labelList& patchMeshPoints = pp.meshPoints();
|
||||||
|
|
||||||
|
if (isA<processorPolyPatch>(pp))
|
||||||
|
{
|
||||||
|
const processorPolyPatch& procPatch =
|
||||||
|
refCast<const processorPolyPatch>(pp);
|
||||||
|
|
||||||
|
label& nPatchPoints = patchPointCounter[patchI];
|
||||||
|
|
||||||
|
if (procPatch.master())
|
||||||
|
{
|
||||||
|
forAll (patchMeshPoints, mpI)
|
||||||
|
{
|
||||||
|
label& pl = globalLabel_[patchMeshPoints[mpI]];
|
||||||
|
|
||||||
|
if (pl < 0)
|
||||||
|
{
|
||||||
|
nProcPoints++;
|
||||||
|
nPatchPoints++;
|
||||||
|
pl = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slave processor patches - first pass
|
||||||
|
forAll (patches, patchI)
|
||||||
|
{
|
||||||
|
const polyPatch& pp = patches[patchI];
|
||||||
|
const labelList& patchMeshPoints = pp.meshPoints();
|
||||||
|
|
||||||
|
if (isA<processorPolyPatch>(pp))
|
||||||
|
{
|
||||||
|
const processorPolyPatch& procPatch =
|
||||||
|
refCast<const processorPolyPatch>(pp);
|
||||||
|
|
||||||
|
if (!procPatch.master())
|
||||||
|
{
|
||||||
|
forAll (patchMeshPoints, mpI)
|
||||||
|
{
|
||||||
|
label& pl = globalLabel_[patchMeshPoints[mpI]];
|
||||||
|
|
||||||
|
if (pl == -4)
|
||||||
|
{
|
||||||
|
pl = -2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regular patches - first pass
|
||||||
|
forAll (patches, patchI)
|
||||||
|
{
|
||||||
|
const polyPatch& pp = patches[patchI];
|
||||||
|
const labelList& patchMeshPoints = pp.meshPoints();
|
||||||
|
|
||||||
|
if (!isA<processorPolyPatch>(pp))
|
||||||
|
{
|
||||||
|
label& nPatchPoints = patchPointCounter[patchI];
|
||||||
|
|
||||||
|
forAll (patchMeshPoints, mpI)
|
||||||
|
{
|
||||||
|
label& pl = globalLabel_[patchMeshPoints[mpI]];
|
||||||
|
|
||||||
|
if (pl == -4)
|
||||||
|
{
|
||||||
|
nProcPoints++;
|
||||||
|
nPatchPoints++;
|
||||||
|
pl = -3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// "Internal" points - first pass
|
||||||
|
label nInternalPoints = 0;
|
||||||
|
forAll (globalLabel_, pI)
|
||||||
|
{
|
||||||
|
if (globalLabel_[pI] == -4)
|
||||||
|
{
|
||||||
|
nInternalPoints++;
|
||||||
|
nProcPoints++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gather-Scatter counter data
|
||||||
|
Pstream::gatherList(procPointCounter);
|
||||||
|
Pstream::scatterList(procPointCounter);
|
||||||
|
|
||||||
|
// Convert counters to offsets
|
||||||
|
procPointOffset_[0] = mesh_.globalData().nGlobalPoints();
|
||||||
|
for (label procI = 1; procI < procPointOffset_.size(); procI++)
|
||||||
|
{
|
||||||
|
procPointOffset_[procI] =
|
||||||
|
procPointCounter[procI-1] + procPointOffset_[procI-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
patchPointOffset_[0] =
|
||||||
|
procPointOffset_[Pstream::myProcNo()] + nInternalPoints;
|
||||||
|
for (label patchI = 1; patchI < patchPointOffset_.size(); patchI++)
|
||||||
|
{
|
||||||
|
patchPointOffset_[patchI] =
|
||||||
|
patchPointCounter[patchI-1] + patchPointOffset_[patchI-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
const pointField& points = mesh_.points();
|
||||||
|
|
||||||
|
// Master processor patches - second pass
|
||||||
|
// Send patch offset to slave and assign global labels to points on
|
||||||
|
// master processor patches and regular patches
|
||||||
|
forAll (patches, patchI)
|
||||||
|
{
|
||||||
|
const polyPatch& pp = patches[patchI];
|
||||||
|
const labelList& patchMeshPoints = pp.meshPoints();
|
||||||
|
const label patchPO = patchPointOffset_[patchI];
|
||||||
|
|
||||||
|
if (isA<processorPolyPatch>(pp))
|
||||||
|
{
|
||||||
|
const processorPolyPatch& procPatch =
|
||||||
|
refCast<const processorPolyPatch>(pp);
|
||||||
|
|
||||||
|
if (procPatch.master())
|
||||||
|
{
|
||||||
|
// Master processor patch
|
||||||
|
// Send the offset to the slave and mark the points through a
|
||||||
|
// face loop to establish an order that can be untangled on
|
||||||
|
// slave side
|
||||||
|
|
||||||
|
OPstream toProc
|
||||||
|
(
|
||||||
|
Pstream::nonBlocking,
|
||||||
|
procPatch.neighbProcNo()
|
||||||
|
);
|
||||||
|
toProc<< patchPO;
|
||||||
|
|
||||||
|
pointField pointLocs(patchMeshPoints.size());
|
||||||
|
label glPointLabelsI = 0;
|
||||||
|
forAll (pp, faceI)
|
||||||
|
{
|
||||||
|
const face& curFace = pp[faceI];
|
||||||
|
|
||||||
|
forAll (curFace, fpI)
|
||||||
|
{
|
||||||
|
const label pointI = curFace[fpI];
|
||||||
|
label& pl = globalLabel_[pointI];
|
||||||
|
|
||||||
|
if (pl == -1)
|
||||||
|
{
|
||||||
|
pl = patchPO + glPointLabelsI;
|
||||||
|
pointLocs[glPointLabelsI] = points[pointI];
|
||||||
|
glPointLabelsI++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slave processor and regular patches - second pass
|
||||||
|
// Receive data on slave and assign global labels to points on
|
||||||
|
// master processor patches and regular patches
|
||||||
|
forAll (patches, patchI)
|
||||||
|
{
|
||||||
|
const polyPatch& pp = patches[patchI];
|
||||||
|
|
||||||
|
if (isA<processorPolyPatch>(pp))
|
||||||
|
{
|
||||||
|
const processorPolyPatch& procPatch =
|
||||||
|
refCast<const processorPolyPatch>(pp);
|
||||||
|
|
||||||
|
if (!procPatch.master())
|
||||||
|
{
|
||||||
|
// Slave processor patch - second pass
|
||||||
|
// Receive the offset from master and mark the points by taking
|
||||||
|
// into account that the points in the faces are in reverse
|
||||||
|
// order
|
||||||
|
|
||||||
|
IPstream fromProc
|
||||||
|
(
|
||||||
|
Pstream::nonBlocking,
|
||||||
|
procPatch.neighbProcNo()
|
||||||
|
);
|
||||||
|
|
||||||
|
label masterPatchPO(readLabel(fromProc));
|
||||||
|
|
||||||
|
label glPointLabelsI = 0;
|
||||||
|
forAll (pp, faceI)
|
||||||
|
{
|
||||||
|
const face curFace = pp[faceI].reverseFace();
|
||||||
|
|
||||||
|
forAll (curFace, fpI)
|
||||||
|
{
|
||||||
|
const label pointI = curFace[fpI];
|
||||||
|
label& pl = globalLabel_[pointI];
|
||||||
|
|
||||||
|
if (pl == -2)
|
||||||
|
{
|
||||||
|
pl = masterPatchPO + glPointLabelsI;
|
||||||
|
glPointLabelsI++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Regular patch - second pass
|
||||||
|
const labelList& patchMeshPoints = pp.meshPoints();
|
||||||
|
const label patchPO = patchPointOffset_[patchI];
|
||||||
|
label glPointLabelsI = 0;
|
||||||
|
forAll (patchMeshPoints, mpI)
|
||||||
|
{
|
||||||
|
label& pl = globalLabel_[patchMeshPoints[mpI]];
|
||||||
|
|
||||||
|
if (pl == -3)
|
||||||
|
{
|
||||||
|
pl = patchPO + glPointLabelsI;
|
||||||
|
glPointLabelsI++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// "Internal" points - second pass
|
||||||
|
nInternalPoints = 0;
|
||||||
|
forAll (globalLabel_, pI)
|
||||||
|
{
|
||||||
|
label& pl = globalLabel_[pI];
|
||||||
|
|
||||||
|
if (pl == -4)
|
||||||
|
{
|
||||||
|
pl = procPointOffset_[Pstream::myProcNo()] + nInternalPoints;
|
||||||
|
nInternalPoints++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::globalProcPointIndex::globalProcPointIndex(const polyMesh& mesh)
|
||||||
|
:
|
||||||
|
mesh_(mesh),
|
||||||
|
procPointOffset_(Pstream::nProcs()+1),
|
||||||
|
patchPointOffset_(mesh_.boundaryMesh().size()+1),
|
||||||
|
globalLabel_(mesh_.nPoints(), -4)
|
||||||
|
{
|
||||||
|
calcPointIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
135
src/foam/meshes/polyMesh/globalMeshData/globalProcPointIndex.H
Normal file
135
src/foam/meshes/polyMesh/globalMeshData/globalProcPointIndex.H
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | foam-extend: Open Source CFD
|
||||||
|
\\ / O peration | Version: 4.1
|
||||||
|
\\ / A nd | Web: http://www.foam-extend.org
|
||||||
|
\\/ M anipulation | For copyright notice see file Copyright
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of foam-extend.
|
||||||
|
|
||||||
|
foam-extend is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
foam-extend is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::globalProcPointIndex
|
||||||
|
|
||||||
|
Description
|
||||||
|
The class creates a unique global point index for each processor points
|
||||||
|
(pair) in the mesh. Master and slave processor points carry the same index.
|
||||||
|
|
||||||
|
Point offsets counts a number of unique points on each processor,
|
||||||
|
excluding slave processor patch points and global points.
|
||||||
|
|
||||||
|
Currently, faces are ordered with internal faces first, followed by patch
|
||||||
|
faces in patch order, excluding slave processor patches.
|
||||||
|
If needed, this can be changed to group processor faces with internal faces
|
||||||
|
to facilitate parallel I/O. HJ, 4/May/2018
|
||||||
|
|
||||||
|
Author
|
||||||
|
Henrik Rusche, Wikki GmbH
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
globalProcPointIndex.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef globalProcPointIndex_H
|
||||||
|
#define globalProcPointIndex_H
|
||||||
|
|
||||||
|
#include "polyMesh.H"
|
||||||
|
#include "labelList.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// Forward declaration of classes
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class globalProcPointIndex Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class globalProcPointIndex
|
||||||
|
{
|
||||||
|
// Private data
|
||||||
|
|
||||||
|
//- Mesh reference
|
||||||
|
const polyMesh& mesh_;
|
||||||
|
|
||||||
|
//- Processor point index offset
|
||||||
|
labelList procPointOffset_;
|
||||||
|
|
||||||
|
//- point index offset for patches in local mesh
|
||||||
|
labelList patchPointOffset_;
|
||||||
|
|
||||||
|
//- Global poins label for all points of current mesh
|
||||||
|
// Sized to number of live points in the mesh
|
||||||
|
labelList globalLabel_;
|
||||||
|
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Disallow default bitwise copy construct
|
||||||
|
globalProcPointIndex(const globalProcPointIndex&);
|
||||||
|
|
||||||
|
//- Disallow default bitwise assignment
|
||||||
|
void operator=(const globalProcPointIndex&);
|
||||||
|
|
||||||
|
//- Calculate point index
|
||||||
|
void calcPointIndex();
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from mesh
|
||||||
|
globalProcPointIndex(const polyMesh&);
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor - default
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
//- Return point index offset per processor
|
||||||
|
inline const labelList& procPointOffset() const
|
||||||
|
{
|
||||||
|
return procPointOffset_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const labelList& patchPointOffset() const
|
||||||
|
{
|
||||||
|
return patchPointOffset_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Return global point label for all points of current mesh
|
||||||
|
// Sized to number of live points in the mesh
|
||||||
|
const labelList globalLabel() const
|
||||||
|
{
|
||||||
|
return globalLabel_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
|
@ -506,6 +506,40 @@ void Foam::Cloud<ParticleType>::rebuild
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class ParticleType>
|
||||||
|
Foam::labelList Foam::Cloud<ParticleType>::nParticlesPerCell() const
|
||||||
|
{
|
||||||
|
Pout << "In nParticlesPerCell" << endl;
|
||||||
|
labelList nppc (pMesh().nCells(), 0);
|
||||||
|
|
||||||
|
forAllConstIter(typename Cloud<ParticleType>, *this, pIter)
|
||||||
|
{
|
||||||
|
const ParticleType& p = pIter();
|
||||||
|
const label celli = p.cell();
|
||||||
|
|
||||||
|
// Check
|
||||||
|
if (celli < 0 || celli >= pMesh().nCells())
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"Foam::Cloud<ParticleType>::nParticlesPerCell()"
|
||||||
|
)
|
||||||
|
<< "Illegal cell number " << celli
|
||||||
|
<< " at position " << p.position() << nl
|
||||||
|
<< "Cell number should be between 0 and "
|
||||||
|
<< pMesh().nCells()-1 << nl
|
||||||
|
<< "On this mesh the particle should be in cell "
|
||||||
|
<< pMesh().findCell(p.position())
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
nppc[celli]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nppc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class ParticleType>
|
template<class ParticleType>
|
||||||
void Foam::Cloud<ParticleType>::writePositions() const
|
void Foam::Cloud<ParticleType>::writePositions() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -290,6 +290,9 @@ public:
|
||||||
const PtrList<labelIOList>& faceProcAddressing
|
const PtrList<labelIOList>& faceProcAddressing
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//- Count and return number of particles per cell
|
||||||
|
virtual labelList nParticlesPerCell() const;
|
||||||
|
|
||||||
|
|
||||||
// Read
|
// Read
|
||||||
|
|
||||||
|
|
|
@ -134,7 +134,8 @@ public:
|
||||||
donorProcNo_(-1),
|
donorProcNo_(-1),
|
||||||
donorPoint_(vector::zero),
|
donorPoint_(vector::zero),
|
||||||
extendedDonorCells_(),
|
extendedDonorCells_(),
|
||||||
extendedDonorPoints_()
|
extendedDonorPoints_(),
|
||||||
|
withinBB_(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
//- Construct from acceptor data
|
//- Construct from acceptor data
|
||||||
|
|
|
@ -67,54 +67,44 @@ void Foam::adaptiveOverlapFringe::suitabilityFractionSlope
|
||||||
scalar& beta
|
scalar& beta
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
// Linear regression coefficients equations implemented down there:
|
// Linear regression coefficients y = alpha + beta*x
|
||||||
// beta = (n*sum(x_i*y_i)-sum(x_i)*sum(y_i)) / (n*sum(x_i^2)-(sum(x_i))^2)
|
// beta = sum((x_i - x_mean)*(y_i - y_mean))/sum(x_i - x_mean)^2
|
||||||
// alpha = sum(y_i)/n - beta* (sum(x_i)/n
|
// alpha = y_mean - beta*x_mean
|
||||||
|
// x -> iteration number
|
||||||
|
// y -> suitability
|
||||||
|
|
||||||
// Iteration ordinal numbers sum (iteration ordinal number represents x
|
// Calculate mean values first
|
||||||
// value in x-y coordinate system)
|
scalar iterMean = 0;
|
||||||
scalar iterSum = 0;
|
scalar suitabilityMean = 0;
|
||||||
|
|
||||||
// Sum of squared iteration ordinal numbers
|
|
||||||
scalar iterSquaredSum = 0;
|
|
||||||
|
|
||||||
// Average donor/acceptor suitability fraction values sum (average
|
|
||||||
// suitability represents y value in x-y coordinate system)
|
|
||||||
scalar suitabilitySum = 0;
|
|
||||||
|
|
||||||
// Sum of iteration ordinal number multiplied by donor/acceptor suitability
|
|
||||||
// fraction value from one iteration
|
|
||||||
scalar iterXSuitabilitySum = 0;
|
|
||||||
|
|
||||||
// Loop through all iteration data objects and calculate values needed for
|
|
||||||
// linear regression calculation
|
|
||||||
forAllConstIter(FIFOStack<iterationData>, iterHist, it)
|
forAllConstIter(FIFOStack<iterationData>, iterHist, it)
|
||||||
{
|
{
|
||||||
iterSum += it().iteration();
|
iterMean += it().iteration();
|
||||||
iterSquaredSum += pow(it().iteration(), 2);
|
suitabilityMean += it().suitability();
|
||||||
suitabilitySum += it().suitability();
|
|
||||||
iterXSuitabilitySum += it().iteration()*it().suitability();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Number of iterations is equal to iterationDataHistory_ size
|
reduce(iterMean, sumOp<scalar>());
|
||||||
const label n = iterationDataHistory_.size();
|
iterMean /= iterHist.size();
|
||||||
|
reduce(suitabilityMean, sumOp<scalar>());
|
||||||
|
suitabilityMean /= iterHist.size();
|
||||||
|
|
||||||
// Calculate slope (i.e. if y = alpha + beta*x, slope is beta)
|
// Calculate denominator and numerator for beta
|
||||||
beta =
|
scalar n = 0;
|
||||||
(n*iterXSuitabilitySum - iterSum*suitabilitySum)/
|
scalar d = 0;
|
||||||
(n*iterSquaredSum - pow(iterSum, 2));
|
|
||||||
|
|
||||||
// Calculate mean iteration number - actually we don't need to calculate
|
forAllConstIter(FIFOStack<iterationData>, iterHist, it)
|
||||||
// it beacuse we are only interested in trend, i.e we need only slope
|
{
|
||||||
// (beta). Maybe I will need it for diagrams in my master thesis, so
|
n += (it().iteration() - iterMean)*
|
||||||
// calculate it for now.
|
(it().suitability() - suitabilityMean);
|
||||||
const scalar meanIter = iterSum/n;
|
d += Foam::sqr((it().iteration() - iterMean));
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate mean suitability from all iterations
|
reduce(n, sumOp<scalar>());
|
||||||
const scalar meanSuitability = suitabilitySum/n;
|
reduce(d, sumOp<scalar>());
|
||||||
|
|
||||||
// Calculate intercept
|
// Calculate regression coefficients
|
||||||
alpha = meanSuitability - beta*meanIter;
|
beta = n/d;
|
||||||
|
alpha = suitabilityMean - beta*iterMean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -179,20 +169,30 @@ void Foam::adaptiveOverlapFringe::calcAddressing() const
|
||||||
// holes)
|
// holes)
|
||||||
boolList eligibleAcceptors(mesh.nCells(), true);
|
boolList eligibleAcceptors(mesh.nCells(), true);
|
||||||
|
|
||||||
// Read user specified holes into allHoles list. Note: if the cell set
|
// Read user specified holes into allHoles list. Note: use cellZone rather
|
||||||
// is not found, the list will be empty
|
// than cellSet to have correct behaviour on dynamic mesh simulations
|
||||||
cellSet allHoles
|
// We will silently proceed if the zone is not found since this option is
|
||||||
(
|
// not mandatory but is useful in certain cases
|
||||||
mesh,
|
|
||||||
holesSetName_,
|
// Get zone index
|
||||||
IOobject::READ_IF_PRESENT,
|
const label zoneID = mesh.cellZones().findZoneID(holesZoneName_);
|
||||||
IOobject::NO_WRITE
|
|
||||||
);
|
// Create a hash set for allHoles
|
||||||
|
labelHashSet allHoles;
|
||||||
|
|
||||||
|
if (zoneID > -1)
|
||||||
|
{
|
||||||
|
// Get the zone for holes and append them to set
|
||||||
|
const labelList& specifiedHoles = mesh.cellZones()[zoneID];
|
||||||
|
|
||||||
|
allHoles.insert(specifiedHoles);
|
||||||
|
}
|
||||||
|
// else silently proceed without user-specified holes
|
||||||
|
|
||||||
// Extend allHoles with cutHoles
|
// Extend allHoles with cutHoles
|
||||||
forAll (cutHoles, chI)
|
forAll (cutHoles, chI)
|
||||||
{
|
{
|
||||||
// Note: cellSet is a hashSet so it automatically removes duplicates
|
// Note: duplicated are removed because we're using hash set
|
||||||
allHoles.insert(cutHoles[chI]);
|
allHoles.insert(cutHoles[chI]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,7 +393,7 @@ Foam::adaptiveOverlapFringe::adaptiveOverlapFringe
|
||||||
acceptorsPtr_(NULL),
|
acceptorsPtr_(NULL),
|
||||||
finalDonorAcceptorsPtr_(NULL),
|
finalDonorAcceptorsPtr_(NULL),
|
||||||
|
|
||||||
holesSetName_(dict.lookupOrDefault<word>("holes", word())),
|
holesZoneName_(dict.lookupOrDefault<word>("holes", word())),
|
||||||
initPatchNames_
|
initPatchNames_
|
||||||
(
|
(
|
||||||
dict.lookupOrDefault<wordList>("initPatchNames", wordList())
|
dict.lookupOrDefault<wordList>("initPatchNames", wordList())
|
||||||
|
@ -408,6 +408,14 @@ Foam::adaptiveOverlapFringe::adaptiveOverlapFringe
|
||||||
(
|
(
|
||||||
dict.lookupOrDefault<label>("specifiedIterationsNumber", 5)
|
dict.lookupOrDefault<label>("specifiedIterationsNumber", 5)
|
||||||
),
|
),
|
||||||
|
minSuitabilityRate_
|
||||||
|
(
|
||||||
|
dict.lookupOrDefault<scalar>("minSuitabilityRate", 0.0)
|
||||||
|
),
|
||||||
|
maxIter_
|
||||||
|
(
|
||||||
|
dict.lookupOrDefault<label>("maximumIterations", 100)
|
||||||
|
),
|
||||||
relativeCounter_(specifiedIterationsNumber_),
|
relativeCounter_(specifiedIterationsNumber_),
|
||||||
additionalIterations_
|
additionalIterations_
|
||||||
(
|
(
|
||||||
|
@ -667,6 +675,7 @@ bool Foam::adaptiveOverlapFringe::updateIteration
|
||||||
(additionalIterations_)
|
(additionalIterations_)
|
||||||
&& (fringeIter_ == relativeCounter_)
|
&& (fringeIter_ == relativeCounter_)
|
||||||
&& (specifiedIterationsNumber_ > 1)
|
&& (specifiedIterationsNumber_ > 1)
|
||||||
|
&& (fringeIter_ < maxIter_)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Slope (i.e. if y = alpha + beta*x, slope is beta)
|
// Slope (i.e. if y = alpha + beta*x, slope is beta)
|
||||||
|
@ -695,7 +704,7 @@ bool Foam::adaptiveOverlapFringe::updateIteration
|
||||||
|
|
||||||
// If the donor/acceptor suitability gradient is positive,
|
// If the donor/acceptor suitability gradient is positive,
|
||||||
// make 1 additional iteration
|
// make 1 additional iteration
|
||||||
if (beta > 0)
|
if (beta > minSuitabilityRate_)
|
||||||
{
|
{
|
||||||
// Pop the bottom element of the stack
|
// Pop the bottom element of the stack
|
||||||
iterationDataHistory_.pop();
|
iterationDataHistory_.pop();
|
||||||
|
@ -1076,16 +1085,26 @@ bool Foam::adaptiveOverlapFringe::updateIteration
|
||||||
reduce(nAccToHoles, sumOp<label>());
|
reduce(nAccToHoles, sumOp<label>());
|
||||||
Info<< "Converted " << nAccToHoles << " acceptors to holes." << endl;
|
Info<< "Converted " << nAccToHoles << " acceptors to holes." << endl;
|
||||||
|
|
||||||
|
// Bugfix: Although we have found suitable overlap, we need to update
|
||||||
|
// acceptors as well because eligible donors for acceptors of other
|
||||||
|
// regions are calculated based on these acceptors (and holes)
|
||||||
|
labelList& acceptors = *acceptorsPtr_;
|
||||||
|
acceptors.setSize(finalDAPairs.size());
|
||||||
|
forAll (acceptors, aI)
|
||||||
|
{
|
||||||
|
acceptors[aI] = finalDAPairs[aI].acceptorCell();
|
||||||
|
}
|
||||||
|
|
||||||
// Construct final donor/acceptor list
|
// Construct final donor/acceptor list
|
||||||
finalDonorAcceptorsPtr_ = new donorAcceptorList
|
finalDonorAcceptorsPtr_ = new donorAcceptorList
|
||||||
(
|
(
|
||||||
finalDAPairs
|
finalDAPairs.xfer()
|
||||||
);
|
);
|
||||||
|
|
||||||
// Construct final fringe holes list
|
// Construct final fringe holes list
|
||||||
fringeHolesPtr_ = new labelList
|
fringeHolesPtr_ = new labelList
|
||||||
(
|
(
|
||||||
fringeHoles
|
fringeHoles.xfer()
|
||||||
);
|
);
|
||||||
|
|
||||||
// Print information
|
// Print information
|
||||||
|
|
|
@ -105,7 +105,7 @@ class adaptiveOverlapFringe
|
||||||
//- Name of the cell set defining initial holes (empty by default).
|
//- Name of the cell set defining initial holes (empty by default).
|
||||||
// Useful when the resolution of the background mesh is much
|
// Useful when the resolution of the background mesh is much
|
||||||
// coarser than the front mesh and no hole is found
|
// coarser than the front mesh and no hole is found
|
||||||
const word holesSetName_;
|
const word holesZoneName_;
|
||||||
|
|
||||||
//- Optional list of patches to start the iterative fringe assembly
|
//- Optional list of patches to start the iterative fringe assembly
|
||||||
// process (empty list by default). Useful when we actually have
|
// process (empty list by default). Useful when we actually have
|
||||||
|
@ -125,6 +125,14 @@ class adaptiveOverlapFringe
|
||||||
// be made
|
// be made
|
||||||
const label specifiedIterationsNumber_;
|
const label specifiedIterationsNumber_;
|
||||||
|
|
||||||
|
//- User specified suitability trend rate. If the trend is larger
|
||||||
|
// than the specified trend rate, additional iterations are
|
||||||
|
// performed
|
||||||
|
const scalar minSuitabilityRate_;
|
||||||
|
|
||||||
|
//- Maximum number of iterations
|
||||||
|
const label maxIter_;
|
||||||
|
|
||||||
//- Relative iteration counter
|
//- Relative iteration counter
|
||||||
mutable label relativeCounter_;
|
mutable label relativeCounter_;
|
||||||
|
|
||||||
|
|
|
@ -224,6 +224,21 @@ public:
|
||||||
<< " on processor: " << daPair.acceptorProcNo()
|
<< " on processor: " << daPair.acceptorProcNo()
|
||||||
<< " did not find donor candidate."
|
<< " did not find donor candidate."
|
||||||
<< nl
|
<< nl
|
||||||
|
<< "Additional information: "
|
||||||
|
<< nl
|
||||||
|
<< (
|
||||||
|
daPair.withinBB()
|
||||||
|
? " Within bounding box"
|
||||||
|
: " Not within bounding box"
|
||||||
|
)
|
||||||
|
<< nl << tab
|
||||||
|
<< "Donor index: " << daPair.donorCell()
|
||||||
|
<< nl << tab
|
||||||
|
<< "Donor processor index: " << daPair.donorProcNo()
|
||||||
|
<< nl << tab
|
||||||
|
<< "Number of extended donors: "
|
||||||
|
<< daPair.extendedDonorCells().size()
|
||||||
|
<< nl << nl
|
||||||
<< "Please review your fringe assembly settings"
|
<< "Please review your fringe assembly settings"
|
||||||
<< " (or try using adaptiveOverlap fringe algorithm)."
|
<< " (or try using adaptiveOverlap fringe algorithm)."
|
||||||
<< abort(FatalError);
|
<< abort(FatalError);
|
||||||
|
|
|
@ -188,26 +188,37 @@ void Foam::overlapFringe::calcAddressing() const
|
||||||
// holes)
|
// holes)
|
||||||
boolList eligibleAcceptors(mesh.nCells(), true);
|
boolList eligibleAcceptors(mesh.nCells(), true);
|
||||||
|
|
||||||
// Read user specified holes into allHoles list. Note: if the cell set
|
// Read user specified holes into allHoles list. Note: use cellZone rather
|
||||||
// is not found, the list will be empty
|
// than cellSet to have correct behaviour on dynamic mesh simulations
|
||||||
labelList allHoles
|
// We will silently proceed if the zone is not found since this option is
|
||||||
(
|
// not mandatory but is useful in certain cases
|
||||||
cellSet
|
|
||||||
(
|
// Get zone index
|
||||||
mesh,
|
const label zoneID = mesh.cellZones().findZoneID(holesZoneName_);
|
||||||
holesSetName_,
|
|
||||||
IOobject::READ_IF_PRESENT,
|
// Create a hash set for allHoles
|
||||||
IOobject::NO_WRITE
|
labelHashSet allHoles;
|
||||||
).toc()
|
|
||||||
);
|
if (zoneID > -1)
|
||||||
|
{
|
||||||
|
// Get the zone for holes and append them to set
|
||||||
|
const labelList& specifiedHoles = mesh.cellZones()[zoneID];
|
||||||
|
|
||||||
|
allHoles.insert(specifiedHoles);
|
||||||
|
}
|
||||||
|
// else silently proceed without user-specified holes
|
||||||
|
|
||||||
// Extend allHoles with cutHoles
|
// Extend allHoles with cutHoles
|
||||||
allHoles.append(cutHoles);
|
forAll (cutHoles, chI)
|
||||||
|
{
|
||||||
|
// Note: duplicated are removed because we're using hash set
|
||||||
|
allHoles.insert(cutHoles[chI]);
|
||||||
|
}
|
||||||
|
|
||||||
// Mark all holes
|
// Mark all holes
|
||||||
forAll (allHoles, hI)
|
forAllConstIter (labelHashSet, allHoles, iter)
|
||||||
{
|
{
|
||||||
const label& holeCellI = allHoles[hI];
|
const label& holeCellI = iter.key();
|
||||||
|
|
||||||
// Mask eligible acceptors
|
// Mask eligible acceptors
|
||||||
eligibleAcceptors[holeCellI] = false;
|
eligibleAcceptors[holeCellI] = false;
|
||||||
|
@ -225,10 +236,10 @@ void Foam::overlapFringe::calcAddressing() const
|
||||||
dynamicLabelList candidateAcceptors(mesh.nCells());
|
dynamicLabelList candidateAcceptors(mesh.nCells());
|
||||||
|
|
||||||
// Loop through all holes and find acceptor candidates
|
// Loop through all holes and find acceptor candidates
|
||||||
forAll (allHoles, hI)
|
forAllConstIter (labelHashSet, allHoles, iter)
|
||||||
{
|
{
|
||||||
// Get neighbours of this hole cell
|
// Get neighbours of this hole cell
|
||||||
const labelList& hNbrs = cc[allHoles[hI]];
|
const labelList& hNbrs = cc[iter.key()];
|
||||||
|
|
||||||
// Loop through neighbours of this hole cell
|
// Loop through neighbours of this hole cell
|
||||||
forAll (hNbrs, nbrI)
|
forAll (hNbrs, nbrI)
|
||||||
|
@ -370,7 +381,7 @@ void Foam::overlapFringe::calcAddressing() const
|
||||||
// Transfer the acceptor list and allocate empty fringeHoles list, which
|
// Transfer the acceptor list and allocate empty fringeHoles list, which
|
||||||
// may be populated in updateIteration member function
|
// may be populated in updateIteration member function
|
||||||
acceptorsPtr_ = new labelList(candidateAcceptors.xfer());
|
acceptorsPtr_ = new labelList(candidateAcceptors.xfer());
|
||||||
fringeHolesPtr_ = new labelList(cutHoles);
|
fringeHolesPtr_ = new labelList(allHoles.toc().xfer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -398,7 +409,7 @@ Foam::overlapFringe::overlapFringe
|
||||||
acceptorsPtr_(NULL),
|
acceptorsPtr_(NULL),
|
||||||
finalDonorAcceptorsPtr_(NULL),
|
finalDonorAcceptorsPtr_(NULL),
|
||||||
|
|
||||||
holesSetName_(dict.lookupOrDefault<word>("holes", word())),
|
holesZoneName_(dict.lookupOrDefault<word>("holes", word())),
|
||||||
initPatchNames_
|
initPatchNames_
|
||||||
(
|
(
|
||||||
dict.lookupOrDefault<wordList>("initPatchNames", wordList())
|
dict.lookupOrDefault<wordList>("initPatchNames", wordList())
|
||||||
|
@ -687,8 +698,15 @@ bool Foam::overlapFringe::updateIteration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tranfer back the allFringeHoles dynamic list into member data
|
// Bugfix: Although we have found suitable overlap, we need to update
|
||||||
fringeHolesPtr_->transfer(allFringeHoles);
|
// acceptors as well because eligible donors for acceptors of other
|
||||||
|
// regions are calculated based on these acceptors (and holes)
|
||||||
|
labelList& acceptors = *acceptorsPtr_;
|
||||||
|
acceptors.setSize(finalDAPairs.size());
|
||||||
|
forAll (acceptors, aI)
|
||||||
|
{
|
||||||
|
acceptors[aI] = finalDAPairs[aI].acceptorCell();
|
||||||
|
}
|
||||||
|
|
||||||
// Transfer ownership of the final donor/acceptor list to the
|
// Transfer ownership of the final donor/acceptor list to the
|
||||||
// finalDonorAcceptorsPtr_
|
// finalDonorAcceptorsPtr_
|
||||||
|
@ -697,6 +715,9 @@ bool Foam::overlapFringe::updateIteration
|
||||||
finalDAPairs.xfer()
|
finalDAPairs.xfer()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Tranfer back the allFringeHoles dynamic list into member data
|
||||||
|
fringeHolesPtr_->transfer(allFringeHoles);
|
||||||
|
|
||||||
// At least 100*minGlobalFraction_ % of suitable donor/acceptor pairs
|
// At least 100*minGlobalFraction_ % of suitable donor/acceptor pairs
|
||||||
// have been found.
|
// have been found.
|
||||||
Info<< "Converted " << nAccToHoles << " acceptors to holes."
|
Info<< "Converted " << nAccToHoles << " acceptors to holes."
|
||||||
|
|
|
@ -96,7 +96,7 @@ class overlapFringe
|
||||||
//- Name of the cell set defining initial holes (empty by default).
|
//- Name of the cell set defining initial holes (empty by default).
|
||||||
// Useful when the resolution of the background mesh is much
|
// Useful when the resolution of the background mesh is much
|
||||||
// coarser than the front mesh and no hole is found
|
// coarser than the front mesh and no hole is found
|
||||||
const word holesSetName_;
|
const word holesZoneName_;
|
||||||
|
|
||||||
//- Optional list of patches to start the iterative fringe assembly
|
//- Optional list of patches to start the iterative fringe assembly
|
||||||
// process (empty list by default). Useful when we actually have
|
// process (empty list by default). Useful when we actually have
|
||||||
|
|
|
@ -55,18 +55,33 @@ void Foam::oversetMesh::calcCellClassification() const
|
||||||
nHoleCells += regions_[regionI].holes().size();
|
nHoleCells += regions_[regionI].holes().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
Pout<< "Number of acceptor cells: " << nAcceptorCells << endl;
|
|
||||||
acceptorCellsPtr_ = new labelList(nAcceptorCells);
|
acceptorCellsPtr_ = new labelList(nAcceptorCells);
|
||||||
labelList& acceptor = *acceptorCellsPtr_;
|
labelList& acceptor = *acceptorCellsPtr_;
|
||||||
|
|
||||||
Pout<< "Number of donor cells: " << nDonorCells << endl;
|
|
||||||
donorCellsPtr_ = new labelList(nDonorCells);
|
donorCellsPtr_ = new labelList(nDonorCells);
|
||||||
labelList& donor = *donorCellsPtr_;
|
labelList& donor = *donorCellsPtr_;
|
||||||
|
|
||||||
Pout<< "Number of hole cells: " << nHoleCells << endl;
|
|
||||||
holeCellsPtr_ = new labelList(nHoleCells);
|
holeCellsPtr_ = new labelList(nHoleCells);
|
||||||
labelList& hole = *holeCellsPtr_;
|
labelList& hole = *holeCellsPtr_;
|
||||||
|
|
||||||
|
// Print out processor specific information in debug
|
||||||
|
if (oversetMesh::debug)
|
||||||
|
{
|
||||||
|
Pout<< "Number of acceptor cells: " << nAcceptorCells << endl;
|
||||||
|
Pout<< "Number of donor cells: " << nDonorCells << endl;
|
||||||
|
Pout<< "Number of hole cells: " << nHoleCells << endl;
|
||||||
|
}
|
||||||
|
// Else print global information
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Info<< "Number of acceptor cells: "
|
||||||
|
<< returnReduce(nAcceptorCells, sumOp<label>()) << endl;
|
||||||
|
Info<< "Number of donor cells: "
|
||||||
|
<< returnReduce(nDonorCells, sumOp<label>()) << endl;
|
||||||
|
Info<< "Number of hole cells: "
|
||||||
|
<< returnReduce(nHoleCells, sumOp<label>()) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
// Reset counters
|
// Reset counters
|
||||||
nAcceptorCells = 0;
|
nAcceptorCells = 0;
|
||||||
nDonorCells = 0;
|
nDonorCells = 0;
|
||||||
|
|
|
@ -190,18 +190,9 @@ void Foam::oversetRegion::calcDonorAcceptorCells() const
|
||||||
// Update global flag
|
// Update global flag
|
||||||
foundGlobalOverlap &= regionFoundSuitableOverlap;
|
foundGlobalOverlap &= regionFoundSuitableOverlap;
|
||||||
|
|
||||||
// If the overlap has not been found for this region, we need to
|
// Deletion of demand driven data relocated to the end of
|
||||||
// reset:
|
// updateDonorAcceptors() member function. Makes more sense to have
|
||||||
// - holeCells (depend on fringe holes)
|
// it there. VV, 13/Jan/2019.
|
||||||
// - eligibleDonors (depend on fringe holes and acceptors),
|
|
||||||
// - cellSearch (depends on eligible donors).
|
|
||||||
if (!regionFoundSuitableOverlap)
|
|
||||||
{
|
|
||||||
deleteDemandDrivenData(curRegion.cellSearchPtr_);
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteDemandDrivenData(curRegion.holeCellsPtr_);
|
|
||||||
deleteDemandDrivenData(curRegion.eligibleDonorCellsPtr_);
|
|
||||||
}
|
}
|
||||||
} while (!foundGlobalOverlap);
|
} while (!foundGlobalOverlap);
|
||||||
|
|
||||||
|
@ -1317,6 +1308,20 @@ bool Foam::oversetRegion::updateDonorAcceptors() const
|
||||||
|
|
||||||
// STAGE 11: Filter possibly multiple remote donors
|
// STAGE 11: Filter possibly multiple remote donors
|
||||||
|
|
||||||
|
// Sanity check before moving on. For each initial acceptor, we must
|
||||||
|
// receive at least 1 corresponding donor (even if it is not found,
|
||||||
|
// indicating an orphan cell) from different processors.
|
||||||
|
if (a.size() > completeDonorAcceptorList.size())
|
||||||
|
{
|
||||||
|
FatalErrorIn("void oversetRegion::updateDonorAcceptors() const")
|
||||||
|
<< "Size of initial acceptor set: " << a.size()
|
||||||
|
<< " is larger than the size of the distributed "
|
||||||
|
<< " donor/acceptor list: " << completeDonorAcceptorList.size()
|
||||||
|
<< nl
|
||||||
|
<< "This should not have happened..."
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
// Create a masking field indicating that a certain acceptor has been
|
// Create a masking field indicating that a certain acceptor has been
|
||||||
// visited
|
// visited
|
||||||
boolList isVisited(a.size(), false);
|
boolList isVisited(a.size(), false);
|
||||||
|
@ -1379,35 +1384,16 @@ bool Foam::oversetRegion::updateDonorAcceptors() const
|
||||||
curDA.donorPoint(),
|
curDA.donorPoint(),
|
||||||
curDA.withinBB()
|
curDA.withinBB()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Bugfix: also need to reset extended donors since a better
|
||||||
|
// candidate has been found. VV, 1/Jan/2019
|
||||||
|
curDACombined.setExtendedDonors(curDA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update withinBB flag if the donor is within bounding box of acceptor
|
// Check whether all acceptors have been visited. Useful check if in
|
||||||
// (previously we checked whether the acceptor is within bounding box of
|
// no-debug mode
|
||||||
// donor)
|
|
||||||
forAll (combinedDonorAcceptorList, daI)
|
|
||||||
{
|
|
||||||
donorAcceptor& curDA = combinedDonorAcceptorList[daI];
|
|
||||||
|
|
||||||
// If the acceptor is not within bounding box of donor, set the flag
|
|
||||||
// other way around
|
|
||||||
if (!curDA.withinBB())
|
|
||||||
{
|
|
||||||
curDA.setWithinBB
|
|
||||||
(
|
|
||||||
mesh_.pointInCellBB
|
|
||||||
(
|
|
||||||
curDA.donorPoint(),
|
|
||||||
curDA.acceptorCell()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check whether all acceptors have been visited. Used for testing/debugging
|
|
||||||
// parallel comms
|
|
||||||
if (oversetMesh::debug)
|
|
||||||
{
|
{
|
||||||
bool allVisited = true;
|
bool allVisited = true;
|
||||||
|
|
||||||
|
@ -1435,12 +1421,35 @@ bool Foam::oversetRegion::updateDonorAcceptors() const
|
||||||
<< nl
|
<< nl
|
||||||
<< "Try switching off useLocalBoundingBoxes for all regions"
|
<< "Try switching off useLocalBoundingBoxes for all regions"
|
||||||
<< nl
|
<< nl
|
||||||
<< "(this optimisation is switched on by default)."
|
<< "(this optimisation is switched off by default)."
|
||||||
<< abort(FatalError);
|
<< abort(FatalError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update withinBB flag if the donor is within bounding box of acceptor
|
||||||
|
// (previously we checked whether the acceptor is within bounding box of
|
||||||
|
// donor)
|
||||||
|
forAll (combinedDonorAcceptorList, daI)
|
||||||
|
{
|
||||||
|
donorAcceptor& curDA = combinedDonorAcceptorList[daI];
|
||||||
|
|
||||||
|
// If the acceptor is not within bounding box of donor, set the flag
|
||||||
|
// other way around
|
||||||
|
if (!curDA.withinBB())
|
||||||
|
{
|
||||||
|
curDA.setWithinBB
|
||||||
|
(
|
||||||
|
mesh_.pointInCellBB
|
||||||
|
(
|
||||||
|
curDA.donorPoint(),
|
||||||
|
curDA.acceptorCell()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// STAGE 12: Finish the iteration by updating the fringe, which will
|
// STAGE 12: Finish the iteration by updating the fringe, which will
|
||||||
// actually hold final and some intermediate steps for donor/acceptor
|
// actually hold final and some intermediate steps for donor/acceptor
|
||||||
// assembly process
|
// assembly process
|
||||||
|
@ -1450,6 +1459,13 @@ bool Foam::oversetRegion::updateDonorAcceptors() const
|
||||||
bool suitableOverlapFound =
|
bool suitableOverlapFound =
|
||||||
fringePtr_->updateIteration(combinedDonorAcceptorList);
|
fringePtr_->updateIteration(combinedDonorAcceptorList);
|
||||||
|
|
||||||
|
// Delete all necessary demand driven data for this region since we have
|
||||||
|
// just updated the iteration. Therefore, cellSearch, eligibleDonors and
|
||||||
|
// holes need to be updated
|
||||||
|
deleteDemandDrivenData(cellSearchPtr_);
|
||||||
|
deleteDemandDrivenData(eligibleDonorCellsPtr_);
|
||||||
|
deleteDemandDrivenData(holeCellsPtr_);
|
||||||
|
|
||||||
return suitableOverlapFound;
|
return suitableOverlapFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ bool Foam::curveSet::trackToBoundary
|
||||||
const vector offset =
|
const vector offset =
|
||||||
sampleCoords_[sampleI + 1] - sampleCoords_[sampleI];
|
sampleCoords_[sampleI + 1] - sampleCoords_[sampleI];
|
||||||
|
|
||||||
const scalar smallDist = mag(tol*offset);
|
const scalar smallDist = mag(tol_()*offset);
|
||||||
|
|
||||||
point oldPos = trackPt;
|
point oldPos = trackPt;
|
||||||
label facei = -1;
|
label facei = -1;
|
||||||
|
@ -174,7 +174,7 @@ void Foam::curveSet::calcSamples
|
||||||
{
|
{
|
||||||
const vector offset =
|
const vector offset =
|
||||||
sampleCoords_[sampleI+1] - sampleCoords_[sampleI];
|
sampleCoords_[sampleI+1] - sampleCoords_[sampleI];
|
||||||
const scalar smallDist = mag(tol*offset);
|
const scalar smallDist = mag(tol_()*offset);
|
||||||
|
|
||||||
|
|
||||||
// Get all boundary intersections
|
// Get all boundary intersections
|
||||||
|
|
|
@ -43,6 +43,16 @@ namespace Foam
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
const Foam::debug::optimisationSwitch
|
||||||
|
Foam::faceOnlySet::maxNSteps_
|
||||||
|
(
|
||||||
|
"maximumFaceOnlySetStepNumber",
|
||||||
|
100
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,7 +68,7 @@ bool Foam::faceOnlySet::trackToBoundary
|
||||||
{
|
{
|
||||||
// distance vector between sampling points
|
// distance vector between sampling points
|
||||||
const vector offset = end_ - start_;
|
const vector offset = end_ - start_;
|
||||||
const vector smallVec = tol*offset;
|
const vector smallVec = tol_()*offset;
|
||||||
const scalar smallDist = mag(smallVec);
|
const scalar smallDist = mag(smallVec);
|
||||||
|
|
||||||
// Alias
|
// Alias
|
||||||
|
@ -115,7 +125,7 @@ void Foam::faceOnlySet::calcSamples
|
||||||
|
|
||||||
const vector offset = (end_ - start_);
|
const vector offset = (end_ - start_);
|
||||||
const vector normOffset = offset/mag(offset);
|
const vector normOffset = offset/mag(offset);
|
||||||
const vector smallVec = tol*offset;
|
const vector smallVec = tol_()*offset;
|
||||||
const scalar smallDist = mag(smallVec);
|
const scalar smallDist = mag(smallVec);
|
||||||
|
|
||||||
|
|
||||||
|
@ -198,7 +208,7 @@ void Foam::faceOnlySet::calcSamples
|
||||||
// index in bHits; current boundary intersection
|
// index in bHits; current boundary intersection
|
||||||
label bHitI = 1;
|
label bHitI = 1;
|
||||||
|
|
||||||
while(true)
|
while(segmentI <= maxNSteps_())
|
||||||
{
|
{
|
||||||
if (trackFaceI != -1)
|
if (trackFaceI != -1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -63,6 +63,13 @@ class faceOnlySet
|
||||||
point end_;
|
point end_;
|
||||||
|
|
||||||
|
|
||||||
|
// Static data
|
||||||
|
|
||||||
|
//- Maximum number of steps for intersection search. Introduced to avoid
|
||||||
|
// inifinite loops (IG 4/Dec/2018)
|
||||||
|
static const debug::optimisationSwitch maxNSteps_;
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- Samples from startTrackPt/CellI. Updates particle/samplePt/sampleI
|
//- Samples from startTrackPt/CellI. Updates particle/samplePt/sampleI
|
||||||
|
|
|
@ -33,13 +33,29 @@ License
|
||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
const scalar sampledSet::tol = 1e-6;
|
|
||||||
|
|
||||||
defineTypeNameAndDebug(sampledSet, 0);
|
defineTypeNameAndDebug(sampledSet, 0);
|
||||||
defineRunTimeSelectionTable(sampledSet, word);
|
defineRunTimeSelectionTable(sampledSet, word);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
const Foam::debug::tolerancesSwitch
|
||||||
|
Foam::sampledSet::tol_
|
||||||
|
(
|
||||||
|
"sampleSetTolerance",
|
||||||
|
1e-5
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::debug::tolerancesSwitch
|
||||||
|
Foam::sampledSet::pushTol_
|
||||||
|
(
|
||||||
|
"sampleSetPushTolerance",
|
||||||
|
0.1
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::label Foam::sampledSet::getBoundaryCell(const label faceI) const
|
Foam::label Foam::sampledSet::getBoundaryCell(const label faceI) const
|
||||||
|
@ -189,7 +205,7 @@ Foam::point Foam::sampledSet::pushIn
|
||||||
const point& cellCtr = mesh().cellCentres()[cellI];
|
const point& cellCtr = mesh().cellCentres()[cellI];
|
||||||
|
|
||||||
point newSample =
|
point newSample =
|
||||||
facePt + tol*(cellCtr - facePt);
|
facePt + pushTol_()*(cellCtr - facePt);
|
||||||
|
|
||||||
if (!searchEngine().pointInCell(newSample, cellI))
|
if (!searchEngine().pointInCell(newSample, cellI))
|
||||||
{
|
{
|
||||||
|
@ -221,7 +237,7 @@ bool Foam::sampledSet::getTrackingPoint
|
||||||
label& trackFaceI
|
label& trackFaceI
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
const scalar smallDist = mag(tol*offset);
|
const scalar smallDist = mag(tol_()*offset);
|
||||||
|
|
||||||
bool isGoodSample = false;
|
bool isGoodSample = false;
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,8 @@ SourceFiles
|
||||||
#include "runTimeSelectionTables.H"
|
#include "runTimeSelectionTables.H"
|
||||||
#include "autoPtr.H"
|
#include "autoPtr.H"
|
||||||
#include "coordSet.H"
|
#include "coordSet.H"
|
||||||
|
#include "debug.H"
|
||||||
|
#include "tolerancesSwitch.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
@ -201,7 +203,11 @@ public:
|
||||||
|
|
||||||
//- Tolerance when comparing points. Usually relative to difference
|
//- Tolerance when comparing points. Usually relative to difference
|
||||||
// between start_ and end_
|
// between start_ and end_
|
||||||
const static scalar tol;
|
static const debug::tolerancesSwitch tol_;
|
||||||
|
|
||||||
|
//- Tolerance used to push points out of the face. It is relative to the
|
||||||
|
// distance between the cell face centre and cell centre.
|
||||||
|
static const debug::tolerancesSwitch pushTol_;
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
|
@ -96,7 +96,7 @@ bool Foam::uniformSet::trackToBoundary
|
||||||
{
|
{
|
||||||
// distance vector between sampling points
|
// distance vector between sampling points
|
||||||
const vector offset = (end_ - start_)/(nPoints_ - 1);
|
const vector offset = (end_ - start_)/(nPoints_ - 1);
|
||||||
const vector smallVec = tol*offset;
|
const vector smallVec = tol_()*offset;
|
||||||
const scalar smallDist = mag(smallVec);
|
const scalar smallDist = mag(smallVec);
|
||||||
|
|
||||||
// Alias
|
// Alias
|
||||||
|
@ -233,7 +233,7 @@ void Foam::uniformSet::calcSamples
|
||||||
|
|
||||||
const vector offset = (end_ - start_)/(nPoints_ - 1);
|
const vector offset = (end_ - start_)/(nPoints_ - 1);
|
||||||
const vector normOffset = offset/mag(offset);
|
const vector normOffset = offset/mag(offset);
|
||||||
const vector smallVec = tol*offset;
|
const vector smallVec = tol_()*offset;
|
||||||
const scalar smallDist = mag(smallVec);
|
const scalar smallDist = mag(smallVec);
|
||||||
|
|
||||||
// Get all boundary intersections
|
// Get all boundary intersections
|
||||||
|
|
|
@ -57,9 +57,22 @@ Foam::basicChemistryModel::basicChemistryModel
|
||||||
chemistry_(lookup("chemistry")),
|
chemistry_(lookup("chemistry")),
|
||||||
deltaTChem_
|
deltaTChem_
|
||||||
(
|
(
|
||||||
mesh.nCells(),
|
IOobject
|
||||||
|
(
|
||||||
|
"deltaTChem",
|
||||||
|
mesh.time().constant(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedScalar
|
||||||
|
(
|
||||||
|
"deltaTChem0",
|
||||||
|
dimTime,
|
||||||
readScalar(lookup("initialChemicalTimeStep"))
|
readScalar(lookup("initialChemicalTimeStep"))
|
||||||
)
|
)
|
||||||
|
)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ SourceFiles
|
||||||
|
|
||||||
#include "IOdictionary.H"
|
#include "IOdictionary.H"
|
||||||
#include "Switch.H"
|
#include "Switch.H"
|
||||||
#include "scalarField.H"
|
#include "volFields.H"
|
||||||
#include "volFieldsFwd.H"
|
#include "volFieldsFwd.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
@ -77,7 +77,9 @@ protected:
|
||||||
Switch chemistry_;
|
Switch chemistry_;
|
||||||
|
|
||||||
//- Latest estimation of integration step
|
//- Latest estimation of integration step
|
||||||
scalarField deltaTChem_;
|
// HR 14.12.18: Upgraded to volScalarField in order to enable automatic
|
||||||
|
// mapping/resizing after a topo change. Also needed for PLB.
|
||||||
|
volScalarField deltaTChem_;
|
||||||
|
|
||||||
|
|
||||||
// Protected member functions
|
// Protected member functions
|
||||||
|
|
|
@ -298,7 +298,7 @@ public:
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Solve the turbulence equations and correct the turbulence viscosity
|
//- Solve the turbulence equations and correct the turbulence viscosity
|
||||||
virtual void correct() = 0;
|
virtual void correct();
|
||||||
|
|
||||||
//- Read RASProperties dictionary
|
//- Read RASProperties dictionary
|
||||||
virtual bool read() = 0;
|
virtual bool read() = 0;
|
||||||
|
|
|
@ -207,7 +207,7 @@ public:
|
||||||
virtual tmp<fvVectorMatrix> divDevReff() const = 0;
|
virtual tmp<fvVectorMatrix> divDevReff() const = 0;
|
||||||
|
|
||||||
//- Solve the turbulence equations and correct the turbulence viscosity
|
//- Solve the turbulence equations and correct the turbulence viscosity
|
||||||
virtual void correct() = 0;
|
virtual void correct();
|
||||||
|
|
||||||
//- Read turbulenceProperties dictionary
|
//- Read turbulenceProperties dictionary
|
||||||
virtual bool read() = 0;
|
virtual bool read() = 0;
|
||||||
|
|
Reference in a new issue