Decomposition/redistribution: Separated choice of mesh decomposition and redistribution methods
When snappyHexMesh is run in parallel it re-balances the mesh during refinement
and layer addition by redistribution which requires a decomposition method
that operates in parallel, e.g. hierachical or ptscotch. decomposePar uses a
decomposition method which operates in serial e.g. hierachical but NOT
ptscotch. In order to run decomposePar followed by snappyHexMesh in parallel it
has been necessary to change the method specified in decomposeParDict but now
this is avoided by separately specifying the decomposition and distribution
methods, e.g. in the incompressible/simpleFoam/motorBike case:
numberOfSubdomains 6;
decomposer hierarchical;
distributor ptscotch;
hierarchicalCoeffs
{
n (3 2 1);
order xyz;
}
The distributor entry is also used for run-time mesh redistribution, e.g. in the
multiphase/interFoam/RAS/floatingObject case re-distribution for load-balancing
is enabled in constant/dynamicMeshDict:
distributor
{
type distributor;
libs ("libfvMeshDistributors.so");
redistributionInterval 10;
}
which uses the distributor specified in system/decomposeParDict:
distributor hierarchical;
This rationalisation provides the structure for development of mesh
redistribution and load-balancing.
This commit is contained in:
@ -3,6 +3,7 @@ domainDecomposition.C
|
||||
domainDecompositionMesh.C
|
||||
domainDecompositionDistribute.C
|
||||
dimFieldDecomposer.C
|
||||
fvFieldDecomposer.C
|
||||
pointFieldDecomposer.C
|
||||
lagrangianFieldDecomposer.C
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
EXE_INC = \
|
||||
-I$(LIB_SRC)/parallel/decompose/decompose/lnInclude \
|
||||
-I$(LIB_SRC)/parallel/decompose/decompositionMethods/lnInclude \
|
||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||
-I$(LIB_SRC)/dynamicMesh/lnInclude \
|
||||
@ -9,7 +8,6 @@ EXE_INC = \
|
||||
|
||||
EXE_LIBS = \
|
||||
-ldynamicMesh \
|
||||
-ldecompose \
|
||||
-lgenericPatchFields \
|
||||
-ldecompositionMethods -L$(FOAM_LIBBIN)/dummy -lmetisDecomp -lscotchDecomp \
|
||||
-llagrangian \
|
||||
|
||||
@ -79,10 +79,12 @@ Usage
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "OSspecific.H"
|
||||
#include "fvCFD.H"
|
||||
#include "IOobjectList.H"
|
||||
#include "domainDecomposition.H"
|
||||
#include "decompositionMethod.H"
|
||||
#include "argList.H"
|
||||
#include "timeSelector.H"
|
||||
#include "regionProperties.H"
|
||||
|
||||
#include "labelIOField.H"
|
||||
#include "labelFieldIOField.H"
|
||||
#include "scalarIOField.H"
|
||||
@ -95,16 +97,14 @@ Usage
|
||||
#include "symmTensorFieldIOField.H"
|
||||
#include "tensorIOField.H"
|
||||
#include "tensorFieldIOField.H"
|
||||
#include "pointFields.H"
|
||||
#include "regionProperties.H"
|
||||
#include "systemDict.H"
|
||||
|
||||
#include "readFields.H"
|
||||
#include "dimFieldDecomposer.H"
|
||||
#include "fvFieldDecomposer.H"
|
||||
#include "pointFieldDecomposer.H"
|
||||
#include "lagrangianFieldDecomposer.H"
|
||||
#include "decompositionModel.H"
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -277,9 +277,6 @@ int main(int argc, char *argv[])
|
||||
bool forceOverwrite = args.optionFound("force");
|
||||
bool ifRequiredDecomposition = args.optionFound("ifRequired");
|
||||
|
||||
const word dictName("decomposeParDict");
|
||||
|
||||
|
||||
if (decomposeGeomOnly)
|
||||
{
|
||||
Info<< "Skipping decomposing fields"
|
||||
@ -381,16 +378,10 @@ int main(int argc, char *argv[])
|
||||
// Determine the existing processor count directly
|
||||
label nProcs = fileHandler().nProcs(runTime.path(), regionDir);
|
||||
|
||||
// Get the dictionary IO
|
||||
const typeIOobject<IOdictionary> dictIO
|
||||
(
|
||||
systemDictIO(dictName, args, runTime, regionName)
|
||||
);
|
||||
|
||||
// Get requested numberOfSubdomains. Note: have no mesh yet so
|
||||
// cannot use decompositionModel::New
|
||||
// Get requested numberOfSubdomains
|
||||
const label nDomains =
|
||||
IOdictionary(dictIO).lookup<label>("numberOfSubdomains");
|
||||
decompositionMethod::decomposeParDict(runTime)
|
||||
.lookup<label>("numberOfSubdomains");
|
||||
|
||||
// Give file handler a chance to determine the output directory
|
||||
const_cast<fileOperation&>(fileHandler()).setNProcs(nDomains);
|
||||
@ -405,7 +396,7 @@ int main(int argc, char *argv[])
|
||||
<< nProcs << " domains"
|
||||
<< nl
|
||||
<< "instead of " << nDomains
|
||||
<< " domains as specified in " << dictName
|
||||
<< " domains as specified in decomposeParDict"
|
||||
<< nl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
@ -431,14 +422,13 @@ int main(int argc, char *argv[])
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
dictIO.objectPath()
|
||||
)
|
||||
);
|
||||
|
||||
// Decompose the mesh
|
||||
if (!decomposeFieldsOnly)
|
||||
{
|
||||
mesh.decomposeMesh(dictIO.objectPath());
|
||||
mesh.decomposeMesh();
|
||||
|
||||
mesh.writeDecomposition(decomposeSets);
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2011-2019 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2011-2021 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -25,7 +25,6 @@ License
|
||||
|
||||
#include "dimFieldDecomposer.H"
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::dimFieldDecomposer::dimFieldDecomposer
|
||||
|
||||
@ -24,20 +24,12 @@ License
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "domainDecomposition.H"
|
||||
#include "dictionary.H"
|
||||
#include "labelIOList.H"
|
||||
#include "processorPolyPatch.H"
|
||||
#include "processorCyclicPolyPatch.H"
|
||||
#include "fvMesh.H"
|
||||
#include "OSspecific.H"
|
||||
#include "Map.H"
|
||||
#include "DynamicList.H"
|
||||
#include "decompositionMethod.H"
|
||||
#include "fvFieldDecomposer.H"
|
||||
#include "IOobjectList.H"
|
||||
#include "cellSet.H"
|
||||
#include "faceSet.H"
|
||||
#include "pointSet.H"
|
||||
#include "decompositionModel.H"
|
||||
#include "hexRef8Data.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
@ -71,8 +63,7 @@ void Foam::domainDecomposition::mark
|
||||
|
||||
Foam::domainDecomposition::domainDecomposition
|
||||
(
|
||||
const IOobject& io,
|
||||
const fileName& dictFile
|
||||
const IOobject& io
|
||||
)
|
||||
:
|
||||
fvMesh(io, false),
|
||||
@ -96,11 +87,8 @@ Foam::domainDecomposition::domainDecomposition
|
||||
),
|
||||
nProcs_
|
||||
(
|
||||
decompositionModel::New
|
||||
(
|
||||
*this,
|
||||
dictFile
|
||||
).lookup<int>("numberOfSubdomains")
|
||||
decompositionMethod::decomposeParDict(time())
|
||||
.lookup<int>("numberOfSubdomains")
|
||||
),
|
||||
distributed_(false),
|
||||
cellToProc_(nCells()),
|
||||
@ -115,11 +103,11 @@ Foam::domainDecomposition::domainDecomposition
|
||||
procProcessorPatchSubPatchIDs_(nProcs_),
|
||||
procProcessorPatchSubPatchStarts_(nProcs_)
|
||||
{
|
||||
decompositionModel::New
|
||||
decompositionMethod::decomposeParDict(time()).readIfPresent
|
||||
(
|
||||
*this,
|
||||
dictFile
|
||||
).readIfPresent("distributed", distributed_);
|
||||
"distributed",
|
||||
distributed_
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2011-2019 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2011-2021 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -114,7 +114,7 @@ class domainDecomposition
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
void distributeCells(const fileName& dictFile);
|
||||
void distributeCells();
|
||||
|
||||
//- Mark all elements with value or -2 if occur twice
|
||||
static void mark
|
||||
@ -156,12 +156,8 @@ public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from IOobject and decomposition dictionary name
|
||||
domainDecomposition
|
||||
(
|
||||
const IOobject& io,
|
||||
const fileName& dictFile
|
||||
);
|
||||
//- Construct from IOobject
|
||||
domainDecomposition(const IOobject& io);
|
||||
|
||||
|
||||
//- Destructor
|
||||
@ -182,8 +178,8 @@ public:
|
||||
return distributed_;
|
||||
}
|
||||
|
||||
//- Decompose mesh.
|
||||
void decomposeMesh(const fileName& dict);
|
||||
//- Decompose mesh
|
||||
void decomposeMesh();
|
||||
|
||||
//- Write decomposition
|
||||
bool writeDecomposition(const bool decomposeSets);
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2011-2021 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -25,26 +25,23 @@ License
|
||||
|
||||
#include "domainDecomposition.H"
|
||||
#include "decompositionMethod.H"
|
||||
#include "cpuTime.H"
|
||||
#include "cellSet.H"
|
||||
#include "regionSplit.H"
|
||||
#include "Tuple2.H"
|
||||
#include "faceSet.H"
|
||||
#include "decompositionModel.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::domainDecomposition::distributeCells(const fileName& dict)
|
||||
void Foam::domainDecomposition::distributeCells()
|
||||
{
|
||||
Info<< "\nCalculating distribution of cells" << endl;
|
||||
|
||||
cpuTime decompositionTime;
|
||||
const decompositionModel& method = decompositionModel::New(*this, dict);
|
||||
const dictionary decomposeParDict
|
||||
(
|
||||
decompositionMethod::decomposeParDict(time())
|
||||
);
|
||||
|
||||
scalarField cellWeights;
|
||||
if (method.found("weightField"))
|
||||
if (decomposeParDict.found("weightField"))
|
||||
{
|
||||
word weightName = method.lookup("weightField");
|
||||
const word weightName = decomposeParDict.lookup("weightField");
|
||||
|
||||
volScalarField weights
|
||||
(
|
||||
@ -61,7 +58,9 @@ void Foam::domainDecomposition::distributeCells(const fileName& dict)
|
||||
cellWeights = weights.primitiveField();
|
||||
}
|
||||
|
||||
cellToProc_ = method.decomposer().decompose(*this, cellWeights);
|
||||
cellToProc_ =
|
||||
decompositionMethod::NewDecomposer(decomposeParDict)
|
||||
->decompose(*this, cellWeights);
|
||||
|
||||
Info<< "\nFinished decomposition in "
|
||||
<< decompositionTime.elapsedCpuTime()
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2011-2020 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2011-2021 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -31,9 +31,6 @@ Description
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "domainDecomposition.H"
|
||||
#include "IOstreams.H"
|
||||
#include "boolList.H"
|
||||
#include "cyclicPolyPatch.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
@ -94,10 +91,10 @@ void Foam::domainDecomposition::addInterProcFace
|
||||
}
|
||||
|
||||
|
||||
void Foam::domainDecomposition::decomposeMesh(const fileName& dict)
|
||||
void Foam::domainDecomposition::decomposeMesh()
|
||||
{
|
||||
// Decide which cell goes to which processor
|
||||
distributeCells(dict);
|
||||
distributeCells();
|
||||
|
||||
// Distribute the cells according to the given processor label
|
||||
|
||||
|
||||
@ -0,0 +1,202 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2011-2021 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "fvFieldDecomposer.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::labelList Foam::fvFieldDecomposer::patchFieldDecomposer::alignAddressing
|
||||
(
|
||||
const labelUList& addressingSlice,
|
||||
const label addressingOffset
|
||||
) const
|
||||
{
|
||||
labelList addressing(addressingSlice.size());
|
||||
|
||||
forAll(addressing, i)
|
||||
{
|
||||
// Subtract one to align addressing.
|
||||
addressing[i] = addressingSlice[i] - (addressingOffset + 1);
|
||||
}
|
||||
|
||||
return addressing;
|
||||
}
|
||||
|
||||
|
||||
Foam::fvFieldDecomposer::patchFieldDecomposer::patchFieldDecomposer
|
||||
(
|
||||
const labelUList& addressingSlice,
|
||||
const label addressingOffset
|
||||
)
|
||||
:
|
||||
labelList(alignAddressing(addressingSlice, addressingOffset)),
|
||||
directFvPatchFieldMapper(static_cast<const labelList&>(*this))
|
||||
{}
|
||||
|
||||
|
||||
Foam::labelList Foam::fvFieldDecomposer::processorVolPatchFieldDecomposer::
|
||||
alignAddressing
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const labelUList& addressingSlice
|
||||
) const
|
||||
{
|
||||
labelList addressing(addressingSlice.size());
|
||||
|
||||
const labelList& own = mesh.faceOwner();
|
||||
const labelList& neighb = mesh.faceNeighbour();
|
||||
|
||||
forAll(addressing, i)
|
||||
{
|
||||
// Subtract one to align addressing.
|
||||
label ai = mag(addressingSlice[i]) - 1;
|
||||
|
||||
if (ai < neighb.size())
|
||||
{
|
||||
// This is a regular face. it has been an internal face
|
||||
// of the original mesh and now it has become a face
|
||||
// on the parallel boundary.
|
||||
// Give face the value of the neighbour.
|
||||
|
||||
if (addressingSlice[i] >= 0)
|
||||
{
|
||||
// I have the owner so use the neighbour value
|
||||
addressing[i] = neighb[ai];
|
||||
}
|
||||
else
|
||||
{
|
||||
addressing[i] = own[ai];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is a face that used to be on a cyclic boundary
|
||||
// but has now become a parallel patch face. I cannot
|
||||
// do the interpolation properly (I would need to look
|
||||
// up the different (face) list of data), so I will
|
||||
// just grab the value from the owner cell
|
||||
|
||||
addressing[i] = own[ai];
|
||||
}
|
||||
}
|
||||
|
||||
return addressing;
|
||||
}
|
||||
|
||||
|
||||
Foam::fvFieldDecomposer::processorVolPatchFieldDecomposer::
|
||||
processorVolPatchFieldDecomposer
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const labelUList& addressingSlice
|
||||
)
|
||||
:
|
||||
labelList(alignAddressing(mesh, addressingSlice)),
|
||||
directFvPatchFieldMapper(static_cast<const labelList&>(*this))
|
||||
{}
|
||||
|
||||
|
||||
Foam::fvFieldDecomposer::fvFieldDecomposer
|
||||
(
|
||||
const fvMesh& completeMesh,
|
||||
const fvMesh& procMesh,
|
||||
const labelList& faceAddressing,
|
||||
const labelList& cellAddressing,
|
||||
const labelList& boundaryAddressing
|
||||
)
|
||||
:
|
||||
completeMesh_(completeMesh),
|
||||
procMesh_(procMesh),
|
||||
faceAddressing_(faceAddressing),
|
||||
cellAddressing_(cellAddressing),
|
||||
boundaryAddressing_(boundaryAddressing),
|
||||
patchFieldDecomposerPtrs_
|
||||
(
|
||||
procMesh_.boundary().size(),
|
||||
static_cast<patchFieldDecomposer*>(nullptr)
|
||||
),
|
||||
processorVolPatchFieldDecomposerPtrs_
|
||||
(
|
||||
procMesh_.boundary().size(),
|
||||
static_cast<processorVolPatchFieldDecomposer*>(nullptr)
|
||||
)
|
||||
{
|
||||
forAll(boundaryAddressing_, patchi)
|
||||
{
|
||||
const fvPatch& procPatch = procMesh.boundary()[patchi];
|
||||
|
||||
label fromPatchi = boundaryAddressing_[patchi];
|
||||
if (fromPatchi < 0 && isA<processorCyclicFvPatch>(procPatch))
|
||||
{
|
||||
const label referPatchi =
|
||||
refCast<const processorCyclicPolyPatch>
|
||||
(procPatch.patch()).referPatchID();
|
||||
fromPatchi = boundaryAddressing_[referPatchi];
|
||||
}
|
||||
|
||||
if (fromPatchi >= 0)
|
||||
{
|
||||
patchFieldDecomposerPtrs_[patchi] = new patchFieldDecomposer
|
||||
(
|
||||
procMesh_.boundary()[patchi].patchSlice(faceAddressing_),
|
||||
completeMesh_.boundaryMesh()[fromPatchi].start()
|
||||
);
|
||||
}
|
||||
|
||||
if (boundaryAddressing_[patchi] < 0)
|
||||
{
|
||||
processorVolPatchFieldDecomposerPtrs_[patchi] =
|
||||
new processorVolPatchFieldDecomposer
|
||||
(
|
||||
completeMesh_,
|
||||
procMesh_.boundary()[patchi].patchSlice(faceAddressing_)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::fvFieldDecomposer::~fvFieldDecomposer()
|
||||
{
|
||||
forAll(patchFieldDecomposerPtrs_, patchi)
|
||||
{
|
||||
if (patchFieldDecomposerPtrs_[patchi])
|
||||
{
|
||||
delete patchFieldDecomposerPtrs_[patchi];
|
||||
}
|
||||
}
|
||||
|
||||
forAll(processorVolPatchFieldDecomposerPtrs_, patchi)
|
||||
{
|
||||
if (processorVolPatchFieldDecomposerPtrs_[patchi])
|
||||
{
|
||||
delete processorVolPatchFieldDecomposerPtrs_[patchi];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,219 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2011-2021 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::fvFieldDecomposer
|
||||
|
||||
Description
|
||||
Finite Volume volume and surface field decomposer.
|
||||
|
||||
SourceFiles
|
||||
fvFieldDecomposer.C
|
||||
fvFieldDecomposerDecomposeFields.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef fvFieldDecomposer_H
|
||||
#define fvFieldDecomposer_H
|
||||
|
||||
#include "fvMesh.H"
|
||||
#include "directFvPatchFieldMapper.H"
|
||||
#include "surfaceFields.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
class IOobjectList;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class fvFieldDecomposer Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class fvFieldDecomposer
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//- Patch field decomposer class
|
||||
class patchFieldDecomposer
|
||||
:
|
||||
public labelList,
|
||||
public directFvPatchFieldMapper
|
||||
{
|
||||
// Private Member Functions
|
||||
|
||||
labelList alignAddressing
|
||||
(
|
||||
const labelUList& addressingSlice,
|
||||
const label addressingOffset
|
||||
) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct given addressing
|
||||
patchFieldDecomposer
|
||||
(
|
||||
const labelUList& addressingSlice,
|
||||
const label addressingOffset
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
//- Processor patch field decomposer class. Maps either owner or
|
||||
// neighbour data (no interpolate anymore - processorFvPatchField
|
||||
// holds neighbour data)
|
||||
class processorVolPatchFieldDecomposer
|
||||
:
|
||||
public labelList,
|
||||
public directFvPatchFieldMapper
|
||||
{
|
||||
// Private Member Functions
|
||||
|
||||
labelList alignAddressing
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const labelUList& addressingSlice
|
||||
) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Construct given addressing
|
||||
processorVolPatchFieldDecomposer
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const labelUList& addressingSlice
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private Data
|
||||
|
||||
//- Reference to complete mesh
|
||||
const fvMesh& completeMesh_;
|
||||
|
||||
//- Reference to processor mesh
|
||||
const fvMesh& procMesh_;
|
||||
|
||||
//- Reference to face addressing
|
||||
const labelList& faceAddressing_;
|
||||
|
||||
//- Reference to cell addressing
|
||||
const labelList& cellAddressing_;
|
||||
|
||||
//- Reference to boundary addressing
|
||||
const labelList& boundaryAddressing_;
|
||||
|
||||
//- List of patch field decomposers
|
||||
List<patchFieldDecomposer*> patchFieldDecomposerPtrs_;
|
||||
|
||||
List<processorVolPatchFieldDecomposer*>
|
||||
processorVolPatchFieldDecomposerPtrs_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Helper: map & optionally flip a (face) field
|
||||
template<class Type>
|
||||
static tmp<Field<Type>> mapField
|
||||
(
|
||||
const Field<Type>& field,
|
||||
const labelUList& mapAndSign,
|
||||
const bool applyFlip
|
||||
);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
fvFieldDecomposer
|
||||
(
|
||||
const fvMesh& completeMesh,
|
||||
const fvMesh& procMesh,
|
||||
const labelList& faceAddressing,
|
||||
const labelList& cellAddressing,
|
||||
const labelList& boundaryAddressing
|
||||
);
|
||||
|
||||
//- Disallow default bitwise copy construction
|
||||
fvFieldDecomposer(const fvFieldDecomposer&) = delete;
|
||||
|
||||
|
||||
//- Destructor
|
||||
~fvFieldDecomposer();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Decompose volume field
|
||||
template<class Type>
|
||||
tmp<GeometricField<Type, fvPatchField, volMesh>>
|
||||
decomposeField
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& field,
|
||||
const bool allowUnknownPatchFields = false
|
||||
) const;
|
||||
|
||||
//- Decompose surface field
|
||||
template<class Type>
|
||||
tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
|
||||
decomposeField
|
||||
(
|
||||
const GeometricField<Type, fvsPatchField, surfaceMesh>& field
|
||||
) const;
|
||||
|
||||
template<class GeoField>
|
||||
void decomposeFields(const PtrList<GeoField>& fields) const;
|
||||
|
||||
|
||||
// Member Operators
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const fvFieldDecomposer&) = delete;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "fvFieldDecomposerDecomposeFields.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,380 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2011-2021 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "fvFieldDecomposer.H"
|
||||
#include "processorFvPatchField.H"
|
||||
#include "processorFvsPatchField.H"
|
||||
#include "processorCyclicFvPatchField.H"
|
||||
#include "processorCyclicFvsPatchField.H"
|
||||
#include "emptyFvPatchFields.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>> Foam::fvFieldDecomposer::mapField
|
||||
(
|
||||
const Field<Type>& field,
|
||||
const labelUList& mapAndSign,
|
||||
const bool applyFlip
|
||||
)
|
||||
{
|
||||
tmp<Field<Type>> tfld(new Field<Type>(mapAndSign.size()));
|
||||
Field<Type>& fld = tfld.ref();
|
||||
|
||||
if (applyFlip)
|
||||
{
|
||||
forAll(mapAndSign, i)
|
||||
{
|
||||
if (mapAndSign[i] < 0)
|
||||
{
|
||||
fld[i] = -field[-mapAndSign[i] - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
fld[i] = field[mapAndSign[i] - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ignore face flipping
|
||||
fld.map(field, mag(mapAndSign) - 1);
|
||||
}
|
||||
return tfld;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh>>
|
||||
Foam::fvFieldDecomposer::decomposeField
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& field,
|
||||
const bool allowUnknownPatchFields
|
||||
) const
|
||||
{
|
||||
// 1. Create the complete field with dummy patch fields
|
||||
PtrList<fvPatchField<Type>> patchFields(boundaryAddressing_.size());
|
||||
|
||||
forAll(boundaryAddressing_, patchi)
|
||||
{
|
||||
patchFields.set
|
||||
(
|
||||
patchi,
|
||||
fvPatchField<Type>::New
|
||||
(
|
||||
calculatedFvPatchField<Type>::typeName,
|
||||
procMesh_.boundary()[patchi],
|
||||
DimensionedField<Type, volMesh>::null()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Create the field for the processor
|
||||
tmp<GeometricField<Type, fvPatchField, volMesh>> tresF
|
||||
(
|
||||
new GeometricField<Type, fvPatchField, volMesh>
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
field.name(),
|
||||
procMesh_.time().timeName(),
|
||||
procMesh_,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
procMesh_,
|
||||
field.dimensions(),
|
||||
Field<Type>(field.primitiveField(), cellAddressing_),
|
||||
patchFields
|
||||
)
|
||||
);
|
||||
GeometricField<Type, fvPatchField, volMesh>& resF = tresF.ref();
|
||||
|
||||
|
||||
// 2. Change the fvPatchFields to the correct type using a mapper
|
||||
// constructor (with reference to the now correct internal field)
|
||||
|
||||
typename GeometricField<Type, fvPatchField, volMesh>::
|
||||
Boundary& bf = resF.boundaryFieldRef();
|
||||
|
||||
forAll(bf, patchi)
|
||||
{
|
||||
const fvPatch& procPatch = procMesh_.boundary()[patchi];
|
||||
|
||||
label fromPatchi = boundaryAddressing_[patchi];
|
||||
if (fromPatchi < 0 && isA<processorCyclicFvPatch>(procPatch))
|
||||
{
|
||||
const label referPatchi =
|
||||
refCast<const processorCyclicPolyPatch>
|
||||
(procPatch.patch()).referPatchID();
|
||||
if (field.boundaryField()[referPatchi].overridesConstraint())
|
||||
{
|
||||
fromPatchi = boundaryAddressing_[referPatchi];
|
||||
}
|
||||
}
|
||||
|
||||
if (fromPatchi >= 0)
|
||||
{
|
||||
bf.set
|
||||
(
|
||||
patchi,
|
||||
fvPatchField<Type>::New
|
||||
(
|
||||
field.boundaryField()[fromPatchi],
|
||||
procPatch,
|
||||
resF(),
|
||||
*patchFieldDecomposerPtrs_[patchi]
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (isA<processorCyclicFvPatch>(procPatch))
|
||||
{
|
||||
bf.set
|
||||
(
|
||||
patchi,
|
||||
new processorCyclicFvPatchField<Type>
|
||||
(
|
||||
procPatch,
|
||||
resF(),
|
||||
(*processorVolPatchFieldDecomposerPtrs_[patchi])
|
||||
(
|
||||
field.primitiveField()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (isA<processorFvPatch>(procPatch))
|
||||
{
|
||||
bf.set
|
||||
(
|
||||
patchi,
|
||||
new processorFvPatchField<Type>
|
||||
(
|
||||
procPatch,
|
||||
resF(),
|
||||
(*processorVolPatchFieldDecomposerPtrs_[patchi])
|
||||
(
|
||||
field.primitiveField()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (allowUnknownPatchFields)
|
||||
{
|
||||
bf.set
|
||||
(
|
||||
patchi,
|
||||
new emptyFvPatchField<Type>
|
||||
(
|
||||
procPatch,
|
||||
resF()
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Unknown type." << abort(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the field for the processor
|
||||
return tresF;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::GeometricField<Type, Foam::fvsPatchField, Foam::surfaceMesh>>
|
||||
Foam::fvFieldDecomposer::decomposeField
|
||||
(
|
||||
const GeometricField<Type, fvsPatchField, surfaceMesh>& field
|
||||
) const
|
||||
{
|
||||
// Apply flipping to surfaceScalarFields only
|
||||
const bool doFlip = (pTraits<Type>::nComponents == 1);
|
||||
|
||||
|
||||
// Problem with addressing when a processor patch picks up both internal
|
||||
// faces and faces from cyclic boundaries. This is a bit of a hack, but
|
||||
// I cannot find a better solution without making the internal storage
|
||||
// mechanism for surfaceFields correspond to the one of faces in polyMesh
|
||||
// (i.e. using slices)
|
||||
Field<Type> allFaceField(field.mesh().nFaces());
|
||||
|
||||
forAll(field.primitiveField(), i)
|
||||
{
|
||||
allFaceField[i] = field.primitiveField()[i];
|
||||
}
|
||||
|
||||
forAll(field.boundaryField(), patchi)
|
||||
{
|
||||
const Field<Type> & p = field.boundaryField()[patchi];
|
||||
|
||||
const label patchStart = field.mesh().boundaryMesh()[patchi].start();
|
||||
|
||||
forAll(p, i)
|
||||
{
|
||||
allFaceField[patchStart + i] = p[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 1. Create the complete field with dummy patch fields
|
||||
PtrList<fvsPatchField<Type>> patchFields(boundaryAddressing_.size());
|
||||
|
||||
forAll(boundaryAddressing_, patchi)
|
||||
{
|
||||
patchFields.set
|
||||
(
|
||||
patchi,
|
||||
fvsPatchField<Type>::New
|
||||
(
|
||||
calculatedFvsPatchField<Type>::typeName,
|
||||
procMesh_.boundary()[patchi],
|
||||
DimensionedField<Type, surfaceMesh>::null()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
tmp<GeometricField<Type, fvsPatchField, surfaceMesh>> tresF
|
||||
(
|
||||
new GeometricField<Type, fvsPatchField, surfaceMesh>
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
field.name(),
|
||||
procMesh_.time().timeName(),
|
||||
procMesh_,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
procMesh_,
|
||||
field.dimensions(),
|
||||
mapField
|
||||
(
|
||||
field,
|
||||
labelList::subList
|
||||
(
|
||||
faceAddressing_,
|
||||
procMesh_.nInternalFaces()
|
||||
),
|
||||
doFlip
|
||||
),
|
||||
patchFields
|
||||
)
|
||||
);
|
||||
GeometricField<Type, fvsPatchField, surfaceMesh>& resF = tresF.ref();
|
||||
|
||||
|
||||
// 2. Change the fvsPatchFields to the correct type using a mapper
|
||||
// constructor (with reference to the now correct internal field)
|
||||
|
||||
typename GeometricField<Type, fvsPatchField, surfaceMesh>::
|
||||
Boundary& bf = resF.boundaryFieldRef();
|
||||
|
||||
forAll(boundaryAddressing_, patchi)
|
||||
{
|
||||
const fvPatch& procPatch = procMesh_.boundary()[patchi];
|
||||
|
||||
if (boundaryAddressing_[patchi] >= 0)
|
||||
{
|
||||
bf.set
|
||||
(
|
||||
patchi,
|
||||
fvsPatchField<Type>::New
|
||||
(
|
||||
field.boundaryField()[boundaryAddressing_[patchi]],
|
||||
procPatch,
|
||||
resF(),
|
||||
*patchFieldDecomposerPtrs_[patchi]
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (isA<processorCyclicFvPatch>(procPatch))
|
||||
{
|
||||
// Do our own mapping. Avoids a lot of mapping complexity.
|
||||
bf.set
|
||||
(
|
||||
patchi,
|
||||
new processorCyclicFvsPatchField<Type>
|
||||
(
|
||||
procPatch,
|
||||
resF(),
|
||||
mapField
|
||||
(
|
||||
allFaceField,
|
||||
procPatch.patchSlice(faceAddressing_),
|
||||
doFlip
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (isA<processorFvPatch>(procPatch))
|
||||
{
|
||||
// Do our own mapping. Avoids a lot of mapping complexity.
|
||||
bf.set
|
||||
(
|
||||
patchi,
|
||||
new processorFvsPatchField<Type>
|
||||
(
|
||||
procPatch,
|
||||
resF(),
|
||||
mapField
|
||||
(
|
||||
allFaceField,
|
||||
procPatch.patchSlice(faceAddressing_),
|
||||
doFlip
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Unknown type." << abort(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the field for the processor
|
||||
return tresF;
|
||||
}
|
||||
|
||||
|
||||
template<class GeoField>
|
||||
void Foam::fvFieldDecomposer::decomposeFields
|
||||
(
|
||||
const PtrList<GeoField>& fields
|
||||
) const
|
||||
{
|
||||
forAll(fields, fieldi)
|
||||
{
|
||||
decomposeField(fields[fieldi])().write();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2011-2021 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -23,7 +23,6 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "GeometricField.H"
|
||||
#include "readFields.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
Reference in New Issue
Block a user