Merge branch 'finiteArea-decompose' into 'develop'

support parallel creation of finiteArea meshes with on-the-fly decomposition of fields #2084

See merge request Development/openfoam!457
This commit is contained in:
Sergio Ferraris
2021-05-28 18:14:53 +00:00
115 changed files with 4872 additions and 2333 deletions

View File

@ -1,8 +1,13 @@
EXE_INC = \ EXE_INC = \
-I$(LIB_SRC)/finiteArea/lnInclude \ -I$(LIB_SRC)/finiteArea/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \ -I$(LIB_SRC)/fileFormats/lnInclude \
-I$(LIB_SRC)/cfdTools/general/lnInclude -I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/parallel/decompose/faDecompose/lnInclude \
-I$(LIB_SRC)/parallel/reconstruct/faReconstruct/lnInclude
EXE_LIBS = \ EXE_LIBS = \
-lfiniteArea \ -lfiniteArea \
-lfiniteVolume -lfileFormats \
-lmeshTools \
-lfaDecompose \
-lfaReconstruct

View File

@ -0,0 +1,94 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
Description
Decompose area fields, when mesh was generated in parallel
\*---------------------------------------------------------------------------*/
if (Pstream::parRun())
{
faMeshReconstructor reconstructor(areaMesh);
reconstructor.writeAddressing();
// Handle area fields
// ------------------
PtrList<areaScalarField> areaScalarFields;
PtrList<areaVectorField> areaVectorFields;
PtrList<areaSphericalTensorField> areaSphTensorFields;
PtrList<areaSymmTensorField> areaSymmTensorFields;
PtrList<areaTensorField> areaTensorFields;
const faMesh& fullMesh = reconstructor.mesh();
{
// Use uncollated (or master uncollated) file handler here.
// - each processor is reading in the identical serial fields.
// - nothing should be parallel-coordinated.
// Similarly, if we write the serial finite-area mesh, this is only
// done from one processor!
reconstructor.writeMesh();
const bool oldDistributed = fileHandler().distributed();
auto oldHandler = fileHandler(fileOperation::NewUncollated());
fileHandler().distributed(true);
IOobjectList objects(fullMesh.time(), runTime.timeName());
faFieldDecomposer::readFields(fullMesh, objects, areaScalarFields);
faFieldDecomposer::readFields(fullMesh, objects, areaVectorFields);
faFieldDecomposer::readFields(fullMesh, objects, areaSphTensorFields);
faFieldDecomposer::readFields(fullMesh, objects, areaSymmTensorFields);
faFieldDecomposer::readFields(fullMesh, objects, areaTensorFields);
// Restore old settings
if (oldHandler)
{
fileHandler(std::move(oldHandler));
}
fileHandler().distributed(oldDistributed);
}
const label nAreaFields =
(
areaScalarFields.size()
+ areaVectorFields.size()
+ areaSphTensorFields.size()
+ areaSymmTensorFields.size()
+ areaTensorFields.size()
);
if (nAreaFields)
{
Info<< "Decomposing " << nAreaFields << " area fields" << nl << endl;
faFieldDecomposer fieldDecomposer
(
fullMesh,
areaMesh,
reconstructor.edgeProcAddressing(),
reconstructor.faceProcAddressing(),
reconstructor.boundaryProcAddressing()
);
fieldDecomposer.decomposeFields(areaScalarFields);
fieldDecomposer.decomposeFields(areaVectorFields);
fieldDecomposer.decomposeFields(areaSphTensorFields);
fieldDecomposer.decomposeFields(areaSymmTensorFields);
fieldDecomposer.decomposeFields(areaTensorFields);
}
}
// ************************************************************************* //

View File

@ -0,0 +1,43 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
Description
OBJ output of faMesh edges
\*---------------------------------------------------------------------------*/
{
Info<< "Writing edges in obj format" << endl;
word outputName("faMesh-edges.obj");
if (Pstream::parRun())
{
outputName = word
(
"faMesh-edges-" + Foam::name(Pstream::myProcNo()) + ".obj"
);
}
OBJstream os(runTime.globalPath()/outputName);
os.writeQuoted
(
("# " + outputName + "\n"),
false
);
os.write(areaMesh.patch().edges(), areaMesh.patch().localPoints());
}
// ************************************************************************* //

View File

@ -0,0 +1,97 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
Description
Search for the appropriate faMeshDefinition dictionary....
\*---------------------------------------------------------------------------*/
const word dictName("faMeshDefinition");
autoPtr<IOdictionary> meshDictPtr;
{
fileName dictPath;
const word& regionDir =
(regionName == polyMesh::defaultRegion ? word::null : regionName);
if (args.readIfPresent("dict", dictPath))
{
// Dictionary specified on the command-line ...
if (isDir(dictPath))
{
dictPath /= dictName;
}
}
else if
(
// Check global location
exists
(
runTime.path()/runTime.caseConstant()
/regionDir/faMesh::meshSubDir/dictName
)
)
{
// Dictionary present in constant faMesh directory (old-style)
dictPath =
runTime.constant()
/regionDir/faMesh::meshSubDir/dictName;
// Warn that constant/faMesh/faMeshDefinition was used
// instead of system/faMeshDefinition
#if 0
WarningIn(args.executable())
<< "Using the old faMeshDefinition location: "
<< dictPath << nl
<< " instead of default location: "
<< runTime.system()/regionDir/dictName << nl
<< endl;
#endif
}
else
{
// Assume dictionary is in the system directory
dictPath = runTime.system()/regionDir/dictName;
}
IOobject meshDictIO
(
dictPath,
runTime,
IOobject::MUST_READ,
IOobject::NO_WRITE,
false, // no registerObject
true // is globalObject
);
if (!meshDictIO.typeHeaderOk<IOdictionary>(true))
{
FatalErrorInFunction
<< meshDictIO.objectPath() << nl
<< exit(FatalError);
}
Info<< "Creating faMesh from definition: "
<< runTime.relativePath(meshDictIO.objectPath()) << endl;
meshDictPtr = autoPtr<IOdictionary>::New(meshDictIO);
}
IOdictionary& meshDefDict = *meshDictPtr;
// ************************************************************************* //

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -28,6 +29,8 @@ Application
Description Description
A mesh generator for finiteArea mesh. A mesh generator for finiteArea mesh.
When called in parallel, it will also try to act like decomposePar,
create procAddressing and decompose serial finite-area fields.
Author Author
Zeljko Tukovic, FAMENA Zeljko Tukovic, FAMENA
@ -35,36 +38,20 @@ Author
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "objectRegistry.H"
#include "Time.H" #include "Time.H"
#include "argList.H" #include "argList.H"
#include "OSspecific.H" #include "OSspecific.H"
#include "faMesh.H" #include "faMesh.H"
#include "fvMesh.H" #include "IOdictionary.H"
#include "IOobjectList.H"
#include "areaFields.H"
#include "faFieldDecomposer.H"
#include "faMeshReconstructor.H"
#include "OBJstream.H"
using namespace Foam; using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
class faPatchData
{
public:
word name_;
word type_;
dictionary dict_;
label ownPolyPatchID_;
label ngbPolyPatchID_;
labelList edgeLabels_;
faPatchData()
:
name_(word::null),
type_(word::null),
ownPolyPatchID_(-1),
ngbPolyPatchID_(-1)
{}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@ -73,286 +60,64 @@ int main(int argc, char *argv[])
( (
"A mesh generator for finiteArea mesh" "A mesh generator for finiteArea mesh"
); );
argList::addOption
(
"empty-patch",
"name",
"Specify name for a default empty patch",
false // An advanced option, but not enough to worry about that
);
argList::addOption("dict", "file", "Alternative faMeshDefinition");
argList::addBoolOption
(
"write-edges-obj",
"Write mesh edges as obj files and exit",
false // could make an advanced option
);
#include "addRegionOption.H" #include "addRegionOption.H"
argList::noParallel();
#include "setRootCase.H" #include "setRootCase.H"
#include "createTime.H" #include "createTime.H"
#include "createNamedMesh.H" #include "createNamedPolyMesh.H"
// Reading faMeshDefinition dictionary // Reading faMeshDefinition dictionary
IOdictionary faMeshDefinition #include "findMeshDefinitionDict.H"
(
IOobject
(
"faMeshDefinition",
runTime.constant(),
"faMesh",
mesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
)
);
wordList polyMeshPatches // Inject/overwrite name for optional 'empty' patch
( word patchName;
faMeshDefinition.get<wordList>("polyMeshPatches") if (args.readIfPresent("empty-patch", patchName))
);
const dictionary& bndDict = faMeshDefinition.subDict("boundary");
const wordList faPatchNames(bndDict.toc());
List<faPatchData> faPatches(faPatchNames.size()+1);
forAll(faPatchNames, patchI)
{ {
const dictionary& curPatchDict = bndDict.subDict(faPatchNames[patchI]); meshDefDict.add("emptyPatch", patchName, true);
faPatches[patchI].name_ = faPatchNames[patchI];
faPatches[patchI].type_ = curPatchDict.get<word>("type");
const word ownName(curPatchDict.get<word>("ownerPolyPatch"));
faPatches[patchI].ownPolyPatchID_ =
mesh.boundaryMesh().findPatchID(ownName);
if (faPatches[patchI].ownPolyPatchID_ < 0)
{
FatalErrorIn("makeFaMesh:")
<< "neighbourPolyPatch " << ownName << " does not exist"
<< exit(FatalError);
} }
const word neiName(curPatchDict.get<word>("neighbourPolyPatch")); // Create
faMesh areaMesh(mesh, meshDefDict);
faPatches[patchI].ngbPolyPatchID_ = bool quickExit = false;
mesh.boundaryMesh().findPatchID(neiName);
if (faPatches[patchI].ngbPolyPatchID_ < 0) if (args.found("write-edges-obj"))
{ {
FatalErrorIn("makeFaMesh:") quickExit = true;
<< "neighbourPolyPatch " << neiName << " does not exist" #include "faMeshWriteEdgesOBJ.H"
<< exit(FatalError);
}
} }
// Setting faceLabels list size if (quickExit)
label size = 0;
labelList patchIDs(polyMeshPatches.size(), -1);
forAll(polyMeshPatches, patchI)
{ {
patchIDs[patchI] = Info<< "\nEnd\n" << endl;
mesh.boundaryMesh().findPatchID(polyMeshPatches[patchI]); return 0;
if (patchIDs[patchI] < 0)
{
FatalErrorIn("makeFaMesh:")
<< "Patch " << polyMeshPatches[patchI] << " does not exist"
<< exit(FatalError);
} }
size += mesh.boundaryMesh()[patchIDs[patchI]].size(); // Set the precision of the points data to 10
} IOstream::defaultPrecision(10);
labelList faceLabels(size, -1); Info<< nl << "Write finite area mesh." << nl;
sort(patchIDs);
// Filling of faceLabels list
label faceI = -1;
forAll(polyMeshPatches, patchI)
{
label start = mesh.boundaryMesh()[patchIDs[patchI]].start();
label size = mesh.boundaryMesh()[patchIDs[patchI]].size();
for (label i = 0; i < size; ++i)
{
faceLabels[++faceI] = start + i;
}
}
// Creating faMesh
Info << "Create faMesh ... ";
faMesh areaMesh
(
mesh,
faceLabels
);
Info << "Done" << endl;
// Determination of faPatch ID for each boundary edge.
// Result is in the bndEdgeFaPatchIDs list
const indirectPrimitivePatch& patch = areaMesh.patch();
labelList faceCells(faceLabels.size(), -1);
forAll(faceCells, faceI)
{
label faceID = faceLabels[faceI];
faceCells[faceI] = mesh.faceOwner()[faceID];
}
labelList meshEdges =
patch.meshEdges
(
mesh.edges(),
mesh.cellEdges(),
faceCells
);
const labelListList& edgeFaces = mesh.edgeFaces();
const label nTotalEdges = patch.nEdges();
const label nInternalEdges = patch.nInternalEdges();
labelList bndEdgeFaPatchIDs(nTotalEdges - nInternalEdges, -1);
for (label edgeI = nInternalEdges; edgeI < nTotalEdges; ++edgeI)
{
label curMeshEdge = meshEdges[edgeI];
labelList curEdgePatchIDs(2, label(-1));
label patchI = -1;
forAll(edgeFaces[curMeshEdge], faceI)
{
label curFace = edgeFaces[curMeshEdge][faceI];
label curPatchID = mesh.boundaryMesh().whichPatch(curFace);
if (curPatchID != -1)
{
curEdgePatchIDs[++patchI] = curPatchID;
}
}
for (label pI = 0; pI < faPatches.size() - 1; ++pI)
{
if
(
(
curEdgePatchIDs[0] == faPatches[pI].ownPolyPatchID_
&& curEdgePatchIDs[1] == faPatches[pI].ngbPolyPatchID_
)
||
(
curEdgePatchIDs[1] == faPatches[pI].ownPolyPatchID_
&& curEdgePatchIDs[0] == faPatches[pI].ngbPolyPatchID_
)
)
{
bndEdgeFaPatchIDs[edgeI - nInternalEdges] = pI;
break;
}
}
}
// Set edgeLabels for each faPatch
for (label pI=0; pI<(faPatches.size()-1); ++pI)
{
SLList<label> tmpList;
forAll(bndEdgeFaPatchIDs, eI)
{
if (bndEdgeFaPatchIDs[eI] == pI)
{
tmpList.append(nInternalEdges + eI);
}
}
faPatches[pI].edgeLabels_ = tmpList;
}
// Check for undefined edges
SLList<label> tmpList;
forAll(bndEdgeFaPatchIDs, eI)
{
if (bndEdgeFaPatchIDs[eI] == -1)
{
tmpList.append(nInternalEdges + eI);
}
}
if (tmpList.size() > 0)
{
label pI = faPatches.size()-1;
faPatches[pI].name_ = "undefined";
faPatches[pI].type_ = "patch";
faPatches[pI].edgeLabels_ = tmpList;
}
// Add good patches to faMesh
SLList<faPatch*> faPatchLst;
for (label pI = 0; pI < faPatches.size(); ++pI)
{
faPatches[pI].dict_.add("type", faPatches[pI].type_);
faPatches[pI].dict_.add("edgeLabels", faPatches[pI].edgeLabels_);
faPatches[pI].dict_.add
(
"ngbPolyPatchIndex",
faPatches[pI].ngbPolyPatchID_
);
if(faPatches[pI].edgeLabels_.size() > 0)
{
faPatchLst.append
(
faPatch::New
(
faPatches[pI].name_,
faPatches[pI].dict_,
pI,
areaMesh.boundary()
).ptr()
);
}
}
word emptyPatchName;
if (args.readIfPresent("addEmptyPatch", emptyPatchName))
{
dictionary emptyPatchDict;
emptyPatchDict.add("type", "empty");
emptyPatchDict.add("edgeLabels", labelList());
emptyPatchDict.add("ngbPolyPatchIndex", -1);
faPatchLst.append
(
faPatch::New
(
emptyPatchName,
emptyPatchDict,
faPatchLst.size(),
areaMesh.boundary()
).ptr()
);
}
Info << "Add faPatches ... ";
areaMesh.addFaPatches(List<faPatch*>(faPatchLst));
Info << "Done" << endl;
// Writing faMesh
Info << "Write finite area mesh ... ";
areaMesh.write(); areaMesh.write();
Info<< endl;
Info << "\nEnd" << endl; #include "decomposeFaFields.H"
Info << "\nEnd\n" << endl;
return 0; return 0;
} }

View File

@ -1,4 +1,5 @@
decomposePar.C decomposePar.C
domainDecomposition.C domainDecomposition.C
domainDecompositionMesh.C domainDecompositionMesh.C
domainDecompositionDistribute.C domainDecompositionDistribute.C
@ -7,10 +8,6 @@ domainDecompositionWrite.C
domainDecompositionDryRun.C domainDecompositionDryRun.C
domainDecompositionDryRunWrite.C domainDecompositionDryRunWrite.C
dimFieldDecomposer.C
pointFieldDecomposer.C
faMeshDecomposition.C
faFieldDecomposer.C
lagrangianFieldDecomposer.C lagrangianFieldDecomposer.C
EXE = $(FOAM_APPBIN)/decomposePar EXE = $(FOAM_APPBIN)/decomposePar

View File

@ -6,7 +6,8 @@ EXE_INC = \
-I$(LIB_SRC)/lagrangian/basic/lnInclude \ -I$(LIB_SRC)/lagrangian/basic/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude \ -I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/parallel/decompose/decompositionMethods/lnInclude \ -I$(LIB_SRC)/parallel/decompose/decompositionMethods/lnInclude \
-I$(LIB_SRC)/parallel/decompose/decompose/lnInclude -I$(LIB_SRC)/parallel/decompose/decompose/lnInclude \
-I$(LIB_SRC)/parallel/decompose/faDecompose/lnInclude
EXE_LIBS = \ EXE_LIBS = \
-lfiniteArea \ -lfiniteArea \
@ -18,5 +19,6 @@ EXE_LIBS = \
-lgenericPatchFields \ -lgenericPatchFields \
-ldecompositionMethods \ -ldecompositionMethods \
-ldecompose \ -ldecompose \
-lfaDecompose \
-L$(FOAM_LIBBIN)/dummy \ -L$(FOAM_LIBBIN)/dummy \
-lkahipDecomp -lmetisDecomp -lscotchDecomp -lkahipDecomp -lmetisDecomp -lscotchDecomp

View File

@ -162,7 +162,6 @@ Usage
#include "regionProperties.H" #include "regionProperties.H"
#include "readFields.H" #include "readFields.H"
#include "dimFieldDecomposer.H"
#include "fvFieldDecomposer.H" #include "fvFieldDecomposer.H"
#include "pointFieldDecomposer.H" #include "pointFieldDecomposer.H"
#include "lagrangianFieldDecomposer.H" #include "lagrangianFieldDecomposer.H"
@ -173,11 +172,52 @@ Usage
#include "faMeshDecomposition.H" #include "faMeshDecomposition.H"
#include "faFieldDecomposer.H" #include "faFieldDecomposer.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam namespace Foam
{ {
// Read proc addressing at specific instance.
// Uses polyMesh/fvMesh meshSubDir by default
autoPtr<labelIOList> procAddressing
(
const fvMesh& procMesh,
const word& name,
const word& instance,
const word& local = fvMesh::meshSubDir
)
{
return autoPtr<labelIOList>::New
(
IOobject
(
name,
instance,
local,
procMesh,
IOobject::MUST_READ,
IOobject::NO_WRITE,
false // do not register
)
);
}
// Read proc addressing at specific instance.
// Uses the finiteArea meshSubDir
autoPtr<labelIOList> faProcAddressing
(
const fvMesh& procMesh,
const word& name,
const word& instance,
const word& local = faMesh::meshSubDir
)
{
return procAddressing(procMesh, name, instance, local);
}
// Return cached or read proc addressing from facesInstance
const labelIOList& procAddressing const labelIOList& procAddressing
( (
const PtrList<fvMesh>& procMeshList, const PtrList<fvMesh>& procMeshList,
@ -193,19 +233,7 @@ const labelIOList& procAddressing
procAddressingList.set procAddressingList.set
( (
proci, proci,
new labelIOList procAddressing(procMesh, name, procMesh.facesInstance())
(
IOobject
(
name,
procMesh.facesInstance(),
procMesh.meshSubDir,
procMesh,
IOobject::MUST_READ,
IOobject::NO_WRITE,
false
)
)
); );
} }
return procAddressingList[proci]; return procAddressingList[proci];
@ -275,7 +303,7 @@ void decomposeUniform
} }
} }
} } // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -682,7 +710,6 @@ int main(int argc, char *argv[])
PtrList<labelIOList> cellProcAddressingList(mesh.nProcs()); PtrList<labelIOList> cellProcAddressingList(mesh.nProcs());
PtrList<labelIOList> boundaryProcAddressingList(mesh.nProcs()); PtrList<labelIOList> boundaryProcAddressingList(mesh.nProcs());
PtrList<fvFieldDecomposer> fieldDecomposerList(mesh.nProcs()); PtrList<fvFieldDecomposer> fieldDecomposerList(mesh.nProcs());
PtrList<dimFieldDecomposer> dimFieldDecomposerList(mesh.nProcs());
PtrList<labelIOList> pointProcAddressingList(mesh.nProcs()); PtrList<labelIOList> pointProcAddressingList(mesh.nProcs());
PtrList<pointFieldDecomposer> pointFieldDecomposerList PtrList<pointFieldDecomposer> pointFieldDecomposerList
( (
@ -1047,7 +1074,6 @@ int main(int argc, char *argv[])
{ {
Info<< "Processor " << proci << ": field transfer" << endl; Info<< "Processor " << proci << ": field transfer" << endl;
// open the database // open the database
if (!processorDbList.set(proci)) if (!processorDbList.set(proci))
{ {
@ -1112,7 +1138,7 @@ int main(int argc, char *argv[])
); );
// FV fields // FV fields: volume, surface, internal
{ {
if (!fieldDecomposerList.set(proci)) if (!fieldDecomposerList.set(proci))
{ {
@ -1132,6 +1158,7 @@ int main(int argc, char *argv[])
const fvFieldDecomposer& fieldDecomposer = const fvFieldDecomposer& fieldDecomposer =
fieldDecomposerList[proci]; fieldDecomposerList[proci];
// vol fields
fieldDecomposer.decomposeFields(volScalarFields); fieldDecomposer.decomposeFields(volScalarFields);
fieldDecomposer.decomposeFields(volVectorFields); fieldDecomposer.decomposeFields(volVectorFields);
fieldDecomposer.decomposeFields fieldDecomposer.decomposeFields
@ -1141,6 +1168,7 @@ int main(int argc, char *argv[])
fieldDecomposer.decomposeFields(volSymmTensorFields); fieldDecomposer.decomposeFields(volSymmTensorFields);
fieldDecomposer.decomposeFields(volTensorFields); fieldDecomposer.decomposeFields(volTensorFields);
// surface fields
fieldDecomposer.decomposeFields(surfaceScalarFields); fieldDecomposer.decomposeFields(surfaceScalarFields);
fieldDecomposer.decomposeFields(surfaceVectorFields); fieldDecomposer.decomposeFields(surfaceVectorFields);
fieldDecomposer.decomposeFields fieldDecomposer.decomposeFields
@ -1153,6 +1181,13 @@ int main(int argc, char *argv[])
); );
fieldDecomposer.decomposeFields(surfaceTensorFields); fieldDecomposer.decomposeFields(surfaceTensorFields);
// internal fields
fieldDecomposer.decomposeFields(dimScalarFields);
fieldDecomposer.decomposeFields(dimVectorFields);
fieldDecomposer.decomposeFields(dimSphericalTensorFields);
fieldDecomposer.decomposeFields(dimSymmTensorFields);
fieldDecomposer.decomposeFields(dimTensorFields);
if (times.size() == 1) if (times.size() == 1)
{ {
// Clear cached decomposer // Clear cached decomposer
@ -1160,37 +1195,6 @@ int main(int argc, char *argv[])
} }
} }
// Dimensioned fields
{
if (!dimFieldDecomposerList.set(proci))
{
dimFieldDecomposerList.set
(
proci,
new dimFieldDecomposer
(
mesh,
procMesh,
faceProcAddressing,
cellProcAddressing
)
);
}
const dimFieldDecomposer& dimDecomposer =
dimFieldDecomposerList[proci];
dimDecomposer.decomposeFields(dimScalarFields);
dimDecomposer.decomposeFields(dimVectorFields);
dimDecomposer.decomposeFields(dimSphericalTensorFields);
dimDecomposer.decomposeFields(dimSymmTensorFields);
dimDecomposer.decomposeFields(dimTensorFields);
if (times.size() == 1)
{
dimFieldDecomposerList.set(proci, nullptr);
}
}
// Point fields // Point fields
if if
@ -1366,18 +1370,24 @@ int main(int argc, char *argv[])
faMesh::meshSubDir, faMesh::meshSubDir,
mesh, mesh,
IOobject::READ_IF_PRESENT, IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE IOobject::NO_WRITE,
false // not registered
); );
if (faMeshBoundaryIOobj.typeHeaderOk<faBoundaryMesh>(true)) if (faMeshBoundaryIOobj.typeHeaderOk<faBoundaryMesh>(true))
{ {
Info << "\nFinite area mesh decomposition" << endl; Info<< "\nFinite area mesh decomposition" << endl;
faMeshDecomposition aMesh(mesh); // Always based on the volume decomposition!
faMeshDecomposition aMesh
(
mesh,
mesh.nProcs(),
mesh.model()
);
aMesh.decomposeMesh(); aMesh.decomposeMesh();
aMesh.writeDecomposition(); aMesh.writeDecomposition();
@ -1404,13 +1414,29 @@ int main(int argc, char *argv[])
PtrList<edgeScalarField> edgeScalarFields; PtrList<edgeScalarField> edgeScalarFields;
readFields(aMesh, objects, edgeScalarFields); readFields(aMesh, objects, edgeScalarFields);
Info << endl; const label nAreaFields =
(
areaScalarFields.size()
+ areaVectorFields.size()
+ areaSphericalTensorFields.size()
+ areaSymmTensorFields.size()
+ areaTensorFields.size()
+ edgeScalarFields.size()
);
Info<< endl;
Info<< "Finite area field transfer: "
<< nAreaFields << " fields" << endl;
// Split the fields over processors // Split the fields over processors
for (label procI = 0; procI < mesh.nProcs(); procI++) for
(
label proci = 0;
nAreaFields && proci < mesh.nProcs();
++proci
)
{ {
Info<< "Processor " << procI Info<< " Processor " << proci << endl;
<< ": finite area field transfer" << endl;
// open the database // open the database
Time processorDb Time processorDb
@ -1418,7 +1444,7 @@ int main(int argc, char *argv[])
Time::controlDictName, Time::controlDictName,
args.rootPath(), args.rootPath(),
args.caseName() args.caseName()
/ ("processor" + Foam::name(procI)) / ("processor" + Foam::name(proci))
); );
processorDb.setTime(runTime); processorDb.setTime(runTime);
@ -1441,7 +1467,7 @@ int main(int argc, char *argv[])
// procAddressing // procAddressing
// ( // (
// procMeshList, // procMeshList,
// procI, // proci,
// "faceProcAddressing", // "faceProcAddressing",
// faceProcAddressingList // faceProcAddressingList
// ); // );
@ -1450,60 +1476,39 @@ int main(int argc, char *argv[])
// procAddressing // procAddressing
// ( // (
// procMeshList, // procMeshList,
// procI, // proci,
// "boundaryProcAddressing", // "boundaryProcAddressing",
// boundaryProcAddressingList // boundaryProcAddressingList
// ); // );
labelIOList faceProcAddressing // Addressing from faMesh (not polyMesh) meshSubDir
(
IOobject autoPtr<labelIOList> tfaceProcAddr =
faProcAddressing
( (
procFvMesh,
"faceProcAddressing", "faceProcAddressing",
"constant", runTime.constant()
procMesh.meshSubDir,
procFvMesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
)
); );
auto& faceProcAddressing = *tfaceProcAddr;
labelIOList boundaryProcAddressing autoPtr<labelIOList> tboundaryProcAddr =
( faProcAddressing
IOobject
( (
procFvMesh,
"boundaryProcAddressing", "boundaryProcAddressing",
"constant", runTime.constant()
procMesh.meshSubDir,
procFvMesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
)
); );
auto& boundaryProcAddressing = *tboundaryProcAddr;
// FA fields autoPtr<labelIOList> tedgeProcAddr =
if faProcAddressing
( (
areaScalarFields.size()
|| areaVectorFields.size()
|| areaSphericalTensorFields.size()
|| areaSymmTensorFields.size()
|| areaTensorFields.size()
|| edgeScalarFields.size()
)
{
labelIOList edgeProcAddressing
(
IOobject
(
"edgeProcAddressing",
"constant",
procMesh.meshSubDir,
procFvMesh, procFvMesh,
IOobject::MUST_READ, "edgeProcAddressing",
IOobject::NO_WRITE runTime.constant()
)
); );
const auto& edgeProcAddressing = *tedgeProcAddr;
faFieldDecomposer fieldDecomposer faFieldDecomposer fieldDecomposer
( (
@ -1520,10 +1525,7 @@ int main(int argc, char *argv[])
( (
areaSphericalTensorFields areaSphericalTensorFields
); );
fieldDecomposer.decomposeFields fieldDecomposer.decomposeFields(areaSymmTensorFields);
(
areaSymmTensorFields
);
fieldDecomposer.decomposeFields(areaTensorFields); fieldDecomposer.decomposeFields(areaTensorFields);
fieldDecomposer.decomposeFields(edgeScalarFields); fieldDecomposer.decomposeFields(edgeScalarFields);
@ -1532,7 +1534,6 @@ int main(int argc, char *argv[])
} }
} }
} }
}
Info<< "\nEnd\n" << endl; Info<< "\nEnd\n" << endl;

View File

@ -120,16 +120,27 @@ Foam::domainDecomposition::domainDecomposition
procProcessorPatchSubPatchIDs_(nProcs_), procProcessorPatchSubPatchIDs_(nProcs_),
procProcessorPatchSubPatchStarts_(nProcs_) procProcessorPatchSubPatchStarts_(nProcs_)
{ {
decompositionModel::New updateParameters(this->model());
(
*this,
decompDictFile
).readIfPresent("distributed", distributed_);
} }
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::decompositionModel& Foam::domainDecomposition::model() const
{
return decompositionModel::New(*this, decompDictFile_);
}
void Foam::domainDecomposition::updateParameters
(
const dictionary& params
)
{
params.readIfPresent("distributed", distributed_);
}
bool Foam::domainDecomposition::writeDecomposition(const bool decomposeSets) bool Foam::domainDecomposition::writeDecomposition(const bool decomposeSets)
{ {
Info<< "\nConstructing processor meshes" << endl; Info<< "\nConstructing processor meshes" << endl;
@ -408,10 +419,9 @@ bool Foam::domainDecomposition::writeDecomposition(const bool decomposeSets)
nInterProcPatches += curSubPatchIDs[procPatchi].size(); nInterProcPatches += curSubPatchIDs[procPatchi].size();
} }
List<polyPatch*> procPatches PtrList<polyPatch> procPatches
( (
curPatchSizes.size() + nInterProcPatches, curPatchSizes.size() + nInterProcPatches
reinterpret_cast<polyPatch*>(0)
); );
label nPatches = 0; label nPatches = 0;
@ -434,13 +444,17 @@ bool Foam::domainDecomposition::writeDecomposition(const bool decomposeSets)
); );
// Map existing patches // Map existing patches
procPatches[nPatches] = meshPatch.clone procPatches.set
(
nPatches,
meshPatch.clone
( (
procMesh.boundaryMesh(), procMesh.boundaryMesh(),
nPatches, nPatches,
patchMapper.directAddressing(), patchMapper.directAddressing(),
curPatchStarts[patchi] curPatchStarts[patchi]
).ptr(); )
);
nPatches++; nPatches++;
} }
@ -464,7 +478,9 @@ bool Foam::domainDecomposition::writeDecomposition(const bool decomposeSets)
if (subPatchID[i] == -1) if (subPatchID[i] == -1)
{ {
// From internal faces // From internal faces
procPatches[nPatches] = procPatches.set
(
nPatches,
new processorPolyPatch new processorPolyPatch
( (
size, size,
@ -473,6 +489,7 @@ bool Foam::domainDecomposition::writeDecomposition(const bool decomposeSets)
procMesh.boundaryMesh(), procMesh.boundaryMesh(),
proci, proci,
curNeighbourProcessors[procPatchi] curNeighbourProcessors[procPatchi]
)
); );
} }
else else
@ -483,7 +500,9 @@ bool Foam::domainDecomposition::writeDecomposition(const bool decomposeSets)
boundaryMesh()[subPatchID[i]] boundaryMesh()[subPatchID[i]]
); );
procPatches[nPatches] = procPatches.set
(
nPatches,
new processorCyclicPolyPatch new processorCyclicPolyPatch
( (
size, size,
@ -494,12 +513,12 @@ bool Foam::domainDecomposition::writeDecomposition(const bool decomposeSets)
curNeighbourProcessors[procPatchi], curNeighbourProcessors[procPatchi],
pcPatch.name(), pcPatch.name(),
pcPatch.transform() pcPatch.transform()
)
); );
} }
curStart += size; curStart += size;
++nPatches;
nPatches++;
} }
} }

View File

@ -26,12 +26,8 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "domainDecomposition.H" #include "domainDecomposition.H"
#include "decompositionMethod.H"
#include "cpuTime.H" #include "cpuTime.H"
#include "cellSet.H" #include "decompositionMethod.H"
#include "regionSplit.H"
#include "Tuple2.H"
#include "faceSet.H"
#include "decompositionModel.H" #include "decompositionModel.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -1,238 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd
-------------------------------------------------------------------------------
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 "faFieldDecomposer.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
faFieldDecomposer::patchFieldDecomposer::patchFieldDecomposer
(
const label sizeBeforeMapping,
const labelUList& addressingSlice,
const label addressingOffset
)
:
sizeBeforeMapping_(sizeBeforeMapping),
directAddressing_(addressingSlice)
{
forAll(directAddressing_, i)
{
// Subtract one to align addressing.
// directAddressing_[i] -= addressingOffset + 1;
// ZT, 12/Nov/2010
directAddressing_[i] -= addressingOffset;
}
}
faFieldDecomposer::processorAreaPatchFieldDecomposer::
processorAreaPatchFieldDecomposer
(
const faMesh& mesh,
const labelUList& addressingSlice
)
:
sizeBeforeMapping_(mesh.nFaces()),
addressing_(addressingSlice.size()),
weights_(addressingSlice.size())
{
const scalarField& weights = mesh.weights().internalField();
const labelList& own = mesh.edgeOwner();
const labelList& neighb = mesh.edgeNeighbour();
forAll(addressing_, i)
{
// Subtract one to align addressing.
label ai = addressingSlice[i];
// label ai = mag(addressingSlice[i]) - 1;
if (ai < neighb.size())
{
// This is a regular edge. it has been an internal edge
// of the original mesh and now it has become a edge
// on the parallel boundary
addressing_[i].setSize(2);
weights_[i].setSize(2);
addressing_[i][0] = own[ai];
addressing_[i][1] = neighb[ai];
weights_[i][0] = weights[ai];
weights_[i][1] = 1.0 - weights[ai];
}
else
{
// This is a edge that used to be on a cyclic boundary
// but has now become a parallel patch edge. I cannot
// do the interpolation properly (I would need to look
// up the different (edge) list of data), so I will
// just grab the value from the owner face
//
addressing_[i].setSize(1);
weights_[i].setSize(1);
addressing_[i][0] = own[ai];
weights_[i][0] = 1.0;
}
}
}
faFieldDecomposer::processorEdgePatchFieldDecomposer::
processorEdgePatchFieldDecomposer
(
label sizeBeforeMapping,
const labelUList& addressingSlice
)
:
sizeBeforeMapping_(sizeBeforeMapping),
addressing_(addressingSlice.size()),
weights_(addressingSlice.size())
{
forAll(addressing_, i)
{
addressing_[i].setSize(1);
weights_[i].setSize(1);
addressing_[i][0] = mag(addressingSlice[i]) - 1;
weights_[i][0] = sign(addressingSlice[i]);
}
}
faFieldDecomposer::faFieldDecomposer
(
const faMesh& completeMesh,
const faMesh& procMesh,
const labelList& edgeAddressing,
const labelList& faceAddressing,
const labelList& boundaryAddressing
)
:
completeMesh_(completeMesh),
procMesh_(procMesh),
edgeAddressing_(edgeAddressing),
faceAddressing_(faceAddressing),
boundaryAddressing_(boundaryAddressing),
patchFieldDecomposerPtrs_
(
procMesh_.boundary().size(),
static_cast<patchFieldDecomposer*>(NULL)
),
processorAreaPatchFieldDecomposerPtrs_
(
procMesh_.boundary().size(),
static_cast<processorAreaPatchFieldDecomposer*>(NULL)
),
processorEdgePatchFieldDecomposerPtrs_
(
procMesh_.boundary().size(),
static_cast<processorEdgePatchFieldDecomposer*>(NULL)
)
{
forAll(boundaryAddressing_, patchi)
{
if (boundaryAddressing_[patchi] >= 0)
{
patchFieldDecomposerPtrs_[patchi] = new patchFieldDecomposer
(
completeMesh_.boundary()[boundaryAddressing_[patchi]].size(),
procMesh_.boundary()[patchi].patchSlice(edgeAddressing_),
// completeMesh_.boundaryMesh()
completeMesh_.boundary()
[
boundaryAddressing_[patchi]
].start()
);
}
else
{
processorAreaPatchFieldDecomposerPtrs_[patchi] =
new processorAreaPatchFieldDecomposer
(
completeMesh_,
procMesh_.boundary()[patchi].patchSlice(edgeAddressing_)
);
processorEdgePatchFieldDecomposerPtrs_[patchi] =
new processorEdgePatchFieldDecomposer
(
procMesh_.boundary()[patchi].size(),
static_cast<const labelUList&>
(
procMesh_.boundary()[patchi].patchSlice
(
edgeAddressing_
)
)
);
}
}
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
faFieldDecomposer::~faFieldDecomposer()
{
forAll(patchFieldDecomposerPtrs_, patchi)
{
if (patchFieldDecomposerPtrs_[patchi])
{
delete patchFieldDecomposerPtrs_[patchi];
}
}
forAll(processorAreaPatchFieldDecomposerPtrs_, patchi)
{
if (processorAreaPatchFieldDecomposerPtrs_[patchi])
{
delete processorAreaPatchFieldDecomposerPtrs_[patchi];
}
}
forAll(processorEdgePatchFieldDecomposerPtrs_, patchi)
{
if (processorEdgePatchFieldDecomposerPtrs_[patchi])
{
delete processorEdgePatchFieldDecomposerPtrs_[patchi];
}
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -31,7 +31,7 @@ Description
SourceFiles SourceFiles
lagrangianFieldDecomposer.C lagrangianFieldDecomposer.C
lagrangianFieldDecomposerDecomposeFields.C lagrangianFieldDecomposerFields.C
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -84,7 +84,7 @@ public:
//- Construct from components //- Construct from components
lagrangianFieldDecomposer lagrangianFieldDecomposer
( (
const polyMesh& mesh, const polyMesh& mesh, //<! unused
const polyMesh& procMesh, const polyMesh& procMesh,
const labelList& faceProcAddressing, const labelList& faceProcAddressing,
const labelList& cellProcAddressing, const labelList& cellProcAddressing,
@ -156,7 +156,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository #ifdef NoRepository
#include "lagrangianFieldDecomposerDecomposeFields.C" #include "lagrangianFieldDecomposerFields.C"
#endif #endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -42,7 +42,7 @@ void Foam::readFields
typedef GeometricField<Type, PatchField, GeoMesh> GeoField; typedef GeometricField<Type, PatchField, GeoMesh> GeoField;
// Search list of objects for fields of type GeoField // Search list of objects for fields of type GeoField
IOobjectList fieldObjects(objects.lookupClass(GeoField::typeName)); IOobjectList fieldObjects(objects.lookupClass<GeoField>());
// Remove the cellDist field // Remove the cellDist field
auto iter = fieldObjects.find("cellDist"); auto iter = fieldObjects.find("cellDist");
@ -51,12 +51,12 @@ void Foam::readFields
fieldObjects.erase(iter); fieldObjects.erase(iter);
} }
// Get sorted set of names (different processors might read objects in // Use sorted set of names
// different order) // (different processors might read objects in different order)
const wordList masterNames(fieldObjects.sortedNames()); const wordList masterNames(fieldObjects.sortedNames());
// Construct the fields // Construct the fields
fields.setSize(masterNames.size()); fields.resize(masterNames.size());
forAll(masterNames, i) forAll(masterNames, i)
{ {
@ -76,17 +76,14 @@ void Foam::readFields
) )
{ {
// Search list of objects for fields of type GeomField // Search list of objects for fields of type GeomField
IOobjectList fieldObjects(objects.lookupClass(GeoField::typeName)); IOobjectList fieldObjects(objects.lookupClass<GeoField>());
// Construct the fields // Use sorted set of names
fields.setSize(fieldObjects.size()); // (different processors might read objects in different order)
// Get sorted set of names (different processors might read objects in
// different order)
const wordList masterNames(fieldObjects.sortedNames()); const wordList masterNames(fieldObjects.sortedNames());
// Construct the fields // Construct the fields
fields.setSize(masterNames.size()); fields.resize(masterNames.size());
forAll(masterNames, i) forAll(masterNames, i)
{ {

View File

@ -1,5 +1,3 @@
processorFaMeshes.C
faFieldReconstructor.C
reconstructPar.C reconstructPar.C
EXE = $(FOAM_APPBIN)/reconstructPar EXE = $(FOAM_APPBIN)/reconstructPar

View File

@ -4,7 +4,8 @@ EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \ -I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/lagrangian/basic/lnInclude \ -I$(LIB_SRC)/lagrangian/basic/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude \ -I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/parallel/reconstruct/reconstruct/lnInclude -I$(LIB_SRC)/parallel/reconstruct/reconstruct/lnInclude \
-I$(LIB_SRC)/parallel/reconstruct/faReconstruct/lnInclude
EXE_LIBS = \ EXE_LIBS = \
-lfiniteArea \ -lfiniteArea \
@ -13,4 +14,5 @@ EXE_LIBS = \
-llagrangian \ -llagrangian \
-lgenericPatchFields \ -lgenericPatchFields \
-ldynamicMesh \ -ldynamicMesh \
-lreconstruct -lreconstruct \
-lfaReconstruct

View File

@ -39,7 +39,7 @@ SourceFiles
#define writeAreaFields_H #define writeAreaFields_H
#include "readFields.H" #include "readFields.H"
#include "foamVtkIndPatchGeoFieldsWriter.H" #include "foamVtkUIndPatchGeoFieldsWriter.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -47,7 +47,7 @@ namespace Foam
{ {
// Writer type for finite-area mesh + fields // Writer type for finite-area mesh + fields
typedef vtk::indirectPatchGeoFieldsWriter vtkWriterType_areaMesh; typedef vtk::uindirectPatchGeoFieldsWriter vtkWriterType_areaMesh;
template<class GeoField> template<class GeoField>
bool writeAreaField bool writeAreaField

View File

@ -6,7 +6,7 @@
# \\/ M anipulation | # \\/ M anipulation |
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# Copyright (C) 2011-2016 OpenFOAM Foundation # Copyright (C) 2011-2016 OpenFOAM Foundation
# Copyright (C) 2015-2020 OpenCFD Ltd. # Copyright (C) 2015-2021 OpenCFD Ltd.
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# License # License
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later. # This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
@ -138,15 +138,16 @@ cleanCase()
then then
rm -f polyMesh/blockMeshDict rm -f polyMesh/blockMeshDict
echo echo
echo "Warning: not removing constant/polyMesh/ " echo "Warning: not removing constant/polyMesh/"
echo " it contains a blockMeshDict, which should normally be under system/ instead" echo " It contains a 'blockMeshDict.m4' file."
echo " Relocate the file to system/ to avoid this warning"
echo echo
elif [ -e polyMesh/blockMeshDict ] elif [ -e polyMesh/blockMeshDict ]
then then
echo echo
echo "Warning: not removing constant/polyMesh/ " echo "Warning: not removing constant/polyMesh/"
echo " it contains a blockMeshDict, which should normally be under system/ instead" echo " It contains a 'blockMeshDict' file."
echo echo " Relocate the file to system/ to avoid this warning"
else else
# Remove polyMesh entirely if there is no blockMeshDict # Remove polyMesh entirely if there is no blockMeshDict
rm -rf polyMesh rm -rf polyMesh
@ -187,12 +188,26 @@ cleanUcomponents()
} }
cleanFaMesh () cleanFaMesh()
{ {
rm -rf \ (
constant/faMesh/faceLabels* \ cd constant 2>/dev/null || exit 0
constant/faMesh/faBoundary* \
; # Old constant/polyMesh location for blockMeshDict still in use?
# - emit a gentle warning
if [ -e faMesh/faMeshDefinition ]
then
rm -f faMesh/faceLabels* faMesh/faBoundary*
echo
echo "Warning: not removing the constant/faMesh/ directory"
echo " It contains a 'faMeshDefinition' file"
echo " Relocate the file to system/ to avoid this warning"
echo
else
# Remove faMesh/ entirely if there is no faMeshDefinition
rm -rf faMesh
fi
)
} }

View File

@ -48,7 +48,7 @@ License
#include "turbulentTransportModel.H" #include "turbulentTransportModel.H"
#include "demandDrivenData.H" #include "demandDrivenData.H"
#include "unitConversion.H" #include "unitConversion.H"
#include "foamVtkIndPatchWriter.H" #include "foamVtkUIndPatchWriter.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -2270,7 +2270,7 @@ bool Foam::interfaceTrackingFvMesh::update()
void Foam::interfaceTrackingFvMesh::writeVTK() const void Foam::interfaceTrackingFvMesh::writeVTK() const
{ {
vtk::indirectPatchWriter writer vtk::uindirectPatchWriter writer
( (
aMesh().patch(), aMesh().patch(),
vtk::formatType::LEGACY_ASCII, vtk::formatType::LEGACY_ASCII,

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd. Copyright (C) 2019-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -40,17 +40,6 @@ namespace Foam
} }
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
void Foam::fa::option::constructMeshObjects()
{
regionMeshPtr_.reset(new faMesh(mesh_));
vsmPtr_.reset(new volSurfaceMapping(regionMeshPtr_()));
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fa::option::option Foam::fa::option::option
@ -67,16 +56,15 @@ Foam::fa::option::option
patch_(patch), patch_(patch),
dict_(dict), dict_(dict),
coeffs_(dict.optionalSubDict(modelType + "Coeffs")), coeffs_(dict.optionalSubDict(modelType + "Coeffs")),
active_(dict.getOrDefault<Switch>("active", true)),
fieldNames_(), fieldNames_(),
applied_(), applied_(),
regionName_(dict.get<word>("region")), regionName_(dict.get<word>("region")),
regionMeshPtr_(nullptr), regionMeshPtr_(nullptr),
vsmPtr_(nullptr) vsmPtr_(nullptr),
active_(dict.getOrDefault("active", true)),
log(true)
{ {
constructMeshObjects(); Log << incrIndent << indent << "Source: " << name_ << endl << decrIndent;
Info<< incrIndent << indent << "Source: " << name_ << endl << decrIndent;
} }

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd. Copyright (C) 2019-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -75,13 +75,12 @@ SourceFiles
#ifndef faOption_H #ifndef faOption_H
#define faOption_H #define faOption_H
#include "faMatrices.H" #include "faMatricesFwd.H"
#include "areaFields.H" #include "areaFieldsFwd.H"
#include "dictionary.H" #include "dictionary.H"
#include "Switch.H"
#include "runTimeSelectionTables.H"
#include "fvMesh.H" #include "fvMesh.H"
#include "volSurfaceMapping.H" #include "volSurfaceMapping.H"
#include "runTimeSelectionTables.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -124,27 +123,35 @@ protected:
//- Dictionary containing source coefficients //- Dictionary containing source coefficients
dictionary coeffs_; dictionary coeffs_;
//- Source active flag
Switch active_;
//- Field names to apply source to - populated by derived models //- Field names to apply source to - populated by derived models
wordList fieldNames_; wordList fieldNames_;
//- Applied flag list - corresponds to each fieldNames_ entry //- Applied flag list - corresponds to each fieldNames_ entry
List<bool> applied_; List<bool> applied_;
//- Region name //- Region name (finite-area)
word regionName_; word regionName_;
//- Pointer to the region mesh database private:
autoPtr<faMesh> regionMeshPtr_;
//-Volume-to surface mapping // Private Data
autoPtr<volSurfaceMapping> vsmPtr_;
//- Demand-driven: pointer to region mesh database
mutable autoPtr<faMesh> regionMeshPtr_;
//- Demand-driven: volume-to-surface mapping
mutable autoPtr<volSurfaceMapping> vsmPtr_;
//- Source active flag
bool active_;
public: public:
//- Switch write log to Info
bool log;
//- Runtime type information //- Runtime type information
TypeName("option"); TypeName("option");
@ -188,7 +195,6 @@ public:
//- on the freestore from an Istream //- on the freestore from an Istream
class iNew class iNew
{ {
//- Reference to the patch //- Reference to the patch
const fvPatch& patch_; const fvPatch& patch_;
@ -239,37 +245,37 @@ public:
// Access // Access
//- Return const access to the source name //- Return const access to the source name
inline const word& name() const; inline const word& name() const noexcept;
//- Return const access to the mesh database //- Return const access to the mesh database
inline const fvMesh& mesh() const; inline const fvMesh& mesh() const noexcept;
//- Return const access to fvPatch //- Return const access to fvPatch
inline const fvPatch& patch() const; inline const fvPatch& patch() const noexcept;
//- Return dictionary //- Return dictionary
inline const dictionary& coeffs() const; inline const dictionary& coeffs() const noexcept;
//- Return const access to the source active flag //- Return const access to the source active flag
inline bool active() const; inline bool active() const noexcept;
//- Set the applied flag to true for field index fieldi //- Set the applied flag to true for field index fieldi
inline void setApplied(const label fieldi); inline void setApplied(const label fieldi);
//- Return the region mesh database //- The region name
inline const word& regionName() const noexcept;
//- Return the region mesh database (demand-driven)
inline const faMesh& regionMesh() const; inline const faMesh& regionMesh() const;
//- Return volSurfaceMapping //- Return volSurfaceMapping (demand-driven)
inline const volSurfaceMapping& vsm() const; inline const volSurfaceMapping& vsm() const;
//- Region name
inline const word& regionName() const;
// Edit // Edit
//- Return access to the source active flag //- Change source active flag, return previous value
inline Switch& active(); inline bool active(const bool on) noexcept;
// Checks // Checks

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd. Copyright (C) 2019-2021 OpenCFD Ltd.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -27,49 +27,51 @@ License
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline const Foam::word& Foam::fa::option::name() const inline const Foam::word& Foam::fa::option::name() const noexcept
{ {
return name_; return name_;
} }
inline const Foam::fvMesh& Foam::fa::option::mesh() const inline const Foam::fvMesh& Foam::fa::option::mesh() const noexcept
{ {
return mesh_; return mesh_;
} }
inline const Foam::fvPatch& Foam::fa::option::patch() const inline const Foam::fvPatch& Foam::fa::option::patch() const noexcept
{ {
return patch_; return patch_;
} }
inline const Foam::dictionary& Foam::fa::option::coeffs() const inline const Foam::dictionary& Foam::fa::option::coeffs() const noexcept
{ {
return coeffs_; return coeffs_;
} }
inline bool Foam::fa::option::active() const inline bool Foam::fa::option::active() const noexcept
{ {
return active_; return active_;
} }
inline bool Foam::fa::option::active(const bool on) noexcept
{
bool old(active_);
active_ = on;
return old;
}
inline void Foam::fa::option::setApplied(const label fieldi) inline void Foam::fa::option::setApplied(const label fieldi)
{ {
applied_[fieldi] = true; applied_[fieldi] = true;
} }
inline Foam::Switch& Foam::fa::option::active() inline const Foam::word& Foam::fa::option::regionName() const noexcept
{
return active_;
}
inline const Foam::word& Foam::fa::option::regionName() const
{ {
return regionName_; return regionName_;
} }
@ -77,31 +79,21 @@ inline const Foam::word& Foam::fa::option::regionName() const
inline const Foam::faMesh& Foam::fa::option::regionMesh() const inline const Foam::faMesh& Foam::fa::option::regionMesh() const
{ {
if (regionMeshPtr_.valid()) if (!regionMeshPtr_)
{ {
return regionMeshPtr_(); regionMeshPtr_.reset(new faMesh(mesh_));
} }
else return *regionMeshPtr_;
{
FatalErrorInFunction
<< "Region mesh not available" << abort(FatalError);
}
return *(new faMesh(mesh_));
} }
inline const Foam::volSurfaceMapping& Foam::fa::option::vsm() const inline const Foam::volSurfaceMapping& Foam::fa::option::vsm() const
{ {
if (vsmPtr_.valid()) if (!vsmPtr_)
{ {
return vsmPtr_(); vsmPtr_.reset(new volSurfaceMapping(this->regionMesh()));
} }
else return *vsmPtr_;
{
FatalErrorInFunction
<< "vsmPtr not available" << abort(FatalError);
}
return *(new volSurfaceMapping(regionMeshPtr_()));
} }

View File

@ -92,7 +92,7 @@ Foam::fa::optionList::optionList
const dictionary& dict const dictionary& dict
) )
: :
PtrList<option>(), PtrList<fa::option>(),
mesh_(p.boundaryMesh().mesh()), mesh_(p.boundaryMesh().mesh()),
patch_(p), patch_(p),
checkTimeIndex_(mesh_.time().startTimeIndex() + 2) checkTimeIndex_(mesh_.time().startTimeIndex() + 2)
@ -103,7 +103,7 @@ Foam::fa::optionList::optionList
Foam::fa::optionList::optionList(const fvPatch& p) Foam::fa::optionList::optionList(const fvPatch& p)
: :
PtrList<option>(), PtrList<fa::option>(),
mesh_(p.boundaryMesh().mesh()), mesh_(p.boundaryMesh().mesh()),
patch_(p), patch_(p),
checkTimeIndex_(mesh_.time().startTimeIndex() + 2) checkTimeIndex_(mesh_.time().startTimeIndex() + 2)

View File

@ -46,10 +46,9 @@ SourceFile
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Forward Declarations
namespace Foam namespace Foam
{ {
// Forward declaration of friend functions and operators
namespace fa namespace fa
{ {
class optionList; class optionList;
@ -66,7 +65,7 @@ namespace fa
class optionList class optionList
: :
public PtrList<option> public PtrList<fa::option>
{ {
protected: protected:
@ -118,7 +117,7 @@ public:
// Constructors // Constructors
//- Construct null //- Construct from patch
optionList(const fvPatch& p); optionList(const fvPatch& p);
//- Construct from mesh and dictionary //- Construct from mesh and dictionary
@ -126,8 +125,7 @@ public:
//- Destructor //- Destructor
virtual ~optionList() virtual ~optionList() = default;
{}
// Member Functions // Member Functions

View File

@ -26,6 +26,7 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "profiling.H" #include "profiling.H"
#include "areaFields.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd. Copyright (C) 2019-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -102,7 +102,7 @@ namespace fa
class faceSetOption class faceSetOption
: :
public option public fa::option
{ {
public: public:

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd. Copyright (C) 2019-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -98,7 +98,7 @@ namespace fa
class contactHeatFluxSource class contactHeatFluxSource
: :
public faceSetOption, public fa::faceSetOption,
public temperatureCoupledBase public temperatureCoupledBase
{ {
// Private Data // Private Data

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd. Copyright (C) 2019-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -26,8 +26,8 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "externalFileSource.H" #include "externalFileSource.H"
#include "faMatrices.H" #include "fam.H"
#include "faCFD.H" #include "faScalarMatrix.H"
#include "zeroGradientFaPatchFields.H" #include "zeroGradientFaPatchFields.H"
#include "addToRunTimeSelectionTable.H" #include "addToRunTimeSelectionTable.H"

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd. Copyright (C) 2019-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -89,7 +89,7 @@ namespace fa
class externalFileSource class externalFileSource
: :
public faceSetOption public fa::faceSetOption
{ {
// Private Data // Private Data

View File

@ -26,7 +26,8 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "externalHeatFluxSource.H" #include "externalHeatFluxSource.H"
#include "addToRunTimeSelectionTable.H" #include "fam.H"
#include "faScalarMatrix.H"
#include "physicoChemicalConstants.H" #include "physicoChemicalConstants.H"
#include "zeroGradientFaPatchFields.H" #include "zeroGradientFaPatchFields.H"
#include "addToRunTimeSelectionTable.H" #include "addToRunTimeSelectionTable.H"

View File

@ -121,7 +121,6 @@ SourceFiles
#include "Function1.H" #include "Function1.H"
#include "areaFields.H" #include "areaFields.H"
#include "faceSetOption.H" #include "faceSetOption.H"
#include "faCFD.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -136,7 +135,7 @@ namespace fa
class externalHeatFluxSource class externalHeatFluxSource
: :
public faceSetOption public fa::faceSetOption
{ {
public: public:

View File

@ -26,8 +26,8 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "jouleHeatingSource.H" #include "jouleHeatingSource.H"
#include "faMatrices.H" #include "fam.H"
#include "faCFD.H" #include "faScalarMatrix.H"
#include "addToRunTimeSelectionTable.H" #include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd. Copyright (C) 2019-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -156,7 +156,7 @@ namespace fa
class jouleHeatingSource class jouleHeatingSource
: :
public faceSetOption public fa::faceSetOption
{ {
// Private Data // Private Data

View File

@ -1,11 +1,13 @@
faMesh/faGlobalMeshData/faGlobalMeshData.C faMesh/faGlobalMeshData/faGlobalMeshData.C
faMesh/faMesh.C faMesh/faMesh.C
faMesh/faMeshDemandDrivenData.C faMesh/faMeshDemandDrivenData.C
faMesh/faMeshPatches.C
faMesh/faMeshUpdate.C faMesh/faMeshUpdate.C
faMesh/faBoundaryMesh/faBoundaryMesh.C faMesh/faBoundaryMesh/faBoundaryMesh.C
faPatches = faMesh/faPatches faPatches = faMesh/faPatches
$(faPatches)/faPatch/faPatch.C $(faPatches)/faPatch/faPatch.C
$(faPatches)/faPatch/faPatchData.C
$(faPatches)/faPatch/faPatchNew.C $(faPatches)/faPatch/faPatchNew.C
$(faPatches)/basic/coupled/coupledFaPatch.C $(faPatches)/basic/coupled/coupledFaPatch.C
$(faPatches)/constraint/empty/emptyFaPatch.C $(faPatches)/constraint/empty/emptyFaPatch.C

View File

@ -0,0 +1,59 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Description
Forward declarations of standard faMatrix types/specializations.
\*---------------------------------------------------------------------------*/
#ifndef faMatricesFwd_H
#define faMatricesFwd_H
#include "fieldTypes.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type> class faMatrix;
typedef faMatrix<scalar> faScalarMatrix;
typedef faMatrix<vector> faVectorMatrix;
typedef faMatrix<sphericalTensor> faSphericalTensorMatrix;
typedef faMatrix<symmTensor> faSymmTensorMatrix;
typedef faMatrix<tensor> faTensorMatrix;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -54,7 +54,7 @@ Foam::faBoundaryMesh::faBoundaryMesh
{ {
faPatchList& patches = *this; faPatchList& patches = *this;
// Read polyPatchList // Read faPatch list
Istream& is = readStream(typeName); Istream& is = readStream(typeName);
PtrList<entry> patchEntries(is); PtrList<entry> patchEntries(is);
@ -117,12 +117,6 @@ void Foam::faBoundaryMesh::calcGeometry()
} }
const Foam::faMesh& Foam::faBoundaryMesh::mesh() const
{
return mesh_;
}
Foam::lduInterfacePtrsList Foam::faBoundaryMesh::interfaces() const Foam::lduInterfacePtrsList Foam::faBoundaryMesh::interfaces() const
{ {
lduInterfacePtrsList interfaces(size()); lduInterfacePtrsList interfaces(size());
@ -143,6 +137,26 @@ Foam::lduInterfacePtrsList Foam::faBoundaryMesh::interfaces() const
} }
Foam::label Foam::faBoundaryMesh::nNonProcessor() const
{
const faPatchList& patches = *this;
label nonProc = 0;
for (const faPatch& p : patches)
{
if (isA<processorFaPatch>(p))
{
break;
}
++nonProc;
}
return nonProc;
}
Foam::wordList Foam::faBoundaryMesh::names() const Foam::wordList Foam::faBoundaryMesh::names() const
{ {
return PtrListOps::get<word>(*this, nameOp<faPatch>()); return PtrListOps::get<word>(*this, nameOp<faPatch>());
@ -155,6 +169,71 @@ Foam::wordList Foam::faBoundaryMesh::types() const
} }
Foam::labelList Foam::faBoundaryMesh::patchStarts() const
{
// Manually: faPatch does not have independent start() information
const faPatchList& patches = *this;
labelList list(patches.size());
label beg = mesh_.nInternalEdges();
forAll(patches, patchi)
{
const label len = patches[patchi].nEdges();
list[patchi] = beg;
beg += len;
}
return list;
}
Foam::labelList Foam::faBoundaryMesh::patchSizes() const
{
return
PtrListOps::get<label>
(
*this,
[](const faPatch& p) { return p.nEdges(); } // avoid virtual
);
}
Foam::List<Foam::labelRange> Foam::faBoundaryMesh::patchRanges() const
{
const faPatchList& patches = *this;
List<labelRange> list(patches.size());
label beg = mesh_.nInternalEdges();
forAll(patches, patchi)
{
const label len = patches[patchi].nEdges();
list[patchi].reset(beg, len);
beg += len;
}
return list;
}
Foam::label Foam::faBoundaryMesh::start() const
{
return mesh_.nInternalEdges();
}
Foam::label Foam::faBoundaryMesh::nEdges() const
{
return mesh_.nBoundaryEdges();
}
Foam::labelRange Foam::faBoundaryMesh::range() const
{
return labelRange(mesh_.nInternalEdges(), mesh_.nBoundaryEdges());
}
Foam::labelList Foam::faBoundaryMesh::indices Foam::labelList Foam::faBoundaryMesh::indices
( (
const wordRe& matcher, const wordRe& matcher,
@ -355,6 +434,22 @@ bool Foam::faBoundaryMesh::writeData(Ostream& os) const
} }
bool Foam::faBoundaryMesh::writeObject
(
IOstreamOption streamOpt,
const bool valid
) const
{
// Allow/disallow compression?
// 1. keep readable
// 2. save some space
// ??? streamOpt.compression(IOstreamOption::UNCOMPRESSED);
return regIOobject::writeObject(streamOpt, valid);
}
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
Foam::Ostream& Foam::operator<<(Ostream& os, const faBoundaryMesh& bm) Foam::Ostream& Foam::operator<<(Ostream& os, const faBoundaryMesh& bm)
{ {
bm.writeData(os); bm.writeData(os);

View File

@ -53,8 +53,6 @@ Author
namespace Foam namespace Foam
{ {
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Forward Declarations // Forward Declarations
class faMesh; class faMesh;
class faBoundaryMesh; class faBoundaryMesh;
@ -89,14 +87,14 @@ public:
// Constructors // Constructors
//- Construct from dictionary //- Construct from faMesh
faBoundaryMesh faBoundaryMesh
( (
const IOobject& io, const IOobject& io,
const faMesh& fam const faMesh& fam
); );
//- Construct given size //- Construct from faMesh and given size
faBoundaryMesh faBoundaryMesh
( (
const IOobject& io, const IOobject& io,
@ -111,25 +109,47 @@ public:
// Member Functions // Member Functions
// Access
//- Calculate the geometry for the patches
// (transformation tensors etc.)
void calcGeometry();
//- Return the mesh reference //- Return the mesh reference
const faMesh& mesh() const; const faMesh& mesh() const noexcept
{
return mesh_;
}
//- Return a list of pointers for each patch //- Return a list of pointers for each patch
//- with only those pointing to interfaces being set //- with only those pointing to interfaces being set
lduInterfacePtrsList interfaces() const; lduInterfacePtrsList interfaces() const;
//- The number of patches before the first processor patch.
label nNonProcessor() const;
//- Return a list of patch names //- Return a list of patch names
wordList names() const; wordList names() const;
//- Return a list of patch types //- Return a list of patch types
wordList types() const; wordList types() const;
//- Return a list of patch start indices
labelList patchStarts() const;
//- Return a list of patch sizes (number of edges in each patch)
labelList patchSizes() const;
//- Return a list of patch ranges
List<labelRange> patchRanges() const;
//- The start label of the edges in the faMesh edges list
// Same as mesh.nInternalEdges()
label start() const;
//- The number of boundary edges for the underlying mesh
// Same as mesh.nBoundaryEdges()
label nEdges() const;
//- The edge range for all boundary edges
// Spans [nInternalEdges, nEdges) of the underlying mesh
labelRange range() const;
//- Return patch indices for all matches. //- Return patch indices for all matches.
// A no-op (returns -1) for an empty key // A no-op (returns -1) for an empty key
// \note Matching patchGroups currently not supported // \note Matching patchGroups currently not supported
@ -156,17 +176,28 @@ public:
// Edit // Edit
//- Calculate the geometry for the patches
// (transformation tensors etc.)
void calcGeometry();
//- Correct faBoundaryMesh after moving points //- Correct faBoundaryMesh after moving points
void movePoints(const pointField&); void movePoints(const pointField&);
//- Correct faBoundaryMesh after topology update //- Correct faBoundaryMesh after topology update
void updateMesh(); void updateMesh();
//- writeData member function required by regIOobject //- The writeData member function required by regIOobject
bool writeData(Ostream&) const; bool writeData(Ostream& os) const;
//- Write using stream options
virtual bool writeObject
(
IOstreamOption streamOpt,
const bool valid
) const;
// Ostream operator // Ostream Operator
friend Ostream& operator<<(Ostream&, const faBoundaryMesh&); friend Ostream& operator<<(Ostream&, const faBoundaryMesh&);

View File

@ -47,75 +47,122 @@ namespace Foam
defineTypeNameAndDebug(faMesh, 0); defineTypeNameAndDebug(faMesh, 0);
} }
const Foam::word Foam::faMesh::prefix("finite-area");
Foam::word Foam::faMesh::meshSubDir = "faMesh"; Foam::word Foam::faMesh::meshSubDir = "faMesh";
const int Foam::faMesh::quadricsFit_ = 0; const int Foam::faMesh::quadricsFit_ = 0; // Tuning
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam
{
// Convert patch names to face labels. Preserve patch order
static labelList selectPatchFaces
(
const polyBoundaryMesh& pbm,
const wordList& polyPatchNames
)
{
labelHashSet patchIDs;
label nFaceLabels = 0;
for (const word& patchName : polyPatchNames)
{
const label polyPatchi = pbm.findPatchID(patchName);
if (polyPatchi < 0)
{
FatalErrorInFunction
<< "Patch " << patchName << " not found"
<< exit(FatalError);
}
if (patchIDs.insert(polyPatchi))
{
nFaceLabels += pbm[polyPatchi].size();
}
}
labelList faceLabels(nFaceLabels);
nFaceLabels = 0;
for (const label polyPatchi : patchIDs.sortedToc())
{
for (const label facei : pbm[polyPatchi].range())
{
faceLabels[nFaceLabels] = facei;
++nFaceLabels;
}
}
return faceLabels;
}
} // End namespace Foam
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::faMesh::initPatch() const
{
if (patchPtr_)
{
delete patchPtr_;
}
patchPtr_ = new uindirectPrimitivePatch
(
UIndirectList<face>(mesh().faces(), faceLabels_),
mesh().points()
);
}
void Foam::faMesh::setPrimitiveMeshData() void Foam::faMesh::setPrimitiveMeshData()
{ {
DebugInFunction << "Setting primitive data" << endl; DebugInFunction << "Setting primitive data" << endl;
const indirectPrimitivePatch& bp = patch(); const uindirectPrimitivePatch& bp = patch();
const labelListList& edgeFaces = bp.edgeFaces();
// Set faMesh edges // Dimensions
edges_.setSize(bp.nEdges());
label edgeI = -1; nEdges_ = bp.nEdges();
nInternalEdges_ = bp.nInternalEdges();
label nIntEdges = bp.nInternalEdges();
for (label curEdge = 0; curEdge < nIntEdges; ++curEdge)
{
edges_[++edgeI] = bp.edges()[curEdge];
}
forAll(boundary(), patchI)
{
const labelList& curP = boundary()[patchI];
forAll(curP, eI)
{
edges_[++edgeI] = bp.edges()[curP[eI]];
}
}
nEdges_ = edges_.size();
nInternalEdges_ = nIntEdges;
// Set edge owner and neighbour
edgeOwner_.setSize(nEdges());
edgeNeighbour_.setSize(nInternalEdges());
edgeI = -1;
const labelListList& bpef = bp.edgeFaces();
for (label curEdge = 0; curEdge < nIntEdges; ++curEdge)
{
edgeOwner_[++edgeI] = bpef[curEdge][0];
edgeNeighbour_[edgeI] = bpef[curEdge][1];
}
forAll(boundary(), patchI)
{
const labelList& curP = boundary()[patchI];
forAll(curP, eI)
{
edgeOwner_[++edgeI] = bpef[curP[eI]][0];
}
}
// Set number of faces
nFaces_ = bp.size(); nFaces_ = bp.size();
// Set number of points
nPoints_ = bp.nPoints(); nPoints_ = bp.nPoints();
edges_.resize(nEdges_);
edgeOwner_.resize(nEdges_);
edgeNeighbour_.resize(nInternalEdges_);
// Internal edges
for (label edgei = 0; edgei < nInternalEdges_; ++edgei)
{
edges_[edgei] = bp.edges()[edgei];
edgeOwner_[edgei] = edgeFaces[edgei][0];
edgeNeighbour_[edgei] = edgeFaces[edgei][1];
}
// Continue with boundary edges
label edgei = nInternalEdges_;
for (const faPatch& p : boundary())
{
for (const label patchEdgei : p.edgeLabels())
{
edges_[edgei] = bp.edges()[patchEdgei];
edgeOwner_[edgei] = edgeFaces[patchEdgei][0];
++edgei;
}
}
} }
@ -161,15 +208,20 @@ void Foam::faMesh::clearOut() const
{ {
clearGeom(); clearGeom();
clearAddressing(); clearAddressing();
deleteDemandDrivenData(globalMeshDataPtr_); globalMeshDataPtr_.reset(nullptr);
} }
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::faMesh::faMesh(const polyMesh& pMesh, const zero)
:
faMesh(pMesh, labelList())
{}
Foam::faMesh::faMesh(const polyMesh& pMesh) Foam::faMesh::faMesh(const polyMesh& pMesh)
: :
GeoMesh<polyMesh>(pMesh),
MeshObject<polyMesh, Foam::UpdateableMeshObject, faMesh>(pMesh), MeshObject<polyMesh, Foam::UpdateableMeshObject, faMesh>(pMesh),
edgeInterpolation(*this), edgeInterpolation(*this),
faSchemes(mesh()), faSchemes(mesh()),
@ -181,7 +233,7 @@ Foam::faMesh::faMesh(const polyMesh& pMesh)
( (
"faceLabels", "faceLabels",
time().findInstance(meshDir(), "faceLabels"), time().findInstance(meshDir(), "faceLabels"),
meshSubDir, faMesh::meshSubDir,
mesh(), mesh(),
IOobject::MUST_READ, IOobject::MUST_READ,
IOobject::NO_WRITE IOobject::NO_WRITE
@ -193,7 +245,7 @@ Foam::faMesh::faMesh(const polyMesh& pMesh)
( (
"faBoundary", "faBoundary",
time().findInstance(meshDir(), "faBoundary"), time().findInstance(meshDir(), "faBoundary"),
meshSubDir, faMesh::meshSubDir,
mesh(), mesh(),
IOobject::MUST_READ, IOobject::MUST_READ,
IOobject::NO_WRITE IOobject::NO_WRITE
@ -220,7 +272,7 @@ Foam::faMesh::faMesh(const polyMesh& pMesh)
correctPatchPointNormalsPtr_(nullptr), correctPatchPointNormalsPtr_(nullptr),
globalMeshDataPtr_(nullptr) globalMeshDataPtr_(nullptr)
{ {
DebugInFunction << "Creating faMesh from IOobject" << endl; DebugInFunction << "Creating from IOobject" << endl;
setPrimitiveMeshData(); setPrimitiveMeshData();
@ -244,7 +296,7 @@ Foam::faMesh::faMesh(const polyMesh& pMesh)
( (
"S0", "S0",
time().timeName(), time().timeName(),
meshSubDir, faMesh::meshSubDir,
mesh(), mesh(),
IOobject::MUST_READ, IOobject::MUST_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
@ -258,10 +310,9 @@ Foam::faMesh::faMesh(const polyMesh& pMesh)
Foam::faMesh::faMesh Foam::faMesh::faMesh
( (
const polyMesh& pMesh, const polyMesh& pMesh,
const labelList& faceLabels const UList<label>& faceLabels
) )
: :
GeoMesh<polyMesh>(pMesh),
MeshObject<polyMesh, Foam::UpdateableMeshObject, faMesh>(pMesh), MeshObject<polyMesh, Foam::UpdateableMeshObject, faMesh>(pMesh),
edgeInterpolation(*this), edgeInterpolation(*this),
faSchemes(mesh()), faSchemes(mesh()),
@ -273,7 +324,7 @@ Foam::faMesh::faMesh
( (
"faceLabels", "faceLabels",
mesh().facesInstance(), mesh().facesInstance(),
meshSubDir, faMesh::meshSubDir,
mesh(), mesh(),
IOobject::NO_READ, IOobject::NO_READ,
IOobject::NO_WRITE IOobject::NO_WRITE
@ -286,13 +337,13 @@ Foam::faMesh::faMesh
( (
"faBoundary", "faBoundary",
mesh().facesInstance(), mesh().facesInstance(),
meshSubDir, faMesh::meshSubDir,
mesh(), mesh(),
IOobject::NO_READ, IOobject::NO_READ,
IOobject::NO_WRITE IOobject::NO_WRITE
), ),
*this, *this,
0 label(0)
), ),
comm_(Pstream::worldComm), comm_(Pstream::worldComm),
patchPtr_(nullptr), patchPtr_(nullptr),
@ -313,434 +364,77 @@ Foam::faMesh::faMesh
edgeTransformTensorsPtr_(nullptr), edgeTransformTensorsPtr_(nullptr),
correctPatchPointNormalsPtr_(nullptr), correctPatchPointNormalsPtr_(nullptr),
globalMeshDataPtr_(nullptr) globalMeshDataPtr_(nullptr)
{}
Foam::faMesh::faMesh(const polyPatch& pp)
:
faMesh
(
pp.boundaryMesh().mesh(),
identity(pp.range())
)
{ {
DebugInFunction << "Creating faMesh from components" << endl; DebugInFunction << "Creating from polyPatch:" << pp.name() << endl;
// Add single faPatch "default", but with processor connections
PtrList<faPatch> newPatches
(
createOnePatch("default")
);
addFaPatches(newPatches);
setPrimitiveMeshData();
// Create global mesh data
if (Pstream::parRun())
{
globalData();
}
// Calculate topology for the patches (processor-processor comms etc.)
boundary_.updateMesh();
// Calculate the geometry for the patches (transformation tensors etc.)
boundary_.calcGeometry();
} }
Foam::faMesh::faMesh Foam::faMesh::faMesh
( (
const polyMesh& pMesh, const polyMesh& pMesh,
const fileName& defFile const dictionary& faMeshDefinition
) )
: :
GeoMesh<polyMesh>(pMesh), faMesh
MeshObject<polyMesh, Foam::UpdateableMeshObject, faMesh>(pMesh),
edgeInterpolation(*this),
faSchemes(mesh()),
faSolution(mesh()),
data(mesh()),
faceLabels_
( (
IOobject pMesh,
( selectPatchFaces
"faceLabels",
mesh().facesInstance(),
meshSubDir,
mesh(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
List<label>(0)
),
boundary_
(
IOobject
(
"faBoundary",
mesh().facesInstance(),
meshSubDir,
mesh(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
*this,
0
),
comm_(Pstream::worldComm),
patchPtr_(nullptr),
lduPtr_(nullptr),
curTimeIndex_(time().timeIndex()),
SPtr_(nullptr),
S0Ptr_(nullptr),
S00Ptr_(nullptr),
patchStartsPtr_(nullptr),
LePtr_(nullptr),
magLePtr_(nullptr),
centresPtr_(nullptr),
edgeCentresPtr_(nullptr),
faceAreaNormalsPtr_(nullptr),
edgeAreaNormalsPtr_(nullptr),
pointAreaNormalsPtr_(nullptr),
faceCurvaturesPtr_(nullptr),
edgeTransformTensorsPtr_(nullptr),
correctPatchPointNormalsPtr_(nullptr),
globalMeshDataPtr_(nullptr)
{
DebugInFunction << "Creating faMesh from definition file" << endl;
// Reading faMeshDefinition dictionary
IOdictionary faMeshDefinition
(
IOobject
(
defFile,
mesh().time().constant(),
meshSubDir,
mesh(),
IOobject::MUST_READ,
IOobject::NO_WRITE
)
);
const wordList polyMeshPatches
( (
pMesh.boundaryMesh(),
faMeshDefinition.get<wordList>("polyMeshPatches") faMeshDefinition.get<wordList>("polyMeshPatches")
);
const dictionary& bndDict = faMeshDefinition.subDict("boundary");
const wordList faPatchNames(bndDict.toc());
List<faPatchData> faPatches(faPatchNames.size() + 1);
const polyBoundaryMesh& pbm = pMesh.boundaryMesh();
forAll(faPatchNames, patchI)
{
dictionary curPatchDict = bndDict.subDict(faPatchNames[patchI]);
faPatches[patchI].name_ = faPatchNames[patchI];
faPatches[patchI].type_ = curPatchDict.get<word>("type");
faPatches[patchI].ownPolyPatchID_ =
pbm.findPatchID(curPatchDict.get<word>("ownerPolyPatch"));
faPatches[patchI].ngbPolyPatchID_ =
pbm.findPatchID(curPatchDict.get<word>("neighbourPolyPatch"));
}
// Setting faceLabels list size
label size = 0;
labelList patchIDs(polyMeshPatches.size(), -1);
forAll(polyMeshPatches, patchI)
{
patchIDs[patchI] = pbm.findPatchID(polyMeshPatches[patchI]);
size += pbm[patchIDs[patchI]].size();
}
faceLabels_ = labelList(size, -1);
// Filling of faceLabels list
label faceI = -1;
sort(patchIDs);
forAll(polyMeshPatches, patchI)
{
label start = pbm[patchIDs[patchI]].start();
label size = pbm[patchIDs[patchI]].size();
for (label i = 0; i < size; ++i)
{
faceLabels_[++faceI] = start + i;
}
}
// Determination of faPatch ID for each boundary edge.
// Result is in the bndEdgeFaPatchIDs list
labelList faceCells(faceLabels_.size(), -1);
forAll(faceCells, faceI)
{
label faceID = faceLabels_[faceI];
faceCells[faceI] = mesh().faceOwner()[faceID];
}
labelList meshEdges =
patch().meshEdges
(
mesh().edges(),
mesh().cellEdges(),
faceCells
);
const labelListList& edgeFaces = mesh().edgeFaces();
const label nTotalEdges = patch().nEdges();
const label nInternalEdges = patch().nInternalEdges();
labelList bndEdgeFaPatchIDs(nTotalEdges - nInternalEdges, -1);
for (label edgeI = nInternalEdges; edgeI < nTotalEdges; ++edgeI)
{
label curMeshEdge = meshEdges[edgeI];
labelList curEdgePatchIDs(2, label(-1));
label patchI = -1;
forAll(edgeFaces[curMeshEdge], faceI)
{
label curFace = edgeFaces[curMeshEdge][faceI];
label curPatchID = pbm.whichPatch(curFace);
if (curPatchID != -1)
{
curEdgePatchIDs[++patchI] = curPatchID;
}
}
for (label pI = 0; pI < faPatches.size() - 1; ++pI)
{
if
(
(
curEdgePatchIDs[0] == faPatches[pI].ownPolyPatchID_
&& curEdgePatchIDs[1] == faPatches[pI].ngbPolyPatchID_
)
||
(
curEdgePatchIDs[1] == faPatches[pI].ownPolyPatchID_
&& curEdgePatchIDs[0] == faPatches[pI].ngbPolyPatchID_
) )
) )
{ {
bndEdgeFaPatchIDs[edgeI - nInternalEdges] = pI; DebugInFunction << "Creating from definition (dictionary)" << endl;
break;
}
}
}
PtrList<faPatch> newPatches
// Set edgeLabels for each faPatch
for (label pI = 0; pI < (faPatches.size() - 1); ++pI)
{
SLList<label> tmpList;
forAll(bndEdgeFaPatchIDs, eI)
{
if (bndEdgeFaPatchIDs[eI] == pI)
{
tmpList.append(nInternalEdges + eI);
}
}
faPatches[pI].edgeLabels_ = tmpList;
}
// Check for undefined edges
SLList<label> tmpList;
forAll(bndEdgeFaPatchIDs, eI)
{
if (bndEdgeFaPatchIDs[eI] == -1)
{
tmpList.append(nInternalEdges + eI);
}
}
if (tmpList.size() > 0)
{
// Check for processor edges
labelList allUndefEdges(tmpList);
labelList ngbPolyPatch(allUndefEdges.size(), -1);
forAll(ngbPolyPatch, edgeI)
{
label curEdge = allUndefEdges[edgeI];
label curPMeshEdge = meshEdges[curEdge];
forAll(edgeFaces[curPMeshEdge], faceI)
{
label curFace = edgeFaces[curPMeshEdge][faceI];
if (faceLabels_.found(curFace))
{
label polyPatchID = pbm.whichPatch(curFace);
if (polyPatchID != -1)
{
ngbPolyPatch[edgeI] = polyPatchID;
}
}
}
}
// Count ngb processorPolyPatch-es
labelHashSet processorPatchSet;
forAll(ngbPolyPatch, edgeI)
{
if (ngbPolyPatch[edgeI] != -1)
{
if (isA<processorPolyPatch>(pbm[ngbPolyPatch[edgeI]]))
{
processorPatchSet.insert(ngbPolyPatch[edgeI]);
}
}
}
labelList processorPatches(processorPatchSet.toc());
faPatches.setSize(faPatches.size() + processorPatches.size());
for (label i = 0; i < processorPatches.size(); ++i)
{
SLList<label> tmpLst;
forAll(ngbPolyPatch, eI)
{
if (ngbPolyPatch[eI] == processorPatches[i])
{
tmpLst.append(allUndefEdges[eI]);
}
}
faPatches[faPatchNames.size() + i].edgeLabels_ = tmpLst;
faPatches[faPatchNames.size() + i].name_ =
pbm[processorPatches[i]].name();
faPatches[faPatchNames.size() + i].type_ =
processorFaPatch::typeName;
faPatches[faPatchNames.size() + i].ngbPolyPatchID_ =
processorPatches[i];
}
// Remaining undefined edges
SLList<label> undefEdges;
forAll(ngbPolyPatch, eI)
{
if (ngbPolyPatch[eI] == -1)
{
undefEdges.append(allUndefEdges[eI]);
}
else if (!isA<processorPolyPatch>(pbm[ngbPolyPatch[eI]]))
{
undefEdges.append(allUndefEdges[eI]);
}
}
if (undefEdges.size() > 0)
{
label pI = faPatches.size()-1;
faPatches[pI].name_ = "undefined";
faPatches[pI].type_ = "patch";
faPatches[pI].edgeLabels_ = undefEdges;
}
else
{
faPatches.setSize(faPatches.size() - 1);
}
}
else
{
faPatches.setSize(faPatches.size() - 1);
}
// Reorder processorFaPatch using
// ordering of ngb processorPolyPatch
forAll(faPatches, patchI)
{
if (faPatches[patchI].type_ == processorFaPatch::typeName)
{
labelList ngbFaces(faPatches[patchI].edgeLabels_.size(), -1);
forAll(ngbFaces, edgeI)
{
label curEdge = faPatches[patchI].edgeLabels_[edgeI];
label curPMeshEdge = meshEdges[curEdge];
forAll(edgeFaces[curPMeshEdge], faceI)
{
label curFace = edgeFaces[curPMeshEdge][faceI];
label curPatchID = pbm.whichPatch(curFace);
if (curPatchID == faPatches[patchI].ngbPolyPatchID_)
{
ngbFaces[edgeI] = curFace;
}
}
}
SortableList<label> sortedNgbFaces(ngbFaces);
labelList reorderedEdgeLabels(ngbFaces.size(), -1);
for (label i = 0; i < reorderedEdgeLabels.size(); ++i)
{
reorderedEdgeLabels[i] =
faPatches[patchI].edgeLabels_
[
sortedNgbFaces.indices()[i]
];
}
faPatches[patchI].edgeLabels_ = reorderedEdgeLabels;
}
}
// Add good patches to faMesh
SLList<faPatch*> faPatchLst;
for (label pI = 0; pI < faPatches.size(); ++pI)
{
faPatches[pI].dict_.add("type", faPatches[pI].type_);
faPatches[pI].dict_.add("edgeLabels", faPatches[pI].edgeLabels_);
faPatches[pI].dict_.add
( (
"ngbPolyPatchIndex", createPatchList
faPatches[pI].ngbPolyPatchID_ (
faMeshDefinition.subDict("boundary"),
// Optional 'empty' patch
faMeshDefinition.getOrDefault<word>("emptyPatch", word::null),
// Optional specification for default patch
faMeshDefinition.findDict("defaultPatch")
)
); );
if (faPatches[pI].type_ == processorFaPatch::typeName)
{
if (faPatches[pI].ngbPolyPatchID_ == -1)
{
FatalErrorInFunction
<< "ngbPolyPatch is not defined for processorFaPatch: "
<< faPatches[pI].name_
<< abort(FatalError);
}
const processorPolyPatch& procPolyPatch = addFaPatches(newPatches);
refCast<const processorPolyPatch>
(
pbm[faPatches[pI].ngbPolyPatchID_]
);
faPatches[pI].dict_.add("myProcNo", procPolyPatch.myProcNo());
faPatches[pI].dict_.add
(
"neighbProcNo",
procPolyPatch.neighbProcNo()
);
}
faPatchLst.append
(
faPatch::New
(
faPatches[pI].name_,
faPatches[pI].dict_,
pI,
boundary()
).ptr()
);
}
addFaPatches(List<faPatch*>(faPatchLst));
// Create global mesh data // Create global mesh data
if (Pstream::parRun()) if (Pstream::parRun())
@ -762,7 +456,7 @@ Foam::faMesh::faMesh
( (
"S0", "S0",
time().timeName(), time().timeName(),
meshSubDir, faMesh::meshSubDir,
mesh(), mesh(),
IOobject::MUST_READ, IOobject::MUST_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
@ -773,111 +467,6 @@ Foam::faMesh::faMesh
} }
Foam::faMesh::faMesh
(
const polyMesh& pMesh,
const label polyPatchID
)
:
GeoMesh<polyMesh>(pMesh),
MeshObject<polyMesh, Foam::UpdateableMeshObject, faMesh>(pMesh),
edgeInterpolation(*this),
faSchemes(mesh()),
faSolution(mesh()),
data(mesh()),
faceLabels_
(
IOobject
(
"faceLabels",
mesh().facesInstance(),
meshSubDir,
mesh(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
labelList(pMesh.boundaryMesh()[polyPatchID].size(), -1)
),
boundary_
(
IOobject
(
"faBoundary",
mesh().facesInstance(),
meshSubDir,
mesh(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
*this,
0
),
comm_(Pstream::worldComm),
patchPtr_(nullptr),
lduPtr_(nullptr),
curTimeIndex_(time().timeIndex()),
SPtr_(nullptr),
S0Ptr_(nullptr),
S00Ptr_(nullptr),
patchStartsPtr_(nullptr),
LePtr_(nullptr),
magLePtr_(nullptr),
centresPtr_(nullptr),
edgeCentresPtr_(nullptr),
faceAreaNormalsPtr_(nullptr),
edgeAreaNormalsPtr_(nullptr),
pointAreaNormalsPtr_(nullptr),
faceCurvaturesPtr_(nullptr),
edgeTransformTensorsPtr_(nullptr),
correctPatchPointNormalsPtr_(nullptr),
globalMeshDataPtr_(nullptr)
{
DebugInFunction << "Creating faMesh from polyPatch" << endl;
const polyBoundaryMesh& pbm = pMesh.boundaryMesh();
// Set faceLabels
forAll(faceLabels_, faceI)
{
faceLabels_[faceI] = pbm[polyPatchID].start() + faceI;
}
// Add one faPatch
const indirectPrimitivePatch& bp = patch();
const label nTotalEdges = bp.nEdges();
const label nInternalEdges = bp.nInternalEdges();
labelList edgeLabels(nTotalEdges - nInternalEdges, -1);
forAll(edgeLabels, edgeI)
{
edgeLabels[edgeI] = nInternalEdges + edgeI;
}
dictionary patchDict;
patchDict.add("type", "patch");
patchDict.add("edgeLabels", edgeLabels);
patchDict.add("ngbPolyPatchIndex", -1);
List<faPatch*> faPatchLst(1);
faPatchLst[0] = faPatch::New("default", patchDict, 0, boundary()).ptr();
addFaPatches(faPatchLst);
setPrimitiveMeshData();
// Calculate topology for the patches (processor-processor comms etc.)
boundary_.updateMesh();
// Calculate the geometry for the patches (transformation tensors etc.)
boundary_.calcGeometry();
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::faMesh::~faMesh() Foam::faMesh::~faMesh()
@ -890,7 +479,7 @@ Foam::faMesh::~faMesh()
Foam::fileName Foam::faMesh::meshDir() const Foam::fileName Foam::faMesh::meshDir() const
{ {
return mesh().dbDir()/meshSubDir; return mesh().dbDir()/faMesh::meshSubDir;
} }
@ -912,98 +501,6 @@ const Foam::fileName& Foam::faMesh::facesInstance() const
} }
const Foam::indirectPrimitivePatch& Foam::faMesh::patch() const
{
if (!patchPtr_)
{
patchPtr_ = new indirectPrimitivePatch
(
IndirectList<face>
(
mesh().faces(),
faceLabels_
),
mesh().points()
);
}
return *patchPtr_;
}
Foam::indirectPrimitivePatch& Foam::faMesh::patch()
{
if (!patchPtr_)
{
patchPtr_ = new indirectPrimitivePatch
(
IndirectList<face>
(
mesh().faces(),
faceLabels_
),
mesh().points()
);
}
return *patchPtr_;
}
const Foam::pointField& Foam::faMesh::points() const
{
return patch().localPoints();
}
const Foam::edgeList& Foam::faMesh::edges() const
{
return edges_;
}
const Foam::faceList& Foam::faMesh::faces() const
{
return patch().localFaces();
}
void Foam::faMesh::addFaPatches(const List<faPatch*>& p)
{
DebugInFunction << "Adding patches to faMesh" << endl;
if (boundary().size() > 0)
{
FatalErrorInFunction
<< "boundary already exists"
<< abort(FatalError);
}
boundary_.setSize(p.size());
forAll(p, patchI)
{
boundary_.set(patchI, p[patchI]);
}
setPrimitiveMeshData();
boundary_.checkDefinition();
}
Foam::label Foam::faMesh::comm() const
{
return comm_;
}
Foam::label& Foam::faMesh::comm()
{
return comm_;
}
bool Foam::faMesh::hasDb() const bool Foam::faMesh::hasDb() const
{ {
return true; return true;
@ -1016,12 +513,6 @@ const Foam::objectRegistry& Foam::faMesh::thisDb() const
} }
const Foam::faBoundaryMesh& Foam::faMesh::boundary() const
{
return boundary_;
}
const Foam::labelList& Foam::faMesh::patchStarts() const const Foam::labelList& Foam::faMesh::patchStarts() const
{ {
if (!patchStartsPtr_) if (!patchStartsPtr_)
@ -1193,7 +684,7 @@ const Foam::faGlobalMeshData& Foam::faMesh::globalData() const
{ {
if (!globalMeshDataPtr_) if (!globalMeshDataPtr_)
{ {
globalMeshDataPtr_ = new faGlobalMeshData(*this); globalMeshDataPtr_.reset(new faGlobalMeshData(*this));
} }
return *globalMeshDataPtr_; return *globalMeshDataPtr_;

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -42,7 +43,6 @@ Author
#ifndef faMesh_H #ifndef faMesh_H
#define faMesh_H #define faMesh_H
#include "GeoMesh.H"
#include "MeshObject.H" #include "MeshObject.H"
#include "polyMesh.H" #include "polyMesh.H"
#include "lduMesh.H" #include "lduMesh.H"
@ -53,7 +53,7 @@ Author
#include "DimensionedField.H" #include "DimensionedField.H"
#include "areaFieldsFwd.H" #include "areaFieldsFwd.H"
#include "edgeFieldsFwd.H" #include "edgeFieldsFwd.H"
#include "indirectPrimitivePatch.H" #include "uindirectPrimitivePatch.H"
#include "edgeInterpolation.H" #include "edgeInterpolation.H"
#include "labelIOList.H" #include "labelIOList.H"
#include "FieldFields.H" #include "FieldFields.H"
@ -67,9 +67,11 @@ Author
namespace Foam namespace Foam
{ {
// Class forward declarations // Forward Declarations
class faMeshLduAddressing; class faMeshLduAddressing;
class faMeshMapper; class faMeshMapper;
class faPatchData;
template<class T> class LabelledItem;
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class faMesh Declaration Class faMesh Declaration
@ -77,7 +79,6 @@ class faMeshMapper;
class faMesh class faMesh
: :
public GeoMesh<polyMesh>,
public MeshObject<polyMesh, Foam::UpdateableMeshObject, faMesh>, public MeshObject<polyMesh, Foam::UpdateableMeshObject, faMesh>,
public lduMesh, public lduMesh,
public edgeInterpolation, public edgeInterpolation,
@ -85,7 +86,7 @@ class faMesh
public faSolution, public faSolution,
public data public data
{ {
// Private data // Private Data
//- Face labels //- Face labels
labelIOList faceLabels_; labelIOList faceLabels_;
@ -130,7 +131,7 @@ class faMesh
// Demand-driven data // Demand-driven data
//- Primitive patch //- Primitive patch
mutable indirectPrimitivePatch* patchPtr_; mutable uindirectPrimitivePatch* patchPtr_;
//- Ldu addressing data //- Ldu addressing data
mutable faMeshLduAddressing* lduPtr_; mutable faMeshLduAddressing* lduPtr_;
@ -187,7 +188,7 @@ class faMesh
// Other mesh-related data // Other mesh-related data
//- Parallel info //- Parallel info
mutable faGlobalMeshData* globalMeshDataPtr_; mutable autoPtr<faGlobalMeshData> globalMeshDataPtr_;
// Static Private Data // Static Private Data
@ -204,6 +205,8 @@ class faMesh
//- No copy assignment //- No copy assignment
void operator=(const faMesh&) = delete; void operator=(const faMesh&) = delete;
//- Set indirect patch, removing any old one
void initPatch() const;
//- Set primitive mesh data //- Set primitive mesh data
void setPrimitiveMeshData(); void setPrimitiveMeshData();
@ -262,9 +265,39 @@ class faMesh
//- Clear demand-driven data //- Clear demand-driven data
void clearOut() const; void clearOut() const;
// Helpers
//- Get the polyPatch pairs for the boundary edges (natural order)
List<LabelledItem<edge>> getBoundaryEdgePatchPairs() const;
//- Create a single patch
PtrList<faPatch> createOnePatch
(
const word& patchName,
const word& patchType = ""
) const;
//- Create list of patches from boundary definition
PtrList<faPatch> createPatchList
(
const dictionary& bndDict,
const word& emptyPatchName = "",
const dictionary* defaultPatchDefinition = nullptr
) const;
//- Reorder processor edges using order of the
//- neighbour processorPolyPatch
void reorderProcEdges
(
faPatchData& patchDef,
const List<LabelledItem<edge>>& bndEdgePatchPairs
) const;
public: public:
// Public typedefs // Public Typedefs
typedef faMesh Mesh; typedef faMesh Mesh;
typedef faBoundaryMesh BoundaryMesh; typedef faBoundaryMesh BoundaryMesh;
@ -273,36 +306,38 @@ public:
//- Runtime type information //- Runtime type information
TypeName("faMesh"); TypeName("faMesh");
//- The prefix to local: %finite-area
static const word prefix;
//- Return the mesh sub-directory name (usually "faMesh") //- The mesh sub-directory name (usually "faMesh")
static word meshSubDir; static word meshSubDir;
// Constructors // Constructors
//- Construct from polyMesh //- Construct zero-sized from polyMesh
explicit faMesh(const polyMesh& m); // Boundary is added using addFaPatches() member function
faMesh(const polyMesh& pMesh, const Foam::zero);
//- Construct from components without boundary. //- Construct from polyMesh
explicit faMesh(const polyMesh& pMesh);
//- Construct for specified face labels without boundary.
// Boundary is added using addFaPatches() member function // Boundary is added using addFaPatches() member function
faMesh faMesh
( (
const polyMesh& m, const polyMesh& pMesh,
const labelList& faceLabels const UList<label>& faceLabels
); );
//- Construct from finite area mesh definition file //- Construct from single polyPatch
faMesh explicit faMesh(const polyPatch& pp);
(
const polyMesh& m,
const fileName& defFile
);
//- Construct from polyPatch //- Construct from definition
faMesh faMesh
( (
const polyMesh& m, const polyMesh& pMesh,
const label polyPatchID const dictionary& faMeshDefinition
); );
@ -315,22 +350,27 @@ public:
// Helpers // Helpers
//- Add boundary patches. Constructor helper //- Add boundary patches. Constructor helper
void addFaPatches(const List<faPatch*> &); void addFaPatches
(
PtrList<faPatch>& plist,
const bool validBoundary = true
);
//- Add boundary patches. Constructor helper
void addFaPatches
(
const List<faPatch*>& p,
const bool validBoundary = true
);
// Database // Database
//- Return access to polyMesh //- Return access to polyMesh
const polyMesh& mesh() const inline const polyMesh& mesh() const;
{
return //- Interface to referenced polyMesh (similar to GeoMesh)
MeshObject const polyMesh& operator()() const { return mesh(); }
<
polyMesh,
Foam::UpdateableMeshObject,
faMesh
>::mesh();
}
//- Return the local mesh directory (dbDir()/meshSubDir) //- Return the local mesh directory (dbDir()/meshSubDir)
fileName meshDir() const; fileName meshDir() const;
@ -347,61 +387,51 @@ public:
const fileName& facesInstance() const; const fileName& facesInstance() const;
// Communication support
//- Return communicator used for parallel communication
inline label comm() const noexcept;
//- Return communicator used for parallel communication
inline label& comm() noexcept;
// Mesh size parameters // Mesh size parameters
inline label nPoints() const //- Number of local mesh points
{ inline label nPoints() const noexcept;
return nPoints_;
}
inline label nEdges() const //- Number of local mesh edges
{ inline label nEdges() const noexcept;
return nEdges_;
}
inline label nInternalEdges() const //- Number of internal faces
{ inline label nInternalEdges() const noexcept;
return nInternalEdges_;
}
inline label nFaces() const //- Number of boundary edges (== nEdges - nInternalEdges)
{ inline label nBoundaryEdges() const noexcept;
return nFaces_;
} //- Number of patch faces
inline label nFaces() const noexcept;
// Primitive mesh data // Primitive mesh data
//- Return mesh points //- Return local patch points
const pointField& points() const; inline const pointField& points() const;
//- Return edges //- Return local patch edges with reordered boundary
const edgeList& edges() const; inline const edgeList& edges() const noexcept;
//- Return faces //- Return local patch faces
const faceList& faces() const; inline const faceList& faces() const;
//- Edge owner addressing //- Edge owner addressing
inline const labelList& edgeOwner() const inline const labelList& edgeOwner() const noexcept;
{
return edgeOwner_;
}
//- Edge neighbour addressing //- Edge neighbour addressing
inline const labelList& edgeNeighbour() const inline const labelList& edgeNeighbour() const noexcept;
{
return edgeNeighbour_;
}
// Communication support
//- Return communicator used for parallel communication
label comm() const;
//- Return communicator used for parallel communication
label& comm();
// Access // Access
@ -419,13 +449,10 @@ public:
} }
//- Return constant reference to boundary mesh //- Return constant reference to boundary mesh
const faBoundaryMesh& boundary() const; inline const faBoundaryMesh& boundary() const noexcept;
//- Return faMesh face labels //- Return faMesh face labels
const labelList& faceLabels() const inline const labelList& faceLabels() const noexcept;
{
return faceLabels_;
}
//- Return parallel info //- Return parallel info
@ -453,10 +480,10 @@ public:
return lduAddr().upperAddr(); return lduAddr().upperAddr();
} }
//- Return true if given edge label is internal to the mesh //- True if given edge label is internal to the mesh
inline bool isInternalEdge(const label edgeIndex) const bool isInternalEdge(const label edgeIndex) const
{ {
return edgeIndex < nInternalEdges(); return (edgeIndex < nInternalEdges_);
} }
@ -487,10 +514,10 @@ public:
// Demand-driven data // Demand-driven data
//- Return constant reference to primitive patch //- Return constant reference to primitive patch
const indirectPrimitivePatch& patch() const; inline const uindirectPrimitivePatch& patch() const;
//- Return reference to primitive patch //- Return reference to primitive patch
indirectPrimitivePatch& patch(); inline uindirectPrimitivePatch& patch();
//- Return patch starts //- Return patch starts
const labelList& patchStarts() const; const labelList& patchStarts() const;
@ -546,6 +573,7 @@ public:
//- Set whether point normals should be corrected for a patch //- Set whether point normals should be corrected for a patch
boolList& correctPatchPointNormals() const; boolList& correctPatchPointNormals() const;
//- Write mesh //- Write mesh
virtual bool write(const bool valid = true) const; virtual bool write(const bool valid = true) const;
@ -564,6 +592,8 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "faMeshI.H"
#ifdef NoRepository #ifdef NoRepository
#include "faPatchFaMeshTemplates.C" #include "faPatchFaMeshTemplates.C"
#endif #endif

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2018-2020 OpenCFD Ltd. Copyright (C) 2018-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -40,6 +40,30 @@ License
#include "processorFaPatchFields.H" #include "processorFaPatchFields.H"
#include "emptyFaPatchFields.H" #include "emptyFaPatchFields.H"
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam
{
// A bitSet (size patch nPoints()) with boundary points marked
static Foam::bitSet markupBoundaryPoints(const uindirectPrimitivePatch& p)
{
// Initially all unmarked
bitSet markPoints(p.nPoints());
for (const edge& e : p.boundaryEdges())
{
// Mark boundary points
markPoints.set(e.first());
markPoints.set(e.second());
}
return markPoints;
}
} // End namespace Foam
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::faMesh::calcLduAddressing() const void Foam::faMesh::calcLduAddressing() const
@ -70,16 +94,7 @@ void Foam::faMesh::calcPatchStarts() const
<< abort(FatalError); << abort(FatalError);
} }
patchStartsPtr_ = new labelList(boundary().size(), -1); patchStartsPtr_ = new labelList(boundary().patchStarts());
labelList& patchStarts = *patchStartsPtr_;
patchStarts[0] = nInternalEdges();
for (label i = 1; i < boundary().size(); ++i)
{
patchStarts[i] =
patchStarts[i - 1] + boundary()[i - 1].faPatch::size();
}
} }
@ -211,13 +226,11 @@ void Foam::faMesh::calcMagLe() const
const pointField& localPoints = points(); const pointField& localPoints = points();
const edgeList::subList internalEdges = label edgei = 0;
edgeList::subList(edges(), nInternalEdges()); for (const edge& e : patch().internalEdges())
forAll(internalEdges, edgeI)
{ {
magLe.ref()[edgeI] = internalEdges[edgeI].mag(localPoints); magLe.ref()[edgei] = e.mag(localPoints);
++edgei;
} }
@ -331,13 +344,12 @@ void Foam::faMesh::calcEdgeCentres() const
const pointField& localPoints = points(); const pointField& localPoints = points();
const edgeList::subList internalEdges =
edgeList::subList(edges(), nInternalEdges());
label edgei = 0;
forAll(internalEdges, edgeI) for (const edge& e : patch().internalEdges())
{ {
edgeCentres.ref()[edgeI] = internalEdges[edgeI].centre(localPoints); edgeCentres.ref()[edgei] = e.centre(localPoints);
++edgei;
} }
@ -850,31 +862,10 @@ Foam::labelList Foam::faMesh::internalPoints() const
DebugInFunction DebugInFunction
<< "Calculating internal points" << endl; << "Calculating internal points" << endl;
const edgeList& edges = patch().edges(); bitSet markPoints(markupBoundaryPoints(this->patch()));
label nIntEdges = patch().nInternalEdges(); markPoints.flip();
List<bool> internal(nPoints(), true); return markPoints.sortedToc();
for (label curEdge = nIntEdges; curEdge < edges.size(); ++curEdge)
{
internal[edges[curEdge].start()] = false;
internal[edges[curEdge].end()] = false;
}
SLList<label> internalPoints;
forAll(internal, pointI)
{
if (internal[pointI])
{
internalPoints.append(pointI);
}
}
labelList result(internalPoints);
return result;
} }
@ -883,31 +874,9 @@ Foam::labelList Foam::faMesh::boundaryPoints() const
DebugInFunction DebugInFunction
<< "Calculating boundary points" << endl; << "Calculating boundary points" << endl;
const edgeList& edges = patch().edges(); bitSet markPoints(markupBoundaryPoints(this->patch()));
label nIntEdges = patch().nInternalEdges();
List<bool> internal(nPoints(), true); return markPoints.sortedToc();
for (label curEdge = nIntEdges; curEdge < edges.size(); ++curEdge)
{
internal[edges[curEdge].start()] = false;
internal[edges[curEdge].end()] = false;
}
SLList<label> boundaryPoints;
forAll(internal, pointI)
{
if (!internal[pointI])
{
boundaryPoints.append(pointI);
}
}
labelList result(boundaryPoints);
return result;
} }
@ -1168,7 +1137,7 @@ void Foam::faMesh::calcPointAreaNormals() const
if (correctPatchPointNormals(patchI) && !fap.coupled()) if (correctPatchPointNormals(patchI) && !fap.coupled())
{ {
if (fap.ngbPolyPatchIndex() == -1) if (fap.ngbPolyPatchIndex() < 0)
{ {
FatalErrorInFunction FatalErrorInFunction
<< "Neighbour polyPatch index is not defined " << "Neighbour polyPatch index is not defined "

View File

@ -0,0 +1,142 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
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/>.
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline const Foam::polyMesh& Foam::faMesh::mesh() const
{
return
MeshObject<polyMesh, Foam::UpdateableMeshObject, faMesh>::mesh();
}
inline const Foam::faBoundaryMesh& Foam::faMesh::boundary() const noexcept
{
return boundary_;
}
inline Foam::label Foam::faMesh::comm() const noexcept
{
return comm_;
}
inline Foam::label& Foam::faMesh::comm() noexcept
{
return comm_;
}
inline Foam::label Foam::faMesh::nPoints() const noexcept
{
return nPoints_;
}
inline Foam::label Foam::faMesh::nEdges() const noexcept
{
return nEdges_;
}
inline Foam::label Foam::faMesh::nInternalEdges() const noexcept
{
return nInternalEdges_;
}
inline Foam::label Foam::faMesh::nBoundaryEdges() const noexcept
{
return nEdges_ - nInternalEdges_;
}
inline Foam::label Foam::faMesh::nFaces() const noexcept
{
return nFaces_;
}
inline const Foam::pointField& Foam::faMesh::points() const
{
return patch().localPoints();
}
inline const Foam::edgeList& Foam::faMesh::edges() const noexcept
{
return edges_;
}
inline const Foam::faceList& Foam::faMesh::faces() const
{
return patch().localFaces();
}
inline const Foam::labelList& Foam::faMesh::edgeOwner() const noexcept
{
return edgeOwner_;
}
inline const Foam::labelList& Foam::faMesh::edgeNeighbour() const noexcept
{
return edgeNeighbour_;
}
inline const Foam::labelList& Foam::faMesh::faceLabels() const noexcept
{
return faceLabels_;
}
inline const Foam::uindirectPrimitivePatch& Foam::faMesh::patch() const
{
if (!patchPtr_)
{
initPatch();
}
return *patchPtr_;
}
inline Foam::uindirectPrimitivePatch& Foam::faMesh::patch()
{
if (!patchPtr_)
{
initPatch();
}
return *patchPtr_;
}
// ************************************************************************* //

View File

@ -0,0 +1,954 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017 Wikki Ltd
Copyright (C) 2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
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 "faMesh.H"
#include "IndirectList.H"
#include "faPatchData.H"
#include "processorPolyPatch.H"
#include "processorFaPatch.H"
#include "globalMeshData.H"
#include "indirectPrimitivePatch.H"
#include "edgeHashes.H"
#include "LabelledItem.H"
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam
{
// Manage patch pairs with a 'labelled' edge.
// The edge first/second correspond to the owner/neighbour patches.
// The index is a face index on the neighbour patch (FUTURE).
// Local typedefs
typedef LabelledItem<edge> patchPairInfo;
typedef List<patchPairInfo> patchPairInfoList;
typedef UIndirectList<patchPairInfo> patchPairInfoUIndList;
// Handling of dangling coupled edges.
// Tag values to "push" with special -(patchId+2)
struct combineDanglingEdge
{
const label upperLimit;
// Set dangling patchId from real patchId
static void setDangling(patchPairInfo& pairing, const label patchId)
{
pairing.first() = pairing.second() = -(patchId + 2);
pairing.setIndex(-1); // Invalidate
}
// Convert dangling patchId to real patchId
static void correct(patchPairInfo& pairing)
{
if (pairing.first() < -1)
{
pairing.first() = -(pairing.first() + 2);
}
if (pairing.second() < -1)
{
pairing.second() = -(pairing.second() + 2);
}
}
//- Construct with upper limit (the number of non-processor patches)
explicit combineDanglingEdge(const label nNonProcessor)
:
upperLimit(nNonProcessor)
{}
// Combine operation: overwrite unused or processor patches with
// 'dangling' patch information only
void operator()(patchPairInfo& x, const patchPairInfo& y) const
{
if (y.first() < -1 && edge::compare(x, y) == 0)
{
if (x.first() == -1 || x.first() >= upperLimit)
{
x.first() = y.first();
}
if (x.second() == -1 || x.second() >= upperLimit)
{
x.second() = y.first();
x.index() = y.index();
}
}
}
};
// Populate patch pairings according to the boundary edges
void findEdgePatchPairing
(
const polyBoundaryMesh& pbm,
const EdgeMap<label>& edgeToIndex,
patchPairInfoList& patchPairs,
label nMissing = -1
)
{
// Count how many slots (both sides) to be filled
if (nMissing < 0)
{
nMissing = 0;
for (const patchPairInfo& pairing : patchPairs)
{
if (pairing.first() == -1) ++nMissing;
if (pairing.second() == -1) ++nMissing;
}
}
forAll(pbm, patchID)
{
if (!nMissing) break; // Everything filled
const polyPatch& pp = pbm[patchID];
const bool isProcPatch = isA<processorPolyPatch>(pp);
// Examine neighbour boundary edges
for (label edgei = pp.nInternalEdges(); edgei < pp.nEdges(); ++edgei)
{
// Lookup global edge of this neighbour,
// find matching owner boundary edge
const label edgeIndex =
edgeToIndex.lookup(pp.meshEdge(edgei), -1);
if (edgeIndex != -1)
{
// Add patchId.
// - hash-like so will only insert once
// - also add in the attached patch face (there is only one),
// saved in mesh face numbering for processor patches
patchPairInfo& pairing = patchPairs[edgeIndex];
if (pairing.insert(patchID))
{
if (isProcPatch)
{
// Save the mesh face
const label patchFacei = pp.edgeFaces()[edgei][0];
pairing.index() = (pp.start() + patchFacei);
}
--nMissing;
if (!nMissing) break; // Early exit
}
}
}
}
}
} // End namespace Foam
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::faMesh::reorderProcEdges
(
faPatchData& patchDef,
const List<LabelledItem<edge>>& bndEdgePatchPairs
) const
{
if (!patchDef.coupled() || patchDef.edgeLabels_.empty())
{
return;
}
const polyBoundaryMesh& pbm = mesh().boundaryMesh();
const label procPatchID = patchDef.neighPolyPatchId_;
const auto* procPatch = isA<processorPolyPatch>(pbm[procPatchID]);
if (!procPatch)
{
FatalErrorInFunction
<< "Internal addressing error. Patch " << procPatchID
<< " is not a processor patch" << nl
<< abort(FatalError);
}
// Reorder processor edges using order of neighbour processorPolyPatch
const label nProcEdges = patchDef.edgeLabels_.size();
labelList procFaces(nProcEdges, -1);
forAll(procFaces, edgei)
{
const label bndEdgei =
(patchDef.edgeLabels_[edgei] - patch().nInternalEdges());
procFaces[edgei] = bndEdgePatchPairs[bndEdgei].index();
}
// Ascending proc-face numbering
const labelList sortIndices(Foam::sortedOrder(procFaces));
if (procFaces.size() && procFaces[sortIndices[0]] < 0)
{
FatalErrorInFunction
<< "Internal addressing error. Patch " << procPatchID
<< " with negative face" << nl
<< abort(FatalError);
}
const labelList& oldEdgeLabels = patchDef.edgeLabels_;
labelList newEdgeLabels(oldEdgeLabels.size());
// Most of the time, an individual proc-face will only be singly
// attached to the finite-area patch. In rarer case, there could
// multiple connections. For these cases, need to walk the face
// edges - the direction depends on owner vs neighbour side.
EdgeMap<label> multihit;
for (label edgei = 0; edgei < nProcEdges; /*nil*/)
{
const label meshFacei = procFaces[sortIndices[edgei]];
// Find all identical faces
label endEdgei = edgei + 1; // one beyond
while
(
(endEdgei < nProcEdges)
&& (meshFacei == procFaces[sortIndices[endEdgei]])
)
{
++endEdgei;
}
if (edgei + 1 == endEdgei)
{
// Simplest case - a single connection
newEdgeLabels[edgei] = oldEdgeLabels[sortIndices[edgei]];
}
else
{
multihit.clear();
// Map from global edge to patch local edgeId
for (label i = edgei; i < endEdgei; ++i)
{
const label patchEdgei = oldEdgeLabels[sortIndices[i]];
// The edge in mesh numbering
multihit.insert
(
patch().meshEdge(patchEdgei),
patchEdgei
);
}
if (multihit.size() != (endEdgei - edgei))
{
FatalErrorInFunction
<< "Could only hash " << multihit.size()
<< " edges from " << (endEdgei - edgei)
<< " ... indicates a non-manifold connection" << nl
<< multihit << nl
<< abort(FatalError);
}
const face& f = mesh().faces()[meshFacei];
forAll(f, fedgei) // Note size() == nEdges()
{
edge e =
(
patchDef.owner()
? f.edge(fedgei) // Forward walk
: f.rcEdge(fedgei) // Reverse walk
);
auto iter = multihit.find(e);
if (iter.found())
{
newEdgeLabels[edgei++] = iter.val();
multihit.erase(iter);
if (multihit.empty())
{
break;
}
}
}
if (edgei != endEdgei)
{
FatalErrorInFunction
<< "Missed " << (edgei < endEdgei)
<< " edges for face: " << meshFacei
<< " ... indicates serious geometry issue" << nl
<< multihit << nl
<< abort(FatalError);
}
if (!multihit.empty())
{
FatalErrorInFunction
<< "Missed edges for face: " << meshFacei
<< " ... indicates serious geometry issue" << nl
<< multihit << nl
<< abort(FatalError);
}
}
edgei = endEdgei;
}
patchDef.edgeLabels_.transfer(newEdgeLabels);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::faMesh::addFaPatches
(
PtrList<faPatch>& plist,
const bool validBoundary
)
{
if (!boundary().empty())
{
FatalErrorInFunction
<< "boundary already exists"
<< abort(FatalError);
}
globalMeshDataPtr_.reset(nullptr);
boundary_.transfer(plist);
setPrimitiveMeshData();
if (validBoundary)
{
boundary_.checkDefinition();
}
}
void Foam::faMesh::addFaPatches
(
const List<faPatch*>& p,
const bool validBoundary
)
{
// Acquire ownership of the pointers
PtrList<faPatch> plist(const_cast<List<faPatch*>&>(p));
addFaPatches(plist, validBoundary);
}
Foam::PtrList<Foam::faPatch> Foam::faMesh::createOnePatch
(
const word& patchName,
const word& patchType
) const
{
dictionary onePatchDict;
if (!patchName.empty())
{
onePatchDict.add("name", patchName);
}
if (!patchType.empty())
{
onePatchDict.add("type", patchType);
}
return createPatchList
(
dictionary::null,
word::null, // Name for empty patch placeholder
&onePatchDict // Definitions for defaultPatch
);
}
Foam::List<Foam::LabelledItem<Foam::edge>>
Foam::faMesh::getBoundaryEdgePatchPairs() const
{
const polyBoundaryMesh& pbm = mesh().boundaryMesh();
const label nInternalEdges = patch().nInternalEdges();
const label nBoundaryEdges = patch().nBoundaryEdges();
// Map edges (mesh numbering) back to a boundary index
EdgeMap<label> edgeToBoundaryIndex(2*nBoundaryEdges);
// Use labelled 'edge' for accounting of patch pairs
patchPairInfoList bndEdgePatchPairs(nBoundaryEdges);
// Pass 1:
// - setup lookup (edge -> bnd index)
// - add owner patch for each boundary edge
{
const SubList<labelList> bndEdgeToPatchFace
(
patch().edgeFaces(),
patch().nBoundaryEdges(),
patch().nInternalEdges()
);
for (label bndEdgei = 0; bndEdgei < nBoundaryEdges; ++bndEdgei)
{
edgeToBoundaryIndex.insert
(
patch().meshEdge(bndEdgei + nInternalEdges),
edgeToBoundaryIndex.size()
);
// The attached patch face (there is only one):
const label patchFacei = bndEdgeToPatchFace[bndEdgei][0];
const label meshFacei = faceLabels_[patchFacei];
const label patchId = pbm.whichPatch(meshFacei);
bndEdgePatchPairs[bndEdgei].insert(patchId);
}
}
// Pass 2:
// - Add in first neighbour patch for the boundary edges
// - examine all possible connecting neighbours
findEdgePatchPairing
(
pbm,
edgeToBoundaryIndex,
bndEdgePatchPairs,
edgeToBoundaryIndex.size() // Number of places to still fill
);
// Nothing dangling if running in serial - can return already
if (!Pstream::parRun())
{
return bndEdgePatchPairs;
}
// In parallel need to check for "dangling" edges, which are finiteArea
// boundary edges that only exist on one side of a proc boundary.
// Eg, proc boundary coincides with the outer extent of the finiteArea
const globalMeshData& globalData = mesh().globalData();
const indirectPrimitivePatch& cpp = globalData.coupledPatch();
const mapDistribute& map = globalData.globalEdgeSlavesMap();
// Construct coupled edge usage with all data
List<unsigned char> coupledEdgesUsed(map.constructSize(), 0u);
forAll(cpp.edges(), coupledEdgei)
{
const auto iter =
edgeToBoundaryIndex.cfind(cpp.meshEdge(coupledEdgei));
// Used from this side or other other side
coupledEdgesUsed[coupledEdgei] = (iter.found() ? 1 : 2);
}
// Save the original (pre-sync) coupling state
const List<unsigned char> coupledEdgesOrig(coupledEdgesUsed);
globalData.syncData
(
coupledEdgesUsed,
globalData.globalEdgeSlaves(),
globalData.globalEdgeTransformedSlaves(), // probably not used
map,
bitOrEqOp<unsigned char>()
);
// Check for one-sided edge coupling (coupled value == 3)
// original == 1:
// - coupled to a real finiteArea edge.
// - receive a patch-pair value
//
// original == 2:
// - a "dangled" edge. Information required for other procs.
// - push a patch-pair value
// Map edges (mesh numbering) back to a coupled index.
// These are the edges to 'push' information for.
EdgeMap<label> edgeToCoupledIndex;
label nEdgesPull = 0;
forAll(coupledEdgesUsed, coupledEdgei)
{
if (coupledEdgesUsed[coupledEdgei] == 3)
{
if (coupledEdgesOrig[coupledEdgei] == 1)
{
// Coupled side with finiteArea
++nEdgesPull;
}
else if (coupledEdgesOrig[coupledEdgei] == 2)
{
// Coupled side without finiteArea
edgeToCoupledIndex.insert
(
cpp.meshEdge(coupledEdgei),
coupledEdgei
);
}
}
}
// Nothing to do - can return already
if (returnReduce(edgeToCoupledIndex.empty(), andOp<bool>()))
{
return bndEdgePatchPairs;
}
// Data locations to pull
labelList patchEdgeLabels(nEdgesPull);
labelList coupledEdgeLabels(nEdgesPull);
// Populate the locations
{
nEdgesPull = 0;
forAll(cpp.edges(), coupledEdgei)
{
if
(
coupledEdgesUsed[coupledEdgei] == 3
&& coupledEdgesOrig[coupledEdgei] == 1
)
{
// Pull this edge
const auto iter =
edgeToBoundaryIndex.cfind(cpp.meshEdge(coupledEdgei));
if (iter.found())
{
patchEdgeLabels[nEdgesPull] = iter.val();
coupledEdgeLabels[nEdgesPull] = coupledEdgei;
++nEdgesPull;
}
else
{
// Should be impossible to fail here
FatalErrorInFunction
<< "Failed on second lookup of "
<< cpp.meshEdge(coupledEdgei) << nl
<< abort(FatalError);
}
}
}
if (nEdgesPull != coupledEdgeLabels.size())
{
FatalErrorInFunction
<< "Failed lookup of some coupled edges" << nl
<< abort(FatalError);
}
}
//- Construct edge sync with all data
patchPairInfoList cppEdgeData(map.constructSize());
// Fill in for 'push' locations. Only really interested in the owner
// (corresponds to non-proc connection), but grab everything
findEdgePatchPairing
(
pbm,
edgeToCoupledIndex,
cppEdgeData,
2*edgeToCoupledIndex.size() // Accept both sides?
);
const label nNonProcessor = pbm.nNonProcessor();
// Adjust patch information to reflect dangling patch neighbour
// Tag with -(value+2)
forAllConstIters(edgeToCoupledIndex, iter)
{
const edge& e = iter.key();
const label coupledEdgei = iter.val();
patchPairInfo& pairing = cppEdgeData[coupledEdgei];
const label ownerPatchId = pairing.first();
// Some sanity checks
if (ownerPatchId < 0)
{
FatalErrorInFunction
<< "Error finding dangling edge at "
<< cpp.points()[e.first()] << ' '
<< cpp.points()[e.second()] << nl
<< abort(FatalError);
}
else if (ownerPatchId >= nNonProcessor)
{
FatalErrorInFunction
<< "Cannot handle edge on processor-processor connection at "
<< cpp.points()[e.first()] << ' '
<< cpp.points()[e.second()] << nl
<< abort(FatalError);
}
combineDanglingEdge::setDangling(pairing, ownerPatchId);
// TBD:
// may wish to remember the corresponding proc number,
// if we wish to bridge across 'fan-like' connections.
//
// pairing.setIndex(-(Pstream::myProcNo() + 2));
}
// Synchronize edge information
const combineDanglingEdge edgeCombineOp(nNonProcessor);
globalMeshData::syncData
(
cppEdgeData,
globalData.globalEdgeSlaves(),
globalData.globalEdgeTransformedSlaves(), // probably not used
map,
edgeCombineOp
);
// Combine back from pushed cpp-edge data
forAll(patchEdgeLabels, i)
{
patchPairInfo& pairing = bndEdgePatchPairs[patchEdgeLabels[i]];
const patchPairInfo& other = cppEdgeData[coupledEdgeLabels[i]];
edgeCombineOp(pairing, other);
// Resolve special tagging
combineDanglingEdge::correct(pairing);
}
return bndEdgePatchPairs;
}
Foam::PtrList<Foam::faPatch> Foam::faMesh::createPatchList
(
const dictionary& bndDict,
const word& emptyPatchName,
const dictionary* defaultPatchDefinition
) const
{
const polyBoundaryMesh& pbm = mesh().boundaryMesh();
// Transcribe into patch definitions
DynamicList<faPatchData> faPatchDefs(bndDict.size() + 4);
for (const entry& dEntry : bndDict)
{
if (!dEntry.isDict())
{
WarningInFunction
<< "Not a dictionary entry: " << dEntry.name() << nl;
continue;
}
const dictionary& patchDict = dEntry.dict();
// Add entry
faPatchDefs.append(faPatchData());
auto& patchDef = faPatchDefs.last();
patchDef.name_ = dEntry.keyword();
patchDef.type_ = patchDict.get<word>("type");
const word ownName(patchDict.get<word>("ownerPolyPatch"));
const word neiName(patchDict.get<word>("neighbourPolyPatch"));
patchDef.ownerPolyPatchId_ = pbm.findPatchID(ownName);
patchDef.neighPolyPatchId_ = pbm.findPatchID(neiName);
if (patchDef.ownerPolyPatchId_ < 0)
{
FatalErrorInFunction
<< "ownerPolyPatch " << ownName << " not found"
<< exit(FatalError);
}
if (patchDef.neighPolyPatchId_ < 0)
{
FatalErrorInFunction
<< "neighbourPolyPatch " << neiName << " not found"
<< exit(FatalError);
}
}
// Additional empty placeholder patch?
if (!emptyPatchName.empty())
{
faPatchDefs.append(faPatchData());
auto& patchDef = faPatchDefs.last();
patchDef.name_ = emptyPatchName;
patchDef.type_ = "empty";
}
// Placeholder for any undefined edges
const label undefPatchId = faPatchDefs.size();
{
faPatchDefs.append(faPatchData());
auto& patchDef = faPatchDefs.last();
patchDef.name_ = "undefined";
patchDef.type_ = "patch";
if (defaultPatchDefinition)
{
(*defaultPatchDefinition).readIfPresent("name", patchDef.name_);
(*defaultPatchDefinition).readIfPresent("type", patchDef.type_);
}
}
// ----------------------------------------------------------------------
const label nInternalEdges = patch().nInternalEdges();
const label nBoundaryEdges = patch().nBoundaryEdges();
patchPairInfoList bndEdgePatchPairs(this->getBoundaryEdgePatchPairs());
labelList bndEdgeFaPatchIDs(nBoundaryEdges, -1);
for (label bndEdgei = 0; bndEdgei < nBoundaryEdges; ++bndEdgei)
{
const patchPairInfo& patchPair = bndEdgePatchPairs[bndEdgei];
if (patchPair.valid())
{
// Non-negative, unique pairing
// - find corresponding definition
for (label patchi = 0; patchi < faPatchDefs.size(); ++patchi)
{
if (faPatchDefs[patchi].foundPatchPair(patchPair))
{
bndEdgeFaPatchIDs[bndEdgei] = patchi;
break;
}
}
}
}
// Extract which edges map to which patch
// and set edgeLabels for each faPatch
DynamicList<label> selectEdges(bndEdgeFaPatchIDs.size());
for (label patchi = 0; patchi < faPatchDefs.size(); ++patchi)
{
auto& patchDef = faPatchDefs[patchi];
selectEdges.clear();
forAll(bndEdgeFaPatchIDs, bndEdgei)
{
if (bndEdgeFaPatchIDs[bndEdgei] == patchi)
{
selectEdges.append(bndEdgei + nInternalEdges);
}
}
patchDef.edgeLabels_ = selectEdges;
}
// Check for undefined edges
selectEdges.clear();
forAll(bndEdgeFaPatchIDs, bndEdgei)
{
if (bndEdgeFaPatchIDs[bndEdgei] == -1)
{
selectEdges.append(bndEdgei + nInternalEdges);
}
}
// Save the information
faPatchDefs[undefPatchId].edgeLabels_ = selectEdges;
bool hasUndefined = returnReduce(!selectEdges.empty(), orOp<bool>());
if (hasUndefined)
{
// The initial edges to consider
const labelList& undefinedEdges =
faPatchDefs[undefPatchId].edgeLabels_;
// Check for edges that butt against a processor (or other) patch
labelList edgeNbrPolyPatch(undefinedEdges.size(), -1);
forAll(edgeNbrPolyPatch, edgei)
{
const label patchEdgei = undefinedEdges[edgei];
const label bndEdgei = (patchEdgei - nInternalEdges);
edgeNbrPolyPatch[edgei] = bndEdgePatchPairs[bndEdgei].second();
}
// Categorize as processor/non-processor associations
labelHashSet procPatchIDs;
labelHashSet nonProcPatchIDs;
for (const label polyPatchID : edgeNbrPolyPatch)
{
if (polyPatchID == -1)
{
nonProcPatchIDs.insert(polyPatchID);
}
else if
(
!nonProcPatchIDs.found(polyPatchID)
&& !procPatchIDs.found(polyPatchID)
)
{
if (isA<processorPolyPatch>(pbm[polyPatchID]))
{
procPatchIDs.insert(polyPatchID);
}
else
{
nonProcPatchIDs.insert(polyPatchID);
}
}
}
// Select by processor association
for (const label polyPatchID : procPatchIDs.sortedToc())
{
selectEdges.clear();
forAll(edgeNbrPolyPatch, edgei)
{
if (edgeNbrPolyPatch[edgei] == polyPatchID)
{
selectEdges.append(undefinedEdges[edgei]);
}
}
faPatchDefs.append(faPatchData());
auto& patchDef = faPatchDefs.last();
patchDef.name_ = pbm[polyPatchID].name();
patchDef.type_ = processorFaPatch::typeName;
patchDef.neighPolyPatchId_ = polyPatchID; // Needed for reorder
const auto* ppp = isA<processorPolyPatch>(pbm[polyPatchID]);
if (ppp)
{
patchDef.ownerProcId_ = ppp->myProcNo();
patchDef.neighProcId_ = ppp->neighbProcNo();
}
patchDef.edgeLabels_ = selectEdges;
}
// Check for any remaining undefined edges
selectEdges.clear();
// Simply grab any/all (don't worry about which patch)
if (!nonProcPatchIDs.empty())
{
forAll(edgeNbrPolyPatch, edgei)
{
const label polyPatchID = edgeNbrPolyPatch[edgei];
if (nonProcPatchIDs.found(polyPatchID))
{
selectEdges.append(undefinedEdges[edgei]);
}
}
}
// Complete the information
faPatchDefs[undefPatchId].edgeLabels_ = selectEdges;
hasUndefined = returnReduce(!selectEdges.empty(), orOp<bool>());
}
// Remove unnecessary entry
if (!hasUndefined)
{
faPatchDefs.remove(undefPatchId);
}
for (auto& patchDef : faPatchDefs)
{
if (patchDef.coupled())
{
reorderProcEdges(patchDef, bndEdgePatchPairs);
patchDef.neighPolyPatchId_ = -1; // No lookup of neighbour faces
}
}
// Now convert list of definitions to list of patches
label nPatches = 0;
PtrList<faPatch> newPatches(faPatchDefs.size());
for (faPatchData& patchDef : faPatchDefs)
{
newPatches.set
(
nPatches,
faPatch::New
(
patchDef.name(), // name
patchDef.dict(false), // withEdgeLabels == false
nPatches, // index
boundary()
)
);
// Transfer edge labels
newPatches[nPatches].resetEdges(std::move(patchDef.edgeLabels_));
++nPatches;
}
return newPatches;
}
// ************************************************************************* //

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2020 OpenCFD Ltd. Copyright (C) 2020-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -61,11 +61,12 @@ void Foam::faMesh::updateMesh(const mapPolyMesh& mpm)
// Set new labels // Set new labels
m.faceLabels_ = mapper.areaMap().newFaceLabels(); m.faceLabels_ = mapper.areaMap().newFaceLabels();
const indirectPrimitivePatch& bp = patch(); const uindirectPrimitivePatch& bp = patch();
// Collect patch data // Collect patch data
const label nTotalEdges = bp.nEdges(); const label nTotalEdges = bp.nEdges();
const label nInternalEdges = bp.nInternalEdges(); const label nInternalEdges = bp.nInternalEdges();
const label nBoundaryEdges = bp.nBoundaryEdges();
const labelListList& edgeFaces = bp.edgeFaces(); const labelListList& edgeFaces = bp.edgeFaces();
labelListList patchEdges(boundary_.size()); labelListList patchEdges(boundary_.size());
@ -73,7 +74,7 @@ void Foam::faMesh::updateMesh(const mapPolyMesh& mpm)
// Special handling required for faces that have more than one edge // Special handling required for faces that have more than one edge
// Each patch will be visited separately // Each patch will be visited separately
labelList edgeToPatch(nTotalEdges - nInternalEdges, -1); labelList edgeToPatch(nBoundaryEdges, -1);
const labelList& newFaceLabelsMap = mapper.areaMap().newFaceLabelsMap(); const labelList& newFaceLabelsMap = mapper.areaMap().newFaceLabelsMap();
const labelListList& oldPatchEdgeFaces = mapper.oldPatchEdgeFaces(); const labelListList& oldPatchEdgeFaces = mapper.oldPatchEdgeFaces();
@ -81,7 +82,7 @@ void Foam::faMesh::updateMesh(const mapPolyMesh& mpm)
forAll(oldPatchEdgeFaces, patchI) forAll(oldPatchEdgeFaces, patchI)
{ {
labelList& curPatchEdges = patchEdges[patchI]; labelList& curPatchEdges = patchEdges[patchI];
curPatchEdges.setSize(nTotalEdges - nInternalEdges); curPatchEdges.resize(nBoundaryEdges);
label nCurPatchEdges = 0; label nCurPatchEdges = 0;
// Note: it is possible to pick up the old-to-new boundary patch // Note: it is possible to pick up the old-to-new boundary patch

View File

@ -117,10 +117,4 @@ void Foam::coupledFaPatch::calcTransformTensors
} }
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::coupledFaPatch::~coupledFaPatch()
{}
// ************************************************************************* // // ************************************************************************* //

View File

@ -135,7 +135,7 @@ public:
//- Destructor //- Destructor
virtual ~coupledFaPatch(); virtual ~coupledFaPatch() = default;
// Member Functions // Member Functions

View File

@ -28,19 +28,50 @@ License
#include "emptyFaPatch.H" #include "emptyFaPatch.H"
#include "addToRunTimeSelectionTable.H" #include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam namespace Foam
{ {
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Patch name // Patch name
defineTypeNameAndDebug(emptyFaPatch, 0); defineTypeNameAndDebug(emptyFaPatch, 0);
// Add the patch constructor functions to the hash tables // Add the patch constructor functions to the hash tables
addToRunTimeSelectionTable(faPatch, emptyFaPatch, dictionary); addToRunTimeSelectionTable(faPatch, emptyFaPatch, dictionary);
} // End namespace Foam
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::emptyFaPatch::emptyFaPatch
(
const word& name,
const label index,
const faBoundaryMesh& bm,
const label ngbPolyPatchIndex
)
:
emptyFaPatch(name, labelList(), index, bm, ngbPolyPatchIndex)
{}
Foam::emptyFaPatch::emptyFaPatch
(
const word& name,
const labelList& edgeLabels,
const label index,
const faBoundaryMesh& bm,
const label ngbPolyPatchIndex
)
:
faPatch(name, edgeLabels, index, bm, ngbPolyPatchIndex)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// Over-riding the face normals return from the underlying patch // Over-riding the face normals return from the underlying patch
// This is the only piece of info used out of the underlying primitivePatch // This is the only piece of info used out of the underlying primitivePatch
// I choose to store it there because it is used in primitive patch operations // I choose to store it there because it is used in primitive patch operations
@ -54,8 +85,4 @@ addToRunTimeSelectionTable(faPatch, emptyFaPatch, dictionary);
// } // }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* // // ************************************************************************* //

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -57,7 +58,6 @@ class emptyFaPatch
: :
public faPatch public faPatch
{ {
public: public:
//- Runtime type information //- Runtime type information
@ -66,6 +66,15 @@ public:
// Constructors // Constructors
//- Minimal construct from components
emptyFaPatch
(
const word& name,
const label index,
const faBoundaryMesh& bm,
const label ngbPolyPatchIndex = -1
);
//- Construct from components //- Construct from components
emptyFaPatch emptyFaPatch
( (
@ -74,10 +83,7 @@ public:
const label index, const label index,
const faBoundaryMesh& bm, const faBoundaryMesh& bm,
const label ngbPolyPatchIndex const label ngbPolyPatchIndex
) );
:
faPatch(name, edgeLabels, index, bm, ngbPolyPatchIndex)
{}
//- Construct from dictionary //- Construct from dictionary
emptyFaPatch emptyFaPatch
@ -114,6 +120,7 @@ public:
); );
} }
// Member Functions // Member Functions
virtual label size() const virtual label size() const
@ -124,7 +131,6 @@ public:
//- Return face normals. Over-riding base class return to get zero size //- Return face normals. Over-riding base class return to get zero size
// //
// virtual const vectorField& edgeNormals() const; // virtual const vectorField& edgeNormals() const;
}; };

View File

@ -122,7 +122,6 @@ protected:
public: public:
//- Runtime type information //- Runtime type information
// TypeName(processorPolyPatch::typeName_());
TypeName("processor"); TypeName("processor");
@ -174,7 +173,7 @@ public:
virtual ~processorFaPatch(); virtual ~processorFaPatch();
// Member functions // Member Functions
//- Return interface size //- Return interface size
virtual label interfaceSize() const virtual label interfaceSize() const

View File

@ -70,7 +70,7 @@ Foam::symmetryFaPatch::symmetryFaPatch
: :
faPatch(name, dict, index, bm) faPatch(name, dict, index, bm)
{ {
if (ngbPolyPatchIndex() == -1) if (ngbPolyPatchIndex() < 0)
{ {
FatalErrorInFunction FatalErrorInFunction
<< "Neighbour polyPatch index is not specified for faPatch " << "Neighbour polyPatch index is not specified for faPatch "

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -87,22 +88,21 @@ Foam::wedgeFaPatch::wedgeFaPatch
axisPoint_(-1), axisPoint_(-1),
axisPointChecked_(false) axisPointChecked_(false)
{ {
if (ngbPolyPatchIndex() == -1) if (ngbPolyPatchIndex() < 0)
{ {
FatalErrorInFunction FatalErrorInFunction
<< "Neighbour polyPatch index is not specified for faPatch " << "Neighbour polyPatch index is not specified for faPatch "
<< this->name() << exit(FatalError); << this->name() << exit(FatalError);
} }
if (isA<wedgePolyPatch>(bm.mesh()().boundaryMesh()[ngbPolyPatchIndex()])) const auto* wedgePtr = isA<wedgePolyPatch>
{
const wedgePolyPatch& wedge =
refCast<const wedgePolyPatch>
( (
bm.mesh()().boundaryMesh()[ngbPolyPatchIndex()] bm.mesh()().boundaryMesh()[ngbPolyPatchIndex()]
); );
wedgePolyPatchPtr_ = &wedge; if (wedgePtr)
{
wedgePolyPatchPtr_ = wedgePtr;
} }
else else
{ {

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2019-2020 OpenCFD Ltd. Copyright (C) 2019-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -21,7 +21,7 @@ License
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details. for more details.
// You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -68,7 +68,7 @@ Foam::faPatch::faPatch
: :
labelList(edgeLabels), labelList(edgeLabels),
patchIdentifier(name, index), patchIdentifier(name, index),
ngbPolyPatchIndex_(ngbPolyPatchIndex), nbrPolyPatchId_(ngbPolyPatchIndex),
boundaryMesh_(bm), boundaryMesh_(bm),
edgeFacesPtr_(nullptr), edgeFacesPtr_(nullptr),
pointLabelsPtr_(nullptr), pointLabelsPtr_(nullptr),
@ -86,7 +86,7 @@ Foam::faPatch::faPatch
: :
labelList(dict.get<labelList>("edgeLabels")), labelList(dict.get<labelList>("edgeLabels")),
patchIdentifier(name, dict, index), patchIdentifier(name, dict, index),
ngbPolyPatchIndex_(dict.get<label>("ngbPolyPatchIndex")), nbrPolyPatchId_(dict.get<label>("ngbPolyPatchIndex")),
boundaryMesh_(bm), boundaryMesh_(bm),
edgeFacesPtr_(nullptr), edgeFacesPtr_(nullptr),
pointLabelsPtr_(nullptr), pointLabelsPtr_(nullptr),
@ -98,7 +98,7 @@ Foam::faPatch::faPatch(const faPatch& p, const faBoundaryMesh& bm)
: :
labelList(p), labelList(p),
patchIdentifier(p, p.index()), patchIdentifier(p, p.index()),
ngbPolyPatchIndex_(p.ngbPolyPatchIndex_), nbrPolyPatchId_(p.nbrPolyPatchId_),
boundaryMesh_(bm), boundaryMesh_(bm),
edgeFacesPtr_(nullptr), edgeFacesPtr_(nullptr),
pointLabelsPtr_(nullptr), pointLabelsPtr_(nullptr),
@ -116,13 +116,13 @@ Foam::faPatch::~faPatch()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::label Foam::faPatch::ngbPolyPatchIndex() const Foam::label Foam::faPatch::ngbPolyPatchIndex() const noexcept
{ {
return ngbPolyPatchIndex_; return nbrPolyPatchId_;
} }
const Foam::faBoundaryMesh& Foam::faPatch::boundaryMesh() const const Foam::faBoundaryMesh& Foam::faPatch::boundaryMesh() const noexcept
{ {
return boundaryMesh_; return boundaryMesh_;
} }
@ -240,38 +240,22 @@ const Foam::labelListList& Foam::faPatch::pointEdges() const
Foam::labelList Foam::faPatch::ngbPolyPatchFaces() const Foam::labelList Foam::faPatch::ngbPolyPatchFaces() const
{ {
labelList ngbFaces; if (nbrPolyPatchId_ < 0)
if (ngbPolyPatchIndex() == -1)
{ {
return ngbFaces; return labelList();
} }
ngbFaces.setSize(faPatch::size()); labelList ngbFaces(faPatch::size());
const faMesh& aMesh = boundaryMesh().mesh(); const faMesh& aMesh = boundaryMesh().mesh();
const polyMesh& pMesh = aMesh(); const polyMesh& pMesh = aMesh.mesh();
const indirectPrimitivePatch& patch = aMesh.patch(); const auto& patch = aMesh.patch();
const labelListList& edgeFaces = pMesh.edgeFaces(); const labelListList& edgeFaces = pMesh.edgeFaces();
labelList faceCells(patch.size(), -1); const labelList meshEdges
forAll(faceCells, faceI)
{
label faceID = aMesh.faceLabels()[faceI];
faceCells[faceI] = pMesh.faceOwner()[faceID];
}
labelList meshEdges
( (
patch.meshEdges patch.meshEdges(pMesh.edges(), pMesh.pointEdges())
(
pMesh.edges(),
pMesh.cellEdges(),
faceCells
)
); );
forAll(ngbFaces, edgeI) forAll(ngbFaces, edgeI)
@ -288,7 +272,7 @@ Foam::labelList Foam::faPatch::ngbPolyPatchFaces() const
label curPatchID = pMesh.boundaryMesh().whichPatch(curFace); label curPatchID = pMesh.boundaryMesh().whichPatch(curFace);
if (curPatchID == ngbPolyPatchIndex()) if (curPatchID == nbrPolyPatchId_)
{ {
ngbFaces[edgeI] = curFace; ngbFaces[edgeI] = curFace;
} }
@ -308,14 +292,14 @@ Foam::labelList Foam::faPatch::ngbPolyPatchFaces() const
Foam::tmp<Foam::vectorField> Foam::faPatch::ngbPolyPatchFaceNormals() const Foam::tmp<Foam::vectorField> Foam::faPatch::ngbPolyPatchFaceNormals() const
{ {
if (nbrPolyPatchId_ < 0)
{
return tmp<vectorField>::New();
}
auto tfN = tmp<vectorField>::New(); auto tfN = tmp<vectorField>::New();
auto& fN = tfN.ref(); auto& fN = tfN.ref();
if (ngbPolyPatchIndex() == -1)
{
return tfN;
}
fN.setSize(faPatch::size()); fN.setSize(faPatch::size());
labelList ngbFaces = ngbPolyPatchFaces(); labelList ngbFaces = ngbPolyPatchFaces();
@ -336,7 +320,7 @@ Foam::tmp<Foam::vectorField> Foam::faPatch::ngbPolyPatchFaceNormals() const
Foam::tmp<Foam::vectorField> Foam::faPatch::ngbPolyPatchPointNormals() const Foam::tmp<Foam::vectorField> Foam::faPatch::ngbPolyPatchPointNormals() const
{ {
if (ngbPolyPatchIndex() == -1) if (nbrPolyPatchId_ < 0)
{ {
return tmp<vectorField>::New(); return tmp<vectorField>::New();
} }
@ -468,12 +452,17 @@ void Foam::faPatch::movePoints(const pointField& points)
{} {}
void Foam::faPatch::resetEdges(const labelList& newEdges) void Foam::faPatch::resetEdges(const UList<label>& newEdges)
{ {
Info<< "Resetting patch edges" << endl;
labelList::operator=(newEdges);
clearOut(); clearOut();
static_cast<labelList&>(*this) = newEdges;
}
void Foam::faPatch::resetEdges(labelList&& newEdges)
{
clearOut();
static_cast<labelList&>(*this) = std::move(newEdges);
} }
@ -483,9 +472,8 @@ void Foam::faPatch::write(Ostream& os) const
patchIdentifier::write(os); patchIdentifier::write(os);
const labelList& edgeLabels = *this; os.writeEntry("ngbPolyPatchIndex", nbrPolyPatchId_);
edgeLabels.writeEntry("edgeLabels", os); static_cast<const labelList&>(*this).writeEntry("edgeLabels", os);
os.writeEntry("ngbPolyPatchIndex", ngbPolyPatchIndex_);
} }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2020 OpenCFD Ltd. Copyright (C) 2020-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -58,6 +58,7 @@ SourceFiles
namespace Foam namespace Foam
{ {
// Forward Declarations
class faBoundaryMesh; class faBoundaryMesh;
class faPatch; class faPatch;
Ostream& operator<<(Ostream&, const faPatch&); Ostream& operator<<(Ostream&, const faPatch&);
@ -74,7 +75,7 @@ class faPatch
// Private Data // Private Data
//- Neighbour polyPatch index //- Neighbour polyPatch index
const label ngbPolyPatchIndex_; const label nbrPolyPatchId_;
//- Reference to boundary mesh //- Reference to boundary mesh
const faBoundaryMesh& boundaryMesh_; const faBoundaryMesh& boundaryMesh_;
@ -100,7 +101,6 @@ class faPatch
//- No copy assignment //- No copy assignment
void operator=(const faPatch&) = delete; void operator=(const faPatch&) = delete;
//- Clear out topological patch data //- Clear out topological patch data
void clearOut(); void clearOut();
@ -225,17 +225,31 @@ public:
// Member Functions // Member Functions
//- Return number of patch points //- Return the list of edges
const labelList& edgeLabels() const noexcept
{
return static_cast<const labelList&>(*this);
}
void edgeLabels(const UList<label>& newEdgeLabels);
//- Number of patch points
label nPoints() const label nPoints() const
{ {
return pointLabels().size(); return pointLabels().size();
} }
//- Number of edge labels (boundary edges) addressed by this patch
label nEdges() const noexcept
{
return labelList::size();
}
//- Return neighbour polyPatch index //- Return neighbour polyPatch index
label ngbPolyPatchIndex() const; label ngbPolyPatchIndex() const noexcept;
//- Return boundaryMesh reference //- Return boundaryMesh reference
const faBoundaryMesh& boundaryMesh() const; const faBoundaryMesh& boundaryMesh() const noexcept;
//- Return true if this patch is coupled //- Return true if this patch is coupled
virtual bool coupled() const virtual bool coupled() const
@ -246,7 +260,7 @@ public:
//- Patch start in edge list //- Patch start in edge list
label start() const; label start() const;
//- Patch size //- Patch size is the number of edge labels
virtual label size() const virtual label size() const
{ {
return labelList::size(); return labelList::size();
@ -330,8 +344,11 @@ public:
// Topological changes // Topological changes
//- Reset edge list //- Reset the list of edges (use with caution)
void resetEdges(const labelList&); void resetEdges(const UList<label>& newEdges);
//- Reset the list of edges (use with caution)
void resetEdges(labelList&& newEdges);
// Evaluation // Evaluation

View File

@ -0,0 +1,130 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
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 "faPatchData.H"
#include "edge.H"
#include "dictionary.H"
#include "processorFaPatch.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::faPatchData::faPatchData()
:
ownerPolyPatchId_(-1),
neighPolyPatchId_(-1),
ownerProcId_(-1),
neighProcId_(-1)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::word& Foam::faPatchData::name() const noexcept
{
return name_;
}
Foam::dictionary Foam::faPatchData::dict(const bool withEdgeLabels) const
{
dictionary patchDict;
patchDict.add("type", type_);
if (withEdgeLabels)
{
patchDict.add("edgeLabels", edgeLabels_);
}
else
{
patchDict.add("edgeLabels", labelList());
}
patchDict.add("ngbPolyPatchIndex", neighPolyPatchId_);
if (coupled())
{
patchDict.add("myProcNo", ownerProcId_);
patchDict.add("neighbProcNo", neighProcId_);
}
return patchDict;
}
void Foam::faPatchData::clear()
{
name_.clear();
type_.clear();
ownerPolyPatchId_ = -1;
neighPolyPatchId_ = -1;
ownerProcId_ = -1;
neighProcId_ = -1;
edgeLabels_.clear();
}
void Foam::faPatchData::assign(const faPatch& fap)
{
clear();
// Copy information
name_ = fap.name();
type_ = fap.type();
neighPolyPatchId_ = fap.ngbPolyPatchIndex();
edgeLabels_ = fap.edgeLabels();
const auto* fapp = isA<processorFaPatch>(fap);
if (fapp)
{
ownerProcId_ = fapp->myProcNo();
neighProcId_ = fapp->neighbProcNo();
}
}
bool Foam::faPatchData::foundPatchPair(const edge& patchPair) const
{
// Same as edge::compare
return
(
(
ownerPolyPatchId_ == patchPair.first()
&& neighPolyPatchId_ == patchPair.second()
)
||
(
ownerPolyPatchId_ == patchPair.second()
&& neighPolyPatchId_ == patchPair.first()
)
);
}
// ************************************************************************* //

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -27,7 +28,8 @@ Class
Foam::faPatchData Foam::faPatchData
Description Description
Class which holds data needed for faPatch construction Helper class for holding data during faPatch construction.
Most data members are exposed at the moment.
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -41,25 +43,81 @@ Description
namespace Foam namespace Foam
{ {
// Forward Declarations
class edge;
class faPatch;
class dictionary;
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class faPatchData Declaration Class faPatchData Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
struct faPatchData class faPatchData
{ {
public:
// Data Members
word name_; word name_;
word type_; word type_;
dictionary dict_;
label ownPolyPatchID_; label ownerPolyPatchId_;
label ngbPolyPatchID_; label neighPolyPatchId_;
//- The owner/neighbour for processor patches
int ownerProcId_;
int neighProcId_;
// Storge (temporary or otherwise) for edge labels
labelList edgeLabels_; labelList edgeLabels_;
faPatchData()
:
name_(word::null), // Constructors
type_(word::null),
ownPolyPatchID_(-1), //- Default construct
ngbPolyPatchID_(-1) faPatchData();
{}
// Member Functions
// Opaque read-only access
//- Return the name
const word& name() const noexcept;
//- Contents transcribed into a patch dictionary,
//- usually including the edge labels.
dictionary dict(const bool withEdgeLabels = true) const;
// Other Functions
//- Reset data
void clear();
//- Clear and populate with values from finiteArea patch
void assign(const faPatch& fap);
//- True if owner/neighbour processor ids are non-equal
bool coupled() const noexcept
{
return (ownerProcId_ != neighProcId_);
}
//- Does this side own the patch? Also true for non-coupled patches
bool owner() const noexcept
{
return (ownerProcId_ <= neighProcId_);
}
//- Does the other side own the patch?
bool neighbour() const noexcept
{
return !owner();
}
//- True it matches the owner/neighbour patch pair (any order)
bool foundPatchPair(const edge& patchPair) const;
}; };

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -39,10 +40,8 @@ const typename GeometricField::Patch& Foam::faPatch::lookupPatchField
{ {
return patchField<GeometricField, Type> return patchField<GeometricField, Type>
( (
boundaryMesh().mesh()().objectRegistry::lookupObject<GeometricField> boundaryMesh().mesh().mesh().objectRegistry::template
( lookupObject<GeometricField>(name)
name
)
); );
} }

View File

@ -58,9 +58,9 @@ Foam::fv::option::option
mesh_(mesh), mesh_(mesh),
dict_(dict), dict_(dict),
coeffs_(dict.optionalSubDict(modelType + "Coeffs")), coeffs_(dict.optionalSubDict(modelType + "Coeffs")),
active_(dict_.getOrDefault<Switch>("active", true)),
fieldNames_(), fieldNames_(),
applied_(), applied_(),
active_(dict_.getOrDefault("active", true)),
log(true) log(true)
{ {
Log << incrIndent << indent << "Source: " << name_ << endl << decrIndent; Log << incrIndent << indent << "Source: " << name_ << endl << decrIndent;
@ -101,7 +101,7 @@ Foam::autoPtr<Foam::fv::option> Foam::fv::option::New
) << exit(FatalIOError); ) << exit(FatalIOError);
} }
return autoPtr<option>(cstrIter()(name, modelType, coeffs, mesh)); return autoPtr<fv::option>(cstrIter()(name, modelType, coeffs, mesh));
} }

View File

@ -113,23 +113,25 @@ protected:
//- Dictionary containing source coefficients //- Dictionary containing source coefficients
dictionary coeffs_; dictionary coeffs_;
//- Source active flag
Switch active_;
//- Field names to apply source to - populated by derived models //- Field names to apply source to - populated by derived models
wordList fieldNames_; wordList fieldNames_;
//- Applied flag list - corresponds to each fieldNames_ entry //- Applied flag list - corresponds to each fieldNames_ entry
List<bool> applied_; List<bool> applied_;
//- Source active flag
bool active_;
public: public:
//- Switch write log to Info
bool log;
//- Runtime type information //- Runtime type information
TypeName("option"); TypeName("option");
//- Switch write log to Info
bool log;
// Declare run-time constructor selection table // Declare run-time constructor selection table
@ -219,16 +221,16 @@ public:
// Access // Access
//- Return const access to the source name //- Return const access to the source name
inline const word& name() const; inline const word& name() const noexcept;
//- Return const access to the mesh database //- Return const access to the mesh database
inline const fvMesh& mesh() const; inline const fvMesh& mesh() const noexcept;
//- Return dictionary //- Return dictionary
inline const dictionary& coeffs() const; inline const dictionary& coeffs() const noexcept;
//- Return const access to the source active flag //- True if source is active
inline bool active() const; inline bool active() const noexcept;
//- Set the applied flag to true for field index fieldi //- Set the applied flag to true for field index fieldi
inline void setApplied(const label fieldi); inline void setApplied(const label fieldi);
@ -236,8 +238,8 @@ public:
// Edit // Edit
//- Return access to the source active flag //- Change source active flag, return previous value
inline Switch& active(); inline bool active(const bool on) noexcept;
// Checks // Checks

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -27,40 +28,42 @@ License
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline const Foam::word& Foam::fv::option::name() const inline const Foam::word& Foam::fv::option::name() const noexcept
{ {
return name_; return name_;
} }
inline const Foam::fvMesh& Foam::fv::option::mesh() const inline const Foam::fvMesh& Foam::fv::option::mesh() const noexcept
{ {
return mesh_; return mesh_;
} }
inline const Foam::dictionary& Foam::fv::option::coeffs() const inline const Foam::dictionary& Foam::fv::option::coeffs() const noexcept
{ {
return coeffs_; return coeffs_;
} }
inline bool Foam::fv::option::active() const inline bool Foam::fv::option::active() const noexcept
{ {
return active_; return active_;
} }
inline bool Foam::fv::option::active(const bool on) noexcept
{
bool old(active_);
active_ = on;
return old;
}
inline void Foam::fv::option::setApplied(const label fieldi) inline void Foam::fv::option::setApplied(const label fieldi)
{ {
applied_[fieldi] = true; applied_[fieldi] = true;
} }
inline Foam::Switch& Foam::fv::option::active()
{
return active_;
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -89,7 +89,7 @@ void Foam::fv::optionList::checkApplied() const
Foam::fv::optionList::optionList(const fvMesh& mesh, const dictionary& dict) Foam::fv::optionList::optionList(const fvMesh& mesh, const dictionary& dict)
: :
PtrList<option>(), PtrList<fv::option>(),
mesh_(mesh), mesh_(mesh),
checkTimeIndex_(mesh_.time().startTimeIndex() + 2) checkTimeIndex_(mesh_.time().startTimeIndex() + 2)
{ {
@ -99,7 +99,7 @@ Foam::fv::optionList::optionList(const fvMesh& mesh, const dictionary& dict)
Foam::fv::optionList::optionList(const fvMesh& mesh) Foam::fv::optionList::optionList(const fvMesh& mesh)
: :
PtrList<option>(), PtrList<fv::option>(),
mesh_(mesh), mesh_(mesh),
checkTimeIndex_(mesh_.time().startTimeIndex() + 2) checkTimeIndex_(mesh_.time().startTimeIndex() + 2)
{} {}

View File

@ -69,7 +69,7 @@ namespace fv
class optionList class optionList
: :
public PtrList<option> public PtrList<fv::option>
{ {
protected: protected:

View File

@ -117,7 +117,7 @@ namespace fv
class cellSetOption class cellSetOption
: :
public option public fv::option
{ {
public: public:

View File

@ -87,7 +87,7 @@ namespace fv
class interRegionOption class interRegionOption
: :
public option public fv::option
{ {
protected: protected:

View File

@ -118,7 +118,7 @@ namespace fv
class buoyancyEnergy class buoyancyEnergy
: :
public option public fv::option
{ {
// Private Data // Private Data

View File

@ -110,7 +110,7 @@ namespace fv
class buoyancyForce class buoyancyForce
: :
public option public fv::option
{ {
// Private Data // Private Data

View File

@ -175,7 +175,7 @@ namespace fv
class jouleHeatingSource class jouleHeatingSource
: :
public option public fv::option
{ {
// Private Data // Private Data

View File

@ -133,7 +133,7 @@ namespace fv
class multiphaseStabilizedTurbulence class multiphaseStabilizedTurbulence
: :
public option public fv::option
{ {
// Private Data // Private Data

View File

@ -108,7 +108,7 @@ namespace fv
template<class Type> template<class Type>
class PhaseLimitStabilization class PhaseLimitStabilization
: :
public option public fv::option
{ {
// Private Data // Private Data

View File

@ -87,7 +87,7 @@ namespace fv
class tabulatedAccelerationSource class tabulatedAccelerationSource
: :
public option public fv::option
{ {
protected: protected:

View File

@ -111,7 +111,7 @@ namespace fv
class viscousDissipation class viscousDissipation
: :
public option public fv::option
{ {
// Private Data // Private Data

View File

@ -8,6 +8,7 @@ wclean kahipDecomp
wclean scotchDecomp wclean scotchDecomp
wclean decompositionMethods wclean decompositionMethods
wclean decompose wclean decompose
wclean faDecompose
./Allwclean-mpi ./Allwclean-mpi

View File

@ -12,6 +12,7 @@ export FOAM_EXT_LIBBIN
wmake $targetType decompositionMethods wmake $targetType decompositionMethods
wmake $targetType decompose wmake $targetType decompose
wmake $targetType faDecompose
if have_kahip if have_kahip
then then

View File

@ -1,5 +1,8 @@
decompositionInformation.C decompositionInformation.C
decompositionModel.C decompositionModel.C
dimFieldDecomposer.C
fvFieldDecomposer.C fvFieldDecomposer.C
pointFieldDecomposer.C
LIB = $(FOAM_LIBBIN)/libdecompose LIB = $(FOAM_LIBBIN)/libdecompose

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -27,27 +28,30 @@ License
#include "dimFieldDecomposer.H" #include "dimFieldDecomposer.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::dimFieldDecomposer::dimFieldDecomposer Foam::dimFieldDecomposer::dimFieldDecomposer
( (
const fvMesh& completeMesh,
const fvMesh& procMesh, const fvMesh& procMesh,
const labelList& faceAddressing,
const labelList& cellAddressing const labelList& cellAddressing
) )
: :
completeMesh_(completeMesh),
procMesh_(procMesh), procMesh_(procMesh),
faceAddressing_(faceAddressing),
cellAddressing_(cellAddressing) cellAddressing_(cellAddressing)
{} {}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // Foam::dimFieldDecomposer::dimFieldDecomposer
(
Foam::dimFieldDecomposer::~dimFieldDecomposer() const fvMesh& /* unused: completeMesh */,
const fvMesh& procMesh,
const labelList& /* unused: faceAddressing */,
const labelList& cellAddressing
)
:
procMesh_(procMesh),
//UNUSED: faceAddressing_(faceAddressing),
cellAddressing_(cellAddressing)
{} {}

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -31,7 +32,7 @@ Description
SourceFiles SourceFiles
dimFieldDecomposer.C dimFieldDecomposer.C
dimFieldDecomposerDecomposeFields.C dimFieldDecomposerFields.C
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -46,32 +47,25 @@ SourceFiles
namespace Foam namespace Foam
{ {
class IOobjectList;
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class fvFieldDecomposer Declaration Class fvFieldDecomposer Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
class dimFieldDecomposer class dimFieldDecomposer
{ {
private: // Private Data
// Private data
//- Reference to complete mesh
const fvMesh& completeMesh_;
//- Reference to processor mesh //- Reference to processor mesh
const fvMesh& procMesh_; const fvMesh& procMesh_;
//- Reference to face addressing //- Reference to face addressing
const labelList& faceAddressing_; //UNUSED: const labelList& faceAddressing_;
//- Reference to cell addressing //- Reference to cell addressing
const labelList& cellAddressing_; const labelList& cellAddressing_;
// Private Member Functions public:
//- No copy construct //- No copy construct
dimFieldDecomposer(const dimFieldDecomposer&) = delete; dimFieldDecomposer(const dimFieldDecomposer&) = delete;
@ -80,35 +74,41 @@ private:
void operator=(const dimFieldDecomposer&) = delete; void operator=(const dimFieldDecomposer&) = delete;
public:
// Constructors // Constructors
//- Construct from components //- Construct from minimal components
dimFieldDecomposer dimFieldDecomposer
( (
const fvMesh& completeMesh,
const fvMesh& procMesh, const fvMesh& procMesh,
const labelList& faceAddressing, const labelList& cellAddressing
);
//- Construct from components with API as per fvFieldDecomposer
dimFieldDecomposer
(
const fvMesh& completeMesh, //!< unused
const fvMesh& procMesh,
const labelList& faceAddressing, //!< unused
const labelList& cellAddressing const labelList& cellAddressing
); );
//- Destructor //- Destructor
~dimFieldDecomposer(); ~dimFieldDecomposer() = default;
// Member Functions // Member Functions
//- Decompose field //- Decompose field
template<class Type> template<class Type>
tmp<DimensionedField<Type, volMesh>> decomposeField tmp<DimensionedField<Type, volMesh>>
decomposeField
( (
const DimensionedField<Type, volMesh>& field const DimensionedField<Type, volMesh>& field
) const; ) const;
//- Decompose llist of fields //- Decompose list of fields
template<class GeoField> template<class GeoField>
void decomposeFields(const PtrList<GeoField>& fields) const; void decomposeFields(const PtrList<GeoField>& fields) const;
}; };
@ -121,7 +121,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository #ifdef NoRepository
#include "dimFieldDecomposerDecomposeFields.C" #include "dimFieldDecomposerFields.C"
#endif #endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -40,9 +41,8 @@ Foam::dimFieldDecomposer::decomposeField
Field<Type> mappedField(field, cellAddressing_); Field<Type> mappedField(field, cellAddressing_);
// Create the field for the processor // Create the field for the processor
return tmp<DimensionedField<Type, volMesh>> return
( tmp<DimensionedField<Type, volMesh>>::New
new DimensionedField<Type, volMesh>
( (
IOobject IOobject
( (
@ -55,8 +55,7 @@ Foam::dimFieldDecomposer::decomposeField
), ),
procMesh_, procMesh_,
field.dimensions(), field.dimensions(),
mappedField std::move(mappedField)
)
); );
} }
@ -67,9 +66,9 @@ void Foam::dimFieldDecomposer::decomposeFields
const PtrList<GeoField>& fields const PtrList<GeoField>& fields
) const ) const
{ {
forAll(fields, fieldi) for (const auto& fld : fields)
{ {
decomposeField(fields[fieldi])().write(); decomposeField(fld)().write();
} }
} }

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -27,7 +28,6 @@ License
#include "fvFieldDecomposer.H" #include "fvFieldDecomposer.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fvFieldDecomposer::patchFieldDecomposer::patchFieldDecomposer Foam::fvFieldDecomposer::patchFieldDecomposer::patchFieldDecomposer
@ -49,21 +49,19 @@ Foam::fvFieldDecomposer::patchFieldDecomposer::patchFieldDecomposer
Foam::fvFieldDecomposer::processorVolPatchFieldDecomposer:: Foam::fvFieldDecomposer::processorVolPatchFieldDecomposer::
processorVolPatchFieldDecomposer processorVolPatchFieldDecomposer
( (
const fvMesh& mesh, const labelUList& owner, // == mesh.faceOwner()
const labelUList& neigh, // == mesh.faceNeighbour()
const labelUList& addressingSlice const labelUList& addressingSlice
) )
: :
directAddressing_(addressingSlice.size()) directAddressing_(addressingSlice.size())
{ {
const labelList& own = mesh.faceOwner();
const labelList& neighb = mesh.faceNeighbour();
forAll(directAddressing_, i) forAll(directAddressing_, i)
{ {
// Subtract one to align addressing. // Subtract one to align addressing.
label ai = mag(addressingSlice[i]) - 1; label ai = mag(addressingSlice[i]) - 1;
if (ai < neighb.size()) if (ai < neigh.size())
{ {
// This is a regular face. it has been an internal face // This is a regular face. it has been an internal face
// of the original mesh and now it has become a face // of the original mesh and now it has become a face
@ -73,11 +71,11 @@ processorVolPatchFieldDecomposer
if (addressingSlice[i] >= 0) if (addressingSlice[i] >= 0)
{ {
// I have the owner so use the neighbour value // I have the owner so use the neighbour value
directAddressing_[i] = neighb[ai]; directAddressing_[i] = neigh[ai];
} }
else else
{ {
directAddressing_[i] = own[ai]; directAddressing_[i] = owner[ai];
} }
} }
else else
@ -88,12 +86,28 @@ processorVolPatchFieldDecomposer
// up the different (face) list of data), so I will // up the different (face) list of data), so I will
// just grab the value from the owner cell // just grab the value from the owner cell
directAddressing_[i] = own[ai]; directAddressing_[i] = owner[ai];
} }
} }
} }
Foam::fvFieldDecomposer::processorVolPatchFieldDecomposer::
processorVolPatchFieldDecomposer
(
const fvMesh& mesh,
const labelUList& addressingSlice
)
:
processorVolPatchFieldDecomposer
(
mesh.faceOwner(),
mesh.faceNeighbour(),
addressingSlice
)
{}
Foam::fvFieldDecomposer::processorSurfacePatchFieldDecomposer:: Foam::fvFieldDecomposer::processorSurfacePatchFieldDecomposer::
processorSurfacePatchFieldDecomposer processorSurfacePatchFieldDecomposer
( (
@ -105,8 +119,8 @@ processorSurfacePatchFieldDecomposer
{ {
forAll(addressing_, i) forAll(addressing_, i)
{ {
addressing_[i].setSize(1); addressing_[i].resize(1);
weights_[i].setSize(1); weights_[i].resize(1);
addressing_[i][0] = mag(addressingSlice[i]) - 1; addressing_[i][0] = mag(addressingSlice[i]) - 1;
weights_[i][0] = 1; weights_[i][0] = 1;
@ -114,6 +128,27 @@ processorSurfacePatchFieldDecomposer
} }
Foam::fvFieldDecomposer::fvFieldDecomposer
(
const Foam::zero,
const fvMesh& procMesh,
const labelList& faceAddressing,
const labelList& cellAddressing,
const labelList& boundaryAddressing
)
:
procMesh_(procMesh),
faceAddressing_(faceAddressing),
cellAddressing_(cellAddressing),
boundaryAddressing_(boundaryAddressing),
// Mappers
patchFieldDecomposerPtrs_(),
processorVolPatchFieldDecomposerPtrs_(),
processorSurfacePatchFieldDecomposerPtrs_(),
faceSign_()
{}
Foam::fvFieldDecomposer::fvFieldDecomposer Foam::fvFieldDecomposer::fvFieldDecomposer
( (
const fvMesh& completeMesh, const fvMesh& completeMesh,
@ -123,24 +158,85 @@ Foam::fvFieldDecomposer::fvFieldDecomposer
const labelList& boundaryAddressing const labelList& boundaryAddressing
) )
: :
completeMesh_(completeMesh), fvFieldDecomposer
procMesh_(procMesh), (
faceAddressing_(faceAddressing), zero{},
cellAddressing_(cellAddressing), procMesh,
boundaryAddressing_(boundaryAddressing), faceAddressing,
patchFieldDecomposerPtrs_(procMesh_.boundary().size()), cellAddressing,
processorVolPatchFieldDecomposerPtrs_(procMesh_.boundary().size()), boundaryAddressing
processorSurfacePatchFieldDecomposerPtrs_(procMesh_.boundary().size()), )
faceSign_(procMesh_.boundary().size())
{ {
reset(completeMesh);
}
Foam::fvFieldDecomposer::fvFieldDecomposer
(
const List<labelRange>& boundaryRanges,
const labelUList& faceOwner,
const labelUList& faceNeighbour,
const fvMesh& procMesh,
const labelList& faceAddressing,
const labelList& cellAddressing,
const labelList& boundaryAddressing
)
:
fvFieldDecomposer
(
zero{},
procMesh,
faceAddressing,
cellAddressing,
boundaryAddressing
)
{
reset(boundaryRanges, faceOwner, faceNeighbour);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::fvFieldDecomposer::empty() const
{
return patchFieldDecomposerPtrs_.empty();
}
void Foam::fvFieldDecomposer::clear()
{
patchFieldDecomposerPtrs_.clear();
processorVolPatchFieldDecomposerPtrs_.clear();
processorSurfacePatchFieldDecomposerPtrs_.clear();
faceSign_.clear();
}
void Foam::fvFieldDecomposer::reset
(
const List<labelRange>& boundaryRanges,
const labelUList& faceOwner,
const labelUList& faceNeighbour
)
{
clear();
const label nMappers = procMesh_.boundary().size();
patchFieldDecomposerPtrs_.resize(nMappers);
processorVolPatchFieldDecomposerPtrs_.resize(nMappers);
processorSurfacePatchFieldDecomposerPtrs_.resize(nMappers);
faceSign_.resize(nMappers);
forAll(boundaryAddressing_, patchi) forAll(boundaryAddressing_, patchi)
{ {
const label oldPatchi = boundaryAddressing_[patchi];
const fvPatch& fvp = procMesh_.boundary()[patchi]; const fvPatch& fvp = procMesh_.boundary()[patchi];
const labelSubList localPatchSlice(fvp.patchSlice(faceAddressing_));
if if
( (
boundaryAddressing_[patchi] >= 0 oldPatchi >= 0
&& !isA<processorLduInterface>(procMesh.boundary()[patchi]) && !isA<processorLduInterface>(procMesh_.boundary()[patchi])
) )
{ {
patchFieldDecomposerPtrs_.set patchFieldDecomposerPtrs_.set
@ -148,11 +244,8 @@ Foam::fvFieldDecomposer::fvFieldDecomposer
patchi, patchi,
new patchFieldDecomposer new patchFieldDecomposer
( (
fvp.patchSlice(faceAddressing_), localPatchSlice,
completeMesh_.boundaryMesh() boundaryRanges[oldPatchi].start()
[
boundaryAddressing_[patchi]
].start()
) )
); );
} }
@ -163,8 +256,9 @@ Foam::fvFieldDecomposer::fvFieldDecomposer
patchi, patchi,
new processorVolPatchFieldDecomposer new processorVolPatchFieldDecomposer
( (
completeMesh_, faceOwner,
fvp.patchSlice(faceAddressing_) faceNeighbour,
localPatchSlice
) )
); );
@ -173,28 +267,21 @@ Foam::fvFieldDecomposer::fvFieldDecomposer
patchi, patchi,
new processorSurfacePatchFieldDecomposer new processorSurfacePatchFieldDecomposer
( (
static_cast<const labelUList&> static_cast<const labelUList&>(localPatchSlice)
(
fvp.patchSlice
(
faceAddressing_
)
)
) )
); );
faceSign_.set faceSign_.set
( (
patchi, patchi,
new scalarField(fvp.patchSlice(faceAddressing_).size()) new scalarField(localPatchSlice.size())
); );
{ {
const SubList<label> fa = fvp.patchSlice(faceAddressing_);
scalarField& s = faceSign_[patchi]; scalarField& s = faceSign_[patchi];
forAll(s, i) forAll(s, i)
{ {
s[i] = sign(fa[i]); s[i] = sign(localPatchSlice[i]);
} }
} }
} }
@ -202,10 +289,74 @@ Foam::fvFieldDecomposer::fvFieldDecomposer
} }
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // void Foam::fvFieldDecomposer::reset(const fvMesh& completeMesh)
{
clear();
const label nMappers = procMesh_.boundary().size();
patchFieldDecomposerPtrs_.resize(nMappers);
processorVolPatchFieldDecomposerPtrs_.resize(nMappers);
processorSurfacePatchFieldDecomposerPtrs_.resize(nMappers);
faceSign_.resize(nMappers);
Foam::fvFieldDecomposer::~fvFieldDecomposer() forAll(boundaryAddressing_, patchi)
{} {
const label oldPatchi = boundaryAddressing_[patchi];
const fvPatch& fvp = procMesh_.boundary()[patchi];
const labelSubList localPatchSlice(fvp.patchSlice(faceAddressing_));
if
(
oldPatchi >= 0
&& !isA<processorLduInterface>(procMesh_.boundary()[patchi])
)
{
patchFieldDecomposerPtrs_.set
(
patchi,
new patchFieldDecomposer
(
localPatchSlice,
completeMesh.boundaryMesh()[oldPatchi].start()
)
);
}
else
{
processorVolPatchFieldDecomposerPtrs_.set
(
patchi,
new processorVolPatchFieldDecomposer
(
completeMesh,
localPatchSlice
)
);
processorSurfacePatchFieldDecomposerPtrs_.set
(
patchi,
new processorSurfacePatchFieldDecomposer
(
static_cast<const labelUList&>(localPatchSlice)
)
);
faceSign_.set
(
patchi,
new scalarField(localPatchSlice.size())
);
{
scalarField& s = faceSign_[patchi];
forAll(s, i)
{
s[i] = sign(localPatchSlice[i]);
}
}
}
}
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -31,7 +32,7 @@ Description
SourceFiles SourceFiles
fvFieldDecomposer.C fvFieldDecomposer.C
fvFieldDecomposerDecomposeFields.C fvFieldDecomposerFields.C
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -47,8 +48,6 @@ SourceFiles
namespace Foam namespace Foam
{ {
class IOobjectList;
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class fvFieldDecomposer Declaration Class fvFieldDecomposer Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -62,7 +61,7 @@ public:
: :
public fvPatchFieldMapper public fvPatchFieldMapper
{ {
// Private data // Private Data
labelList directAddressing_; labelList directAddressing_;
@ -78,7 +77,7 @@ public:
); );
// Member functions // Member Functions
label size() const label size() const
{ {
@ -110,13 +109,21 @@ public:
: :
public fvPatchFieldMapper public fvPatchFieldMapper
{ {
// Private data // Private Data
labelList directAddressing_; labelList directAddressing_;
public: public:
//- Construct given addressing //- Construct addressing from details
processorVolPatchFieldDecomposer
(
const labelUList& faceOwner,
const labelUList& faceNeigbour,
const labelUList& addressingSlice
);
//- Construct given addressing from complete mesh
processorVolPatchFieldDecomposer processorVolPatchFieldDecomposer
( (
const fvMesh& mesh, const fvMesh& mesh,
@ -124,7 +131,7 @@ public:
); );
// Member functions // Member Functions
label size() const label size() const
{ {
@ -199,10 +206,7 @@ public:
private: private:
// Private data // Private Data
//- Reference to complete mesh
const fvMesh& completeMesh_;
//- Reference to processor mesh //- Reference to processor mesh
const fvMesh& procMesh_; const fvMesh& procMesh_;
@ -225,11 +229,10 @@ private:
PtrList<processorSurfacePatchFieldDecomposer> PtrList<processorSurfacePatchFieldDecomposer>
processorSurfacePatchFieldDecomposerPtrs_; processorSurfacePatchFieldDecomposerPtrs_;
PtrList<scalarField> faceSign_; PtrList<scalarField> faceSign_;
// Private Member Functions public:
//- No copy construct //- No copy construct
fvFieldDecomposer(const fvFieldDecomposer&) = delete; fvFieldDecomposer(const fvFieldDecomposer&) = delete;
@ -238,11 +241,19 @@ private:
void operator=(const fvFieldDecomposer&) = delete; void operator=(const fvFieldDecomposer&) = delete;
public:
// Constructors // Constructors
//- Construct from components //- Construct without mappers, added later with reset()
fvFieldDecomposer
(
const Foam::zero,
const fvMesh& procMesh,
const labelList& faceAddressing,
const labelList& cellAddressing,
const labelList& boundaryAddressing
);
//- Construct from components using information from the complete mesh
fvFieldDecomposer fvFieldDecomposer
( (
const fvMesh& completeMesh, const fvMesh& completeMesh,
@ -252,13 +263,56 @@ public:
const labelList& boundaryAddressing const labelList& boundaryAddressing
); );
//- Construct from components without the complete mesh
fvFieldDecomposer
(
// Information about the complete mesh
const List<labelRange>& boundaryRanges,
const labelUList& faceOwner,
const labelUList& faceNeigbour,
// Addressing for processor mesh
const fvMesh& procMesh,
const labelList& faceAddressing,
const labelList& cellAddressing,
const labelList& boundaryAddressing
);
//- Destructor //- Destructor
~fvFieldDecomposer(); ~fvFieldDecomposer() = default;
// Member Functions // Member Functions
//- True if no mappers have been allocated
bool empty() const;
//- Remove all mappers
void clear();
//- Reset mappers using information from the complete mesh
void reset(const fvMesh& completeMesh);
//- Reset mapper using information about the complete mesh
void reset
(
const List<labelRange>& boundaryRanges,
const labelUList& faceOwner,
const labelUList& faceNeigbour
);
// Mapping
//- Decompose internal field
template<class Type>
tmp<DimensionedField<Type, volMesh>>
decomposeField
(
const DimensionedField<Type, volMesh>& field
) const;
//- Decompose volume field //- Decompose volume field
template<class Type> template<class Type>
tmp<GeometricField<Type, fvPatchField, volMesh>> tmp<GeometricField<Type, fvPatchField, volMesh>>
@ -276,6 +330,7 @@ public:
const GeometricField<Type, fvsPatchField, surfaceMesh>& field const GeometricField<Type, fvsPatchField, surfaceMesh>& field
) const; ) const;
//- Decompose list of fields
template<class GeoField> template<class GeoField>
void decomposeFields(const PtrList<GeoField>& fields) const; void decomposeFields(const PtrList<GeoField>& fields) const;
}; };
@ -288,7 +343,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository #ifdef NoRepository
#include "fvFieldDecomposerDecomposeFields.C" #include "fvFieldDecomposerFields.C"
#endif #endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -34,6 +35,36 @@ License
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
Foam::tmp<Foam::DimensionedField<Type, Foam::volMesh>>
Foam::fvFieldDecomposer::decomposeField
(
const DimensionedField<Type, volMesh>& field
) const
{
// Create and map the internal field values
Field<Type> mappedField(field, cellAddressing_);
// Create the field for the processor
return
tmp<DimensionedField<Type, volMesh>>::New
(
IOobject
(
field.name(),
procMesh_.time().timeName(),
procMesh_,
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
procMesh_,
field.dimensions(),
std::move(mappedField)
);
}
template<class Type> template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh>> Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh>>
Foam::fvFieldDecomposer::decomposeField Foam::fvFieldDecomposer::decomposeField
@ -338,9 +369,9 @@ void Foam::fvFieldDecomposer::decomposeFields
const PtrList<GeoField>& fields const PtrList<GeoField>& fields
) const ) const
{ {
forAll(fields, fieldi) for (const auto& fld : fields)
{ {
decomposeField(fields[fieldi])().write(); decomposeField(fld)().write();
} }
} }

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -76,6 +77,22 @@ Foam::pointFieldDecomposer::patchFieldDecomposer::patchFieldDecomposer
} }
Foam::pointFieldDecomposer::pointFieldDecomposer
(
const Foam::zero,
const pointMesh& procMesh,
const labelList& pointAddressing,
const labelList& boundaryAddressing
)
:
procMesh_(procMesh),
pointAddressing_(pointAddressing),
boundaryAddressing_(boundaryAddressing),
// Mappers
patchFieldDecomposerPtrs_()
{}
Foam::pointFieldDecomposer::pointFieldDecomposer Foam::pointFieldDecomposer::pointFieldDecomposer
( (
const pointMesh& completeMesh, const pointMesh& completeMesh,
@ -84,45 +101,60 @@ Foam::pointFieldDecomposer::pointFieldDecomposer
const labelList& boundaryAddressing const labelList& boundaryAddressing
) )
: :
completeMesh_(completeMesh), pointFieldDecomposer
procMesh_(procMesh),
pointAddressing_(pointAddressing),
boundaryAddressing_(boundaryAddressing),
patchFieldDecomposerPtrs_
( (
procMesh_.boundary().size(), zero{},
static_cast<patchFieldDecomposer*>(nullptr) procMesh,
pointAddressing,
boundaryAddressing
) )
{ {
reset(completeMesh);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::pointFieldDecomposer::empty() const
{
return patchFieldDecomposerPtrs_.empty();
}
void Foam::pointFieldDecomposer::clear()
{
patchFieldDecomposerPtrs_.clear();
}
void Foam::pointFieldDecomposer::reset
(
const pointMesh& completeMesh
)
{
clear();
const label nMappers = procMesh_.boundary().size();
patchFieldDecomposerPtrs_.resize(nMappers);
forAll(boundaryAddressing_, patchi) forAll(boundaryAddressing_, patchi)
{ {
if (boundaryAddressing_[patchi] >= 0) const label oldPatchi = boundaryAddressing_[patchi];
if (oldPatchi >= 0)
{ {
patchFieldDecomposerPtrs_[patchi] = new patchFieldDecomposer patchFieldDecomposerPtrs_.set
( (
completeMesh_.boundary()[boundaryAddressing_[patchi]], patchi,
new patchFieldDecomposer
(
completeMesh.boundary()[oldPatchi],
procMesh_.boundary()[patchi], procMesh_.boundary()[patchi],
pointAddressing_ pointAddressing_
)
); );
} }
} }
} }
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::pointFieldDecomposer::~pointFieldDecomposer()
{
forAll(patchFieldDecomposerPtrs_, patchi)
{
if (patchFieldDecomposerPtrs_[patchi])
{
delete patchFieldDecomposerPtrs_[patchi];
}
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// ************************************************************************* // // ************************************************************************* //

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -31,7 +32,7 @@ Description
SourceFiles SourceFiles
pointFieldDecomposer.C pointFieldDecomposer.C
pointFieldDecomposerDecomposeFields.C pointFieldDecomposerFields.C
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -53,7 +54,6 @@ namespace Foam
class pointFieldDecomposer class pointFieldDecomposer
{ {
public: public:
//- Point patch field decomposer class //- Point patch field decomposer class
@ -107,10 +107,7 @@ public:
private: private:
// Private data // Private Data
//- Reference to complete mesh
const pointMesh& completeMesh_;
//- Reference to processor mesh //- Reference to processor mesh
const pointMesh& procMesh_; const pointMesh& procMesh_;
@ -122,10 +119,10 @@ private:
const labelList& boundaryAddressing_; const labelList& boundaryAddressing_;
//- List of patch field decomposers //- List of patch field decomposers
List<patchFieldDecomposer*> patchFieldDecomposerPtrs_; PtrList<patchFieldDecomposer> patchFieldDecomposerPtrs_;
// Private Member Functions public:
//- No copy construct //- No copy construct
pointFieldDecomposer(const pointFieldDecomposer&) = delete; pointFieldDecomposer(const pointFieldDecomposer&) = delete;
@ -134,10 +131,17 @@ private:
void operator=(const pointFieldDecomposer&) = delete; void operator=(const pointFieldDecomposer&) = delete;
public:
// Constructors // Constructors
//- Construct without mappers, added later with reset()
pointFieldDecomposer
(
const Foam::zero,
const pointMesh& procMesh,
const labelList& pointAddressing,
const labelList& boundaryAddressing
);
//- Construct from components //- Construct from components
pointFieldDecomposer pointFieldDecomposer
( (
@ -149,11 +153,23 @@ public:
//- Destructor //- Destructor
~pointFieldDecomposer(); ~pointFieldDecomposer() = default;
// Member Functions // Member Functions
//- True if no mappers have been allocated
bool empty() const;
//- Remove all mappers
void clear();
//- Reset mappers using information from the complete mesh
void reset(const pointMesh& completeMesh);
// Mapping
//- Decompose point field //- Decompose point field
template<class Type> template<class Type>
tmp<GeometricField<Type, pointPatchField, pointMesh>> tmp<GeometricField<Type, pointPatchField, pointMesh>>
@ -162,6 +178,7 @@ public:
const GeometricField<Type, pointPatchField, pointMesh>& const GeometricField<Type, pointPatchField, pointMesh>&
) const; ) const;
//- Decompose list of fields
template<class GeoField> template<class GeoField>
void decomposeFields(const PtrList<GeoField>& fields) const; void decomposeFields(const PtrList<GeoField>& fields) const;
}; };
@ -174,7 +191,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository #ifdef NoRepository
#include "pointFieldDecomposerDecomposeFields.C" #include "pointFieldDecomposerFields.C"
#endif #endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -46,7 +47,7 @@ Foam::pointFieldDecomposer::decomposeField
// Create and map the patch field values // Create and map the patch field values
forAll(boundaryAddressing_, patchi) forAll(boundaryAddressing_, patchi)
{ {
if (patchFieldDecomposerPtrs_[patchi]) if (patchFieldDecomposerPtrs_.set(patchi))
{ {
patchFields.set patchFields.set
( (
@ -56,7 +57,7 @@ Foam::pointFieldDecomposer::decomposeField
field.boundaryField()[boundaryAddressing_[patchi]], field.boundaryField()[boundaryAddressing_[patchi]],
procMesh_.boundary()[patchi], procMesh_.boundary()[patchi],
DimensionedField<Type, pointMesh>::null(), DimensionedField<Type, pointMesh>::null(),
*patchFieldDecomposerPtrs_[patchi] patchFieldDecomposerPtrs_[patchi]
) )
); );
} }
@ -75,9 +76,8 @@ Foam::pointFieldDecomposer::decomposeField
} }
// Create the field for the processor // Create the field for the processor
return tmp<GeometricField<Type, pointPatchField, pointMesh>> return
( tmp<GeometricField<Type, pointPatchField, pointMesh>>::New
new GeometricField<Type, pointPatchField, pointMesh>
( (
IOobject IOobject
( (
@ -92,7 +92,6 @@ Foam::pointFieldDecomposer::decomposeField
field.dimensions(), field.dimensions(),
internalField, internalField,
patchFields patchFields
)
); );
} }
@ -103,9 +102,9 @@ void Foam::pointFieldDecomposer::decomposeFields
const PtrList<GeoField>& fields const PtrList<GeoField>& fields
) const ) const
{ {
forAll(fields, fieldi) for (const auto& fld : fields)
{ {
decomposeField(fields[fieldi])().write(); decomposeField(fld)().write();
} }
} }

View File

@ -0,0 +1,4 @@
faFieldDecomposer.C
faMeshDecomposition.C
LIB = $(FOAM_LIBBIN)/libfaDecompose

View File

@ -0,0 +1,9 @@
EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/finiteArea/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
LIB_LIBS = \
-lfiniteVolume \
-lfiniteArea \
-lmeshTools

View File

@ -0,0 +1,357 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
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 "faFieldDecomposer.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::faFieldDecomposer::patchFieldDecomposer::patchFieldDecomposer
(
const label sizeBeforeMapping,
const labelUList& addressingSlice,
const label addressingOffset
)
:
sizeBeforeMapping_(sizeBeforeMapping),
directAddressing_(addressingSlice)
{
forAll(directAddressing_, i)
{
// Subtract one to align addressing.
// directAddressing_[i] -= addressingOffset + 1;
// ZT, 12/Nov/2010
directAddressing_[i] -= addressingOffset;
}
}
Foam::faFieldDecomposer::processorAreaPatchFieldDecomposer::
processorAreaPatchFieldDecomposer
(
const label nTotalFaces,
const labelUList& owner, // == mesh.edgeOwner()
const labelUList& neigh, // == mesh.edgeNeighbour()
const labelUList& addressingSlice,
const scalarField& weights
)
:
sizeBeforeMapping_(nTotalFaces),
addressing_(addressingSlice.size()),
weights_(addressingSlice.size())
{
forAll(addressing_, i)
{
// Subtract one to align addressing.
label ai = addressingSlice[i];
// label ai = mag(addressingSlice[i]) - 1;
if (ai < neigh.size())
{
// This is a regular edge. it has been an internal edge
// of the original mesh and now it has become a edge
// on the parallel boundary
addressing_[i].resize(2);
weights_[i].resize(2);
addressing_[i][0] = owner[ai];
addressing_[i][1] = neigh[ai];
if (ai < weights.size())
{
// Edge weights exist/are usable
weights_[i][0] = weights[ai];
weights_[i][1] = 1.0 - weights[ai];
}
else
{
// No edge weights. use equal weighting
weights_[i][0] = 0.5;
weights_[i][1] = 0.5;
}
}
else
{
// This is a edge that used to be on a cyclic boundary
// but has now become a parallel patch edge. I cannot
// do the interpolation properly (I would need to look
// up the different (edge) list of data), so I will
// just grab the value from the owner face
addressing_[i].resize(1);
weights_[i].resize(1);
addressing_[i][0] = owner[ai];
weights_[i][0] = 1.0;
}
}
}
Foam::faFieldDecomposer::processorAreaPatchFieldDecomposer::
processorAreaPatchFieldDecomposer
(
const faMesh& mesh,
const labelUList& addressingSlice
)
:
processorAreaPatchFieldDecomposer
(
mesh.nFaces(),
mesh.edgeOwner(),
mesh.edgeNeighbour(),
addressingSlice,
mesh.weights().internalField()
)
{}
Foam::faFieldDecomposer::processorEdgePatchFieldDecomposer::
processorEdgePatchFieldDecomposer
(
label sizeBeforeMapping,
const labelUList& addressingSlice
)
:
sizeBeforeMapping_(sizeBeforeMapping),
addressing_(addressingSlice.size()),
weights_(addressingSlice.size())
{
forAll(addressing_, i)
{
addressing_[i].resize(1);
weights_[i].resize(1);
addressing_[i][0] = mag(addressingSlice[i]) - 1;
weights_[i][0] = sign(addressingSlice[i]);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::faFieldDecomposer::faFieldDecomposer
(
const Foam::zero,
const faMesh& procMesh,
const labelList& edgeAddressing,
const labelList& faceAddressing,
const labelList& boundaryAddressing
)
:
procMesh_(procMesh),
edgeAddressing_(edgeAddressing),
faceAddressing_(faceAddressing),
boundaryAddressing_(boundaryAddressing),
// Mappers
patchFieldDecomposerPtrs_(),
processorAreaPatchFieldDecomposerPtrs_(),
processorEdgePatchFieldDecomposerPtrs_()
{}
Foam::faFieldDecomposer::faFieldDecomposer
(
const faMesh& completeMesh,
const faMesh& procMesh,
const labelList& edgeAddressing,
const labelList& faceAddressing,
const labelList& boundaryAddressing
)
:
faFieldDecomposer
(
zero{},
procMesh,
edgeAddressing,
faceAddressing,
boundaryAddressing
)
{
reset(completeMesh);
}
Foam::faFieldDecomposer::faFieldDecomposer
(
const label nTotalFaces,
const List<labelRange>& boundaryRanges,
const labelUList& edgeOwner,
const labelUList& edgeNeigbour,
const faMesh& procMesh,
const labelList& edgeAddressing,
const labelList& faceAddressing,
const labelList& boundaryAddressing
)
:
faFieldDecomposer
(
zero{},
procMesh,
edgeAddressing,
faceAddressing,
boundaryAddressing
)
{
reset(nTotalFaces, boundaryRanges, edgeOwner, edgeNeigbour);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::faFieldDecomposer::empty() const
{
return patchFieldDecomposerPtrs_.empty();
}
void Foam::faFieldDecomposer::clear()
{
patchFieldDecomposerPtrs_.clear();
processorAreaPatchFieldDecomposerPtrs_.clear();
processorEdgePatchFieldDecomposerPtrs_.clear();
}
void Foam::faFieldDecomposer::reset
(
const label nTotalFaces,
const List<labelRange>& boundaryRanges,
const labelUList& edgeOwner,
const labelUList& edgeNeigbour
)
{
clear();
const label nMappers = procMesh_.boundary().size();
patchFieldDecomposerPtrs_.resize(nMappers);
processorAreaPatchFieldDecomposerPtrs_.resize(nMappers);
processorEdgePatchFieldDecomposerPtrs_.resize(nMappers);
forAll(boundaryAddressing_, patchi)
{
const label oldPatchi = boundaryAddressing_[patchi];
const faPatch& fap = procMesh_.boundary()[patchi];
const labelSubList localPatchSlice(fap.patchSlice(edgeAddressing_));
if (oldPatchi >= 0)
{
patchFieldDecomposerPtrs_.set
(
patchi,
new patchFieldDecomposer
(
boundaryRanges[oldPatchi].size(),
localPatchSlice,
boundaryRanges[oldPatchi].start()
)
);
}
else
{
processorAreaPatchFieldDecomposerPtrs_.set
(
patchi,
new processorAreaPatchFieldDecomposer
(
nTotalFaces,
edgeOwner,
edgeNeigbour,
localPatchSlice
)
);
processorEdgePatchFieldDecomposerPtrs_.set
(
patchi,
new processorEdgePatchFieldDecomposer
(
procMesh_.boundary()[patchi].size(),
static_cast<const labelUList&>(localPatchSlice)
)
);
}
}
}
void Foam::faFieldDecomposer::reset(const faMesh& completeMesh)
{
clear();
const label nMappers = procMesh_.boundary().size();
patchFieldDecomposerPtrs_.resize(nMappers);
processorAreaPatchFieldDecomposerPtrs_.resize(nMappers);
processorEdgePatchFieldDecomposerPtrs_.resize(nMappers);
forAll(boundaryAddressing_, patchi)
{
const label oldPatchi = boundaryAddressing_[patchi];
const faPatch& fap = procMesh_.boundary()[patchi];
const labelSubList localPatchSlice(fap.patchSlice(edgeAddressing_));
if (oldPatchi >= 0)
{
patchFieldDecomposerPtrs_.set
(
patchi,
new patchFieldDecomposer
(
completeMesh.boundary()[oldPatchi].size(),
localPatchSlice,
completeMesh.boundary()[oldPatchi].start()
)
);
}
else
{
processorAreaPatchFieldDecomposerPtrs_.set
(
patchi,
new processorAreaPatchFieldDecomposer
(
completeMesh,
localPatchSlice
)
);
processorEdgePatchFieldDecomposerPtrs_.set
(
patchi,
new processorEdgePatchFieldDecomposer
(
procMesh_.boundary()[patchi].size(),
static_cast<const labelUList&>(localPatchSlice)
)
);
}
}
}
// ************************************************************************* //

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -35,7 +36,7 @@ Author
SourceFiles SourceFiles
faFieldDecomposer.C faFieldDecomposer.C
faFieldDecomposerDecomposeFields.C faFieldDecomposerFields.C
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -51,6 +52,7 @@ SourceFiles
namespace Foam namespace Foam
{ {
// Forward Declarations
class IOobjectList; class IOobjectList;
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
@ -66,7 +68,7 @@ public:
: :
public faPatchFieldMapper public faPatchFieldMapper
{ {
// Private data // Private Data
label sizeBeforeMapping_; label sizeBeforeMapping_;
labelList directAddressing_; labelList directAddressing_;
@ -118,7 +120,7 @@ public:
: :
public faPatchFieldMapper public faPatchFieldMapper
{ {
// Private data // Private Data
label sizeBeforeMapping_; label sizeBeforeMapping_;
labelListList addressing_; labelListList addressing_;
@ -126,7 +128,17 @@ public:
public: public:
//- Construct given addressing //- Construct addressing from details
processorAreaPatchFieldDecomposer
(
const label nTotalFaces,
const labelUList& edgeOwner,
const labelUList& edgeNeigbour,
const labelUList& addressingSlice,
const scalarField& edgeWeights = scalarField::null()
);
//- Construct given addressing from complete mesh
processorAreaPatchFieldDecomposer processorAreaPatchFieldDecomposer
( (
const faMesh& mesh, const faMesh& mesh,
@ -134,7 +146,7 @@ public:
); );
// Member functions // Member Functions
label size() const label size() const
{ {
@ -187,7 +199,7 @@ public:
); );
// Member functions // Member Functions
label size() const label size() const
{ {
@ -223,10 +235,7 @@ public:
private: private:
// Private data // Private Data
//- Reference to complete mesh
const faMesh& completeMesh_;
//- Reference to processor mesh //- Reference to processor mesh
const faMesh& procMesh_; const faMesh& procMesh_;
@ -241,12 +250,12 @@ private:
const labelList& boundaryAddressing_; const labelList& boundaryAddressing_;
//- List of patch field decomposers //- List of patch field decomposers
List<patchFieldDecomposer*> patchFieldDecomposerPtrs_; PtrList<patchFieldDecomposer> patchFieldDecomposerPtrs_;
List<processorAreaPatchFieldDecomposer*> PtrList<processorAreaPatchFieldDecomposer>
processorAreaPatchFieldDecomposerPtrs_; processorAreaPatchFieldDecomposerPtrs_;
List<processorEdgePatchFieldDecomposer*> PtrList<processorEdgePatchFieldDecomposer>
processorEdgePatchFieldDecomposerPtrs_; processorEdgePatchFieldDecomposerPtrs_;
@ -263,7 +272,17 @@ public:
// Constructors // Constructors
//- Construct from components //- Construct without mappers, added later with reset()
faFieldDecomposer
(
const Foam::zero,
const faMesh& procMesh,
const labelList& edgeAddressing,
const labelList& faceAddressing,
const labelList& boundaryAddressing
);
//- Construct from components using information from the complete mesh
faFieldDecomposer faFieldDecomposer
( (
const faMesh& completeMesh, const faMesh& completeMesh,
@ -273,14 +292,50 @@ public:
const labelList& boundaryAddressing const labelList& boundaryAddressing
); );
//- Construct from components without the complete mesh
faFieldDecomposer
(
// Information about the complete mesh
const label nTotalFaces,
const List<labelRange>& boundaryRanges,
const labelUList& edgeOwner,
const labelUList& edgeNeigbour,
// Destructor // Addressing for processor mesh
const faMesh& procMesh,
const labelList& edgeAddressing,
const labelList& faceAddressing,
const labelList& boundaryAddressing
);
~faFieldDecomposer();
//- Destructor
~faFieldDecomposer() = default;
// Member Functions // Member Functions
//- True if no mappers have been allocated
bool empty() const;
//- Remove all mappers
void clear();
//- Reset mappers using information from the complete mesh
void reset(const faMesh& completeMesh);
//- Reset mapper using information about the complete mesh
void reset
(
const label nTotalFaces,
const List<labelRange>& boundaryRanges,
const labelUList& edgeOwner,
const labelUList& edgeNeigbour
);
// Mapping
//- Decompose area field //- Decompose area field
template<class Type> template<class Type>
tmp<GeometricField<Type, faPatchField, areaMesh>> tmp<GeometricField<Type, faPatchField, areaMesh>>
@ -299,6 +354,33 @@ public:
template<class GeoField> template<class GeoField>
void decomposeFields(const PtrList<GeoField>& fields) const; void decomposeFields(const PtrList<GeoField>& fields) const;
// Reading helpers
//- Read the fields and hold on the pointer list
template
<
class Type,
template<class> class PatchField,
class GeoMesh
>
static void readFields
(
const typename GeoMesh::Mesh& mesh,
const IOobjectList& objects,
PtrList<GeometricField<Type, PatchField, GeoMesh>>& fields,
const bool readOldTime
);
//- Read fields and hold on the pointer list
template<class Mesh, class GeoField>
static void readFields
(
const Mesh& mesh,
const IOobjectList& objects,
PtrList<GeoField>& fields
);
}; };
@ -309,7 +391,8 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository #ifdef NoRepository
# include "faFieldDecomposerDecomposeFields.C" #include "faFieldDecomposerFields.C"
#include "faFieldDecomposerReadFields.C"
#endif #endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -29,16 +30,11 @@ License
#include "processorFaPatchField.H" #include "processorFaPatchField.H"
#include "processorFaePatchField.H" #include "processorFaePatchField.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type> template<class Type>
tmp<GeometricField<Type, faPatchField, areaMesh>> Foam::tmp<Foam::GeometricField<Type, Foam::faPatchField, Foam::areaMesh>>
faFieldDecomposer::decomposeField Foam::faFieldDecomposer::decomposeField
( (
const GeometricField<Type, faPatchField, areaMesh>& field const GeometricField<Type, faPatchField, areaMesh>& field
) const ) const
@ -51,17 +47,19 @@ faFieldDecomposer::decomposeField
forAll(boundaryAddressing_, patchi) forAll(boundaryAddressing_, patchi)
{ {
if (boundaryAddressing_[patchi] >= 0) const label oldPatchi = boundaryAddressing_[patchi];
if (oldPatchi >= 0)
{ {
patchFields.set patchFields.set
( (
patchi, patchi,
faPatchField<Type>::New faPatchField<Type>::New
( (
field.boundaryField()[boundaryAddressing_[patchi]], field.boundaryField()[oldPatchi],
procMesh_.boundary()[patchi], procMesh_.boundary()[patchi],
DimensionedField<Type, areaMesh>::null(), DimensionedField<Type, areaMesh>::null(),
*patchFieldDecomposerPtrs_[patchi] patchFieldDecomposerPtrs_[patchi]
) )
); );
} }
@ -77,7 +75,7 @@ faFieldDecomposer::decomposeField
Field<Type> Field<Type>
( (
field.internalField(), field.internalField(),
*processorAreaPatchFieldDecomposerPtrs_[patchi] processorAreaPatchFieldDecomposerPtrs_[patchi]
) )
) )
); );
@ -85,9 +83,8 @@ faFieldDecomposer::decomposeField
} }
// Create the field for the processor // Create the field for the processor
return tmp<GeometricField<Type, faPatchField, areaMesh>> return
( tmp<GeometricField<Type, faPatchField, areaMesh>>::New
new GeometricField<Type, faPatchField, areaMesh>
( (
IOobject IOobject
( (
@ -101,14 +98,13 @@ faFieldDecomposer::decomposeField
field.dimensions(), field.dimensions(),
internalField, internalField,
patchFields patchFields
)
); );
} }
template<class Type> template<class Type>
tmp<GeometricField<Type, faePatchField, edgeMesh>> Foam::tmp<Foam::GeometricField<Type, Foam::faePatchField, Foam::edgeMesh>>
faFieldDecomposer::decomposeField Foam::faFieldDecomposer::decomposeField
( (
const GeometricField<Type, faePatchField, edgeMesh>& field const GeometricField<Type, faePatchField, edgeMesh>& field
) const ) const
@ -147,7 +143,7 @@ faFieldDecomposer::decomposeField
forAll(field.boundaryField(), patchi) forAll(field.boundaryField(), patchi)
{ {
const Field<Type> & p = field.boundaryField()[patchi]; const Field<Type>& p = field.boundaryField()[patchi];
const label patchStart = field.mesh().boundary()[patchi].start(); const label patchStart = field.mesh().boundary()[patchi].start();
@ -162,17 +158,19 @@ faFieldDecomposer::decomposeField
forAll(boundaryAddressing_, patchi) forAll(boundaryAddressing_, patchi)
{ {
if (boundaryAddressing_[patchi] >= 0) const label oldPatchi = boundaryAddressing_[patchi];
if (oldPatchi >= 0)
{ {
patchFields.set patchFields.set
( (
patchi, patchi,
faePatchField<Type>::New faePatchField<Type>::New
( (
field.boundaryField()[boundaryAddressing_[patchi]], field.boundaryField()[oldPatchi],
procMesh_.boundary()[patchi], procMesh_.boundary()[patchi],
DimensionedField<Type, edgeMesh>::null(), DimensionedField<Type, edgeMesh>::null(),
*patchFieldDecomposerPtrs_[patchi] patchFieldDecomposerPtrs_[patchi]
) )
); );
} }
@ -188,7 +186,7 @@ faFieldDecomposer::decomposeField
Field<Type> Field<Type>
( (
allEdgeField, allEdgeField,
*processorEdgePatchFieldDecomposerPtrs_[patchi] processorEdgePatchFieldDecomposerPtrs_[patchi]
) )
) )
); );
@ -196,9 +194,8 @@ faFieldDecomposer::decomposeField
} }
// Create the field for the processor // Create the field for the processor
return tmp<GeometricField<Type, faePatchField, edgeMesh>> return
( tmp<GeometricField<Type, faePatchField, edgeMesh>>::New
new GeometricField<Type, faePatchField, edgeMesh>
( (
IOobject IOobject
( (
@ -212,13 +209,12 @@ faFieldDecomposer::decomposeField
field.dimensions(), field.dimensions(),
internalField, internalField,
patchFields patchFields
)
); );
} }
template<class GeoField> template<class GeoField>
void faFieldDecomposer::decomposeFields void Foam::faFieldDecomposer::decomposeFields
( (
const PtrList<GeoField>& fields const PtrList<GeoField>& fields
) const ) const
@ -230,8 +226,4 @@ void faFieldDecomposer::decomposeFields
} }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* // // ************************************************************************* //

View File

@ -0,0 +1,99 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
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 "faFieldDecomposer.H"
#include "GeometricField.H"
#include "IOobjectList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type, template<class> class PatchField, class GeoMesh>
void Foam::faFieldDecomposer::readFields
(
const typename GeoMesh::Mesh& mesh,
const IOobjectList& objects,
PtrList<GeometricField<Type, PatchField, GeoMesh>>& fields,
const bool readOldTime
)
{
typedef GeometricField<Type, PatchField, GeoMesh> GeoField;
// Search list of objects for fields of type GeoField
IOobjectList fieldObjects(objects.lookupClass<GeoField>());
/// // Remove the cellDist field
/// auto iter = fieldObjects.find("cellDist");
/// if (iter.found())
/// {
/// fieldObjects.erase(iter);
/// }
// Use sorted set of names
// (different processors might read objects in different order)
const wordList masterNames(fieldObjects.sortedNames());
// Construct the fields
fields.resize(masterNames.size());
forAll(masterNames, i)
{
const IOobject& io = *fieldObjects[masterNames[i]];
fields.set(i, new GeoField(io, mesh, readOldTime));
}
}
template<class Mesh, class GeoField>
void Foam::faFieldDecomposer::readFields
(
const Mesh& mesh,
const IOobjectList& objects,
PtrList<GeoField>& fields
)
{
// Search list of objects for fields of type GeomField
IOobjectList fieldObjects(objects.lookupClass<GeoField>());
// Use sorted set of names
// (different processors might read objects in different order)
const wordList masterNames(fieldObjects.sortedNames());
// Construct the fields
fields.resize(masterNames.size());
forAll(masterNames, i)
{
const IOobject& io = *fieldObjects[masterNames[i]];
fields.set(i, new GeoField(io, mesh));
}
}
// ************************************************************************* //

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2018-2019 OpenCFD Ltd. Copyright (C) 2018-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -34,14 +34,16 @@ License
#include "faMesh.H" #include "faMesh.H"
#include "OSspecific.H" #include "OSspecific.H"
#include "Map.H" #include "Map.H"
#include "SLList.H"
#include "globalMeshData.H" #include "globalMeshData.H"
#include "decompositionModel.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::faMeshDecomposition::distributeFaces() void Foam::faMeshDecomposition::distributeFaces()
{ {
Info<< "\nCalculating distribution of faces" << endl; const word& polyMeshRegionName = mesh().name();
Info<< "\nCalculating distribution of finiteArea faces" << endl;
cpuTime decompositionTime; cpuTime decompositionTime;
@ -58,7 +60,7 @@ void Foam::faMeshDecomposition::distributeFaces()
( (
IOobject IOobject
( (
GeoMesh<polyMesh>::mesh_.name(), polyMeshRegionName,
processorDb.timeName(), processorDb.timeName(),
processorDb processorDb
) )
@ -160,22 +162,12 @@ void Foam::faMeshDecomposition::distributeFaces()
Foam::faMeshDecomposition::faMeshDecomposition Foam::faMeshDecomposition::faMeshDecomposition
( (
const fvMesh& mesh, const fvMesh& mesh,
const fileName& decompDictFile const label nProcessors,
const dictionary& params
) )
: :
faMesh(mesh), faMesh(mesh),
decompDictFile_(decompDictFile), nProcs_(nProcessors),
nProcs_
(
decompositionMethod::nDomains
(
decompositionModel::New
(
mesh,
decompDictFile
)
)
),
distributed_(false), distributed_(false),
hasGlobalFaceZones_(false), hasGlobalFaceZones_(false),
faceToProc_(nFaces()), faceToProc_(nFaces()),
@ -193,53 +185,73 @@ Foam::faMeshDecomposition::faMeshDecomposition
procNeighbourProcessors_(nProcs_), procNeighbourProcessors_(nProcs_),
procProcessorPatchSize_(nProcs_), procProcessorPatchSize_(nProcs_),
procProcessorPatchStartIndex_(nProcs_), procProcessorPatchStartIndex_(nProcs_),
globallySharedPoints_(0), globallySharedPoints_(),
cyclicParallel_(false) cyclicParallel_(false)
{ {
const decompositionModel& model = decompositionModel::New updateParameters(params);
(
mesh,
decompDictFile
);
model.readIfPresent("distributed", distributed_);
hasGlobalFaceZones_ = model.found("globalFaceZones");
} }
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::faMeshDecomposition::updateParameters
(
const dictionary& params
)
{
params.readIfPresent("distributed", distributed_);
if (params.found("globalFaceZones"))
{
hasGlobalFaceZones_ = true;
}
}
void Foam::faMeshDecomposition::decomposeMesh() void Foam::faMeshDecomposition::decomposeMesh()
{ {
// Decide which cell goes to which processor // Decide which cell goes to which processor
distributeFaces(); distributeFaces();
const word& polyMeshRegionName = mesh().name();
Info<< "\nDistributing faces to processors" << endl; Info<< "\nDistributing faces to processors" << endl;
// Memory management labelList nLocalFaces(nProcs_, Zero);
{
List<SLList<label>> procFaceList(nProcs());
forAll(faceToProc_, faceI) // Pass 1: determine local sizes, sanity check
forAll(faceToProc_, facei)
{ {
if (faceToProc_[faceI] >= nProcs()) const label proci = faceToProc_[facei];
if (proci < 0 || proci >= nProcs_)
{ {
FatalErrorIn("Finite area mesh decomposition") FatalErrorInFunction
<< "Impossible processor label " << faceToProc_[faceI] << "Invalid processor label " << proci
<< "for face " << faceI << " for face " << facei << nl
<< abort(FatalError); << abort(FatalError);
} }
else else
{ {
procFaceList[faceToProc_[faceI]].append(faceI); ++nLocalFaces[proci];
} }
} }
// Convert linked lists into normal lists // Adjust lengths
forAll(procFaceList, procI) forAll(nLocalFaces, proci)
{ {
procFaceAddressing_[procI] = procFaceList[procI]; procFaceAddressing_[proci].resize(nLocalFaces[proci]);
nLocalFaces[proci] = 0; // restart list
} }
// Pass 2: fill in local lists
forAll(faceToProc_, facei)
{
const label proci = faceToProc_[facei];
const label localFacei = nLocalFaces[proci];
++nLocalFaces[proci];
procFaceAddressing_[proci][localFacei] = facei;
} }
@ -258,7 +270,7 @@ void Foam::faMeshDecomposition::decomposeMesh()
( (
IOobject IOobject
( (
GeoMesh<polyMesh>::mesh_.name(), polyMeshRegionName,
processorDb.timeName(), processorDb.timeName(),
processorDb processorDb
) )
@ -314,7 +326,7 @@ void Foam::faMeshDecomposition::decomposeMesh()
fvFaceProcAddressingHash.find fvFaceProcAddressingHash.find
( (
faceLabels()[curProcFaceAddressing[faceI]] + 1 faceLabels()[curProcFaceAddressing[faceI]] + 1
)(); ).val();
} }
// create processor finite area mesh // create processor finite area mesh
@ -324,38 +336,35 @@ void Foam::faMeshDecomposition::decomposeMesh()
procFaceLabels_[procI] procFaceLabels_[procI]
); );
const indirectPrimitivePatch& patch = this->patch(); const uindirectPrimitivePatch& patch = this->patch();
const Map<label>& map = patch.meshPointMap(); const Map<label>& map = patch.meshPointMap();
EdgeMap<label> edgesHash; EdgeMap<label> edgesHash;
label edgeI = -1;
const label nIntEdges = patch.nInternalEdges(); const label nIntEdges = patch.nInternalEdges();
for (label curEdge = 0; curEdge < nIntEdges; curEdge++) for (label edgei = 0; edgei < nIntEdges; ++edgei)
{ {
edgesHash.insert(patch.edges()[curEdge], ++edgeI); edgesHash.insert(patch.edges()[edgei], edgesHash.size());
} }
forAll(boundary(), patchI) forAll(boundary(), patchi)
{ {
// Include emptyFaPatch // Include emptyFaPatch
const label size = boundary()[patchi].labelList::size();
const label size = boundary()[patchI].labelList::size(); for (label edgei=0; edgei < size; ++edgei)
for(int eI=0; eI<size; eI++)
{ {
edgesHash.insert edgesHash.insert
( (
patch.edges()[boundary()[patchI][eI]], patch.edges()[boundary()[patchi][edgei]],
++edgeI edgesHash.size()
); );
} }
} }
const indirectPrimitivePatch& procPatch = procMesh.patch(); const uindirectPrimitivePatch& procPatch = procMesh.patch();
const vectorField& procPoints = procPatch.localPoints(); const vectorField& procPoints = procPatch.localPoints();
const labelList& procMeshPoints = procPatch.meshPoints(); const labelList& procMeshPoints = procPatch.meshPoints();
const edgeList& procEdges = procPatch.edges(); const edgeList& procEdges = procPatch.edges();
@ -370,21 +379,18 @@ void Foam::faMeshDecomposition::decomposeMesh()
} }
labelList& curPatchEdgeAddressing = procPatchEdgeAddressing_[procI]; labelList& curPatchEdgeAddressing = procPatchEdgeAddressing_[procI];
curPatchEdgeAddressing.setSize(procEdges.size(), -1); curPatchEdgeAddressing.resize(procEdges.size(), -1);
Map<label>& curMap = procMeshEdgesMap_[procI];
curMap.clear();
curMap.resize(2*procEdges.size());
forAll(procEdges, edgeI) forAll(procEdges, edgeI)
{ {
edge curGlobalEdge = procEdges[edgeI]; edge curGlobalEdge(curPatchPointAddressing, procEdges[edgeI]);
curGlobalEdge[0] = curPatchPointAddressing[curGlobalEdge[0]]; curPatchEdgeAddressing[edgeI] = edgesHash.find(curGlobalEdge).val();
curGlobalEdge[1] = curPatchPointAddressing[curGlobalEdge[1]];
curPatchEdgeAddressing[edgeI] = edgesHash.find(curGlobalEdge)();
} }
Map<label>& curMap = procMeshEdgesMap_[procI];
curMap = Map<label>(2*procEdges.size());
forAll(curPatchEdgeAddressing, edgeI) forAll(curPatchEdgeAddressing, edgeI)
{ {
curMap.insert(curPatchEdgeAddressing[edgeI], edgeI); curMap.insert(curPatchEdgeAddressing[edgeI], edgeI);
@ -1057,7 +1063,7 @@ void Foam::faMeshDecomposition::decomposeMesh()
( (
IOobject IOobject
( (
GeoMesh<polyMesh>::mesh_.name(), polyMeshRegionName,
processorDb.timeName(), processorDb.timeName(),
processorDb processorDb
) )
@ -1083,8 +1089,7 @@ void Foam::faMeshDecomposition::decomposeMesh()
procProcessorPatchSize_[procI]; procProcessorPatchSize_[procI];
labelListList& curPatchEdgeLabels = procPatchEdgeLabels_[procI]; labelListList& curPatchEdgeLabels = procPatchEdgeLabels_[procI];
curPatchEdgeLabels = curPatchEdgeLabels.resize
labelListList
( (
curPatchSize.size() curPatchSize.size()
+ curProcessorPatchSize.size() + curProcessorPatchSize.size()
@ -1137,8 +1142,9 @@ void Foam::faMeshDecomposition::decomposeMesh()
bool Foam::faMeshDecomposition::writeDecomposition() bool Foam::faMeshDecomposition::writeDecomposition()
{ {
Info<< "\nConstructing processor FA meshes" << endl; const word& polyMeshRegionName = mesh().name();
Info<< "\nConstructing processor FA meshes" << endl;
// Make a lookup map for globally shared points // Make a lookup map for globally shared points
Map<label> sharedPointLookup(2*globallySharedPoints_.size()); Map<label> sharedPointLookup(2*globallySharedPoints_.size());
@ -1175,7 +1181,7 @@ bool Foam::faMeshDecomposition::writeDecomposition()
( (
IOobject IOobject
( (
GeoMesh<polyMesh>::mesh_.name(), polyMeshRegionName,
processorDb.timeName(), processorDb.timeName(),
processorDb processorDb
) )
@ -1195,7 +1201,7 @@ bool Foam::faMeshDecomposition::writeDecomposition()
); );
// create finite area mesh // Create finite area mesh
faMesh procMesh faMesh procMesh
( (
procFvMesh, procFvMesh,
@ -1219,11 +1225,9 @@ bool Foam::faMeshDecomposition::writeDecomposition()
const faPatchList& meshPatches = boundary(); const faPatchList& meshPatches = boundary();
List<faPatch*> procPatches PtrList<faPatch> procPatches
( (
curPatchSizes.size() curPatchSizes.size() + curProcessorPatchSizes.size()
+ curProcessorPatchSizes.size(),
reinterpret_cast<faPatch*>(NULL)
); );
label nPatches = 0; label nPatches = 0;
@ -1232,44 +1236,51 @@ bool Foam::faMeshDecomposition::writeDecomposition()
{ {
const labelList& curEdgeLabels = curPatchEdgeLabels[nPatches]; const labelList& curEdgeLabels = curPatchEdgeLabels[nPatches];
const label ngbPolyPatchIndex = const label neiPolyPatchId =
fvBoundaryProcAddressing.find fvBoundaryProcAddressing.find
( (
meshPatches[curBoundaryAddressing[patchi]] meshPatches[curBoundaryAddressing[patchi]]
.ngbPolyPatchIndex() .ngbPolyPatchIndex()
); );
procPatches[nPatches] = procPatches.set
(
nPatches,
meshPatches[curBoundaryAddressing[patchi]].clone meshPatches[curBoundaryAddressing[patchi]].clone
( (
procMesh.boundary(), procMesh.boundary(),
curEdgeLabels, curEdgeLabels,
nPatches, nPatches,
ngbPolyPatchIndex neiPolyPatchId
).ptr(); )
);
nPatches++; ++nPatches;
} }
forAll(curProcessorPatchSizes, procPatchI) forAll(curProcessorPatchSizes, procPatchI)
{ {
const labelList& curEdgeLabels = curPatchEdgeLabels[nPatches]; const labelList& curEdgeLabels = curPatchEdgeLabels[nPatches];
procPatches[nPatches] = procPatches.set
(
nPatches,
new processorFaPatch new processorFaPatch
( (
word("procBoundary") + Foam::name(procI) processorPolyPatch::newName
+ word("to") (
+ Foam::name(curNeighbourProcessors[procPatchI]), procI,
curNeighbourProcessors[procPatchI]
),
curEdgeLabels, curEdgeLabels,
nPatches, nPatches,
procMesh.boundary(), procMesh.boundary(),
-1, -1,
procI, procI,
curNeighbourProcessors[procPatchI] curNeighbourProcessors[procPatchI]
)
); );
nPatches++; ++nPatches;
} }
// Add boundary patches // Add boundary patches
@ -1291,23 +1302,19 @@ bool Foam::faMeshDecomposition::writeDecomposition()
forAll(procMesh.boundary(), patchi) forAll(procMesh.boundary(), patchi)
{ {
if const auto* ppp =
( isA<processorFaPatch>(procMesh.boundary()[patchi]);
procMesh.boundary()[patchi].type()
== processorFaPatch::typeName if (ppp)
)
{ {
const processorFaPatch& ppp = const auto& procPatch = *ppp;
refCast<const processorFaPatch>
(
procMesh.boundary()[patchi]
);
Info<< " Number of edges shared with processor " Info<< " Number of edges shared with processor "
<< ppp.neighbProcNo() << " = " << ppp.size() << endl; << procPatch.neighbProcNo() << " = "
<< procPatch.size() << endl;
nProcPatches++; nProcEdges += procPatch.size();
nProcEdges += ppp.size(); ++nProcPatches;
} }
else else
{ {

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -44,7 +45,6 @@ SourceFiles
#include "fvMesh.H" #include "fvMesh.H"
#include "faMesh.H" #include "faMesh.H"
#include "labelList.H" #include "labelList.H"
#include "SLList.H"
#include "PtrList.H" #include "PtrList.H"
#include "point.H" #include "point.H"
@ -59,10 +59,7 @@ class faMeshDecomposition
: :
public faMesh public faMesh
{ {
// Private data // Private Data
//- Optional non-standard file for decomposeParDict
const fileName decompDictFile_;
//- Number of processors in decomposition //- Number of processors in decomposition
label nProcs_; label nProcs_;
@ -86,7 +83,7 @@ class faMeshDecomposition
labelList procNInternalEdges_; labelList procNInternalEdges_;
//- Edge labels for patches of processor meshes //- Edge labels for patches of processor meshes
List<List<List<label>>> procPatchEdgeLabels_; List<labelListList> procPatchEdgeLabels_;
//- Labels of points for each processor //- Labels of points for each processor
labelListList procPatchPointAddressing_; labelListList procPatchPointAddressing_;
@ -131,18 +128,21 @@ class faMeshDecomposition
void distributeFaces(); void distributeFaces();
public: public:
// Constructors // Constructors
//- Construct from components. //- Construct from components.
//- Values will come from the volume decomposition
// \param mesh the fvMesh // \param mesh the fvMesh
// \param decompDictFile optional non-standard location for the // \param nProcessors the number of processors
// decomposeParDict file // \param params additional parameters, sent to updateParameters
faMeshDecomposition faMeshDecomposition
( (
const fvMesh& mesh, const fvMesh& mesh,
const fileName& decompDictFile = "" const label nProcessors,
const dictionary& params = dictionary::null
); );
@ -152,29 +152,63 @@ public:
// Member Functions // Member Functions
// Settings
//- Number of processor in decomposition //- Number of processor in decomposition
label nProcs() const label nProcs() const
{ {
return nProcs_; return nProcs_;
} }
//- Is the decomposition data to be distributed for each processor //- Is decomposition data to be distributed for each processor
bool distributed() const bool distributed() const
{ {
return distributed_; return distributed_;
} }
//- Change distributed flag
bool distributed(const bool on)
{
bool old(distributed_);
distributed_ = on;
return old;
}
//- Are global face zones used
bool useGlobalFaceZones() const
{
return distributed_;
}
//- Change global face zones flag
bool useGlobalFaceZones(const bool on)
{
bool old(hasGlobalFaceZones_);
hasGlobalFaceZones_ = on;
return old;
}
//- Update flags based on the decomposition model settings
// Sets "distributed", detects presence of "globalFaceZones"
void updateParameters(const dictionary& params);
// Mappings
//- Face-processor decomposition labels
const labelList& faceToProc() const noexcept
{
return faceToProc_;
}
// Decompose
//- Decompose mesh //- Decompose mesh
void decomposeMesh(); void decomposeMesh();
//- Write decomposition //- Write decomposition
bool writeDecomposition(); bool writeDecomposition();
//- Cell-processor decomposition labels
const labelList& faceToProc() const
{
return faceToProc_;
}
}; };

View File

@ -5,5 +5,6 @@ cd "${0%/*}" || exit # Run from this directory
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
wmake $targetType reconstruct wmake $targetType reconstruct
wmake $targetType faReconstruct
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------

View File

@ -0,0 +1,5 @@
processorFaMeshes.C
faFieldReconstructor.C
faMeshReconstructor.C
LIB = $(FOAM_LIBBIN)/libfaReconstruct

View File

@ -0,0 +1,9 @@
EXE_INC = \
-I$(LIB_SRC)/finiteArea/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude
EXE_LIBS = \
-lfiniteArea \
-lfiniteVolume \
-lmeshTools

View File

@ -35,7 +35,7 @@ Author
SourceFiles SourceFiles
faFieldReconstructor.C faFieldReconstructor.C
faFieldReconstructorReconstructFields.C faFieldReconstructorFields.C
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -194,7 +194,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository #ifdef NoRepository
# include "faFieldReconstructorReconstructFields.C" # include "faFieldReconstructorFields.C"
#endif #endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -0,0 +1,637 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
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 "faMeshReconstructor.H"
#include "globalIndex.H"
#include "globalMeshData.H"
#include "edgeHashes.H"
#include "Time.H"
#include "PstreamCombineReduceOps.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
int Foam::faMeshReconstructor::debug = 0;
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::faMeshReconstructor::calcAddressing
(
const labelUList& fvFaceProcAddr
)
{
const globalIndex globalFaceNum(procMesh_.nFaces());
// ----------------------
// boundaryProcAddressing
//
// Trivial since non-processor boundary ordering is identical
const label nPatches = procMesh_.boundary().size();
faBoundaryProcAddr_ = identity(nPatches);
// Mark processor patches
for
(
label patchi = procMesh_.boundary().nNonProcessor();
patchi < nPatches;
++patchi
)
{
faBoundaryProcAddr_[patchi] = -1;
}
// ------------------
// faceProcAddressing
//
// Transcribe/rewrite based on finiteVolume faceProcAddressing
faFaceProcAddr_ = procMesh_.faceLabels();
// From local faceLabels to proc values
for (label& facei : faFaceProcAddr_)
{
// Use finiteVolume info, ignoring face flips
facei = mag(fvFaceProcAddr[facei] - 1);
}
// Make global consistent.
// Starting at '0', without gaps in numbering etc.
// - the sorted order is the obvious solution
{
globalFaceNum.gather(faFaceProcAddr_, singlePatchFaceLabels_);
labelList order(Foam::sortedOrder(singlePatchFaceLabels_));
singlePatchFaceLabels_ = labelList(singlePatchFaceLabels_, order);
globalFaceNum.scatter(order, faFaceProcAddr_);
}
// Broadcast the same information everywhere
Pstream::scatter(singlePatchFaceLabels_);
// ------------------
// edgeProcAddressing
//
// This is more complicated.
// Create a single (serial) patch of the finiteArea mesh without a
// corresponding volume mesh, otherwise it would be the same as
// reconstructPar on the volume mesh (big, slow, etc).
//
// Do manual point-merge and relabeling to avoid dependency on
// finiteVolume pointProcAddressing
faPointProcAddr_.clear(); // Final size == procMesh_.nPoints()
// 1.
// - Topological point merge of the area meshes
// - use the local patch faces and points
// 2.
// - build a single (serial) patch of the finiteArea mesh only
// without any point support from the volume mesh
// - it may be possible to skip this step, but not obvious how
// The collected faces are contiguous per processor, which gives us
// the possibility to easily identify their source by using the
// global face indexing (if needed).
// The ultimate face locations are handled with a separate ordering
// list.
const uindirectPrimitivePatch& procPatch = procMesh_.patch();
{
faceList singlePatchProcFaces; // [proc0faces, proc1faces ...]
labelList uniqueMeshPointLabels;
// Local face points to compact merged point index
labelList pointToGlobal;
autoPtr<globalIndex> globalPointsPtr =
procMesh_.mesh().globalData().mergePoints
(
procPatch.meshPoints(),
procPatch.meshPointMap(), // unused
pointToGlobal,
uniqueMeshPointLabels
);
// Gather faces, renumbered for the *merged* points
faceList tmpFaces(globalFaceNum.localSize());
forAll(tmpFaces, facei)
{
tmpFaces[facei] =
face(pointToGlobal, procPatch.localFaces()[facei]);
}
globalFaceNum.gather
(
tmpFaces,
singlePatchProcFaces,
UPstream::msgType(),
Pstream::commsTypes::scheduled
);
globalPointsPtr().gather
(
UIndirectList<point>
(
procPatch.points(), // NB: mesh points (non-local)
uniqueMeshPointLabels
),
singlePatchPoints_
);
// Transcribe into final assembled order
singlePatchFaces_.resize(singlePatchProcFaces.size());
// Target face ordering
labelList singlePatchProcAddr;
globalFaceNum.gather(faFaceProcAddr_, singlePatchProcAddr);
forAll(singlePatchProcAddr, facei)
{
const label targetFacei = singlePatchProcAddr[facei];
singlePatchFaces_[targetFacei] = singlePatchProcFaces[facei];
}
// Use initial equivalent "global" (serial) patch
// to establish the correct point and face walking order
//
// - only meaningful on master
const primitivePatch initialPatch
(
SubList<face>(singlePatchFaces_),
singlePatchPoints_
);
// Grab the faces/points in local point ordering
tmpFaces = initialPatch.localFaces();
pointField tmpPoints(initialPatch.localPoints());
// The meshPointMap is contiguous, so flatten as linear list
/// Map<label> mpm(initialPatch.meshPointMap());
labelList mpm(initialPatch.nPoints());
forAllConstIters(initialPatch.meshPointMap(), iter)
{
mpm[iter.key()] = iter.val();
}
Pstream::scatter(mpm);
// Rewrite pointToGlobal according to the correct point order
for (label& pointi : pointToGlobal)
{
pointi = mpm[pointi];
}
// Finalize. overwrite
faPointProcAddr_ = std::move(pointToGlobal);
singlePatchFaces_ = std::move(tmpFaces);
singlePatchPoints_ = std::move(tmpPoints);
}
// Broadcast the same information everywhere
Pstream::scatter(singlePatchFaces_);
Pstream::scatter(singlePatchPoints_);
// Now have enough global information to determine global edge mappings
// Equivalent "global" (serial) patch
const primitivePatch onePatch
(
SubList<face>(singlePatchFaces_),
singlePatchPoints_
);
faEdgeProcAddr_.clear();
faEdgeProcAddr_.resize(procMesh_.nEdges(), -1);
{
EdgeMap<label> globalEdgeMapping(2*onePatch.nEdges());
// Pass 1: edge-hash lookup with edges in "natural" patch order
// Can use local edges() directly without remap via meshPoints()
// since the previous sorting means that we are already working
// with faces that are in the local point order and even
// the points themselves are also in the local point order
for (const edge& e : onePatch.edges())
{
globalEdgeMapping.insert(e, globalEdgeMapping.size());
}
// Lookup proc local edges (in natural order) to global equivalent
for (label edgei = 0; edgei < procPatch.nEdges(); ++edgei)
{
const edge globalEdge(faPointProcAddr_, procPatch.edges()[edgei]);
const auto fnd = globalEdgeMapping.cfind(globalEdge);
if (fnd.found())
{
faEdgeProcAddr_[edgei] = fnd.val();
}
else
{
FatalErrorInFunction
<< "Failed to find edge " << globalEdge
<< " this indicates a programming error" << nl
<< exit(FatalError);
}
}
}
// Now have consistent global edge
// This of course would all be too easy.
// The finiteArea edge lists have been defined as their own sorted
// order with sublists etc.
// Gather edge ids for nonProcessor boundaries.
// These will also be in the serial geometry
Map<label> remapGlobal(2*onePatch.nEdges());
for (label edgei = 0; edgei < onePatch.nInternalEdges(); ++edgei)
{
remapGlobal.insert(edgei, remapGlobal.size());
}
//
singlePatchEdgeLabels_.clear();
singlePatchEdgeLabels_.resize(procMesh_.boundary().nNonProcessor());
forAll(singlePatchEdgeLabels_, patchi)
{
const faPatch& fap = procMesh_.boundary()[patchi];
labelList& patchEdgeLabels = singlePatchEdgeLabels_[patchi];
patchEdgeLabels = fap.edgeLabels();
// Renumber from local edges to global edges (natural order)
for (label& edgeId : patchEdgeLabels)
{
edgeId = faEdgeProcAddr_[edgeId];
}
// OR patchEdgeLabels =
// UIndirectList<label>(faEdgeProcAddr_, fap.edgeLabels());
// Collect from all processors
combineReduce
(
patchEdgeLabels,
ListOps::appendEqOp<label>()
);
// Sorted order will be the original non-decomposed order
Foam::sort(patchEdgeLabels);
for (const label sortedEdgei : patchEdgeLabels)
{
remapGlobal.insert(sortedEdgei, remapGlobal.size());
}
}
{
// Use the map to rewrite the local faEdgeProcAddr_
labelList newEdgeProcAddr(faEdgeProcAddr_);
label edgei = procMesh_.nInternalEdges();
for (const faPatch& fap : procMesh_.boundary())
{
for (const label patchEdgei : fap.edgeLabels())
{
const label globalEdgei = faEdgeProcAddr_[patchEdgei];
const auto fnd = remapGlobal.cfind(globalEdgei);
if (fnd.found())
{
newEdgeProcAddr[edgei] = fnd.val();
++edgei;
}
else
{
FatalErrorInFunction
<< "Failed to find edge " << globalEdgei
<< " this indicates a programming error" << nl
<< exit(FatalError);
}
}
}
faEdgeProcAddr_ = std::move(newEdgeProcAddr);
}
}
void Foam::faMeshReconstructor::initPatch() const
{
serialPatchPtr_.reset
(
new primitivePatch
(
SubList<face>(singlePatchFaces_),
singlePatchPoints_
)
);
}
void Foam::faMeshReconstructor::createMesh()
{
const Time& runTime = procMesh_.mesh().time();
// Time for non-parallel case (w/o functionObjects or libs)
serialRunTime_ = Time::New(runTime.globalPath().toAbsolute());
// Trivial polyMesh only containing points and faces.
// This is valid, provided we don't use it for anything complicated.
serialVolMesh_.reset
(
new polyMesh
(
IOobject
(
procMesh_.mesh().name(), // Volume region name
procMesh_.mesh().facesInstance(),
*serialRunTime_,
IOobject::NO_READ,
IOobject::NO_WRITE,
false // not registered
),
pointField(singlePatchPoints_), // copy
faceList(singlePatchFaces_), // copy
labelList(singlePatchFaces_.size(), Zero), // faceOwner
labelList(), // faceNeighbour
false // no syncPar!
)
);
// A simple area-mesh with one-to-one mapping of faceLabels
serialAreaMesh_.reset
(
new faMesh
(
*serialVolMesh_,
identity(singlePatchFaces_.size()) // faceLabels
)
);
auto& completeMesh = *serialAreaMesh_;
// Add in non-processor boundary patches
PtrList<faPatch> completePatches(singlePatchEdgeLabels_.size());
forAll(completePatches, patchi)
{
const labelList& patchEdgeLabels = singlePatchEdgeLabels_[patchi];
const faPatch& fap = procMesh_.boundary()[patchi];
const label neiPolyPatchId = fap.ngbPolyPatchIndex();
completePatches.set
(
patchi,
fap.clone
(
completeMesh.boundary(),
patchEdgeLabels,
patchi, // index
neiPolyPatchId
)
);
}
completeMesh.addFaPatches(completePatches);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::faMeshReconstructor::faMeshReconstructor
(
const faMesh& procMesh
)
:
procMesh_(procMesh)
{
if (!Pstream::parRun())
{
FatalErrorInFunction
<< "Can only be called in parallel!!" << nl
<< exit(FatalError);
}
// Require faceProcAddressing from finiteVolume decomposition
labelIOList fvFaceProcAddressing
(
IOobject
(
"faceProcAddressing",
procMesh_.mesh().facesInstance(),
// Or search?
// procMesh_.time().findInstance
// (
// // Search for polyMesh face instance
// // mesh.facesInstance()
// procMesh_.mesh().meshDir(),
// "faceProcAddressing"
// ),
polyMesh::meshSubDir,
procMesh_.mesh(), // The polyMesh db
IOobject::MUST_READ,
IOobject::NO_WRITE,
false // not registered
)
);
calcAddressing(fvFaceProcAddressing);
}
Foam::faMeshReconstructor::faMeshReconstructor
(
const faMesh& procMesh,
const labelUList& fvFaceProcAddressing
)
:
procMesh_(procMesh)
{
if (!Pstream::parRun())
{
FatalErrorInFunction
<< "Can only be called in parallel!!" << nl
<< exit(FatalError);
}
calcAddressing(fvFaceProcAddressing);
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::faMeshReconstructor::~faMeshReconstructor()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::faMeshReconstructor::clearGeom()
{
serialAreaMesh_.reset(nullptr);
serialVolMesh_.reset(nullptr);
serialRunTime_.reset(nullptr);
}
const Foam::primitivePatch& Foam::faMeshReconstructor::patch() const
{
if (!serialPatchPtr_)
{
initPatch();
}
return *serialPatchPtr_;
}
Foam::primitivePatch& Foam::faMeshReconstructor::patch()
{
if (!serialPatchPtr_)
{
initPatch();
}
return *serialPatchPtr_;
}
const Foam::faMesh& Foam::faMeshReconstructor::mesh() const
{
if (!serialAreaMesh_)
{
const_cast<faMeshReconstructor&>(*this).createMesh();
}
return *serialAreaMesh_;
}
void Foam::faMeshReconstructor::writeAddressing() const
{
writeAddressing(procMesh_.mesh().facesInstance());
}
void Foam::faMeshReconstructor::writeAddressing(const word& timeName) const
{
// Write copies
IOobject ioAddr
(
"procAddressing",
timeName,
faMesh::meshSubDir,
procMesh_.mesh(), // The polyMesh
IOobject::NO_READ,
IOobject::NO_WRITE,
false // not registered
);
// boundaryProcAddressing
ioAddr.rename("boundaryProcAddressing");
labelIOList(ioAddr, faBoundaryProcAddr_).write();
// faceProcAddressing
ioAddr.rename("faceProcAddressing");
labelIOList(ioAddr, faFaceProcAddr_).write();
// pointProcAddressing
ioAddr.rename("pointProcAddressing");
labelIOList(ioAddr, faPointProcAddr_).write();
// edgeProcAddressing
ioAddr.rename("edgeProcAddressing");
labelIOList(ioAddr, faEdgeProcAddr_).write();
}
void Foam::faMeshReconstructor::writeMesh() const
{
writeMesh(procMesh_.mesh().facesInstance());
}
void Foam::faMeshReconstructor::writeMesh(const word& timeName) const
{
const faMesh& fullMesh = this->mesh();
const bool oldDistributed = fileHandler().distributed();
auto oldHandler = fileHandler(fileOperation::NewUncollated());
fileHandler().distributed(true);
if (Pstream::master())
{
const bool oldParRun = Pstream::parRun(false);
IOobject io(fullMesh.boundary());
io.rename("faceLabels");
labelIOList(io, singlePatchFaceLabels_).write();
fullMesh.boundary().write();
Pstream::parRun(oldParRun);
}
// Restore old settings
if (oldHandler)
{
fileHandler(std::move(oldHandler));
}
fileHandler().distributed(oldDistributed);
}
// ************************************************************************* //

View File

@ -0,0 +1,222 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
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::faMeshReconstructor
Description
A bare-bones reconstructor for finiteArea meshes when processor
meshes are available (in parallel) but an equivalent serial faMesh
is needed for reconstruction or decomposition.
In these situations, a serial version of the faMesh is needed,
but preferably without reconstructing the entire volume mesh.
It uses the finiteVolume faceProcAddressing in addition to
the geometric information available from the underlying polyMesh.
The resulting equivalent faMesh can be used for basic operations,
but caution should be exercised before attempting large operations.
SourceFiles
faMeshReconstructor.C
\*---------------------------------------------------------------------------*/
#ifndef faMeshReconstructor_H
#define faMeshReconstructor_H
#include "faMesh.H"
#include "primitivePatch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward Declarations
class Time;
/*---------------------------------------------------------------------------*\
Class faMeshReconstructor Declaration
\*---------------------------------------------------------------------------*/
class faMeshReconstructor
{
// Private Data
//- The processor-specific faMesh
const faMesh& procMesh_;
// Addressing
//- Processor face addressing, derived from finite volume information
labelList faFaceProcAddr_;
//- Processor boundary addressing
labelList faBoundaryProcAddr_;
//- Processor point addressing
labelList faPointProcAddr_;
//- Processor edge addressing
labelList faEdgeProcAddr_;
// Equivalent surface information
//- Faces labels for a single patch
labelList singlePatchFaceLabels_;
//- Faces for a single patch
faceList singlePatchFaces_;
//- Support points for a single patch
pointField singlePatchPoints_;
//- Lists of edge-labels (per edge patch) for the single patch
labelListList singlePatchEdgeLabels_;
// Demand-driven data
//- Primitive patch
mutable autoPtr<primitivePatch> serialPatchPtr_;
//- Time database for serial meshes
autoPtr<Time> serialRunTime_;
//- Dummy volume mesh, used for serial area mesh
autoPtr<polyMesh> serialVolMesh_;
//- Equivalent serial area mesh
autoPtr<faMesh> serialAreaMesh_;
// Private Member Functions
//- Calculate all addressing, using finiteVolume faceProcAddressing
void calcAddressing(const labelUList& fvFaceProcAddr);
//- Set primitive patch, removing any old one
void initPatch() const;
//- Create the serial geometry
void createMesh();
//- No copy construct
faMeshReconstructor(const faMeshReconstructor&) = delete;
//- No copy assignment
void operator=(const faMeshReconstructor&) = delete;
public:
//- Debug flag
static int debug;
// Constructors
//- Construct from components
explicit faMeshReconstructor(const faMesh& procMesh);
//- Construct from components
faMeshReconstructor
(
const faMesh& procMesh,
const labelUList& fvFaceProcAddressing
);
//- Destructor
~faMeshReconstructor();
void clearGeom();
// Member Functions
//- Processor point addressing
const labelList& pointProcAddressing() const noexcept
{
return faPointProcAddr_;
}
//- Processor edge addressing
const labelList& edgeProcAddressing() const noexcept
{
return faEdgeProcAddr_;
}
//- Processor face addressing
const labelList& faceProcAddressing() const noexcept
{
return faFaceProcAddr_;
}
//- Processor boundary addressing
const labelList& boundaryProcAddressing() const noexcept
{
return faBoundaryProcAddr_;
}
//- Serial equivalent patch
const primitivePatch& patch() const;
//- Serial equivalent patch
primitivePatch& patch();
//- Serial equivalent faMesh
const faMesh& mesh() const;
// Write
//- Write proc addressing at the polyMesh faceInstances time
void writeAddressing() const;
//- Write proc addressing at the given time
void writeAddressing(const word& timeName) const;
//- Write equivalent mesh information at the polyMesh faceInstances time
void writeMesh() const;
//- Write equivalent mesh information at the given time
void writeMesh(const word& timeName) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -145,116 +145,4 @@ Foam::processorFaMeshes::processorFaMeshes
} }
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// Foam::fvMesh::readUpdateState Foam::processorFaMeshes::readUpdate()
// {
// fvMesh::readUpdateState stat = fvMesh::UNCHANGED;
// forAll(databases_, procI)
// {
// // Check if any new meshes need to be read.
// fvMesh::readUpdateState procStat = meshes_[procI].readUpdate();
// /*
// if (procStat != fvMesh::UNCHANGED)
// {
// Info<< "Processor " << procI
// << " at time " << databases_[procI].timeName()
// << " detected mesh change " << procStat
// << endl;
// }
// */
// // Combine into overall mesh change status
// if (stat == fvMesh::UNCHANGED)
// {
// stat = procStat;
// }
// else
// {
// if (stat != procStat)
// {
// FatalErrorIn("processorFaMeshes::readUpdate()")
// << "Processor " << procI
// << " has a different polyMesh at time "
// << databases_[procI].timeName()
// << " compared to any previous processors." << nl
// << "Please check time " << databases_[procI].timeName()
// << " directories on all processors for consistent"
// << " mesh files."
// << exit(FatalError);
// }
// }
// }
// if
// (
// stat == fvMesh::TOPO_CHANGE
// || stat == fvMesh::TOPO_PATCH_CHANGE
// )
// {
// // Reread all meshes and addressing
// read();
// }
// return stat;
// }
// void Foam::processorFaMeshes::reconstructPoints(fvMesh& mesh)
// {
// // Read the field for all the processors
// PtrList<pointIOField> procsPoints(meshes_.size());
// forAll(meshes_, procI)
// {
// procsPoints.set
// (
// procI,
// new pointIOField
// (
// IOobject
// (
// "points",
// meshes_[procI].time().timeName(),
// polyMesh::meshSubDir,
// meshes_[procI],
// IOobject::MUST_READ,
// IOobject::NO_WRITE
// )
// )
// );
// }
// // Create the new points
// vectorField newPoints(mesh.nPoints());
// forAll(meshes_, procI)
// {
// const vectorField& procPoints = procsPoints[procI];
// // Set the cell values in the reconstructed field
// const labelList& pointProcAddressingI = pointProcAddressing_[procI];
// if (pointProcAddressingI.size() != procPoints.size())
// {
// FatalErrorIn("processorFaMeshes")
// << "problem :"
// << " pointProcAddressingI:" << pointProcAddressingI.size()
// << " procPoints:" << procPoints.size()
// << abort(FatalError);
// }
// forAll(pointProcAddressingI, pointI)
// {
// newPoints[pointProcAddressingI[pointI]] = procPoints[pointI];
// }
// }
// mesh.movePoints(newPoints);
// mesh.write();
// }
// ************************************************************************* // // ************************************************************************* //

View File

@ -27,7 +27,7 @@ Class
Foam::processorFaMeshes Foam::processorFaMeshes
Description Description
Container for processor mesh addressing. Container for finite-area processor mesh addressing.
Author Author
Zeljko Tukovic, FSB Zagreb Zeljko Tukovic, FSB Zagreb
@ -41,8 +41,8 @@ SourceFiles
#define processorFaMeshes_H #define processorFaMeshes_H
#include "PtrList.H" #include "PtrList.H"
#include "fvMesh.H"
#include "faMesh.H" #include "faMesh.H"
#include "fvMesh.H"
#include "IOobjectList.H" #include "IOobjectList.H"
#include "labelIOList.H" #include "labelIOList.H"
@ -100,29 +100,31 @@ public:
// Member Functions // Member Functions
//- Update the meshes based on the mesh files saved in const PtrList<faMesh>& meshes() const
// time directories {
// fvMesh::readUpdateState readUpdate(); return meshes_;
}
//- Reconstruct point position after motion in parallel
// void reconstructPoints(faMesh& mesh);
PtrList<faMesh>& meshes() PtrList<faMesh>& meshes()
{ {
return meshes_; return meshes_;
} }
const PtrList<labelIOList>& pointProcAddressing() const const PtrList<labelIOList>& pointProcAddressing() const
{ {
return pointProcAddressing_; return pointProcAddressing_;
} }
PtrList<labelIOList>& edgeProcAddressing() PtrList<labelIOList>& edgeProcAddressing()
{ {
return edgeProcAddressing_; return edgeProcAddressing_;
} }
const PtrList<labelIOList>& faceProcAddressing() const const PtrList<labelIOList>& faceProcAddressing() const
{ {
return faceProcAddressing_; return faceProcAddressing_;
} }
const PtrList<labelIOList>& boundaryProcAddressing() const const PtrList<labelIOList>& boundaryProcAddressing() const
{ {
return boundaryProcAddressing_; return boundaryProcAddressing_;

View File

@ -80,7 +80,7 @@ namespace fv
class radiation class radiation
: :
public option public fv::option
{ {
// Private Data // Private Data

Some files were not shown because too many files have changed in this diff Show More