Merge branch 'feature-redistributePar' into 'develop'

redistributePar support for point fields and area fields

See merge request Development/openfoam!538
This commit is contained in:
Andrew Heather
2022-05-25 13:13:03 +00:00
82 changed files with 9354 additions and 4336 deletions

View File

@ -25,11 +25,7 @@ if (doDecompose && Pstream::parRun())
// Handle area fields
// ------------------
PtrList<areaScalarField> areaScalarFields;
PtrList<areaVectorField> areaVectorFields;
PtrList<areaSphericalTensorField> areaSphTensorFields;
PtrList<areaSymmTensorField> areaSymmTensorFields;
PtrList<areaTensorField> areaTensorFields;
faFieldDecomposer::fieldsCache areaFieldsCache;
const faMesh& fullMesh = reconstructor.mesh();
@ -51,26 +47,7 @@ if (doDecompose && Pstream::parRun())
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
);
areaFieldsCache.readAllFields(fullMesh, objects);
// Restore old settings
if (oldHandler)
@ -81,14 +58,7 @@ if (doDecompose && Pstream::parRun())
}
}
const label nAreaFields =
(
areaScalarFields.size()
+ areaVectorFields.size()
+ areaSphTensorFields.size()
+ areaSymmTensorFields.size()
+ areaTensorFields.size()
);
const label nAreaFields = areaFieldsCache.size();
if (nAreaFields)
{
@ -103,41 +73,8 @@ if (doDecompose && Pstream::parRun())
reconstructor.boundaryProcAddressing()
);
if (areaScalarFields.size())
{
Info<< " scalars: "
<< flatOutput(PtrListOps::names(areaScalarFields)) << nl;
fieldDecomposer.decomposeFields(areaScalarFields);
}
if (areaVectorFields.size())
{
Info<< " vectors: "
<< flatOutput(PtrListOps::names(areaVectorFields)) << nl;
fieldDecomposer.decomposeFields(areaVectorFields);
}
if (areaSphTensorFields.size())
{
Info<< " sphTensors: "
<< flatOutput(PtrListOps::names(areaSphTensorFields)) << nl;
fieldDecomposer.decomposeFields(areaSphTensorFields);
}
if (areaSymmTensorFields.size())
{
Info<< " symmTensors: "
<< flatOutput(PtrListOps::names(areaSymmTensorFields)) << nl;
fieldDecomposer.decomposeFields(areaSymmTensorFields);
}
if (areaTensorFields.size())
{
Info<< " tensors: "
<< flatOutput(PtrListOps::names(areaTensorFields)) << nl;
fieldDecomposer.decomposeFields(areaTensorFields);
}
// Report
areaFieldsCache.decomposeAllFields(fieldDecomposer, true);
Info<< endl;
}
}

View File

@ -46,6 +46,7 @@ Original Authors
#include "IOobjectList.H"
#include "areaFields.H"
#include "edgeFields.H"
#include "faFieldDecomposer.H"
#include "faMeshReconstructor.H"
#include "PtrListOps.H"

View File

@ -8,6 +8,4 @@ domainDecompositionWrite.C
domainDecompositionDryRun.C
domainDecompositionDryRunWrite.C
lagrangianFieldDecomposer.C
EXE = $(FOAM_APPBIN)/decomposePar

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2016-2021 OpenCFD Ltd.
Copyright (C) 2016-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -150,29 +150,19 @@ Usage
#include "domainDecomposition.H"
#include "domainDecompositionDryRun.H"
#include "labelIOField.H"
#include "labelFieldIOField.H"
#include "scalarIOField.H"
#include "scalarFieldIOField.H"
#include "vectorIOField.H"
#include "vectorFieldIOField.H"
#include "sphericalTensorIOField.H"
#include "sphericalTensorFieldIOField.H"
#include "symmTensorIOField.H"
#include "symmTensorFieldIOField.H"
#include "tensorIOField.H"
#include "tensorFieldIOField.H"
#include "pointFields.H"
#include "regionProperties.H"
#include "readFields.H"
#include "fieldsDistributor.H"
#include "fvFieldDecomposer.H"
#include "pointFields.H"
#include "pointFieldDecomposer.H"
#include "lagrangianFieldDecomposer.H"
#include "emptyFaPatch.H"
#include "faMeshDecomposition.H"
#include "faFieldDecomposer.H"
#include "faMeshDecomposition.H"
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
@ -838,58 +828,14 @@ int main(int argc, char *argv[])
}
// Vol fields
// ~~~~~~~~~~
PtrList<volScalarField> volScalarFields;
PtrList<volVectorField> volVectorFields;
PtrList<volSphericalTensorField> volSphTensorFields;
PtrList<volSymmTensorField> volSymmTensorFields;
PtrList<volTensorField> volTensorFields;
// Volume/surface/internal fields
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fvFieldDecomposer::fieldsCache volumeFieldCache;
if (doDecompFields)
{
readFields(mesh, objects, volScalarFields, false);
readFields(mesh, objects, volVectorFields, false);
readFields(mesh, objects, volSphTensorFields, false);
readFields(mesh, objects, volSymmTensorFields, false);
readFields(mesh, objects, volTensorFields, false);
}
// Internal fields
// ~~~~~~~~~~~~~~~
PtrList<DimensionedField<scalar, volMesh>> dimScalarFields;
PtrList<DimensionedField<vector, volMesh>> dimVectorFields;
PtrList<DimensionedField<sphericalTensor, volMesh>>
dimSphTensorFields;
PtrList<DimensionedField<symmTensor, volMesh>>
dimSymmTensorFields;
PtrList<DimensionedField<tensor, volMesh>> dimTensorFields;
if (doDecompFields)
{
readFields(mesh, objects, dimScalarFields);
readFields(mesh, objects, dimVectorFields);
readFields(mesh, objects, dimSphTensorFields);
readFields(mesh, objects, dimSymmTensorFields);
readFields(mesh, objects, dimTensorFields);
}
// Surface fields
// ~~~~~~~~~~~~~~
PtrList<surfaceScalarField> surfaceScalarFields;
PtrList<surfaceVectorField> surfaceVectorFields;
PtrList<surfaceSphericalTensorField>
surfaceSphTensorFields;
PtrList<surfaceSymmTensorField> surfaceSymmTensorFields;
PtrList<surfaceTensorField> surfaceTensorFields;
if (doDecompFields)
{
readFields(mesh, objects, surfaceScalarFields, false);
readFields(mesh, objects, surfaceVectorFields, false);
readFields(mesh, objects, surfaceSphTensorFields, false);
readFields(mesh, objects, surfaceSymmTensorFields, false);
readFields(mesh, objects, surfaceTensorFields, false);
volumeFieldCache.readAllFields(mesh, objects);
}
@ -897,19 +843,11 @@ int main(int argc, char *argv[])
// ~~~~~~~~~~~~
const pointMesh& pMesh = pointMesh::New(mesh);
PtrList<pointScalarField> pointScalarFields;
PtrList<pointVectorField> pointVectorFields;
PtrList<pointSphericalTensorField> pointSphTensorFields;
PtrList<pointSymmTensorField> pointSymmTensorFields;
PtrList<pointTensorField> pointTensorFields;
pointFieldDecomposer::fieldsCache pointFieldCache;
if (doDecompFields)
{
readFields(pMesh, objects, pointScalarFields, false);
readFields(pMesh, objects, pointVectorFields, false);
readFields(pMesh, objects, pointSphTensorFields, false);
readFields(pMesh, objects, pointSymmTensorFields, false);
readFields(pMesh, objects, pointTensorFields, false);
pointFieldCache.readAllFields(pMesh, objects);
}
@ -938,63 +876,10 @@ int main(int argc, char *argv[])
cloudDirs.size()
);
PtrList<PtrList<labelIOField>> lagrangianLabelFields
lagrangianFieldDecomposer::fieldsCache lagrangianFieldCache
(
cloudDirs.size()
);
PtrList<PtrList<labelFieldCompactIOField>>
lagrangianLabelFieldFields
(
cloudDirs.size()
);
PtrList<PtrList<scalarIOField>> lagrangianScalarFields
(
cloudDirs.size()
);
PtrList<PtrList<scalarFieldCompactIOField>>
lagrangianScalarFieldFields
(
cloudDirs.size()
);
PtrList<PtrList<vectorIOField>> lagrangianVectorFields
(
cloudDirs.size()
);
PtrList<PtrList<vectorFieldCompactIOField>>
lagrangianVectorFieldFields
(
cloudDirs.size()
);
PtrList<PtrList<sphericalTensorIOField>>
lagrangianSphTensorFields
(
cloudDirs.size()
);
PtrList<PtrList<sphericalTensorFieldCompactIOField>>
lagrangianSphTensorFieldFields
(
cloudDirs.size()
);
PtrList<PtrList<symmTensorIOField>>
lagrangianSymmTensorFields
(
cloudDirs.size()
);
PtrList<PtrList<symmTensorFieldCompactIOField>>
lagrangianSymmTensorFieldFields
(
cloudDirs.size()
);
PtrList<PtrList<tensorIOField>> lagrangianTensorFields
(
cloudDirs.size()
);
PtrList<PtrList<tensorFieldCompactIOField>>
lagrangianTensorFieldFields
(
cloudDirs.size()
);
label cloudI = 0;
@ -1095,88 +980,10 @@ int main(int argc, char *argv[])
false
);
lagrangianFieldDecomposer::readFields
lagrangianFieldCache.readAllFields
(
cloudI,
lagrangianObjects,
lagrangianLabelFields
);
lagrangianFieldDecomposer::readFieldFields
(
cloudI,
lagrangianObjects,
lagrangianLabelFieldFields
);
lagrangianFieldDecomposer::readFields
(
cloudI,
lagrangianObjects,
lagrangianScalarFields
);
lagrangianFieldDecomposer::readFieldFields
(
cloudI,
lagrangianObjects,
lagrangianScalarFieldFields
);
lagrangianFieldDecomposer::readFields
(
cloudI,
lagrangianObjects,
lagrangianVectorFields
);
lagrangianFieldDecomposer::readFieldFields
(
cloudI,
lagrangianObjects,
lagrangianVectorFieldFields
);
lagrangianFieldDecomposer::readFields
(
cloudI,
lagrangianObjects,
lagrangianSphTensorFields
);
lagrangianFieldDecomposer::readFieldFields
(
cloudI,
lagrangianObjects,
lagrangianSphTensorFieldFields
);
lagrangianFieldDecomposer::readFields
(
cloudI,
lagrangianObjects,
lagrangianSymmTensorFields
);
lagrangianFieldDecomposer::readFieldFields
(
cloudI,
lagrangianObjects,
lagrangianSymmTensorFieldFields
);
lagrangianFieldDecomposer::readFields
(
cloudI,
lagrangianObjects,
lagrangianTensorFields
);
lagrangianFieldDecomposer::readFieldFields
(
cloudI,
lagrangianObjects,
lagrangianTensorFieldFields
lagrangianObjects
);
++cloudI;
@ -1185,18 +992,7 @@ int main(int argc, char *argv[])
lagrangianPositions.resize(cloudI);
cellParticles.resize(cloudI);
lagrangianLabelFields.resize(cloudI);
lagrangianLabelFieldFields.resize(cloudI);
lagrangianScalarFields.resize(cloudI);
lagrangianScalarFieldFields.resize(cloudI);
lagrangianVectorFields.resize(cloudI);
lagrangianVectorFieldFields.resize(cloudI);
lagrangianSphTensorFields.resize(cloudI);
lagrangianSphTensorFieldFields.resize(cloudI);
lagrangianSymmTensorFields.resize(cloudI);
lagrangianSymmTensorFieldFields.resize(cloudI);
lagrangianTensorFields.resize(cloudI);
lagrangianTensorFieldFields.resize(cloudI);
lagrangianFieldCache.resize(cloudI);
Info<< endl;
@ -1291,35 +1087,11 @@ int main(int argc, char *argv[])
)
);
}
const fvFieldDecomposer& fieldDecomposer =
fieldDecomposerList[proci];
// Vol fields
fieldDecomposer.decomposeFields(volScalarFields);
fieldDecomposer.decomposeFields(volVectorFields);
fieldDecomposer.decomposeFields(volSphTensorFields);
fieldDecomposer.decomposeFields(volSymmTensorFields);
fieldDecomposer.decomposeFields(volTensorFields);
// Surface fields
fieldDecomposer.decomposeFields(surfaceScalarFields);
fieldDecomposer.decomposeFields(surfaceVectorFields);
fieldDecomposer.decomposeFields
volumeFieldCache.decomposeAllFields
(
surfaceSphTensorFields
fieldDecomposerList[proci]
);
fieldDecomposer.decomposeFields
(
surfaceSymmTensorFields
);
fieldDecomposer.decomposeFields(surfaceTensorFields);
// internal fields
fieldDecomposer.decomposeFields(dimScalarFields);
fieldDecomposer.decomposeFields(dimVectorFields);
fieldDecomposer.decomposeFields(dimSphTensorFields);
fieldDecomposer.decomposeFields(dimSymmTensorFields);
fieldDecomposer.decomposeFields(dimTensorFields);
if (times.size() == 1)
{
@ -1330,14 +1102,7 @@ int main(int argc, char *argv[])
// Point fields
if
(
pointScalarFields.size()
|| pointVectorFields.size()
|| pointSphTensorFields.size()
|| pointSymmTensorFields.size()
|| pointTensorFields.size()
)
if (!pointFieldCache.empty())
{
const labelIOList& pointProcAddressing = procAddressing
(
@ -1363,15 +1128,11 @@ int main(int argc, char *argv[])
)
);
}
const pointFieldDecomposer& pointDecomposer =
pointFieldDecomposerList[proci];
pointDecomposer.decomposeFields(pointScalarFields);
pointDecomposer.decomposeFields(pointVectorFields);
pointDecomposer.decomposeFields(pointSphTensorFields);
pointDecomposer.decomposeFields(pointSymmTensorFields);
pointDecomposer.decomposeFields(pointTensorFields);
pointFieldCache.decomposeAllFields
(
pointFieldDecomposerList[proci]
);
if (times.size() == 1)
{
@ -1382,9 +1143,9 @@ int main(int argc, char *argv[])
// If there is lagrangian data write it out
forAll(lagrangianPositions, cloudI)
forAll(lagrangianPositions, cloudi)
{
if (lagrangianPositions[cloudI].size())
if (lagrangianPositions[cloudi].size())
{
lagrangianFieldDecomposer fieldDecomposer
(
@ -1392,74 +1153,18 @@ int main(int argc, char *argv[])
procMesh,
faceProcAddressing,
cellProcAddressing,
cloudDirs[cloudI],
lagrangianPositions[cloudI],
cellParticles[cloudI]
cloudDirs[cloudi],
lagrangianPositions[cloudi],
cellParticles[cloudi]
);
// Lagrangian fields
{
fieldDecomposer.decomposeFields
(
cloudDirs[cloudI],
lagrangianLabelFields[cloudI]
);
fieldDecomposer.decomposeFieldFields
(
cloudDirs[cloudI],
lagrangianLabelFieldFields[cloudI]
);
fieldDecomposer.decomposeFields
(
cloudDirs[cloudI],
lagrangianScalarFields[cloudI]
);
fieldDecomposer.decomposeFieldFields
(
cloudDirs[cloudI],
lagrangianScalarFieldFields[cloudI]
);
fieldDecomposer.decomposeFields
(
cloudDirs[cloudI],
lagrangianVectorFields[cloudI]
);
fieldDecomposer.decomposeFieldFields
(
cloudDirs[cloudI],
lagrangianVectorFieldFields[cloudI]
);
fieldDecomposer.decomposeFields
(
cloudDirs[cloudI],
lagrangianSphTensorFields[cloudI]
);
fieldDecomposer.decomposeFieldFields
(
cloudDirs[cloudI],
lagrangianSphTensorFieldFields[cloudI]
);
fieldDecomposer.decomposeFields
(
cloudDirs[cloudI],
lagrangianSymmTensorFields[cloudI]
);
fieldDecomposer.decomposeFieldFields
(
cloudDirs[cloudI],
lagrangianSymmTensorFieldFields[cloudI]
);
fieldDecomposer.decomposeFields
(
cloudDirs[cloudI],
lagrangianTensorFields[cloudI]
);
fieldDecomposer.decomposeFieldFields
(
cloudDirs[cloudI],
lagrangianTensorFieldFields[cloudI]
);
}
lagrangianFieldCache.decomposeAllFields
(
cloudi,
cloudDirs[cloudi],
fieldDecomposer
);
}
}
@ -1506,38 +1211,17 @@ int main(int argc, char *argv[])
aMesh.writeDecomposition();
// Area fields
// ~~~~~~~~~~~
PtrList<areaScalarField> areaScalarFields;
PtrList<areaVectorField> areaVectorFields;
PtrList<areaSphericalTensorField> areaSphTensorFields;
PtrList<areaSymmTensorField> areaSymmTensorFields;
PtrList<areaTensorField> areaTensorFields;
// Area/edge fields
// ~~~~~~~~~~~~~~~~
// Edge fields (limited number of types)
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PtrList<edgeScalarField> edgeScalarFields;
faFieldDecomposer::fieldsCache areaFieldCache;
if (doDecompFields)
{
readFields(aMesh, objects, areaScalarFields);
readFields(aMesh, objects, areaVectorFields);
readFields(aMesh, objects, areaSphTensorFields);
readFields(aMesh, objects, areaSymmTensorFields);
readFields(aMesh, objects, areaTensorFields);
readFields(aMesh, objects, edgeScalarFields);
areaFieldCache.readAllFields(aMesh, objects);
}
const label nAreaFields =
(
areaScalarFields.size()
+ areaVectorFields.size()
+ areaSphTensorFields.size()
+ areaSymmTensorFields.size()
+ areaTensorFields.size()
+ edgeScalarFields.size()
);
const label nAreaFields = areaFieldCache.size();
Info<< endl;
Info<< "Finite area field transfer: "
@ -1634,13 +1318,7 @@ int main(int argc, char *argv[])
boundaryProcAddressing
);
fieldDecomposer.decomposeFields(areaScalarFields);
fieldDecomposer.decomposeFields(areaVectorFields);
fieldDecomposer.decomposeFields(areaSphTensorFields);
fieldDecomposer.decomposeFields(areaSymmTensorFields);
fieldDecomposer.decomposeFields(areaTensorFields);
fieldDecomposer.decomposeFields(edgeScalarFields);
areaFieldCache.decomposeAllFields(fieldDecomposer);
}
}
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2019-2021 OpenCFD Ltd.
Copyright (C) 2019-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -37,6 +37,7 @@ License
#include "DynamicList.H"
#include "fvFieldDecomposer.H"
#include "IOobjectList.H"
#include "PtrDynList.H"
#include "cellSet.H"
#include "faceSet.H"
#include "pointSet.H"
@ -178,32 +179,32 @@ bool Foam::domainDecomposition::writeDecomposition(const bool decomposeSets)
}
PtrList<const cellSet> cellSets;
PtrList<const faceSet> faceSets;
PtrList<const pointSet> pointSets;
PtrDynList<const cellSet> cellSets;
PtrDynList<const faceSet> faceSets;
PtrDynList<const pointSet> pointSets;
if (decomposeSets)
{
// Read sets
IOobjectList objects(*this, facesInstance(), "polyMesh/sets");
{
IOobjectList cSets(objects.lookupClass(cellSet::typeName));
forAllConstIters(cSets, iter)
IOobjectList sets(objects.lookupClass<cellSet>());
forAllConstIters(sets, iter)
{
cellSets.append(new cellSet(*iter()));
cellSets.append(new cellSet(*(iter.val())));
}
}
{
IOobjectList fSets(objects.lookupClass(faceSet::typeName));
forAllConstIters(fSets, iter)
IOobjectList sets(objects.lookupClass<faceSet>());
forAllConstIters(sets, iter)
{
faceSets.append(new faceSet(*iter()));
faceSets.append(new faceSet(*(iter.val())));
}
}
{
IOobjectList pSets(objects.lookupClass(pointSet::typeName));
forAllConstIters(pSets, iter)
IOobjectList sets(objects.lookupClass<pointSet>());
forAllConstIters(sets, iter)
{
pointSets.append(new pointSet(*iter()));
pointSets.append(new pointSet(*(iter.val())));
}
}
}
@ -225,13 +226,11 @@ bool Foam::domainDecomposition::writeDecomposition(const bool decomposeSets)
);
label maxProcCells = 0;
label maxProcFaces = 0;
label totProcFaces = 0;
label maxProcPatches = 0;
label totProcPatches = 0;
label maxProcFaces = 0;
// Write out the meshes
for (label proci = 0; proci < nProcs_; proci++)
@ -265,7 +264,6 @@ bool Foam::domainDecomposition::writeDecomposition(const bool decomposeSets)
{
// Mark the original face as used
// Remember to decrement the index by one (turning index)
//
label curF = mag(curFaceLabels[facei]) - 1;
faceLookup[curF] = facei;
@ -855,31 +853,35 @@ bool Foam::domainDecomposition::writeDecomposition(const bool decomposeSets)
Info<< "Number of cells = " << procMesh.nCells() << nl;
if (procMesh.nCells())
{
Info<< " Number of points = " << procMesh.nPoints() << nl;
}
maxProcCells = max(maxProcCells, procMesh.nCells());
label nBoundaryFaces = 0;
label nProcPatches = 0;
label nProcFaces = 0;
forAll(procMesh.boundaryMesh(), patchi)
for (const polyPatch& pp : procMesh.boundaryMesh())
{
if (isA<processorPolyPatch>(procMesh.boundaryMesh()[patchi]))
const auto* cpp = isA<processorPolyPatch>(pp);
if (cpp)
{
const processorPolyPatch& ppp =
refCast<const processorPolyPatch>
(
procMesh.boundaryMesh()[patchi]
);
const auto& procPatch = *cpp;
Info<< " Number of faces shared with processor "
<< ppp.neighbProcNo() << " = " << ppp.size() << endl;
<< procPatch.neighbProcNo() << " = "
<< procPatch.size() << nl;
nProcPatches++;
nProcFaces += ppp.size();
nProcFaces += procPatch.size();
++nProcPatches;
}
else
{
nBoundaryFaces += procMesh.boundaryMesh()[patchi].size();
nBoundaryFaces += pp.size();
}
}
@ -892,103 +894,79 @@ bool Foam::domainDecomposition::writeDecomposition(const bool decomposeSets)
totProcFaces += nProcFaces;
totProcPatches += nProcPatches;
maxProcPatches = max(maxProcPatches, nProcPatches);
maxProcFaces = max(maxProcFaces, nProcFaces);
maxProcPatches = max(maxProcPatches, nProcPatches);
// create and write the addressing information
labelIOList pointProcAddressing
(
IOobject
(
"pointProcAddressing",
procMesh.facesInstance(),
procMesh.meshSubDir,
procMesh,
IOobject::NO_READ,
IOobject::NO_WRITE
),
procPointAddressing_[proci]
);
pointProcAddressing.write();
// Write the addressing information
labelIOList faceProcAddressing
IOobject ioAddr
(
IOobject
(
"faceProcAddressing",
procMesh.facesInstance(),
procMesh.meshSubDir,
procMesh,
IOobject::NO_READ,
IOobject::NO_WRITE
),
procFaceAddressing_[proci]
"procAddressing",
procMesh.facesInstance(),
polyMesh::meshSubDir,
procMesh.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE,
false // not registered
);
faceProcAddressing.write();
labelIOList cellProcAddressing
(
IOobject
(
"cellProcAddressing",
procMesh.facesInstance(),
procMesh.meshSubDir,
procMesh,
IOobject::NO_READ,
IOobject::NO_WRITE
),
procCellAddressing_[proci]
);
cellProcAddressing.write();
// pointProcAddressing
ioAddr.rename("pointProcAddressing");
IOListRef<label>(ioAddr, procPointAddressing_[proci]).write();
// faceProcAddressing
ioAddr.rename("faceProcAddressing");
IOListRef<label>(ioAddr, procFaceAddressing_[proci]).write();
// cellProcAddressing
ioAddr.rename("cellProcAddressing");
IOListRef<label>(ioAddr, procCellAddressing_[proci]).write();
// Write patch map for backwards compatibility.
// (= identity map for original patches, -1 for processor patches)
label nMeshPatches = curPatchSizes.size();
labelList procBoundaryAddressing(identity(nMeshPatches));
procBoundaryAddressing.setSize(nMeshPatches+nProcPatches, -1);
labelList procBoundaryAddr(identity(nMeshPatches));
procBoundaryAddr.resize(nMeshPatches+nProcPatches, -1);
labelIOList boundaryProcAddressing
(
IOobject
(
"boundaryProcAddressing",
procMesh.facesInstance(),
procMesh.meshSubDir,
procMesh,
IOobject::NO_READ,
IOobject::NO_WRITE
),
procBoundaryAddressing
);
boundaryProcAddressing.write();
// boundaryProcAddressing
ioAddr.rename("boundaryProcAddressing");
IOListRef<label>(ioAddr, procBoundaryAddr).write();
}
scalar avgProcCells = scalar(nCells())/nProcs_;
scalar avgProcPatches = scalar(totProcPatches)/nProcs_;
scalar avgProcFaces = scalar(totProcFaces)/nProcs_;
// In case of all faces on one processor. Just to avoid division by 0.
if (totProcPatches == 0)
{
avgProcPatches = 1;
}
if (totProcFaces == 0)
{
avgProcFaces = 1;
}
// Summary stats
Info<< nl
<< "Number of processor faces = " << totProcFaces/2 << nl
<< "Max number of cells = " << maxProcCells
<< " (" << 100.0*(maxProcCells-avgProcCells)/avgProcCells
<< "% above average " << avgProcCells << ")" << nl
<< "Max number of processor patches = " << maxProcPatches
<< " (" << 100.0*(maxProcPatches-avgProcPatches)/avgProcPatches
<< "% above average " << avgProcPatches << ")" << nl
<< "Max number of faces between processors = " << maxProcFaces
<< " (" << 100.0*(maxProcFaces-avgProcFaces)/avgProcFaces
<< "% above average " << avgProcFaces << ")" << nl
<< endl;
<< "Number of processor faces = " << (totProcFaces/2) << nl
<< "Max number of cells = " << maxProcCells;
if (maxProcCells != nCells())
{
scalar avgValue = scalar(nCells())/nProcs_;
Info<< " (" << 100.0*(maxProcCells-avgValue)/avgValue
<< "% above average " << avgValue << ')';
}
Info<< nl;
Info<< "Max number of processor patches = " << maxProcPatches;
if (totProcPatches)
{
scalar avgValue = scalar(totProcPatches)/nProcs_;
Info<< " (" << 100.0*(maxProcPatches-avgValue)/avgValue
<< "% above average " << avgValue << ')';
}
Info<< nl;
Info<< "Max number of faces between processors = " << maxProcFaces;
if (totProcFaces)
{
scalar avgValue = scalar(totProcFaces)/nProcs_;
Info<< " (" << 100.0*(maxProcFaces-avgValue)/avgValue
<< "% above average " << avgValue << ')';
}
Info<< nl << endl;
return true;
}

View File

@ -1,90 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
-------------------------------------------------------------------------------
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 "GeometricField.H"
#include "readFields.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type, template<class> class PatchField, class GeoMesh>
void Foam::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>());
// 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::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

@ -1,48 +0,0 @@
{
// Foam version 2.1 changes the addressing of faces in faceProcAddressing
// The following code checks and modifies the addressing for cases where
// the decomposition has been done with the foam2.0 and earlier tools, but
// the reconstruction is attempted with version 2.1 or later
label minFaceIndex = labelMax;
PtrList<labelIOList>& faceProcAddressing = procMeshes.faceProcAddressing();
forAll(faceProcAddressing, proci)
{
const labelList& curFaceAddr = faceProcAddressing[proci];
forAll(curFaceAddr, facei)
{
if (mag(curFaceAddr[facei]) < minFaceIndex)
{
minFaceIndex = mag(curFaceAddr[facei]);
}
}
}
if (minFaceIndex < 1)
{
WarningInFunction
<< "parallel decomposition addressing." << endl
<< "It looks like you are trying to reconstruct the case "
<< "decomposed with an earlier version of FOAM, which could\n"
<< "potentially cause compatibility problems. The code will "
<< "attempt to update the addressing automatically; in case of\n"
<< "failure, please repeat the decomposition of the case using "
<< "the current version fo decomposePar"
<< endl;
forAll(faceProcAddressing, proci)
{
labelList& curFaceAddr = faceProcAddressing[proci];
forAll(curFaceAddr, facei)
{
curFaceAddr[facei] += sign(curFaceAddr[facei]);
}
faceProcAddressing[proci].write();
}
}
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2015-2021 OpenCFD Ltd.
Copyright (C) 2015-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -334,11 +334,6 @@ int main(int argc, char *argv[])
// Read all meshes and addressing to reconstructed mesh
processorMeshes procMeshes(databases, regionName);
// Check face addressing for meshes that have been decomposed
// with a very old foam version
#include "checkFaceAddressingComp.H"
// Loop over all times
forAll(timeDirs, timei)
{
@ -362,11 +357,11 @@ int main(int argc, char *argv[])
}
// Check if any new meshes need to be read.
fvMesh::readUpdateState meshStat = mesh.readUpdate();
polyMesh::readUpdateState meshStat = mesh.readUpdate();
fvMesh::readUpdateState procStat = procMeshes.readUpdate();
polyMesh::readUpdateState procStat = procMeshes.readUpdate();
if (procStat == fvMesh::POINTS_MOVED)
if (procStat == polyMesh::POINTS_MOVED)
{
// Reconstruct the points for moving mesh cases and write
// them out
@ -407,83 +402,7 @@ int main(int argc, char *argv[])
procMeshes.boundaryProcAddressing()
);
reconstructor.reconstructFvVolumeInternalFields<scalar>
(
objects,
selectedFields
);
reconstructor.reconstructFvVolumeInternalFields<vector>
(
objects,
selectedFields
);
reconstructor.reconstructFvVolumeInternalFields<sphericalTensor>
(
objects,
selectedFields
);
reconstructor.reconstructFvVolumeInternalFields<symmTensor>
(
objects,
selectedFields
);
reconstructor.reconstructFvVolumeInternalFields<tensor>
(
objects,
selectedFields
);
reconstructor.reconstructFvVolumeFields<scalar>
(
objects,
selectedFields
);
reconstructor.reconstructFvVolumeFields<vector>
(
objects,
selectedFields
);
reconstructor.reconstructFvVolumeFields<sphericalTensor>
(
objects,
selectedFields
);
reconstructor.reconstructFvVolumeFields<symmTensor>
(
objects,
selectedFields
);
reconstructor.reconstructFvVolumeFields<tensor>
(
objects,
selectedFields
);
reconstructor.reconstructFvSurfaceFields<scalar>
(
objects,
selectedFields
);
reconstructor.reconstructFvSurfaceFields<vector>
(
objects,
selectedFields
);
reconstructor.reconstructFvSurfaceFields<sphericalTensor>
(
objects,
selectedFields
);
reconstructor.reconstructFvSurfaceFields<symmTensor>
(
objects,
selectedFields
);
reconstructor.reconstructFvSurfaceFields<tensor>
(
objects,
selectedFields
);
reconstructor.reconstructAllFields(objects, selectedFields);
if (reconstructor.nReconstructed() == 0)
{
@ -515,31 +434,7 @@ int main(int argc, char *argv[])
procMeshes.boundaryProcAddressing()
);
reconstructor.reconstructFields<scalar>
(
objects,
selectedFields
);
reconstructor.reconstructFields<vector>
(
objects,
selectedFields
);
reconstructor.reconstructFields<sphericalTensor>
(
objects,
selectedFields
);
reconstructor.reconstructFields<symmTensor>
(
objects,
selectedFields
);
reconstructor.reconstructFields<tensor>
(
objects,
selectedFields
);
reconstructor.reconstructAllFields(objects, selectedFields);
if (reconstructor.nReconstructed() == 0)
{
@ -631,78 +526,7 @@ int main(int argc, char *argv[])
reconstructor.reconstructPositions(cloudName);
reconstructor.reconstructFields<label>
(
cloudName,
cloudObjs,
selectedLagrangianFields
);
reconstructor.reconstructFieldFields<label>
(
cloudName,
cloudObjs,
selectedLagrangianFields
);
reconstructor.reconstructFields<scalar>
(
cloudName,
cloudObjs,
selectedLagrangianFields
);
reconstructor.reconstructFieldFields<scalar>
(
cloudName,
cloudObjs,
selectedLagrangianFields
);
reconstructor.reconstructFields<vector>
(
cloudName,
cloudObjs,
selectedLagrangianFields
);
reconstructor.reconstructFieldFields<vector>
(
cloudName,
cloudObjs,
selectedLagrangianFields
);
reconstructor.reconstructFields<sphericalTensor>
(
cloudName,
cloudObjs,
selectedLagrangianFields
);
reconstructor.reconstructFieldFields<sphericalTensor>
(
cloudName,
cloudObjs,
selectedLagrangianFields
);
reconstructor.reconstructFields<symmTensor>
(
cloudName,
cloudObjs,
selectedLagrangianFields
);
reconstructor.reconstructFieldFields<symmTensor>
(
cloudName,
cloudObjs,
selectedLagrangianFields
);
reconstructor.reconstructFields<tensor>
(
cloudName,
cloudObjs,
selectedLagrangianFields
);
reconstructor.reconstructFieldFields<tensor>
reconstructor.reconstructAllFields
(
cloudName,
cloudObjs,
@ -724,12 +548,12 @@ int main(int argc, char *argv[])
}
else if
(
objects.lookupClass(areaScalarField::typeName).size()
|| objects.lookupClass(areaVectorField::typeName).size()
|| objects.lookupClass(areaSphericalTensorField::typeName).size()
|| objects.lookupClass(areaSymmTensorField::typeName).size()
|| objects.lookupClass(areaTensorField::typeName).size()
|| objects.lookupClass(edgeScalarField::typeName).size()
objects.count<areaScalarField>()
|| objects.count<areaVectorField>()
|| objects.count<areaSphericalTensorField>()
|| objects.count<areaSymmTensorField>()
|| objects.count<areaTensorField>()
|| objects.count<edgeScalarField>()
)
{
Info << "Reconstructing FA fields" << nl << endl;
@ -747,13 +571,7 @@ int main(int argc, char *argv[])
procFaMeshes.boundaryProcAddressing()
);
reconstructor.reconstructFaAreaFields<scalar>(objects);
reconstructor.reconstructFaAreaFields<vector>(objects);
reconstructor.reconstructFaAreaFields<sphericalTensor>(objects);
reconstructor.reconstructFaAreaFields<symmTensor>(objects);
reconstructor.reconstructFaAreaFields<tensor>(objects);
reconstructor.reconstructFaEdgeFields<scalar>(objects);
reconstructor.reconstructAllFields(objects);
}
else
{
@ -782,21 +600,19 @@ int main(int argc, char *argv[])
polyMesh::meshSubDir/"sets"
);
IOobjectList cSets(objects.lookupClass(cellSet::typeName));
forAllConstIters(cSets, iter)
for (const word& setName : objects.sortedNames<cellSet>())
{
cSetNames.insert(iter.key(), cSetNames.size());
cSetNames.insert(setName, cSetNames.size());
}
IOobjectList fSets(objects.lookupClass(faceSet::typeName));
forAllConstIters(fSets, iter)
for (const word& setName : objects.sortedNames<faceSet>())
{
fSetNames.insert(iter.key(), fSetNames.size());
fSetNames.insert(setName, fSetNames.size());
}
IOobjectList pSets(objects.lookupClass(pointSet::typeName));
forAllConstIters(pSets, iter)
for (const word& setName : objects.sortedNames<pointSet>())
{
pSetNames.insert(iter.key(), pSetNames.size());
pSetNames.insert(setName, pSetNames.size());
}
}
@ -840,30 +656,25 @@ int main(int argc, char *argv[])
const labelList& cellMap =
procMeshes.cellProcAddressing()[proci];
IOobjectList cSets
(
objects.lookupClass(cellSet::typeName)
);
forAllConstIters(cSets, iter)
for (const IOobject& io : objects.sorted<cellSet>())
{
// Load cellSet
const cellSet procSet(*iter());
label setI = cSetNames[iter.key()];
if (!cellSets.set(setI))
const cellSet procSet(io);
const label seti = cSetNames[io.name()];
if (!cellSets.set(seti))
{
cellSets.set
(
setI,
seti,
new cellSet
(
mesh,
iter.key(),
io.name(),
procSet.size()
)
);
}
cellSet& cSet = cellSets[setI];
cellSet& cSet = cellSets[seti];
cSet.instance() = runTime.timeName();
for (const label celli : procSet)
@ -876,30 +687,25 @@ int main(int argc, char *argv[])
const labelList& faceMap =
procMeshes.faceProcAddressing()[proci];
IOobjectList fSets
(
objects.lookupClass(faceSet::typeName)
);
forAllConstIters(fSets, iter)
for (const IOobject& io : objects.sorted<faceSet>())
{
// Load faceSet
const faceSet procSet(*iter());
label setI = fSetNames[iter.key()];
if (!faceSets.set(setI))
const faceSet procSet(io);
const label seti = fSetNames[io.name()];
if (!faceSets.set(seti))
{
faceSets.set
(
setI,
seti,
new faceSet
(
mesh,
iter.key(),
io.name(),
procSet.size()
)
);
}
faceSet& fSet = faceSets[setI];
faceSet& fSet = faceSets[seti];
fSet.instance() = runTime.timeName();
for (const label facei : procSet)
@ -911,32 +717,28 @@ int main(int argc, char *argv[])
const labelList& pointMap =
procMeshes.pointProcAddressing()[proci];
IOobjectList pSets
(
objects.lookupClass(pointSet::typeName)
);
forAllConstIters(pSets, iter)
for (const IOobject& io : objects.sorted<pointSet>())
{
// Load pointSet
const pointSet propSet(*iter());
label setI = pSetNames[iter.key()];
if (!pointSets.set(setI))
const pointSet procSet(io);
const label seti = pSetNames[io.name()];
if (!pointSets.set(seti))
{
pointSets.set
(
setI,
seti,
new pointSet
(
mesh,
iter.key(),
propSet.size()
io.name(),
procSet.size()
)
);
}
pointSet& pSet = pointSets[setI];
pointSet& pSet = pointSets[seti];
pSet.instance() = runTime.timeName();
for (const label pointi : propSet)
for (const label pointi : procSet)
{
pSet.insert(pointMap[pointi]);
}

View File

@ -522,14 +522,11 @@ void writeMaps
Info<< " pointProcAddressing" << endl;
ioAddr.rename("pointProcAddressing");
labelIOList(ioAddr, pointProcAddressing).write();
IOListRef<label>(ioAddr, pointProcAddressing).write();
// From processor face to reconstructed mesh face
Info<< " faceProcAddressing" << endl;
ioAddr.rename("faceProcAddressing");
labelIOList faceProcAddr(ioAddr, faceProcAddressing);
// Now add turning index to faceProcAddressing.
@ -572,17 +569,15 @@ void writeMaps
// From processor cell to reconstructed mesh cell
Info<< " cellProcAddressing" << endl;
ioAddr.rename("cellProcAddressing");
labelIOList(ioAddr, cellProcAddressing).write();
IOListRef<label>(ioAddr, cellProcAddressing).write();
// From processor patch to reconstructed mesh patch
Info<< " boundaryProcAddressing" << endl;
ioAddr.rename("boundaryProcAddressing");
labelIOList(ioAddr, boundProcAddressing).write();
IOListRef<label>(ioAddr, boundProcAddressing).write();
Info<< endl;
}

View File

@ -1,6 +1,13 @@
passivePositionParticleCloud.C
parLagrangianRedistributor.C
parFvFieldReconstructor.C
parLagrangianDistributor.C
parLagrangianDistributorFields.C
parPointFieldDistributor.C
parFaFieldDistributorCache.C
parFvFieldDistributor.C
parFvFieldDistributorFields.C
loadOrCreateMesh.C
redistributePar.C

View File

@ -27,6 +27,7 @@ License
\*---------------------------------------------------------------------------*/
#include "loadOrCreateMesh.H"
#include "faMesh.H"
#include "Pstream.H"
#include "OSspecific.H"
@ -66,6 +67,26 @@ Foam::boolList Foam::haveMeshFile
}
void Foam::removeProcAddressing(const faMesh& mesh)
{
IOobject ioAddr
(
"procAddressing",
mesh.facesInstance(),
faMesh::meshSubDir,
mesh.thisDb()
);
for (const auto prefix : {"boundary", "edge", "face", "point"})
{
ioAddr.rename(prefix + word("ProcAddressing"));
const fileName procFile(ioAddr.objectPath());
Foam::rm(procFile);
}
}
void Foam::removeProcAddressing(const polyMesh& mesh)
{
IOobject ioAddr

View File

@ -45,6 +45,9 @@ SourceFiles
namespace Foam
{
// Forward Declarations
class faMesh;
//- Check for availability of specified mesh file (default: "faces")
boolList haveMeshFile
(
@ -55,6 +58,9 @@ boolList haveMeshFile
);
//- Remove procAddressing
void removeProcAddressing(const faMesh& mesh);
//- Remove procAddressing
void removeProcAddressing(const polyMesh& mesh);

View File

@ -0,0 +1,164 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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 "parFaFieldDistributorCache.H"
#include "areaFields.H"
#include "edgeFields.H"
#include "fieldsDistributor.H"
#include "faMeshDistributor.H"
#include "faMeshSubset.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class GeoField>
void Foam::parFaFieldDistributorCache::redistributeAndWrite
(
const faMeshDistributor& distributor,
PtrList<GeoField>& fields,
const bool isWriteProc
)
{
for (GeoField& fld : fields)
{
tmp<GeoField> tfld = distributor.distributeField(fld);
if (isWriteProc)
{
tfld().write();
}
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::parFaFieldDistributorCache::read
(
const Time& baseRunTime,
const fileName& proc0CaseName,
const bool decompose, // i.e. read from undecomposed case
const boolList& areaMeshOnProc,
const fileName& areaMeshInstance,
faMesh& mesh
)
{
Time& runTime = const_cast<Time&>(mesh.time());
const bool oldProcCase = runTime.processorCase();
autoPtr<faMeshSubset> subsetterPtr;
// Missing an area mesh somewhere?
if (areaMeshOnProc.found(false))
{
// A zero-sized mesh with boundaries.
// This is used to create zero-sized fields.
subsetterPtr.reset(new faMeshSubset(mesh, zero{}));
// Deregister from polyMesh ...
auto& obr = const_cast<objectRegistry&>
(
subsetterPtr->subMesh().thisDb()
);
obr.checkOut(faMesh::typeName);
obr.checkOut("faBoundaryMesh");
obr.checkOut("faSchemes");
obr.checkOut("faSolution");
}
// Get original objects (before incrementing time!)
if (Pstream::master() && decompose)
{
runTime.caseName() = baseRunTime.caseName();
runTime.processorCase(false);
}
IOobjectList objects(mesh.mesh(), runTime.timeName());
if (Pstream::master() && decompose)
{
runTime.caseName() = proc0CaseName;
runTime.processorCase(oldProcCase);
}
Info<< "From time " << runTime.timeName()
<< " mesh:" << mesh.mesh().objectRegistry::objectRelPath()
<< " have objects:" << objects.names() << endl;
if (Pstream::master() && decompose)
{
runTime.caseName() = baseRunTime.caseName();
runTime.processorCase(false);
}
#undef doFieldReading
#define doFieldReading(Storage) \
fieldsDistributor::readFields \
( \
areaMeshOnProc, mesh, subsetterPtr, objects, Storage, \
true /* (deregister field) */ \
);
// areaFields
doFieldReading(scalarAreaFields_);
doFieldReading(vectorAreaFields_);
doFieldReading(sphericalTensorAreaFields_);
doFieldReading(symmTensorAreaFields_);
doFieldReading(tensorAreaFields_);
// edgeFields
doFieldReading(scalarEdgeFields_);
doFieldReading(vectorEdgeFields_);
doFieldReading(tensorEdgeFields_);
doFieldReading(sphericalTensorEdgeFields_);
doFieldReading(symmTensorEdgeFields_);
#undef doFieldReading
}
void Foam::parFaFieldDistributorCache::redistributeAndWrite
(
const faMeshDistributor& distributor,
const bool isWriteProc
)
{
redistributeAndWrite(distributor, scalarAreaFields_, isWriteProc);
redistributeAndWrite(distributor, vectorAreaFields_, isWriteProc);
redistributeAndWrite(distributor, sphericalTensorAreaFields_, isWriteProc);
redistributeAndWrite(distributor, symmTensorAreaFields_, isWriteProc);
redistributeAndWrite(distributor, tensorAreaFields_, isWriteProc);
redistributeAndWrite(distributor, scalarEdgeFields_, isWriteProc);
redistributeAndWrite(distributor, vectorEdgeFields_, isWriteProc);
redistributeAndWrite(distributor, sphericalTensorEdgeFields_, isWriteProc);
redistributeAndWrite(distributor, symmTensorEdgeFields_, isWriteProc);
redistributeAndWrite(distributor, tensorEdgeFields_, isWriteProc);
}
// ************************************************************************* //

View File

@ -0,0 +1,128 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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::parFaFieldDistributorCache
Description
Simple container to manage read/write, redistribute finiteArea fields.
SourceFiles
parFaFieldDistributorCache.C
\*---------------------------------------------------------------------------*/
#ifndef Foam_parFaFieldDistributorCache_H
#define Foam_parFaFieldDistributorCache_H
#include "faMesh.H"
#include "faMeshDistributor.H"
#include "areaFieldsFwd.H"
#include "edgeFieldsFwd.H"
#include "PtrList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class parFaFieldDistributorCache Declaration
\*---------------------------------------------------------------------------*/
class parFaFieldDistributorCache
{
// Private Data
#undef declareField
#define declareField(Type) \
PtrList<GeometricField<Type, faPatchField, areaMesh>> Type##AreaFields_; \
PtrList<GeometricField<Type, faePatchField, edgeMesh>> Type##EdgeFields_;
declareField(scalar);
declareField(vector);
declareField(sphericalTensor);
declareField(symmTensor);
declareField(tensor);
#undef declareField
// Private Member Functions
//- Redistribute and write fields of given type (file-scope use)
template<class GeoField>
static void redistributeAndWrite
(
const faMeshDistributor& distributor,
PtrList<GeoField>& fields,
const bool isWriteProc
);
public:
// Constructors
//- No copy construct
parFaFieldDistributorCache(const parFaFieldDistributorCache&) = delete;
//- No copy assignment
void operator=(const parFaFieldDistributorCache&) = delete;
//- Default construct
parFaFieldDistributorCache() = default;
// Member Functions
//- Read distributed fields
void read
(
const Time& baseRunTime,
const fileName& proc0CaseName,
const bool decompose, // i.e. read from undecomposed case
const boolList& areaMeshOnProc,
const fileName& areaMeshInstance,
faMesh& mesh
);
void redistributeAndWrite
(
const faMeshDistributor& distributor,
const bool isWriteProc
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2015 OpenFOAM Foundation
Copyright (C) 2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -25,48 +26,47 @@ License
\*---------------------------------------------------------------------------*/
#include "parFvFieldReconstructor.H"
#include "parFvFieldDistributor.H"
#include "bitSet.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
int Foam::parFvFieldDistributor::verbose_ = 1;
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::parFvFieldReconstructor::createPatchFaceMaps()
void Foam::parFvFieldDistributor::createPatchFaceMaps()
{
const fvBoundaryMesh& fvb = procMesh_.boundary();
const fvBoundaryMesh& fvb = srcMesh_.boundary();
patchFaceMaps_.setSize(fvb.size());
forAll(fvb, patchI)
patchFaceMaps_.resize(fvb.size());
forAll(fvb, patchi)
{
if (!isA<processorFvPatch>(fvb[patchI]))
if (!isA<processorFvPatch>(fvb[patchi]))
{
// Create map for patch faces only
// Mark all used elements (i.e. destination patch faces)
boolList faceIsUsed(distMap_.faceMap().constructSize(), false);
const polyPatch& basePatch = baseMesh_.boundaryMesh()[patchI];
forAll(basePatch, i)
{
faceIsUsed[basePatch.start()+i] = true;
}
// Create compact map for patch faces only
// - compact for used faces only (destination patch faces)
labelList oldToNewSub;
labelList oldToNewConstruct;
// Copy face map
patchFaceMaps_.set
(
patchI,
patchi,
new mapDistributeBase(distMap_.faceMap())
);
// Compact out unused elements
labelList oldToNewSub;
labelList oldToNewConstruct;
patchFaceMaps_[patchI].compact
patchFaceMaps_[patchi].compactRemoteData
(
faceIsUsed,
procMesh_.nFaces(), // maximum index of subMap
bitSet(tgtMesh_.boundaryMesh()[patchi].range()),
oldToNewSub,
oldToNewConstruct,
srcMesh_.nFaces(), // max index of subMap
UPstream::msgType()
);
//Pout<< "patchMap:" << patchFaceMaps_[patchI] << endl;
//Pout<< "patchMap:" << patchFaceMaps_[patchi] << endl;
}
}
}
@ -74,16 +74,16 @@ void Foam::parFvFieldReconstructor::createPatchFaceMaps()
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::parFvFieldReconstructor::parFvFieldReconstructor
Foam::parFvFieldDistributor::parFvFieldDistributor
(
fvMesh& baseMesh,
const fvMesh& procMesh,
const fvMesh& srcMesh,
fvMesh& tgtMesh,
const mapDistributePolyMesh& distMap,
const bool isWriteProc
)
:
baseMesh_(baseMesh),
procMesh_(procMesh),
srcMesh_(srcMesh),
tgtMesh_(tgtMesh),
distMap_(distMap),
isWriteProc_(isWriteProc)
{
@ -93,7 +93,7 @@ Foam::parFvFieldReconstructor::parFvFieldReconstructor
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::parFvFieldReconstructor::reconstructPoints()
void Foam::parFvFieldDistributor::reconstructPoints()
{
// Reconstruct the points for moving mesh cases and write them out
distributedFieldMapper mapper
@ -101,11 +101,13 @@ void Foam::parFvFieldReconstructor::reconstructPoints()
labelUList::null(),
distMap_.pointMap()
);
pointField basePoints(procMesh_.points(), mapper);
baseMesh_.movePoints(basePoints);
pointField newPoints(srcMesh_.points(), mapper);
tgtMesh_.movePoints(newPoints);
if (Pstream::master())
{
baseMesh_.write();
tgtMesh_.write();
}
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2015 OpenFOAM Foundation
Copyright (C) 2018 OpenCFD Ltd.
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -25,22 +25,24 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::parFvFieldReconstructor
Foam::parFvFieldDistributor
Description
Finite volume reconstructor for volume and surface fields.
Runs in parallel. Reconstructs from procMesh to baseMesh. baseMesh
is non-zero cells on processor0 only.
Runs in parallel.
Reconstructs/redistributes from procMesh to baseMesh.
baseMesh is non-zero cells on processor0 only.
SourceFiles
parFvFieldReconstructor.C
parFvFieldReconstructorFields.C
parFvFieldDistributor.C
parFvFieldDistributorFields.C
parFvFieldDistributorTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef parFvFieldReconstructor_H
#define parFvFieldReconstructor_H
#ifndef Foam_parFvFieldDistributor_H
#define Foam_parFvFieldDistributor_H
#include "PtrList.H"
#include "fvMesh.H"
@ -50,34 +52,34 @@ SourceFiles
namespace Foam
{
// Forward declarations
// Forward Declarations
class mapDistributePolyMesh;
class mapDistributeBase;
class IOobjectList;
/*---------------------------------------------------------------------------*\
Class parFvFieldReconstructor Declaration
Class parFvFieldDistributor Declaration
\*---------------------------------------------------------------------------*/
class parFvFieldReconstructor
class parFvFieldDistributor
{
// Private data
// Private Data
//- Reconstructed mesh reference
fvMesh& baseMesh_;
//- Processor mesh reference (source mesh)
const fvMesh& srcMesh_;
//- Processor mesh reference
const fvMesh& procMesh_;
//- Destination mesh reference (eg, reconstructed mesh)
fvMesh& tgtMesh_;
//- Distribution map reference
const mapDistributePolyMesh& distMap_;
//- Do I need to to write (usually master only)
const bool isWriteProc_;
//- Patch mappers
PtrList<mapDistributeBase> patchFaceMaps_;
//- Do I need to write (eg, master only for reconstruct)
bool isWriteProc_;
// Private Member Functions
@ -85,21 +87,30 @@ class parFvFieldReconstructor
void createPatchFaceMaps();
//- No copy construct
parFvFieldReconstructor(const parFvFieldReconstructor&) = delete;
parFvFieldDistributor(const parFvFieldDistributor&) = delete;
//- No copy assignment
void operator=(const parFvFieldReconstructor&) = delete;
void operator=(const parFvFieldDistributor&) = delete;
public:
//- Output verbosity when writing
static int verbose_;
// Constructors
//- Construct from components
parFvFieldReconstructor
//
// \param srcMesh The source mesh (eg, processor)
// \param tgtMesh The target mesh (eg, reconstructed)
// \param distMap The distribution map
// \param isWriteProc Tagged for output writing (on this proc)
parFvFieldDistributor
(
fvMesh& baseMesh,
const fvMesh& procMesh,
const fvMesh& srcMesh,
fvMesh& tgtMesh,
const mapDistributePolyMesh& distMap,
const bool isWriteProc
);
@ -107,61 +118,85 @@ public:
// Member Functions
//- Reconstruct volume internal field
//- Get status of write enabled (on this proc)
bool isWriteProc() const noexcept
{
return isWriteProc_;
}
//- Change status of write enabled (on this proc)
bool isWriteProc(const bool on) noexcept
{
bool old(isWriteProc_);
isWriteProc_ = on;
return old;
}
//- Helper: reconstruct and write mesh points
// (note: should be moved to something like processorMeshes class)
void reconstructPoints();
//- Distribute all fields for known field types
void distributeAllFields
(
const IOobjectList& objects,
const wordRes& selectedFields
) const;
//- Redistribute volume internal field
template<class Type>
tmp<DimensionedField<Type, volMesh>>
reconstructFvVolumeInternalField
distributeField
(
const DimensionedField<Type, volMesh>&
) const;
//- Read and reconstruct volume internal field
//- Read and distribute volume internal field
template<class Type>
tmp<DimensionedField<Type, volMesh>>
reconstructFvVolumeInternalField(const IOobject& fieldIoObject) const;
distributeInternalField(const IOobject& fieldObject) const;
//- Reconstruct volume field
//- Redistribute volume field
template<class Type>
tmp<GeometricField<Type, fvPatchField, volMesh>>
reconstructFvVolumeField
distributeField
(
const GeometricField<Type, fvPatchField, volMesh>& fld
) const;
//- Read and reconstruct volume field
//- Read and distribute volume field
template<class Type>
tmp<GeometricField<Type, fvPatchField, volMesh>>
reconstructFvVolumeField(const IOobject& fieldIoObject) const;
distributeVolumeField(const IOobject& fieldObject) const;
//- Reconstruct surface field
//- Redistribute surface field
template<class Type>
tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
reconstructFvSurfaceField
distributeField
(
const GeometricField<Type, fvsPatchField, surfaceMesh>&
) const;
//- Read and reconstruct surface field
//- Read and distribute surface field
template<class Type>
tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
reconstructFvSurfaceField(const IOobject& fieldIoObject) const;
distributeSurfaceField(const IOobject& fieldObject) const;
//- Read, reconstruct and write all/selected volume internal fields
//- Read, redistribute and write all/selected volume internal fields
template<class Type>
label reconstructFvVolumeInternalFields
label distributeInternalFields
(
const IOobjectList& objects,
const wordRes& selectedFields = wordRes()
) const;
//- Read, reconstruct and write all/selected volume fields
//- Read, redistribute and write all/selected volume fields
template<class Type>
label reconstructFvVolumeFields
label distributeVolumeFields
(
const IOobjectList& objects,
const wordRes& selectedFields = wordRes()
@ -169,15 +204,11 @@ public:
//- Read, reconstruct and write all/selected surface fields
template<class Type>
label reconstructFvSurfaceFields
label distributeSurfaceFields
(
const IOobjectList& objects,
const wordRes& selectedFields = wordRes()
) const;
//- Helper: reconstruct and write mesh points
// (note: should be moved to something like processorMeshes class)
void reconstructPoints();
};
@ -188,7 +219,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "parFvFieldReconstructorFields.C"
# include "parFvFieldDistributorTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -23,55 +23,40 @@ License
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Global
readFields
Description
SourceFiles
readFields.C
\*---------------------------------------------------------------------------*/
#ifndef readFields_H
#define readFields_H
#include "parFvFieldDistributor.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "IOobjectList.H"
#include "PtrList.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
void Foam::parFvFieldDistributor::distributeAllFields
(
const IOobjectList& objects,
const wordRes& selectedFields
) const
{
// Read the fields and hold on the pointer list
template<class Type, template<class> class PatchField, class GeoMesh>
void readFields
(
const typename GeoMesh::Mesh& mesh,
const IOobjectList& objects,
PtrList<GeometricField<Type, PatchField, GeoMesh>>& fields,
const bool readOldTime
);
do
{
#undef doLocalCode
#define doLocalCode(Method) \
{ \
this->Method <scalar> (objects, selectedFields); \
this->Method <vector> (objects, selectedFields); \
this->Method <sphericalTensor> (objects, selectedFields); \
this->Method <symmTensor> (objects, selectedFields); \
this->Method <tensor> (objects, selectedFields); \
}
// Read the fields and hold on the pointer list
template<class Mesh, class GeoField>
void readFields
(
const Mesh& mesh,
const IOobjectList& objects,
PtrList<GeoField>& fields
);
doLocalCode(distributeInternalFields);
doLocalCode(distributeVolumeFields);
doLocalCode(distributeSurfaceFields);
#undef doLocalCode
}
while (false);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "readFields.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -26,7 +26,7 @@ License
\*---------------------------------------------------------------------------*/
#include "parFvFieldReconstructor.H"
#include "parFvFieldDistributor.H"
#include "Time.H"
#include "PtrList.H"
#include "fvPatchFields.H"
@ -44,36 +44,33 @@ License
template<class Type>
Foam::tmp<Foam::DimensionedField<Type, Foam::volMesh>>
Foam::parFvFieldReconstructor::reconstructFvVolumeInternalField
Foam::parFvFieldDistributor::distributeField
(
const DimensionedField<Type, volMesh>& fld
) const
{
// Create internalField by remote mapping
distributedFieldMapper mapper
(
labelUList::null(),
distMap_.cellMap()
);
Field<Type> internalField(fld, mapper);
// Construct a volField
IOobject baseIO
(
fld.name(),
baseMesh_.time().timeName(),
fld.local(),
baseMesh_,
IOobject::NO_READ,
IOobject::NO_WRITE
);
auto tfield = tmp<DimensionedField<Type, volMesh>>::New
(
baseIO,
baseMesh_,
IOobject
(
fld.name(),
tgtMesh_.time().timeName(),
fld.local(),
tgtMesh_,
IOobject::NO_READ,
IOobject::NO_WRITE
),
tgtMesh_,
fld.dimensions(),
internalField
Field<Type>(fld, mapper)
);
tfield.ref().oriented() = fld.oriented();
@ -82,98 +79,86 @@ Foam::parFvFieldReconstructor::reconstructFvVolumeInternalField
}
template<class Type>
Foam::tmp<Foam::DimensionedField<Type, Foam::volMesh>>
Foam::parFvFieldReconstructor::reconstructFvVolumeInternalField
(
const IOobject& fieldIoObject
) const
{
// Read the field
DimensionedField<Type, volMesh> fld
(
fieldIoObject,
procMesh_
);
// Distribute onto baseMesh
return reconstructFvVolumeInternalField(fld);
}
// Reconstruct a field onto the baseMesh
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh>>
Foam::parFvFieldReconstructor::reconstructFvVolumeField
Foam::parFvFieldDistributor::distributeField
(
const GeometricField<Type, fvPatchField, volMesh>& fld
) const
{
// Create the internalField by remote mapping
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Create internalField by remote mapping
distributedFieldMapper mapper
(
labelUList::null(),
distMap_.cellMap()
);
Field<Type> internalField(fld.internalField(), mapper);
DimensionedField<Type, volMesh> internalField
(
IOobject
(
fld.name(),
tgtMesh_.time().timeName(),
fld.local(),
tgtMesh_,
IOobject::NO_READ,
IOobject::NO_WRITE
),
tgtMesh_,
fld.dimensions(),
Field<Type>(fld.internalField(), mapper)
);
internalField.oriented() = fld.oriented();
// Create patchFields by remote mapping
// Note: patchFields still on source mesh, not target mesh
// Create the patchFields by remote mapping
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Note: patchFields still on mesh, not baseMesh
PtrList<fvPatchField<Type>> patchFields(fld.mesh().boundary().size());
PtrList<fvPatchField<Type>> oldPatchFields(fld.mesh().boundary().size());
const auto& bfld = fld.boundaryField();
forAll(bfld, patchI)
forAll(bfld, patchi)
{
if (patchFaceMaps_.set(patchI))
if (patchFaceMaps_.set(patchi))
{
// Clone local patch field
patchFields.set(patchI, bfld[patchI].clone());
oldPatchFields.set(patchi, bfld[patchi].clone());
distributedFvPatchFieldMapper mapper
(
labelUList::null(),
patchFaceMaps_[patchI]
patchFaceMaps_[patchi]
);
// Map into local copy
patchFields[patchI].autoMap(mapper);
oldPatchFields[patchi].autoMap(mapper);
}
}
PtrList<fvPatchField<Type>> basePatchFields
(
baseMesh_.boundary().size()
);
// Clone the patchFields onto the base patches. This is just to reset
// Clone the oldPatchFields onto the target patches. This is just to reset
// the reference to the patch, size and content stay the same.
forAll(patchFields, patchI)
{
if (patchFields.set(patchI))
{
const fvPatch& basePatch = baseMesh_.boundary()[patchI];
const fvPatchField<Type>& pfld = patchFields[patchI];
PtrList<fvPatchField<Type>> newPatchFields(tgtMesh_.boundary().size());
forAll(oldPatchFields, patchi)
{
if (oldPatchFields.set(patchi))
{
const auto& pfld = oldPatchFields[patchi];
labelList dummyMap(identity(pfld.size()));
directFvPatchFieldMapper dummyMapper(dummyMap);
basePatchFields.set
newPatchFields.set
(
patchI,
patchi,
fvPatchField<Type>::New
(
pfld,
basePatch,
tgtMesh_.boundary()[patchi],
DimensionedField<Type, volMesh>::null(),
dummyMapper
)
@ -181,162 +166,143 @@ Foam::parFvFieldReconstructor::reconstructFvVolumeField
}
}
// Add some empty patches on remaining patches (tbd.probably processor
// patches)
forAll(basePatchFields, patchI)
// Add some empty patches on remaining patches
// (... probably processor patches)
forAll(newPatchFields, patchi)
{
if (patchI >= patchFields.size() || !patchFields.set(patchI))
if (!newPatchFields.set(patchi))
{
basePatchFields.set
newPatchFields.set
(
patchI,
patchi,
fvPatchField<Type>::New
(
emptyFvPatchField<Type>::typeName,
baseMesh_.boundary()[patchI],
tgtMesh_.boundary()[patchi],
DimensionedField<Type, volMesh>::null()
)
);
}
}
// Construct a volField
IOobject baseIO
// Return geometric field
return tmp<GeometricField<Type, fvPatchField, volMesh>>::New
(
fld.name(),
baseMesh_.time().timeName(),
fld.local(),
baseMesh_,
IOobject::NO_READ,
IOobject::NO_WRITE
std::move(internalField),
newPatchFields
);
auto tfield = tmp<GeometricField<Type, fvPatchField, volMesh>>::New
(
baseIO,
baseMesh_,
fld.dimensions(),
internalField,
basePatchFields
);
tfield.ref().oriented()= fld.oriented();
return tfield;
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh>>
Foam::parFvFieldReconstructor::reconstructFvVolumeField
(
const IOobject& fieldIoObject
) const
{
// Read the field
GeometricField<Type, fvPatchField, volMesh> fld
(
fieldIoObject,
procMesh_
);
// Distribute onto baseMesh
return reconstructFvVolumeField(fld);
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::fvsPatchField, Foam::surfaceMesh>>
Foam::parFvFieldReconstructor::reconstructFvSurfaceField
Foam::parFvFieldDistributor::distributeField
(
const GeometricField<Type, fvsPatchField, surfaceMesh>& fld
) const
{
// Create the internalField by remote mapping
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Create internalField by remote mapping
distributedFieldMapper mapper
(
labelUList::null(),
distMap_.faceMap()
);
// Create flat field of internalField + all patch fields
Field<Type> flatFld(fld.mesh().nFaces(), Type(Zero));
SubList<Type>(flatFld, fld.internalField().size()) = fld.internalField();
forAll(fld.boundaryField(), patchI)
{
const fvsPatchField<Type>& fvp = fld.boundaryField()[patchI];
SubList<Type>(flatFld, fvp.size(), fvp.patch().start()) = fvp;
Field<Type> primitiveField;
{
// Create flat field of internalField + all patch fields
Field<Type> flatFld(fld.mesh().nFaces(), Type(Zero));
SubList<Type>(flatFld, fld.internalField().size())
= fld.internalField();
for (const fvsPatchField<Type>& fvp : fld.boundaryField())
{
SubList<Type>(flatFld, fvp.size(), fvp.patch().start()) = fvp;
}
// Map all faces
primitiveField = Field<Type>(flatFld, mapper, fld.oriented()());
// Trim to internal faces (note: could also have special mapper)
primitiveField.resize
(
min
(
primitiveField.size(),
tgtMesh_.nInternalFaces()
)
);
}
// Map all faces
Field<Type> internalField(flatFld, mapper, fld.oriented()());
// Trim to internal faces (note: could also have special mapper)
internalField.setSize
DimensionedField<Type, surfaceMesh> internalField
(
min
IOobject
(
internalField.size(),
baseMesh_.nInternalFaces()
)
fld.name(),
tgtMesh_.time().timeName(),
fld.local(),
tgtMesh_,
IOobject::NO_READ,
IOobject::NO_WRITE
),
tgtMesh_,
fld.dimensions(),
std::move(primitiveField)
);
internalField.oriented() = fld.oriented();
// Create the patchFields by remote mapping
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Note: patchFields still on mesh, not baseMesh
PtrList<fvsPatchField<Type>> patchFields(fld.mesh().boundary().size());
// Create patchFields by remote mapping
// Note: patchFields still on source mesh, not target mesh
PtrList<fvsPatchField<Type>> oldPatchFields(fld.mesh().boundary().size());
const auto& bfld = fld.boundaryField();
forAll(bfld, patchI)
forAll(bfld, patchi)
{
if (patchFaceMaps_.set(patchI))
if (patchFaceMaps_.set(patchi))
{
// Clone local patch field
patchFields.set(patchI, bfld[patchI].clone());
oldPatchFields.set(patchi, bfld[patchi].clone());
distributedFvPatchFieldMapper mapper
(
labelUList::null(),
patchFaceMaps_[patchI]
patchFaceMaps_[patchi]
);
// Map into local copy
patchFields[patchI].autoMap(mapper);
oldPatchFields[patchi].autoMap(mapper);
}
}
PtrList<fvsPatchField<Type>> basePatchFields
(
baseMesh_.boundary().size()
);
PtrList<fvsPatchField<Type>> newPatchFields(tgtMesh_.boundary().size());
// Clone the patchFields onto the base patches. This is just to reset
// the reference to the patch, size and content stay the same.
forAll(patchFields, patchI)
forAll(oldPatchFields, patchi)
{
if (patchFields.set(patchI))
if (oldPatchFields.set(patchi))
{
const fvPatch& basePatch = baseMesh_.boundary()[patchI];
const fvsPatchField<Type>& pfld = patchFields[patchI];
const fvsPatchField<Type>& pfld = oldPatchFields[patchi];
labelList dummyMap(identity(pfld.size()));
directFvPatchFieldMapper dummyMapper(dummyMap);
basePatchFields.set
newPatchFields.set
(
patchI,
patchi,
fvsPatchField<Type>::New
(
pfld,
basePatch,
tgtMesh_.boundary()[patchi],
DimensionedField<Type, surfaceMesh>::null(),
dummyMapper
)
@ -344,71 +310,94 @@ Foam::parFvFieldReconstructor::reconstructFvSurfaceField
}
}
// Add some empty patches on remaining patches (tbd.probably processor
// patches)
forAll(basePatchFields, patchI)
// Add some empty patches on remaining patches
// (... probably processor patches)
forAll(newPatchFields, patchi)
{
if (patchI >= patchFields.size() || !patchFields.set(patchI))
if (!newPatchFields.set(patchi))
{
basePatchFields.set
newPatchFields.set
(
patchI,
patchi,
fvsPatchField<Type>::New
(
emptyFvsPatchField<Type>::typeName,
baseMesh_.boundary()[patchI],
tgtMesh_.boundary()[patchi],
DimensionedField<Type, surfaceMesh>::null()
)
);
}
}
// Construct a volField
IOobject baseIO
// Return geometric field
return tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>::New
(
fld.name(),
baseMesh_.time().timeName(),
fld.local(),
baseMesh_,
IOobject::NO_READ,
IOobject::NO_WRITE
std::move(internalField),
newPatchFields
);
}
template<class Type>
Foam::tmp<Foam::DimensionedField<Type, Foam::volMesh>>
Foam::parFvFieldDistributor::distributeInternalField
(
const IOobject& fieldObject
) const
{
// Read field
DimensionedField<Type, volMesh> fld
(
fieldObject,
srcMesh_
);
auto tfield = tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>::New
// Distribute
return distributeField(fld);
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh>>
Foam::parFvFieldDistributor::distributeVolumeField
(
const IOobject& fieldObject
) const
{
// Read field
GeometricField<Type, fvPatchField, volMesh> fld
(
baseIO,
baseMesh_,
fld.dimensions(),
internalField,
basePatchFields
fieldObject,
srcMesh_
);
tfield.ref().oriented() = fld.oriented();
return tfield;
// Distribute
return distributeField(fld);
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::fvsPatchField, Foam::surfaceMesh>>
Foam::parFvFieldReconstructor::reconstructFvSurfaceField
Foam::parFvFieldDistributor::distributeSurfaceField
(
const IOobject& fieldIoObject
const IOobject& fieldObject
) const
{
// Read the field
// Read field
GeometricField<Type, fvsPatchField, surfaceMesh> fld
(
fieldIoObject,
procMesh_
fieldObject,
srcMesh_
);
return reconstructFvSurfaceField(fld);
// Distribute
return distributeField(fld);
}
template<class Type>
Foam::label Foam::parFvFieldReconstructor::reconstructFvVolumeInternalFields
Foam::label Foam::parFvFieldDistributor::distributeInternalFields
(
const IOobjectList& objects,
const wordRes& selectedFields
@ -427,17 +416,25 @@ Foam::label Foam::parFvFieldReconstructor::reconstructFvVolumeInternalFields
label nFields = 0;
for (const word& fieldName : fieldNames)
{
if (!nFields++)
if ("cellDist" == fieldName)
{
Info<< " Reconstructing "
<< fieldType::typeName << "s\n" << nl;
// There is an odd chance this is an internal field
continue;
}
Info<< " " << fieldName << nl;
if (verbose_)
{
if (!nFields)
{
Info<< " Reconstructing "
<< fieldType::typeName << "s\n" << nl;
}
Info<< " " << fieldName << nl;
}
++nFields;
tmp<fieldType> tfld
(
reconstructFvVolumeInternalField<Type>(*(objects[fieldName]))
distributeInternalField<Type>(*(objects[fieldName]))
);
if (isWriteProc_)
{
@ -445,13 +442,13 @@ Foam::label Foam::parFvFieldReconstructor::reconstructFvVolumeInternalFields
}
}
if (nFields) Info<< endl;
if (nFields && verbose_) Info<< endl;
return nFields;
}
template<class Type>
Foam::label Foam::parFvFieldReconstructor::reconstructFvVolumeFields
Foam::label Foam::parFvFieldDistributor::distributeVolumeFields
(
const IOobjectList& objects,
const wordRes& selectedFields
@ -474,16 +471,20 @@ Foam::label Foam::parFvFieldReconstructor::reconstructFvVolumeFields
{
continue;
}
if (!nFields++)
if (verbose_)
{
Info<< " Reconstructing "
<< fieldType::typeName << "s\n" << nl;
if (!nFields)
{
Info<< " Reconstructing "
<< fieldType::typeName << "s\n" << nl;
}
Info<< " " << fieldName << nl;
}
Info<< " " << fieldName << nl;
++nFields;
tmp<fieldType> tfld
(
reconstructFvVolumeField<Type>(*(objects[fieldName]))
distributeVolumeField<Type>(*(objects[fieldName]))
);
if (isWriteProc_)
{
@ -491,13 +492,13 @@ Foam::label Foam::parFvFieldReconstructor::reconstructFvVolumeFields
}
}
if (nFields) Info<< endl;
if (nFields && verbose_) Info<< endl;
return nFields;
}
template<class Type>
Foam::label Foam::parFvFieldReconstructor::reconstructFvSurfaceFields
Foam::label Foam::parFvFieldDistributor::distributeSurfaceFields
(
const IOobjectList& objects,
const wordRes& selectedFields
@ -516,16 +517,20 @@ Foam::label Foam::parFvFieldReconstructor::reconstructFvSurfaceFields
label nFields = 0;
for (const word& fieldName : fieldNames)
{
if (!nFields++)
if (verbose_)
{
Info<< " Reconstructing "
<< fieldType::typeName << "s\n" << nl;
if (!nFields)
{
Info<< " Reconstructing "
<< fieldType::typeName << "s\n" << nl;
}
Info<< " " << fieldName << nl;
}
Info<< " " << fieldName << nl;
++nFields;
tmp<fieldType> tfld
(
reconstructFvSurfaceField<Type>(*(objects[fieldName]))
distributeSurfaceField<Type>(*(objects[fieldName]))
);
if (isWriteProc_)
{
@ -533,7 +538,7 @@ Foam::label Foam::parFvFieldReconstructor::reconstructFvSurfaceFields
}
}
if (nFields) Info<< endl;
if (nFields && verbose_) Info<< endl;
return nFields;
}

View File

@ -27,12 +27,12 @@ License
\*---------------------------------------------------------------------------*/
#include "ListOps.H"
#include "parLagrangianRedistributor.H"
#include "parLagrangianDistributor.H"
#include "passivePositionParticleCloud.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::parLagrangianRedistributor::parLagrangianRedistributor
Foam::parLagrangianDistributor::parLagrangianDistributor
(
const fvMesh& srcMesh,
const fvMesh& tgtMesh,
@ -59,7 +59,7 @@ Foam::parLagrangianRedistributor::parLagrangianRedistributor
// Find all clouds (on all processors) and for each cloud all the objects.
// Result will be synchronised on all processors
void Foam::parLagrangianRedistributor::findClouds
void Foam::parLagrangianDistributor::findClouds
(
const fvMesh& mesh,
wordList& cloudNames,
@ -129,7 +129,7 @@ void Foam::parLagrangianRedistributor::findClouds
Foam::autoPtr<Foam::mapDistributeBase>
Foam::parLagrangianRedistributor::redistributeLagrangianPositions
Foam::parLagrangianDistributor::distributeLagrangianPositions
(
passivePositionParticleCloud& lpi
) const
@ -314,7 +314,7 @@ Foam::parLagrangianRedistributor::redistributeLagrangianPositions
Foam::autoPtr<Foam::mapDistributeBase>
Foam::parLagrangianRedistributor::redistributeLagrangianPositions
Foam::parLagrangianDistributor::distributeLagrangianPositions
(
const word& cloudName
) const
@ -322,7 +322,7 @@ Foam::parLagrangianRedistributor::redistributeLagrangianPositions
// Load cloud and send particle
passivePositionParticleCloud lpi(srcMesh_, cloudName, false);
return redistributeLagrangianPositions(lpi);
return distributeLagrangianPositions(lpi);
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2015 OpenFOAM Foundation
Copyright (C) 2018 OpenCFD Ltd.
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -25,7 +25,7 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::parLagrangianRedistributor
Foam::parLagrangianDistributor
Description
Lagrangian field redistributor.
@ -33,13 +33,14 @@ Description
Runs in parallel. Redistributes from fromMesh to toMesh.
SourceFiles
parLagrangianRedistributor.C
parLagrangianRedistributorFields.C
parLagrangianDistributor.C
parLagrangianDistributorFields.C
parLagrangianDistributorTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef parLagrangianRedistributor_H
#define parLagrangianRedistributor_H
#ifndef Foam_parLagrangianDistributor_H
#define Foam_parLagrangianDistributor_H
#include "PtrList.H"
#include "fvMesh.H"
@ -49,19 +50,19 @@ SourceFiles
namespace Foam
{
// Forward declarations
// Forward Declarations
class mapDistributePolyMesh;
class mapDistributeBase;
class IOobjectList;
class passivePositionParticleCloud;
/*---------------------------------------------------------------------------*\
Class parLagrangianRedistributor Declaration
Class parLagrangianDistributor Declaration
\*---------------------------------------------------------------------------*/
class parLagrangianRedistributor
class parLagrangianDistributor
{
// Private data
// Private Data
//- Source mesh reference
const fvMesh& srcMesh_;
@ -82,10 +83,10 @@ class parLagrangianRedistributor
// Private Member Functions
//- No copy construct
parLagrangianRedistributor(const parLagrangianRedistributor&) = delete;
parLagrangianDistributor(const parLagrangianDistributor&) = delete;
//- No copy assignment
void operator=(const parLagrangianRedistributor&) = delete;
void operator=(const parLagrangianDistributor&) = delete;
public:
@ -93,7 +94,7 @@ public:
// Constructors
//- Construct from components
parLagrangianRedistributor
parLagrangianDistributor
(
const fvMesh& srcMesh,
const fvMesh& tgtMesh,
@ -102,10 +103,10 @@ public:
);
// Member Functions
// Static Functions
//- Find all clouds (on all processors) and for each cloud all
// the objects. Result will be synchronised on all processors
//- the objects. Result will be synchronised on all processors
static void findClouds
(
const fvMesh&,
@ -113,18 +114,6 @@ public:
List<wordList>& objectNames
);
//- Redistribute and write lagrangian positions
autoPtr<mapDistributeBase> redistributeLagrangianPositions
(
passivePositionParticleCloud& cloud
) const;
//- Read, redistribute and write lagrangian positions
autoPtr<mapDistributeBase> redistributeLagrangianPositions
(
const word& cloudName
) const;
//- Pick up any fields of a given type
template<class Type>
static wordList filterObjects
@ -133,26 +122,6 @@ public:
const wordRes& selectedFields = wordRes()
);
//- Read, redistribute and write all/selected lagrangian fields
template<class Type>
label redistributeFields
(
const mapDistributeBase& map,
const word& cloudName,
const IOobjectList& objects,
const wordRes& selectedFields = wordRes()
) const;
//- Read, redistribute and write all/selected lagrangian fieldFields
template<class Type>
label redistributeFieldFields
(
const mapDistributeBase& map,
const word& cloudName,
const IOobjectList& objects,
const wordRes& selectedFields = wordRes()
) const;
//- Read and store all fields of a cloud
template<class Container>
static label readFields
@ -162,14 +131,81 @@ public:
const wordRes& selectedFields = wordRes()
);
//- Read and store all fields for known cloud field types
static label readAllFields
(
const passivePositionParticleCloud& cloud,
const IOobjectList& objects,
const wordRes& selectedFields = wordRes()
);
//- Read and store all fields for known cloud field types
// Uses the current cloud instance to obtain the IOobjectList
static label readAllFields
(
const passivePositionParticleCloud& cloud,
const wordRes& selectedFields = wordRes()
);
// Member Functions
//- Redistribute and write lagrangian positions
autoPtr<mapDistributeBase> distributeLagrangianPositions
(
passivePositionParticleCloud& cloud
) const;
//- Read, redistribute and write lagrangian positions
autoPtr<mapDistributeBase> distributeLagrangianPositions
(
const word& cloudName
) const;
//- Redistribute all fields for known cloud field types
label distributeAllFields
(
const mapDistributeBase& lagrangianMap,
const word& cloudName,
const IOobjectList& cloudObjs,
const wordRes& selectedFields
) const;
//- Redistribute and write all stored lagrangian fields
label distributeAllStoredFields
(
const mapDistributeBase& lagrangianMap,
passivePositionParticleCloud& cloud
) const;
//- Read, redistribute and write all/selected lagrangian fields
template<class Type>
label distributeFields
(
const mapDistributeBase& map,
const word& cloudName,
const IOobjectList& objects,
const wordRes& selectedFields = wordRes()
) const;
//- Read, redistribute and write all/selected lagrangian fieldFields
template<class Type>
label distributeFieldFields
(
const mapDistributeBase& map,
const word& cloudName,
const IOobjectList& objects,
const wordRes& selectedFields = wordRes()
) const;
//- Redistribute and write stored lagrangian fields
template<class Container>
label redistributeStoredFields
label distributeStoredFields
(
const mapDistributeBase& map,
passivePositionParticleCloud& cloud
) const;
};
@ -180,7 +216,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "parLagrangianRedistributorFields.C"
# include "parLagrangianDistributorTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -0,0 +1,195 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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 "parLagrangianDistributor.H"
#include "unmappedPassivePositionParticleCloud.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::label Foam::parLagrangianDistributor::readAllFields
(
const passivePositionParticleCloud& cloud,
const IOobjectList& cloudObjs,
const wordRes& selectedFields
)
{
label nTotal = 0;
do
{
#undef doLocalCode
#define doLocalCode(Type) \
{ \
nTotal += parLagrangianDistributor::readFields \
<IOField<Type>> \
( \
cloud, \
cloudObjs, \
selectedFields \
); \
\
nTotal += parLagrangianDistributor::readFields \
<IOField<Field<Type>>> \
( \
cloud, \
cloudObjs, \
selectedFields \
); \
\
nTotal += parLagrangianDistributor::readFields \
<CompactIOField<Field<Type>, Type>> \
( \
cloud, \
cloudObjs, \
selectedFields \
); \
}
doLocalCode(label);
doLocalCode(scalar);
doLocalCode(vector);
doLocalCode(sphericalTensor);
doLocalCode(symmTensor);
doLocalCode(tensor);
#undef doLocalCode
}
while (false);
return nTotal;
}
Foam::label Foam::parLagrangianDistributor::readAllFields
(
const passivePositionParticleCloud& cloud,
const wordRes& selectedFields
)
{
IOobjectList cloudObjs(cloud, cloud.time().timeName());
return readAllFields(cloud, cloudObjs, selectedFields);
}
Foam::label Foam::parLagrangianDistributor::distributeAllFields
(
const mapDistributeBase& lagrangianMap,
const word& cloudName,
const IOobjectList& cloudObjs,
const wordRes& selectedFields
) const
{
label nTotal = 0;
do
{
#undef doLocalCode
#define doLocalCode(Type) \
{ \
nTotal += this->distributeFields<Type> \
( \
lagrangianMap, \
cloudName, \
cloudObjs, \
selectedFields \
); \
\
nTotal += this->distributeFieldFields<Type> \
( \
lagrangianMap, \
cloudName, \
cloudObjs, \
selectedFields \
); \
}
doLocalCode(label);
doLocalCode(scalar);
doLocalCode(vector);
doLocalCode(sphericalTensor);
doLocalCode(symmTensor);
doLocalCode(tensor);
#undef doLocalCode
}
while (false);
return nTotal;
}
Foam::label Foam::parLagrangianDistributor::distributeAllStoredFields
(
const mapDistributeBase& lagrangianMap,
passivePositionParticleCloud& cloud
) const
{
label nTotal = 0;
do
{
#undef doLocalCode
#define doLocalCode(Type) \
{ \
nTotal += this->distributeStoredFields \
<IOField<Type>> \
( \
lagrangianMap, \
cloud \
); \
\
nTotal += this->distributeStoredFields \
<IOField<Field<Type>>> \
( \
lagrangianMap, \
cloud \
); \
\
nTotal += this->distributeStoredFields \
<CompactIOField<Field<Type>, Type>> \
( \
lagrangianMap, \
cloud \
); \
}
doLocalCode(label);
doLocalCode(scalar);
doLocalCode(vector);
doLocalCode(sphericalTensor);
doLocalCode(symmTensor);
doLocalCode(tensor);
#undef doLocalCode
}
while (false);
return nTotal;
}
// ************************************************************************* //

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2015 OpenFOAM Foundation
Copyright (C) 2018 OpenCFD Ltd.
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -26,18 +26,19 @@ License
\*---------------------------------------------------------------------------*/
#include "parLagrangianRedistributor.H"
#include "parLagrangianDistributor.H"
#include "Time.H"
#include "IOobjectList.H"
#include "mapDistributePolyMesh.H"
#include "cloud.H"
#include "CompactIOField.H"
#include "DynamicList.H"
#include "passivePositionParticleCloud.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Container>
Foam::wordList Foam::parLagrangianRedistributor::filterObjects
Foam::wordList Foam::parLagrangianDistributor::filterObjects
(
const IOobjectList& objects,
const wordRes& selectedFields
@ -64,7 +65,7 @@ Foam::wordList Foam::parLagrangianRedistributor::filterObjects
template<class Type>
Foam::label Foam::parLagrangianRedistributor::redistributeFields
Foam::label Foam::parLagrangianDistributor::distributeFields
(
const mapDistributeBase& map,
const word& cloudName,
@ -76,7 +77,7 @@ Foam::label Foam::parLagrangianRedistributor::redistributeFields
const wordList fieldNames
(
filterObjects<IOField<Type>>
filterObjects<fieldType>
(
objects,
selectedFields
@ -88,7 +89,7 @@ Foam::label Foam::parLagrangianRedistributor::redistributeFields
{
if (!nFields)
{
Info<< " Redistributing lagrangian "
Info<< " Distributing lagrangian "
<< fieldType::typeName << "s\n" << endl;
}
Info<< " " << objectName << endl;
@ -125,11 +126,7 @@ Foam::label Foam::parLagrangianRedistributor::redistributeFields
if (field.size())
{
IOField<Type>
(
fieldIO,
std::move(field)
).write();
IOField<Type>(fieldIO, std::move(field)).write();
}
else
{
@ -146,7 +143,7 @@ Foam::label Foam::parLagrangianRedistributor::redistributeFields
template<class Type>
Foam::label Foam::parLagrangianRedistributor::redistributeFieldFields
Foam::label Foam::parLagrangianDistributor::distributeFieldFields
(
const mapDistributeBase& map,
const word& cloudName,
@ -156,7 +153,9 @@ Foam::label Foam::parLagrangianRedistributor::redistributeFieldFields
{
typedef CompactIOField<Field<Type>, Type> fieldType;
wordList fieldNames
DynamicList<word> fieldNames;
fieldNames.append
(
filterObjects<fieldType>
(
@ -166,27 +165,30 @@ Foam::label Foam::parLagrangianRedistributor::redistributeFieldFields
);
// Append IOField Field names
{
wordList ioFieldNames
fieldNames.append
(
filterObjects<IOField<Field<Type>>>
(
filterObjects<IOField<Field<Type>>>
(
objects,
selectedFields
)
);
fieldNames.append(ioFieldNames);
}
objects,
selectedFields
)
);
const bool verbose_ = true;
label nFields = 0;
for (const word& objectName : fieldNames)
{
if (!nFields++)
if (verbose_)
{
Info<< " Redistributing lagrangian "
<< fieldType::typeName << "s\n" << nl;
if (!nFields)
{
Info<< " Distributing lagrangian "
<< fieldType::typeName << "s\n" << nl;
}
Info<< " " << objectName << nl;
}
Info<< " " << objectName << nl;
++nFields;
// Read if present
CompactIOField<Field<Type>, Type> field
@ -237,13 +239,13 @@ Foam::label Foam::parLagrangianRedistributor::redistributeFieldFields
}
}
if (nFields) Info<< endl;
if (nFields && verbose_) Info<< endl;
return nFields;
}
template<class Container>
Foam::label Foam::parLagrangianRedistributor::readFields
Foam::label Foam::parLagrangianDistributor::readFields
(
const passivePositionParticleCloud& cloud,
const IOobjectList& objects,
@ -261,15 +263,21 @@ Foam::label Foam::parLagrangianRedistributor::readFields
)
);
const bool verbose_ = true;
label nFields = 0;
for (const word& objectName : fieldNames)
{
if (!nFields++)
if (verbose_)
{
Info<< " Reading lagrangian "
<< Container::typeName << "s\n" << nl;
if (!nFields)
{
Info<< " Reading lagrangian "
<< Container::typeName << "s\n" << nl;
}
Info<< " " << objectName << nl;
}
Info<< " " << objectName << nl;
++nFields;
// Read if present
Container* fieldPtr = new Container
@ -288,12 +296,13 @@ Foam::label Foam::parLagrangianRedistributor::readFields
fieldPtr->store();
}
if (nFields && verbose_) Info<< endl;
return nFields;
}
template<class Container>
Foam::label Foam::parLagrangianRedistributor::redistributeStoredFields
Foam::label Foam::parLagrangianDistributor::distributeStoredFields
(
const mapDistributeBase& map,
passivePositionParticleCloud& cloud
@ -304,17 +313,23 @@ Foam::label Foam::parLagrangianRedistributor::redistributeStoredFields
cloud.lookupClass<Container>()
);
const bool verbose_ = true;
label nFields = 0;
forAllIters(fields, iter)
{
Container& field = *(iter.val());
if (!nFields++)
if (verbose_)
{
Info<< " Redistributing lagrangian "
<< Container::typeName << "s\n" << endl;
if (!nFields)
{
Info<< " Distributing lagrangian "
<< Container::typeName << "s\n" << endl;
}
Info<< " " << field.name() << endl;
}
Info<< " " << field.name() << endl;
++nFields;
map.distribute(field);
@ -331,11 +346,7 @@ Foam::label Foam::parLagrangianRedistributor::redistributeStoredFields
if (field.size())
{
Container
(
fieldIO,
std::move(field)
).write();
Container(fieldIO, std::move(field)).write();
}
else
{
@ -347,6 +358,7 @@ Foam::label Foam::parLagrangianRedistributor::redistributeStoredFields
}
}
if (nFields && verbose_) Info<< endl;
return nFields;
}

View File

@ -0,0 +1,238 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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 "parPointFieldDistributor.H"
#include "processorPointPatch.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
int Foam::parPointFieldDistributor::verbose_ = 0;
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::parPointFieldDistributor::parPointFieldDistributor
(
const pointMesh& srcMesh,
const bool savePoints,
const bool isWriteProc
)
:
srcMesh_(srcMesh),
nOldPoints_(srcMesh.size()),
patchMeshPoints_(),
tgtMeshRef_(nullptr),
distMapRef_(nullptr),
patchPointMaps_(),
isWriteProc_(isWriteProc)
{
if (savePoints)
{
saveMeshPoints();
}
}
Foam::parPointFieldDistributor::parPointFieldDistributor
(
const pointMesh& srcMesh,
const pointMesh& tgtMesh,
const mapDistributePolyMesh& distMap,
const bool savePoints,
const bool isWriteProc
)
:
srcMesh_(srcMesh),
nOldPoints_(srcMesh.size()),
patchMeshPoints_(),
tgtMeshRef_(tgtMesh),
distMapRef_(distMap),
patchPointMaps_(),
isWriteProc_(isWriteProc)
{
if (savePoints)
{
saveMeshPoints();
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::parPointFieldDistributor::hasMeshPoints() const
{
return !patchMeshPoints_.empty();
}
bool Foam::parPointFieldDistributor::hasPatchPointMaps() const
{
return !patchPointMaps_.empty();
}
bool Foam::parPointFieldDistributor::hasTarget() const
{
return (tgtMeshRef_ && distMapRef_);
}
void Foam::parPointFieldDistributor::clearMeshPoints()
{
patchMeshPoints_.clear();
}
void Foam::parPointFieldDistributor::clearPatchPointMaps()
{
patchPointMaps_.clear();
}
void Foam::parPointFieldDistributor::saveMeshPoints()
{
const pointBoundaryMesh& patches = srcMesh_.boundary();
patchMeshPoints_.clear();
patchMeshPoints_.resize(patches.size());
forAll(patches, patchi)
{
if (!isA<processorPointPatch>(patches[patchi]))
{
// Copy meshPoints
patchMeshPoints_.set
(
patchi,
new labelList(patches[patchi].meshPoints())
);
}
}
}
void Foam::parPointFieldDistributor::createPatchPointMaps()
{
if (!tgtMeshRef_ || !distMapRef_)
{
FatalErrorInFunction
<< "Cannot create maps without target mesh and/or distribution!"
<< abort(FatalError);
}
const auto& tgtMesh = tgtMeshRef_();
const auto& distMap = distMapRef_();
const auto& newPatches = tgtMesh.boundary();
const auto& oldPatches = srcMesh_.boundary();
patchPointMaps_.clear();
patchPointMaps_.resize(oldPatches.size());
// if (patchPointMaps_.size() != patchMeshPoints_.size())
// {
// // Warn?
// }
forAll(oldPatches, patchi)
{
if (!isA<processorPointPatch>(oldPatches[patchi]))
{
// Create map for patch points only
labelList oldToNewSub;
labelList oldToNewConstruct;
// Copy point map
patchPointMaps_.set
(
patchi,
new mapDistributeBase(distMap.pointMap())
);
const labelList& oldMeshPoints =
(
patchMeshPoints_.test(patchi)
? patchMeshPoints_[patchi]
: oldPatches[patchi].meshPoints() // <- Questionable!
);
patchPointMaps_[patchi].compactData
(
oldMeshPoints,
newPatches[patchi].meshPoints(),
oldToNewSub,
oldToNewConstruct,
nOldPoints_,
UPstream::msgType()
);
}
}
}
void Foam::parPointFieldDistributor::resetTarget()
{
tgtMeshRef_.reset(nullptr);
distMapRef_.reset(nullptr);
// Old maps are now invalid
clearPatchPointMaps();
}
void Foam::parPointFieldDistributor::resetTarget
(
const pointMesh& tgtMesh,
const mapDistributePolyMesh& distMap
)
{
tgtMeshRef_.cref(tgtMesh);
distMapRef_.cref(distMap);
// Old maps are now invalid
clearPatchPointMaps();
}
Foam::label Foam::parPointFieldDistributor::distributeAllFields
(
const IOobjectList& objects,
const wordRes& selected
) const
{
label nTotal = 0;
nTotal += distributePointFields<scalar>(objects, selected);
nTotal += distributePointFields<vector>(objects, selected);
nTotal += distributePointFields<symmTensor>(objects, selected);
nTotal += distributePointFields<sphericalTensor>(objects, selected);
nTotal += distributePointFields<tensor>(objects, selected);
return nTotal;
}
// ************************************************************************* //

View File

@ -0,0 +1,255 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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::parPointFieldDistributor
Description
Distributor/redistributor for point fields,
uses a two (or three) stage construction.
The inconvenient multi-stage construction is needed since the
pointMesh is directly associated with a polyMesh, which will probably
have changed while creating the target mesh. This means that it is
necessary to save the size of the source mesh and all of its
patch meshPoints prior to making any changes (eg, creating the target
mesh).
-# Create with specified source mesh
-# Save the meshPoints (per boundary) for the source mesh
-# Attach a target mesh and mesh distribution
-# Map the point fields
.
Runs in parallel. Redistributes from srcMesh to tgtMesh.
SourceFiles
parPointFieldDistributor.C
parPointFieldDistributorTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef Foam_parPointFieldDistributor_H
#define Foam_parPointFieldDistributor_H
#include "PtrList.H"
#include "pointMesh.H"
#include "pointFieldsFwd.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward Declarations
class mapDistributePolyMesh;
class mapDistributeBase;
class IOobjectList;
/*---------------------------------------------------------------------------*\
Class parPointFieldDistributor Declaration
\*---------------------------------------------------------------------------*/
class parPointFieldDistributor
{
// Private Data
//- The source mesh reference
const pointMesh& srcMesh_;
//- Number of points in the old (source) mesh
const label nOldPoints_;
//- The pointPatch mesh points
PtrList<labelList> patchMeshPoints_;
//- The target (destination) mesh reference
refPtr<pointMesh> tgtMeshRef_;
//- Distribution map reference
refPtr<mapDistributePolyMesh> distMapRef_;
//- Point patch mappers
PtrList<mapDistributeBase> patchPointMaps_;
//- Do I need to write (eg, master only for reconstruct)
bool isWriteProc_;
// Private Member Functions
//- No copy construct
parPointFieldDistributor(const parPointFieldDistributor&) = delete;
//- No copy assignment
void operator=(const parPointFieldDistributor&) = delete;
public:
//- Output verbosity when writing
static int verbose_;
// Constructors
//- Basic construction
//
// \param srcMesh The source pointMesh
// \param savePoints Call saveMeshPoints() immediately
// \param isWriteProc Tagged for output writing (on this proc)
explicit parPointFieldDistributor
(
const pointMesh& srcMesh,
const bool savePoints = false,
const bool isWriteProc = false
);
//- Full construction of source/target
//
// \param srcMesh The source pointMesh
// \param tgtMesh The target pointMesh
// \param distMap The distribution map
// \param savePoints Call saveMeshPoints() immediately
// \param isWriteProc Tagged for output writing (on this proc)
explicit parPointFieldDistributor
(
const pointMesh& srcMesh,
const pointMesh& tgtMesh,
const mapDistributePolyMesh& distMap,
const bool savePoints = false,
const bool isWriteProc = false
);
// Member Functions
//- True if meshPoints (per boundary) for the source mesh
//- have been saved
bool hasMeshPoints() const;
//- True if patch maps (per boundary) exist
bool hasPatchPointMaps() const;
//- True if a target mesh/distribution map has been attached
bool hasTarget() const;
//- Clear out meshPoints (per boundary) for the source mesh
void clearMeshPoints();
//- Clear out patch maps (per boundary)
void clearPatchPointMaps();
//- Create/recreate meshPoints (per boundary) for the source mesh
void saveMeshPoints();
//- Construct per-patch addressing
void createPatchPointMaps();
//- Clear target mesh / distribution map
void resetTarget();
//- Reset target mesh / distribution map
void resetTarget
(
const pointMesh& tgtMesh,
const mapDistributePolyMesh& distMap
);
//- Get status of write enabled (on this proc)
bool isWriteProc() const noexcept
{
return isWriteProc_;
}
//- Change status of write enabled (on this proc)
bool isWriteProc(const bool on) noexcept
{
bool old(isWriteProc_);
isWriteProc_ = on;
return old;
}
// Field Mapping
//- Read, distribute and write all/selected point field types
//- (scalar, vector, ... types)
label distributeAllFields
(
const IOobjectList& objects,
const wordRes& selectedFields = wordRes()
) const;
//- Distribute point field
template<class Type>
tmp<GeometricField<Type, pointPatchField, pointMesh>>
distributeField
(
const GeometricField<Type, pointPatchField, pointMesh>& fld
) const;
//- Read and distribute point field
template<class Type>
tmp<GeometricField<Type, pointPatchField, pointMesh>>
distributePointField
(
const IOobject& fieldObject
) const;
//- Read, distribute and write all/selected point fields
template<class Type>
label distributePointFields
(
const IOobjectList& objects,
const wordRes& selectedFields = wordRes()
) const;
//- Distributed each (unregistered!) point field
//- and store the result on its objectRegistry
template<class Type>
void distributeAndStore
(
const PtrList<GeometricField<Type, pointPatchField, pointMesh>>&
) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "parPointFieldDistributorTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,239 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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 "Time.H"
#include "emptyPointPatchField.H"
#include "IOobjectList.H"
#include "mapDistributePolyMesh.H"
#include "distributedFieldMapper.H"
#include "distributedPointPatchFieldMapper.H"
#include "pointFields.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::pointPatchField, Foam::pointMesh>>
Foam::parPointFieldDistributor::distributeField
(
const GeometricField<Type, pointPatchField, pointMesh>& fld
) const
{
if (!tgtMeshRef_ || !distMapRef_)
{
FatalErrorInFunction
<< "Cannot map field without target mesh and/or distribution!"
<< abort(FatalError);
}
if (!hasPatchPointMaps())
{
const_cast<parPointFieldDistributor&>(*this).createPatchPointMaps();
}
const auto& tgtMesh = tgtMeshRef_();
const auto& distMap = distMapRef_();
// Create internalField by remote mapping
distributedFieldMapper mapper
(
labelUList::null(),
distMap.pointMap()
);
DimensionedField<Type, pointMesh> internalField
(
IOobject
(
fld.name(),
tgtMesh.time().timeName(),
fld.local(),
tgtMesh.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
tgtMesh,
fld.dimensions(),
Field<Type>(fld.internalField(), mapper)
);
internalField.oriented() = fld.oriented();
// Create patchFields by remote mapping
PtrList<pointPatchField<Type>> newPatchFields(tgtMesh.boundary().size());
const auto& bfld = fld.boundaryField();
forAll(bfld, patchi)
{
if (patchPointMaps_.set(patchi))
{
// Clone local patch field
const distributedPointPatchFieldMapper mapper
(
labelUList::null(),
patchPointMaps_[patchi]
);
// Map into local copy
newPatchFields.set
(
patchi,
pointPatchField<Type>::New
(
bfld[patchi],
tgtMesh.boundary()[patchi], // pointPatch
DimensionedField<Type, pointMesh>::null(),
mapper
)
);
// Note: below alternative, 'clone' method will not work since
// there is no clone to reset both internalField reference and
// patch reference. TBD.
//newPatchFields.set
//(
// patchi,
// bfld[patchi].clone
// (
// tgtMesh.boundary()[patchi],
// DimensionedField<Type, pointMesh>::null(),
// mapper
// )
//);
}
}
// Add some empty patchFields on remaining patches (this also handles
// e.g. processorPatchFields or any other constraint type patches)
forAll(newPatchFields, patchi)
{
if (!newPatchFields.set(patchi))
{
newPatchFields.set
(
patchi,
pointPatchField<Type>::New
(
emptyPointPatchField<Type>::typeName,
tgtMesh.boundary()[patchi],
DimensionedField<Type, pointMesh>::null()
)
);
}
}
return
tmp<GeometricField<Type, pointPatchField, pointMesh>>::New
(
std::move(internalField),
newPatchFields
);
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::pointPatchField, Foam::pointMesh>>
Foam::parPointFieldDistributor::distributePointField
(
const IOobject& fieldObject
) const
{
// Read field
GeometricField<Type, pointPatchField, pointMesh> fld
(
fieldObject,
srcMesh_
);
// Redistribute
return distributeField(fld);
}
template<class Type>
Foam::label Foam::parPointFieldDistributor::distributePointFields
(
const IOobjectList& objects,
const wordRes& selectedFields
) const
{
typedef GeometricField<Type, pointPatchField, pointMesh> fieldType;
UPtrList<const IOobject> fieldObjects
(
selectedFields.empty()
? objects.sorted<fieldType>()
: objects.sorted<fieldType>(selectedFields)
);
label nFields = 0;
for (const IOobject& io : fieldObjects)
{
if (verbose_)
{
if (!nFields)
{
Info<< " Reconstructing "
<< fieldType::typeName << "s\n" << nl;
}
Info<< " " << io.name() << nl;
}
++nFields;
tmp<fieldType> tfld(distributePointField<Type>(io));
if (isWriteProc_)
{
tfld().write();
}
}
if (nFields && verbose_) Info<< endl;
return nFields;
}
template<class Type>
void Foam::parPointFieldDistributor::distributeAndStore
(
const PtrList<GeometricField<Type, pointPatchField, pointMesh>>& fields
) const
{
for (const auto& fld : fields)
{
// Distribute and store
auto tfld = distributeField(fld);
tfld.ref().writeOpt(IOobject::AUTO_WRITE);
tfld().mesh().thisDb().store(tfld);
}
}
// ************************************************************************* //

View File

@ -0,0 +1,230 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2015-2022 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
Reading, reconstruct, redistribution of lagrangian fields.
\*---------------------------------------------------------------------------*/
#ifndef Foam_redistributeLagrangian_H
#define Foam_redistributeLagrangian_H
#include "parLagrangianDistributor.H"
#include "unmappedPassivePositionParticleCloud.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Read clouds (note: might not be present on all processors)
PtrList<unmappedPassivePositionParticleCloud>
readLagrangian
(
const fvMesh& mesh,
const wordList& cloudNames,
const wordRes& selectedFields
)
{
PtrList<unmappedPassivePositionParticleCloud> clouds(cloudNames.size());
if (!cloudNames.empty())
{
(void)mesh.tetBasePtIs();
}
// Setup clouds
forAll(cloudNames, i)
{
//Pout<< "Loading cloud " << cloudNames[i] << endl;
clouds.set
(
i,
new unmappedPassivePositionParticleCloud(mesh, cloudNames[i], false)
);
//for (passivePositionParticle& p : clouds[i]))
//{
// Pout<< "Particle position:" << p.position()
// << " cell:" << p.cell()
// << " with cc:" << mesh.cellCentres()[p.cell()]
// << endl;
//}
IOobjectList cloudObjs(clouds[i], clouds[i].time().timeName());
//Pout<< "Found cloud objects:" << cloudObjs.names() << endl;
parLagrangianDistributor::readAllFields
(
clouds[i],
cloudObjs,
selectedFields
);
}
return clouds;
}
// Read clouds (note: might not be present on all processors)
PtrList<unmappedPassivePositionParticleCloud>
readLagrangian
(
const fvMesh& mesh,
const wordRes& selectedFields
)
{
wordList cloudNames;
List<wordList> fieldNames;
// Find all cloudNames on all processors
parLagrangianDistributor::findClouds(mesh, cloudNames, fieldNames);
return readLagrangian(mesh, cloudNames, selectedFields);
}
void reconstructLagrangian
(
autoPtr<parLagrangianDistributor>& distributorPtr,
const fvMesh& baseMesh,
const fvMesh& mesh,
const mapDistributePolyMesh& distMap,
const wordRes& selectedFields
)
{
// Clouds (note: might not be present on all processors)
wordList cloudNames;
List<wordList> fieldNames;
// Find all cloudNames on all processors
parLagrangianDistributor::findClouds(mesh, cloudNames, fieldNames);
if (cloudNames.empty())
{
// Nothing to do
return;
}
// Use existing or create distributor
if (!distributorPtr)
{
distributorPtr.reset
(
new parLagrangianDistributor
(
mesh,
baseMesh,
mesh.nCells(), // range of cell indices in clouds
distMap
)
);
}
const auto& distributor = *distributorPtr;
for (const word& cloudName : cloudNames)
{
Info<< "Reconstructing lagrangian fields for cloud "
<< cloudName << nl << endl;
IOobjectList cloudObjs
(
mesh,
mesh.time().timeName(),
cloud::prefix/cloudName
);
autoPtr<mapDistributeBase> lagrangianMapPtr =
distributor.distributeLagrangianPositions
(
cloudName
);
distributor.distributeAllFields
(
lagrangianMapPtr(),
cloudName,
cloudObjs,
selectedFields
);
}
}
void redistributeLagrangian
(
autoPtr<parLagrangianDistributor>& distributorPtr,
const fvMesh& mesh,
const label nOldCells,
const mapDistributePolyMesh& distMap,
PtrList<unmappedPassivePositionParticleCloud>& clouds
)
{
if (clouds.empty())
{
// Nothing to do
return;
}
// Use existing or create distributor
if (!distributorPtr)
{
distributorPtr.reset
(
new parLagrangianDistributor
(
mesh,
mesh,
nOldCells, // range of cell indices in clouds
distMap
)
);
}
const auto& distributor = *distributorPtr;
for (auto& cloud : clouds)
{
autoPtr<mapDistributeBase> lagrangianMapPtr =
distributor.distributeLagrangianPositions(cloud);
distributor.distributeAllStoredFields
(
lagrangianMapPtr(),
cloud
);
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
#endif
// ************************************************************************* //

View File

@ -944,37 +944,29 @@ Foam::mapDistributeBase::mapDistributeBase
Pstream::exchangeSizes(subMap_, recvSizes, comm_);
// Determine order of receiving
labelListList constructMap(nProcs);
constructSize_ = 0;
constructMap_.resize(nProcs);
// My local segments first
label nLocal = recvSizes[myRank];
// My data first
{
labelList& myMap = constructMap[myRank];
myMap.setSize(nLocal);
forAll(myMap, i)
{
myMap[i] = i;
}
const label len = recvSizes[myRank];
constructMap_[myRank] = identity(len, constructSize_);
constructSize_ += len;
}
label segmenti = nLocal;
forAll(constructMap, proci)
// What the other processors are sending to me
forAll(constructMap_, proci)
{
if (proci != myRank)
{
// What i need to receive is what other processor is sending to me.
label nRecv = recvSizes[proci];
constructMap[proci].setSize(nRecv);
const label len = recvSizes[proci];
for (label i = 0; i < nRecv; i++)
{
constructMap[proci][i] = segmenti++;
}
constructMap_[proci] = identity(len, constructSize_);
constructSize_ += len;
}
}
constructSize_ = segmenti;
constructMap_.transfer(constructMap);
}
@ -1062,402 +1054,6 @@ Foam::label Foam::mapDistributeBase::renumber
}
void Foam::mapDistributeBase::compact
(
const boolList& elemIsUsed,
const int tag
)
{
const label myRank = Pstream::myProcNo(comm_);
const label nProcs = Pstream::nProcs(comm_);
// 1. send back to sender. Have sender delete the corresponding element
// from the submap and do the same to the constructMap locally
// (and in same order).
// Send elemIsUsed field to neighbour. Use nonblocking code from
// mapDistributeBase but in reverse order.
if (Pstream::parRun())
{
label startOfRequests = Pstream::nRequests();
// Set up receives from neighbours
List<boolList> recvFields(nProcs);
for (const int domain : Pstream::allProcs(comm_))
{
const labelList& map = subMap_[domain];
if (domain != myRank && map.size())
{
recvFields[domain].setSize(map.size());
IPstream::read
(
Pstream::commsTypes::nonBlocking,
domain,
recvFields[domain].data_bytes(),
recvFields[domain].size_bytes(),
tag,
comm_
);
}
}
List<boolList> sendFields(nProcs);
for (const int domain : Pstream::allProcs(comm_))
{
const labelList& map = constructMap_[domain];
if (domain != myRank && map.size())
{
boolList& subField = sendFields[domain];
subField.setSize(map.size());
forAll(map, i)
{
subField[i] = accessAndFlip
(
elemIsUsed,
map[i],
constructHasFlip_,
identityOp() // Do not flip elemIsUsed value
);
}
OPstream::write
(
Pstream::commsTypes::nonBlocking,
domain,
subField.cdata_bytes(),
subField.size_bytes(),
tag,
comm_
);
}
}
// Set up 'send' to myself - write directly into recvFields
{
const labelList& map = constructMap_[myRank];
recvFields[myRank].setSize(map.size());
forAll(map, i)
{
recvFields[myRank][i] = accessAndFlip
(
elemIsUsed,
map[i],
constructHasFlip_,
identityOp() // Do not flip elemIsUsed value
);
}
}
// Wait for all to finish
Pstream::waitRequests(startOfRequests);
// Compact out all submap entries that are referring to unused elements
for (const int domain : Pstream::allProcs(comm_))
{
const labelList& map = subMap_[domain];
labelList newMap(map.size());
label newI = 0;
forAll(map, i)
{
if (recvFields[domain][i])
{
// So element is used on destination side
newMap[newI++] = map[i];
}
}
if (newI < map.size())
{
newMap.setSize(newI);
subMap_[domain].transfer(newMap);
}
}
}
// 2. remove from construct map - since end-result (element in elemIsUsed)
// not used.
label maxConstructIndex = -1;
for (const int domain : Pstream::allProcs(comm_))
{
const labelList& map = constructMap_[domain];
labelList newMap(map.size());
label newI = 0;
forAll(map, i)
{
label destinationI = map[i];
if (constructHasFlip_)
{
destinationI = mag(destinationI)-1;
}
// Is element is used on destination side
if (elemIsUsed[destinationI])
{
maxConstructIndex = max(maxConstructIndex, destinationI);
newMap[newI++] = map[i];
}
}
if (newI < map.size())
{
newMap.setSize(newI);
constructMap_[domain].transfer(newMap);
}
}
constructSize_ = maxConstructIndex+1;
// Clear the schedule (note:not necessary if nothing changed)
schedulePtr_.clear();
}
void Foam::mapDistributeBase::compact
(
const boolList& elemIsUsed,
const label localSize, // max index for subMap
labelList& oldToNewSub,
labelList& oldToNewConstruct,
const int tag
)
{
const label myRank = Pstream::myProcNo(comm_);
const label nProcs = Pstream::nProcs(comm_);
// 1. send back to sender. Have sender delete the corresponding element
// from the submap and do the same to the constructMap locally
// (and in same order).
// Send elemIsUsed field to neighbour. Use nonblocking code from
// mapDistributeBase but in reverse order.
if (Pstream::parRun())
{
label startOfRequests = Pstream::nRequests();
// Set up receives from neighbours
List<boolList> recvFields(nProcs);
for (const int domain : Pstream::allProcs(comm_))
{
const labelList& map = subMap_[domain];
if (domain != myRank && map.size())
{
recvFields[domain].setSize(map.size());
IPstream::read
(
Pstream::commsTypes::nonBlocking,
domain,
recvFields[domain].data_bytes(),
recvFields[domain].size_bytes(),
tag,
comm_
);
}
}
List<boolList> sendFields(nProcs);
for (const int domain : Pstream::allProcs(comm_))
{
const labelList& map = constructMap_[domain];
if (domain != myRank && map.size())
{
boolList& subField = sendFields[domain];
subField.setSize(map.size());
forAll(map, i)
{
label index = map[i];
if (constructHasFlip_)
{
index = mag(index)-1;
}
subField[i] = elemIsUsed[index];
}
OPstream::write
(
Pstream::commsTypes::nonBlocking,
domain,
subField.cdata_bytes(),
subField.size_bytes(),
tag,
comm_
);
}
}
// Set up 'send' to myself - write directly into recvFields
{
const labelList& map = constructMap_[myRank];
recvFields[myRank].setSize(map.size());
forAll(map, i)
{
label index = map[i];
if (constructHasFlip_)
{
index = mag(index)-1;
}
recvFields[myRank][i] = elemIsUsed[index];
}
}
// Wait for all to finish
Pstream::waitRequests(startOfRequests);
// Work out which elements on the sending side are needed
{
oldToNewSub.setSize(localSize, -1);
boolList sendElemIsUsed(localSize, false);
for (const int domain : Pstream::allProcs(comm_))
{
const labelList& map = subMap_[domain];
forAll(map, i)
{
if (recvFields[domain][i])
{
label index = map[i];
if (subHasFlip_)
{
index = mag(index)-1;
}
sendElemIsUsed[index] = true;
}
}
}
label newI = 0;
forAll(sendElemIsUsed, i)
{
if (sendElemIsUsed[i])
{
oldToNewSub[i] = newI++;
}
}
}
// Compact out all submap entries that are referring to unused elements
for (const int domain : Pstream::allProcs(comm_))
{
const labelList& map = subMap_[domain];
labelList newMap(map.size());
label newI = 0;
forAll(map, i)
{
if (recvFields[domain][i])
{
// So element is used on destination side
label index = map[i];
label sign = 1;
if (subHasFlip_)
{
if (index < 0)
{
sign = -1;
}
index = mag(index)-1;
}
label newIndex = oldToNewSub[index];
if (subHasFlip_)
{
newIndex = sign*(newIndex+1);
}
newMap[newI++] = newIndex;
}
}
newMap.setSize(newI);
subMap_[domain].transfer(newMap);
}
}
// 2. remove from construct map - since end-result (element in elemIsUsed)
// not used.
oldToNewConstruct.setSize(elemIsUsed.size(), -1);
constructSize_ = 0;
forAll(elemIsUsed, i)
{
if (elemIsUsed[i])
{
oldToNewConstruct[i] = constructSize_++;
}
}
for (const int domain : Pstream::allProcs(comm_))
{
const labelList& map = constructMap_[domain];
labelList newMap(map.size());
label newI = 0;
forAll(map, i)
{
label destinationI = map[i];
label sign = 1;
if (constructHasFlip_)
{
if (destinationI < 0)
{
sign = -1;
}
destinationI = mag(destinationI)-1;
}
// Is element is used on destination side
if (elemIsUsed[destinationI])
{
label newIndex = oldToNewConstruct[destinationI];
if (constructHasFlip_)
{
newIndex = sign*(newIndex+1);
}
newMap[newI++] = newIndex;
}
}
newMap.setSize(newI);
constructMap_[domain].transfer(newMap);
}
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
void Foam::mapDistributeBase::operator=(const mapDistributeBase& rhs)

View File

@ -186,6 +186,34 @@ protected:
labelList& compactStart
);
//- Synchronize send/recv mask buffers as a 'copy' operation.
// Somewhat similar to Pstream::exchangeContainer
//
// The masks must be properly sized by the caller, which avoids
// a needless all-to-all for the sizes and the sizing is already
// given by the maps.
static void exchangeMasks
(
const UList<bitSet>& sendMasks,
UList<bitSet>& recvMasks,
const int tag,
const label comm
);
//- Bi-direction sync of send/recv buffers using bitwise '&='
//- combine operation.
//
// The masks must be properly sized by the caller, which avoids
// a needless all-to-all for the sizes and the sizing is already
// given by the maps.
static void unionCombineMasks
(
UList<bitSet>& sendMasks,
UList<bitSet>& recvMasks,
const int tag,
const label comm
);
template<class T, class CombineOp, class NegateOp>
static void flipAndCombine
@ -225,6 +253,88 @@ private:
// Private Member Functions
//- Helper for compactData (private: filescope only!)
// Establishes the exact send/recv elements used after masking.
//
// \param allowedLocalElems Permissible local mapped elements
// (true/false). Can be longer/shorter than actual number
// of mapped elements.
// \param allowedRemoteElems Permissible remote mapped elements
// (true/false). Can be longer/shorter than actual number
// of mapped elements.
// \param[out] sendMasks Mask of local elements sent to procs.
// \param[out] recvMasks Mask of remote elements received
// from procs
// \param tag The message tag
void calcCompactDataRequirements
(
const bitSet& allowedLocalElems,
const bitSet& allowedRemoteElems,
List<bitSet>& sendMasks, // [out]
List<bitSet>& recvMasks, // [out]
const int tag
);
//- Helper for compactLocalData (private: filescope only!)
// Establishes the exact send/recv elements used after masking.
//
// \param allowedLocalElems Permissible local mapped elements
// (true/false). Can be longer/shorter than actual number
// of mapped elements.
// \param[out] sendMasks Mask of local elements sent to procs.
// \param[out] recvMasks Mask of remote elements received by proc.
// from procs
// \param tag The message tag
void calcCompactLocalDataRequirements
(
const bitSet& allowedLocalElems,
List<bitSet>& sendMasks, // [out]
List<bitSet>& recvMasks, // [out]
const int tag
);
//- Helper for compactRemoteData (private: filescope only!)
// Establishes the exact send/recv elements used after masking.
//
// \param allowedRemoteElems Permissible remote mapped elements
// (true/false). Can be longer/shorter than actual number
// of mapped elements.
// \param[out] sendMasks Mask of local elements sent to procs.
// \param[out] recvMasks Mask of remote elements received by proc.
// \param tag The message tag
void calcCompactRemoteDataRequirements
(
const bitSet& allowedRemoteElems,
List<bitSet>& sendMasks, // [out]
List<bitSet>& recvMasks, // [out]
const int tag
);
//- Implementation for compact{Local,Remote}Data (private).
// Also renumbers the subMap/constructMap if oldToNew maps
// are notNull().
//
// No communication
void compactData
(
const UList<bitSet>& sendMasks,
const UList<bitSet>& recvMasks,
labelList& oldToNewSub,
labelList& oldToNewConstruct,
const label localSize = -1
);
//- Wrapper for compactData (private) that supplies oldToNew
//- maps for renumbering if doRenumber is true.
// No communication
void compactDataImpl
(
const UList<bitSet>& sendMasks,
const UList<bitSet>& recvMasks,
const bool doRenumber
);
//- Helper for renumbering compacted map elements and updating the
//- supplied old-to-new mapping to account for the visit order of
//- the original elements
@ -509,22 +619,163 @@ public:
// Compaction
//- Compact all maps and layout.
// Returns compaction maps for subMap and constructMap
void compact
//- Compact send/receive maps based on selection of
//- originating local (send) elements.
// Determines and removes the correspondingly unneeded elements
// in the send/receive maps.
// Only compacts the maps, does not change the local layout.
//
// \param allowedLocalElems Permissible local mapped elements
// (true/false). Can be longer/shorter than actual number
// of mapped elements.
// \param tag The message tag
// \param doRenumber Apply oldToNew internally to renumber
// entries (uses renumberMap) and adjust the constructSize
//
// \note generally preferable to compact based on remote data
// (ie, the actual receiver)
void compactLocalData
(
const boolList& elemIsUsed,
const bitSet& allowedLocalElems,
const int tag = UPstream::msgType(),
const bool doRenumber = false
);
//- Compact send/receive maps based on selection of
//- remote (receive) elements.
// Determines and removes the correspondingly unneeded elements
// in the send/receive maps.
// Only compacts the maps, does not change the local layout.
//
// \param allowedRemoteElems Permissible remote mapped elements
// (true/false). Can be longer/shorter than actual number
// of mapped elements.
// \param tag The message tag
// \param doRenumber Apply oldToNew internally to renumber
// entries (uses renumberMap) and adjust the constructSize
void compactRemoteData
(
const bitSet& allowedRemoteElems,
const int tag = UPstream::msgType(),
const bool doRenumber = false
);
//- Compact send/receive maps based on selection of
//- originating local (send) elements.
//- Returns compaction mappings for subMap and constructMap.
//
// \param allowedLocalElems Permissible local mapped elements
// (true/false). Can be longer/shorter than actual number
// of mapped elements.
// \param[out] oldToNewSub Old-to-new mapping: subMap
// Disabled if labelList::null(),
// \param[out] oldToNewConstruct Old-to-new mapping: constructMap
// Disabled if labelList::null(),
// \param localSize The max index for subMap (-1: auto-detect)
// \param tag The message tag
//
// \note Applies oldToNew to renumber entries
// (uses renumberMap) and adjust constructSize
//
// \note generally preferable to compact based on remote data
// (ie, the actual receiver)
void compactLocalData
(
const bitSet& allowedLocalElems,
labelList& oldToNewSub,
labelList& oldToNewConstruct,
const label localSize = -1,
const int tag = UPstream::msgType()
);
//- Compact all maps and layout.
// Returns compaction maps for subMap and constructMap
void compact
//- Compact send/receive maps based on selection of
//- remote (receive) elements.
//- Returns compaction mappings for subMap and constructMap.
//
// \param allowedRemoteElems Permissible remote mapped elements
// (true/false). Can be longer/shorter than actual number
// of mapped elements.
// \param[out] oldToNewSub Old-to-new mapping: subMap
// Disabled if labelList::null(),
// \param[out] oldToNewConstruct Old-to-new mapping: constructMap
// Disabled if labelList::null(),
// \param localSize The max index for subMap (-1: auto-detect)
// \param tag The message tag
//
// \note Applies oldToNew to renumber entries
// (uses renumberMap) and adjust constructSize
void compactRemoteData
(
const boolList& elemIsUsed,
const label localSize, // max index for subMap
const bitSet& allowedRemoteElems,
labelList& oldToNewSub,
labelList& oldToNewConstruct,
const label localSize = -1,
const int tag = UPstream::msgType()
);
//- Compact send/receive maps based on selection of
//- originating local (send) and remote (receive) elements.
//
// The resulting compact numbering:
// - \c subMap (and \c oldToNewSub) :
// will follow the original ordering of \c localElements.
// - \c constructMap (and \c oldToNewConstruct) :
// will follow the original ordering of \c remoteElements.
// .
// \warning ill-defined behaviour if \c localElements
// or \c remoteElements contains duplicates.
void compactData
(
const labelUList& localElements,
const labelUList& remoteElements,
labelList& oldToNewSub,
labelList& oldToNewConstruct,
const label localSize = -1,
const int tag = UPstream::msgType()
);
//- Compact send/receive maps based on selection of
//- originating local (send) elements.
//
// The resulting compact numbering:
// - \c subMap (and \c oldToNewSub) :
// will follow the original ordering of \c localElements.
// - \c constructMap (and \c oldToNewConstruct) :
// numbered in simple ascending order.
// .
// \warning ill-defined behaviour if \c localElements
// contains duplicates.
//
// \note generally preferable to compact based on remote data
// (ie, the actual receiver)
void compactLocalData
(
const labelUList& localElements,
labelList& oldToNewSub,
labelList& oldToNewConstruct,
const label localSize = -1,
const int tag = UPstream::msgType()
);
//- Compact send/receive maps based on selection of
//- remote (receive) elements.
//
// The resulting compact numbering:
// - \c subMap (and \c oldToNewSub) :
// numbered in simple ascending order.
// - \c constructMap (and \c oldToNewConstruct) :
// will follow the original ordering of \c remoteElements.
// .
// \warning ill-defined behaviour if \c remoteElements
// contains duplicates.
void compactRemoteData
(
const labelUList& remoteElements,
labelList& oldToNewSub,
labelList& oldToNewConstruct,
const label localSize = -1,
const int tag = UPstream::msgType()
);
@ -745,6 +996,25 @@ public:
{
NotImplemented;
}
//- OpenFOAM-v2112 and earlier naming for compactRemoteData()
//- using boolList.
void compact
(
const boolList& remoteElemUsed,
const int tag = UPstream::msgType()
);
//- OpenFOAM-v2112 and earlier naming for compactRemoteData().
//- using boolList.
void compact
(
const boolList& remoteElemUsed,
const label localSize,
labelList& oldToNewSub,
labelList& oldToNewConstruct,
const int tag = UPstream::msgType()
);
};

View File

@ -36,25 +36,39 @@ namespace Foam
// The maps (labelListList) are not human-modifiable but if we need to
// inspect them in ASCII, it is much more convenient if each sub-list
// is flattened on a single line.
static Ostream& printMaps(Ostream& os, const labelListList& maps)
{
if (os.format() == IOstream::BINARY || maps.empty())
{
os << maps;
}
else
{
os << nl << maps.size() << nl
<< token::BEGIN_LIST << nl;
// Compact single-line output for each labelList
for (const labelList& map : maps)
{
map.writeList(os) << nl;
}
os << token::END_LIST;
}
return os;
}
static void writeMaps(Ostream& os, const word& key, const labelListList& maps)
{
if (os.format() == IOstream::BINARY)
if (os.format() == IOstream::BINARY || maps.empty())
{
os.writeEntry(key, maps);
}
else
{
os << indent << key << nl
<< maps.size() << nl
<< token::BEGIN_LIST << nl;
// Single-line output
for (const labelList& map : maps)
{
map.writeList(os) << nl;
}
os << token::END_LIST << token::END_STATEMENT << nl;
os << indent << key;
printMaps(os, maps) << token::END_STATEMENT << nl;
}
}
@ -129,7 +143,8 @@ Foam::Istream& Foam::operator>>(Istream& is, mapDistributeBase& map)
{
is.fatalCheck(FUNCTION_NAME);
is >> map.constructSize_ >> map.subMap_ >> map.constructMap_
is >> map.constructSize_
>> map.subMap_ >> map.constructMap_
>> map.subHasFlip_ >> map.constructHasFlip_
>> map.comm_;
@ -139,11 +154,14 @@ Foam::Istream& Foam::operator>>(Istream& is, mapDistributeBase& map)
Foam::Ostream& Foam::operator<<(Ostream& os, const mapDistributeBase& map)
{
os << map.constructSize_ << token::NL
<< map.subMap_ << token::NL
<< map.constructMap_ << token::NL
<< map.subHasFlip_ << token::SPACE << map.constructHasFlip_
<< token::SPACE << map.comm_ << token::NL;
os << map.constructSize_ << token::NL;
printMaps(os, map.subMap_) << token::NL;
printMaps(os, map.constructMap_) << token::NL;
os << map.subHasFlip_ << token::SPACE
<< map.constructHasFlip_ << token::SPACE
<< map.comm_ << token::NL;
return os;
}

View File

@ -29,6 +29,252 @@ License
#include "bitSet.H"
#include "ListOps.H"
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam
{
// Setup array of element masks to match maps sizes
//
// \param[out] masks Sized for each position in the maps
// \param maps The element maps
static void blankElementMasks(List<bitSet>& masks, const labelListList& maps)
{
// If base container not already sized
if (masks.empty())
{
masks.resize(maps.size());
}
forAll(masks, proci)
{
masks[proci].reset(); // zero all bits
masks[proci].resize(maps[proci].size());
}
}
// Calculate the element mask correspondig to allowedElems in the maps
//
// \param allowedElems Permissible mapped elements (true/false)
// \param[out] masks True/false for each position within the maps
// \param maps The element maps
// \param hasFlip Map has flip indexing
//
// \return the max index used.
static label calcElementMasks
(
const bitSet& allowedElems,
List<bitSet>& masks, // [out] - often presized before calling
const labelListList& maps,
const bool hasFlip
)
{
// Index after flipping
const auto unflippedIndex =
(
hasFlip
? [](label idx) -> label { return mag(idx)-1; }
: [](label idx) -> label { return idx; }
);
// If not already sized
if (masks.empty())
{
masks.resize(maps.size());
}
label maxIndex = -1;
forAll(masks, proci)
{
bitSet& mask = masks[proci];
const labelList& map = maps[proci];
mask.reset(); // zero all bits
mask.resize(map.size());
forAll(map, i)
{
// Element is used (or not)
const label index = unflippedIndex(map[i]);
if (allowedElems.test(index))
{
mask.set(i);
maxIndex = max(maxIndex, index);
}
}
}
return maxIndex;
}
} // End namespace Foam
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
void Foam::mapDistributeBase::exchangeMasks
(
const UList<bitSet>& sendMasks,
UList<bitSet>& recvMasks,
const int tag,
const label comm
)
{
// Require properly sized mask buffers.
// The information *is* known from the maps, so always use that
// instead having a needless all-to-all for the sizes.
if (sendMasks.size() != recvMasks.size())
{
FatalErrorInFunction
<< "Mismatched mask sizes: "
<< sendMasks.size() << " != "
<< recvMasks.size() << nl
<< Foam::abort(FatalError);
}
const label myRank = UPstream::myProcNo(comm);
if (UPstream::parRun())
{
#ifdef FULLDEBUG
if (sendMasks.size() > UPstream::nProcs(comm))
{
FatalErrorInFunction
<< "Mask sizes (" << sendMasks.size()
<< ") are larger than number of procs:"
<< UPstream::nProcs(comm) << nl
<< Foam::abort(FatalError);
}
#endif
const label startOfRequests = UPstream::nRequests();
forAll(recvMasks, proci)
{
if (proci != myRank && recvMasks[proci].size())
{
IPstream::read
(
UPstream::commsTypes::nonBlocking,
proci,
recvMasks[proci].data_bytes(),
recvMasks[proci].size_bytes(),
tag,
comm
);
}
}
forAll(sendMasks, proci)
{
if (proci != myRank && sendMasks[proci].size())
{
OPstream::write
(
UPstream::commsTypes::nonBlocking,
proci,
sendMasks[proci].cdata_bytes(),
sendMasks[proci].size_bytes(),
tag,
comm
);
}
}
// Wait for all to finish
Pstream::waitRequests(startOfRequests);
}
// Receiving myself is just a copy
recvMasks[myRank] = sendMasks[myRank];
}
void Foam::mapDistributeBase::unionCombineMasks
(
UList<bitSet>& sendMasks,
UList<bitSet>& recvMasks,
const int tag,
const label comm
)
{
// Require properly sized mask buffers.
// The information *is* known from the maps, so always use that
// instead having a needless all-to-all for the sizes.
if (sendMasks.size() != recvMasks.size())
{
FatalErrorInFunction
<< "Mismatched mask sizes: "
<< sendMasks.size() << " != "
<< recvMasks.size() << nl
<< Foam::abort(FatalError);
}
if (Pstream::parRun())
{
// Scratch buffers for union operations
List<bitSet> scratch(recvMasks.size());
// Size for receives
forAll(scratch, proci)
{
scratch[proci].resize(recvMasks[proci].size());
}
// Exchange: from sendMasks -> scratch (intermediate receive)
exchangeMasks(sendMasks, scratch, tag, comm);
// Update recvMasks (as union)
forAll(recvMasks, proci)
{
recvMasks[proci] &= scratch[proci];
}
// Size for sends
forAll(scratch, proci)
{
scratch[proci].resize(sendMasks[proci].size());
}
// Exchange: from recvMasks -> scratch (intermediate send)
exchangeMasks(recvMasks, scratch, tag, comm);
// Final synchronization
forAll(sendMasks, proci)
{
sendMasks[proci] &= scratch[proci];
}
}
else
{
// Non-parallel: 'synchronize' myself
const label myRank = Pstream::myProcNo(comm);
recvMasks[myRank] &= sendMasks[myRank];
sendMasks[myRank] = recvMasks[myRank];
}
// Done with parallel exchanges so can shrink the masks to
// the min-size actually needed.
for (auto& mask : sendMasks)
{
mask.resize_last();
}
for (auto& mask : recvMasks)
{
mask.resize_last();
}
}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
Foam::label Foam::mapDistributeBase::renumberMap
@ -128,4 +374,568 @@ void Foam::mapDistributeBase::renumberVisitOrder
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
void Foam::mapDistributeBase::calcCompactDataRequirements
(
const bitSet& allowedLocalElems,
const bitSet& allowedRemoteElems,
List<bitSet>& sendMasks, // [out]
List<bitSet>& recvMasks, // [out]
const int tag
)
{
sendMasks.resize_nocopy(UPstream::nProcs(comm_));
recvMasks.resize_nocopy(UPstream::nProcs(comm_));
// Determine local elements sent to which procs
calcElementMasks
(
allowedLocalElems,
sendMasks,
subMap_,
subHasFlip_
);
// Determine remote elements received from which procs
calcElementMasks
(
allowedRemoteElems,
recvMasks,
constructMap_,
constructHasFlip_
);
// Synchronize - combine as '&' union
unionCombineMasks(sendMasks, recvMasks, tag, comm_);
}
void Foam::mapDistributeBase::calcCompactLocalDataRequirements
(
const bitSet& allowedLocalElems,
List<bitSet>& sendMasks, // [out]
List<bitSet>& recvMasks, // [out]
const int tag
)
{
sendMasks.resize_nocopy(UPstream::nProcs(comm_));
recvMasks.resize_nocopy(UPstream::nProcs(comm_));
// Determine local elements sent to which procs
calcElementMasks
(
allowedLocalElems,
sendMasks,
subMap_,
subHasFlip_
);
blankElementMasks(recvMasks, constructMap_);
// Exchange: from sendMasks -> recvMasks
exchangeMasks(sendMasks, recvMasks, tag, comm_);
}
void Foam::mapDistributeBase::calcCompactRemoteDataRequirements
(
const bitSet& allowedRemoteElems,
List<bitSet>& sendMasks, // [out]
List<bitSet>& recvMasks, // [out]
const int tag
)
{
sendMasks.resize_nocopy(UPstream::nProcs(comm_));
recvMasks.resize_nocopy(UPstream::nProcs(comm_));
// Determine remote elements received from which procs
calcElementMasks
(
allowedRemoteElems,
recvMasks,
constructMap_,
constructHasFlip_
);
blankElementMasks(sendMasks, subMap_);
// Exchange: from recvMasks -> sendMasks
exchangeMasks(recvMasks, sendMasks, tag, comm_);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
void Foam::mapDistributeBase::compactData
(
const UList<bitSet>& sendMasks,
const UList<bitSet>& recvMasks,
labelList& oldToNewSub,
labelList& oldToNewConstruct,
const label localSize // (known) max sizing for subMap
)
{
// Linear address (subMap) after any flipping
const auto unflippedSendIndex =
(
subHasFlip_
? [](label idx) -> label { return mag(idx)-1; }
: [](label idx) -> label { return idx; }
);
// Linear address (constructMap) after any flipping
const auto unflippedRecvIndex =
(
constructHasFlip_
? [](label idx) -> label { return mag(idx)-1; }
: [](label idx) -> label { return idx; }
);
// Compact renumbering enabled if oldToNew maps are notNull
bitSet indexUsed;
// The subMap old-to-new mapping
if (notNull(oldToNewSub))
{
label subMapSize(localSize);
if (subMapSize < 0)
{
subMapSize = getMappedSize(subMap_, subHasFlip_);
}
oldToNewSub.resize_nocopy(subMapSize);
oldToNewSub = -1;
indexUsed.reset(); // zero all bits
indexUsed.resize(subMapSize);
forAll(sendMasks, proci)
{
const bitSet& mask = sendMasks[proci];
const auto& map = subMap_[proci];
for (const label i : mask)
{
const label index = unflippedSendIndex(map[i]);
indexUsed.set(index);
}
}
label nCompact = 0;
for (const label i : indexUsed)
{
oldToNewSub[i] = nCompact++;
}
}
// The constructMap old-to-new mapping
if (notNull(oldToNewConstruct))
{
oldToNewConstruct.resize_nocopy(constructSize_);
oldToNewConstruct = -1;
indexUsed.reset(); // zero all bits
indexUsed.resize(constructSize_);
forAll(recvMasks, proci)
{
const bitSet& mask = recvMasks[proci];
const auto& map = constructMap_[proci];
for (const label i : mask)
{
const label index = unflippedRecvIndex(map[i]);
indexUsed.set(index);
}
}
label nCompact = 0;
for (const label i : indexUsed)
{
oldToNewConstruct[i] = nCompact++;
}
}
// Compact out subMap entries referring to unused elements
forAll(sendMasks, proci)
{
const bitSet& mask = sendMasks[proci];
labelList& map = subMap_[proci];
label nCompact = 0;
for (const label i : mask)
{
// const label index = unflippedSendIndex(map[i]);
// maxLocalIndex = max(maxLocalIndex, index);
map[nCompact++] = map[i];
}
map.resize(nCompact);
}
// Compact out constructMap entries referring to unused elements
label maxRemoteIndex = -1;
forAll(recvMasks, proci)
{
const bitSet& mask = recvMasks[proci];
labelList& map = constructMap_[proci];
label nCompact = 0;
for (const label i : mask)
{
const label index = unflippedRecvIndex(map[i]);
maxRemoteIndex = max(maxRemoteIndex, index);
map[nCompact++] = map[i];
}
map.resize(nCompact);
}
constructSize_ = maxRemoteIndex+1;
// Do compact renumbering...
if (notNull(oldToNewSub))
{
renumberMap(subMap_, oldToNewSub, subHasFlip_);
}
if (notNull(oldToNewConstruct))
{
constructSize_ =
renumberMap(constructMap_, oldToNewConstruct, constructHasFlip_);
}
// Clear the schedule (note:not necessary if nothing changed)
schedulePtr_.reset(nullptr);
}
void Foam::mapDistributeBase::compactData
(
const labelUList& localElements,
const labelUList& remoteElements,
labelList& oldToNewSub,
labelList& oldToNewConstruct,
const label localSize,
const int tag
)
{
List<bitSet> sendMasks;
List<bitSet> recvMasks;
calcCompactDataRequirements
(
bitSet(localElements),
bitSet(remoteElements),
sendMasks,
recvMasks,
tag
);
// Perform compaction and renumbering
compactData
(
sendMasks,
recvMasks,
oldToNewSub,
oldToNewConstruct,
localSize
);
// Renumber according to visit order
renumberVisitOrder
(
localElements,
oldToNewSub,
subMap_,
subHasFlip_
);
// Renumber according to visit order
renumberVisitOrder
(
remoteElements,
oldToNewConstruct,
constructMap_,
constructHasFlip_
);
}
void Foam::mapDistributeBase::compactLocalData
(
const labelUList& localElements,
labelList& oldToNewSub,
labelList& oldToNewConstruct,
const label localSize,
const int tag
)
{
List<bitSet> sendMasks;
List<bitSet> recvMasks;
calcCompactLocalDataRequirements
(
// Retain items required on the local side
bitSet(localElements),
sendMasks,
recvMasks,
tag
);
// Perform compaction and renumbering
compactData
(
sendMasks,
recvMasks,
oldToNewSub,
oldToNewConstruct,
localSize
);
// Renumber according to visit order
renumberVisitOrder
(
localElements,
oldToNewSub,
subMap_,
subHasFlip_
);
}
void Foam::mapDistributeBase::compactRemoteData
(
const labelUList& remoteElements,
labelList& oldToNewSub,
labelList& oldToNewConstruct,
const label localSize,
const int tag
)
{
List<bitSet> sendMasks;
List<bitSet> recvMasks;
calcCompactRemoteDataRequirements
(
// Retain items required on the remote side
bitSet(remoteElements),
sendMasks,
recvMasks,
tag
);
// Perform compaction and renumbering
compactData
(
sendMasks,
recvMasks,
oldToNewSub,
oldToNewConstruct,
localSize
);
// Renumber according to visit order
renumberVisitOrder
(
remoteElements,
oldToNewConstruct,
constructMap_,
constructHasFlip_
);
}
void Foam::mapDistributeBase::compactDataImpl
(
const UList<bitSet>& sendMasks,
const UList<bitSet>& recvMasks,
const bool doRenumber
)
{
if (doRenumber)
{
labelList oldToNewSub;
labelList oldToNewConstruct;
compactData
(
sendMasks,
recvMasks,
oldToNewSub,
oldToNewConstruct,
-1 // localSize: automatic
);
}
else
{
// Call with placeholder values
compactData
(
sendMasks,
recvMasks,
const_cast<labelList&>(labelList::null()), // disabled
const_cast<labelList&>(labelList::null()), // disabled
-1 // localSize: automatic
);
}
}
void Foam::mapDistributeBase::compactLocalData
(
const bitSet& allowedLocalElems,
const int tag,
const bool doRenumber
)
{
List<bitSet> sendMasks;
List<bitSet> recvMasks;
calcCompactLocalDataRequirements
(
allowedLocalElems,
sendMasks,
recvMasks,
tag
);
compactDataImpl(sendMasks, recvMasks, doRenumber);
}
void Foam::mapDistributeBase::compactRemoteData
(
const bitSet& allowedRemoteElems,
const int tag,
const bool doRenumber
)
{
List<bitSet> sendMasks;
List<bitSet> recvMasks;
calcCompactRemoteDataRequirements
(
allowedRemoteElems,
sendMasks,
recvMasks,
tag
);
compactDataImpl(sendMasks, recvMasks, doRenumber);
}
void Foam::mapDistributeBase::compactLocalData
(
const bitSet& allowedLocalElems,
labelList& oldToNewSub,
labelList& oldToNewConstruct,
const label localSize,
const int tag
)
{
List<bitSet> sendMasks;
List<bitSet> recvMasks;
calcCompactLocalDataRequirements
(
allowedLocalElems,
sendMasks,
recvMasks,
tag
);
compactData
(
sendMasks,
recvMasks,
oldToNewSub,
oldToNewConstruct,
localSize
);
}
void Foam::mapDistributeBase::compactRemoteData
(
const bitSet& allowedRemoteElems,
labelList& oldToNewSub,
labelList& oldToNewConstruct,
const label localSize,
const int tag
)
{
List<bitSet> sendMasks;
List<bitSet> recvMasks;
calcCompactRemoteDataRequirements
(
allowedRemoteElems,
sendMasks,
recvMasks,
tag
);
compactData
(
sendMasks,
recvMasks,
oldToNewSub,
oldToNewConstruct,
localSize
);
}
// * * * * * * * * * * * * * * * Housekeeping * * * * * * * * * * * * * * * //
void Foam::mapDistributeBase::compact
(
const boolList& remoteElemUsed,
const int tag
)
{
// Forward to bitSet version
compactRemoteData(bitSet(remoteElemUsed), tag);
}
void Foam::mapDistributeBase::compact
(
const boolList& remoteElemUsed,
const label localSize,
labelList& oldToNewSub,
labelList& oldToNewConstruct,
const int tag
)
{
// Forward to bitSet version
compactRemoteData
(
bitSet(remoteElemUsed),
oldToNewSub,
oldToNewConstruct,
localSize,
tag
);
}
// ************************************************************************* //

View File

@ -150,9 +150,11 @@ Foam::Istream& Foam::operator>>(Istream& is, mapDistributePolyMesh& map)
is >> map.nOldPoints_
>> map.nOldFaces_
>> map.nOldCells_
>> map.oldPatchSizes_
>> map.oldPatchStarts_
>> map.oldPatchNMeshPoints_
>> map.pointMap_
>> map.faceMap_
>> map.cellMap_
@ -171,6 +173,7 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const mapDistributePolyMesh& map)
<< map.oldPatchSizes_ << token::NL
<< map.oldPatchStarts_ << token::NL
<< map.oldPatchNMeshPoints_ << token::NL
<< map.pointMap_ << token::NL
<< map.faceMap_ << token::NL
<< map.cellMap_ << token::NL

View File

@ -0,0 +1,135 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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
fieldsDistributor
Description
Common methods/utilities for field decomposers/distributors etc.
SourceFiles
fieldsDistributorTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef Foam_fieldsDistributor_H
#define Foam_fieldsDistributor_H
#include "IOobjectList.H"
#include "boolList.H"
#include "PtrList.H"
#include "GeometricField.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class fieldsDistributor Declaration
\*---------------------------------------------------------------------------*/
class fieldsDistributor
{
public:
// Reading helpers
//- Generic mesh-based field reading
template<class GeoField>
static void readField
(
const IOobject& io,
const typename GeoField::Mesh& mesh,
const label i,
PtrList<GeoField>& fields
);
//- Definition of readField for GeometricFields only
template<class Type, template<class> class PatchField, class GeoMesh>
static void readField
(
const IOobject& io,
const typename GeoMesh::Mesh& mesh,
const label i,
PtrList<GeometricField<Type, PatchField, GeoMesh>>& fields
);
//- Read fields and store 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
);
//- Read volume/surface/point/area fields that may or may not exist
//- on all processors
template<class GeoField, class MeshSubsetter>
static void readFields
(
const boolList& haveMeshOnProc,
const typename GeoField::Mesh& mesh,
const autoPtr<MeshSubsetter>& subsetterPtr,
IOobjectList& allObjects,
PtrList<GeoField>& fields,
const bool deregister = false
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "fieldsDistributorTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,330 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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/>.
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class GeoField>
void Foam::fieldsDistributor::readField
(
const IOobject& io,
const typename GeoField::Mesh& mesh,
const label i,
PtrList<GeoField>& fields
)
{
fields.set(i, new GeoField(io, mesh));
}
template<class Type, template<class> class PatchField, class GeoMesh>
void Foam::fieldsDistributor::readField
(
const IOobject& io,
const typename GeoMesh::Mesh& mesh,
const label i,
PtrList<GeometricField<Type, PatchField, GeoMesh>>& fields
)
{
fields.set
(
i,
new GeometricField<Type, PatchField, GeoMesh>(io, mesh, false)
);
}
template<class Type, template<class> class PatchField, class GeoMesh>
void Foam::fieldsDistributor::readFields
(
const typename GeoMesh::Mesh& mesh,
const IOobjectList& objects,
PtrList<GeometricField<Type, PatchField, GeoMesh>>& fields,
const bool readOldTime
)
{
typedef GeometricField<Type, PatchField, GeoMesh> GeoField;
// GeoField fields - sorted for consistent order on all processors
UPtrList<const IOobject> fieldObjects(objects.sorted<GeoField>());
// Construct the fields
fields.resize(fieldObjects.size());
forAll(fieldObjects, i)
{
fields.set(i, new GeoField(fieldObjects[i], mesh, readOldTime));
}
}
template<class Mesh, class GeoField>
void Foam::fieldsDistributor::readFields
(
const Mesh& mesh,
const IOobjectList& objects,
PtrList<GeoField>& fields
)
{
// GeoField fields - sorted for consistent order on all processors
UPtrList<const IOobject> fieldObjects(objects.sorted<GeoField>());
// Construct the fields
fields.resize(fieldObjects.size());
forAll(fieldObjects, i)
{
fields.set(i, new GeoField(fieldObjects[i], mesh));
}
}
template<class GeoField, class MeshSubsetter>
void Foam::fieldsDistributor::readFields
(
const boolList& haveMeshOnProc,
const typename GeoField::Mesh& mesh,
const autoPtr<MeshSubsetter>& subsetterPtr,
IOobjectList& allObjects,
PtrList<GeoField>& fields,
const bool deregister
)
{
// Get my objects of type
IOobjectList objects(allObjects.lookupClass<GeoField>());
// Check that we all have all objects
wordList objectNames = objects.sortedNames();
// Get master names
wordList masterNames(objectNames);
Pstream::broadcast(masterNames);
if (haveMeshOnProc[Pstream::myProcNo()] && objectNames != masterNames)
{
FatalErrorInFunction
<< "Objects not synchronised across processors." << nl
<< "Master has " << flatOutput(masterNames) << nl
<< "Processor " << Pstream::myProcNo()
<< " has " << flatOutput(objectNames)
<< exit(FatalError);
}
fields.clear();
fields.resize(masterNames.size());
if (fields.empty())
{
if (deregister)
{
// Extra safety - remove all such types
HashTable<const GeoField*> other
(
mesh.thisDb().objectRegistry::template lookupClass<GeoField>()
);
forAllConstIters(other, iter)
{
GeoField& fld = const_cast<GeoField&>(*iter.val());
if (!fld.ownedByRegistry())
{
fld.checkOut();
}
}
}
// Early exit
return;
}
// Have master send all fields to processors that don't have a mesh. The
// issue is if a patchField does any parallel operations inside its
// construct-from-dictionary. This will not work when going to more
// processors (e.g. decompose = 1 -> many) ! We could make a special
// exception for decomposePar but nicer would be to have read-communicator
// ... For now detect if decomposing & disable parRun
if (Pstream::master())
{
// Work out if we're decomposing - none of the subprocs has a mesh
bool decompose = true;
for (const int proci : Pstream::subProcs())
{
if (haveMeshOnProc[proci])
{
decompose = false;
}
}
const bool oldParRun = Pstream::parRun();
if (decompose)
{
Pstream::parRun(false);
}
forAll(masterNames, i)
{
const word& name = masterNames[i];
IOobject& io = *objects[name];
io.writeOpt(IOobject::AUTO_WRITE);
// Load field (but not oldTime)
readField(io, mesh, i, fields);
}
Pstream::parRun(oldParRun); // Restore any changes
}
else if (haveMeshOnProc[Pstream::myProcNo()])
{
// Have mesh so just try to load
forAll(masterNames, i)
{
const word& name = masterNames[i];
IOobject& io = *objects[name];
io.writeOpt(IOobject::AUTO_WRITE);
/// Pout<< "Attempt read: " << name << endl;
// Load field (but not oldTime)
readField(io, mesh, i, fields);
}
}
// Missing fields on any processors?
// - construct from dictionary
PtrList<dictionary> fieldDicts;
if (Pstream::master())
{
// Broadcast zero sized fields everywhere (if needed)
// Send like a list of dictionaries
OPBstream toProcs(UPstream::masterNo()); // worldComm
const label nDicts = (subsetterPtr ? fields.size() : label(0));
toProcs << nDicts << token::BEGIN_LIST; // Begin list
if (nDicts)
{
// Disable communication for interpolate() method
const bool oldParRun = Pstream::parRun(false);
const auto& subsetter = subsetterPtr();
forAll(fields, i)
{
tmp<GeoField> tsubfld = subsetter.interpolate(fields[i]);
// Surround each with {} as dictionary entry
toProcs.beginBlock();
toProcs << tsubfld();
toProcs.endBlock();
}
Pstream::parRun(oldParRun); // Restore state
}
toProcs << token::END_LIST << token::NL; // End list
}
else
{
// Receive the broadcast...
IPBstream fromMaster(UPstream::masterNo()); // worldComm
// But only consume where needed...
if (!haveMeshOnProc[Pstream::myProcNo()])
{
fromMaster >> fieldDicts;
}
}
// Use the received dictionaries to create fields
// (will be empty if we didn't require them)
// Disable communication when constructing from dictionary
const bool oldParRun = Pstream::parRun(false);
forAll(fieldDicts, i)
{
fields.set
(
i,
new GeoField
(
IOobject
(
masterNames[i],
mesh.time().timeName(),
mesh.thisDb(),
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
mesh,
fieldDicts[i]
)
);
}
Pstream::parRun(oldParRun); // Restore any changes
// Finally. Can checkOut of registry as required
if (deregister)
{
/// Info<< "De-registering fields:";
for (auto& fld : fields)
{
/// Info<< " " << fld.name();
// Ensure it is not destroyed by polyMesh deletion
fld.checkOut();
}
/// Info<< nl;
// Extra safety - remove all such types
HashTable<const GeoField*> other
(
mesh.thisDb().objectRegistry::template lookupClass<GeoField>()
);
forAllConstIters(other, iter)
{
GeoField& fld = const_cast<GeoField&>(*iter.val());
if (!fld.ownedByRegistry())
{
fld.checkOut();
}
}
}
}
// ************************************************************************* //

View File

@ -24,6 +24,9 @@ $(faPatches)/constraint/wedge/wedgeFaPatch.C
$(faPatches)/constraint/cyclic/cyclicFaPatch.C
$(faPatches)/constraint/symmetry/symmetryFaPatch.C
distributed/faMeshDistributor.C
distributed/faMeshDistributorNew.C
ensight = output/ensight
$(ensight)/ensightFaMesh.C

View File

@ -0,0 +1,200 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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 "faMeshDistributor.H"
#include "BitOps.H"
#include "fileOperation.H"
#include "areaFields.H"
#include "edgeFields.H"
#include "faMeshTools.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
int Foam::faMeshDistributor::verbose_ = 0;
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::faMeshDistributor::createPatchMaps() const
{
const faBoundaryMesh& oldPatches = srcMesh_.boundary();
const faBoundaryMesh& newPatches = tgtMesh_.boundary();
patchEdgeMaps_.clear();
patchEdgeMaps_.resize(oldPatches.size());
// area: edgeMap (volume: faceMap)
const auto& faEdgeMap = distMap_.faceMap();
// The logical edge ranges per patch [target mesh]
List<labelRange> ranges = newPatches.patchRanges();
forAll(oldPatches, patchi)
{
if (!isA<processorFaPatch>(oldPatches[patchi]))
{
// Map non-processor only
// Copy full map
patchEdgeMaps_.set
(
patchi,
new mapDistributeBase(faEdgeMap)
);
// Retain patch elements
patchEdgeMaps_[patchi].compactRemoteData
(
bitSet(ranges[patchi]),
UPstream::msgType(),
true // Also renumber/resize the compact maps
);
}
}
}
void Foam::faMeshDistributor::createInternalEdgeMap() const
{
// area: edgeMap (volume: faceMap)
const auto& faEdgeMap = distMap_.faceMap();
// Copy full map
internalEdgeMap_.reset(new mapDistributeBase(faEdgeMap));
// Retain internal edges
internalEdgeMap_->compactRemoteData
(
bitSet(tgtMesh_.nInternalEdges(), true),
UPstream::msgType(),
true // Also renumber/resize the compact maps
);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::faMeshDistributor::faMeshDistributor
(
const faMesh& srcMesh,
const faMesh& tgtMesh,
const mapDistributePolyMesh& distMap,
const bool isWriteProc
)
:
srcMesh_(srcMesh),
tgtMesh_(tgtMesh),
distMap_(distMap),
internalEdgeMap_(),
patchEdgeMaps_(),
isWriteProc_(isWriteProc)
{
#ifdef FULLDEBUG
{
Pout<< "Create from nFaces:" << srcMesh.faceLabels().size()
<< " to:" << tgtMesh.faceLabels().size() << endl;
vectorField oldFaceCentres(srcMesh_.areaCentres());
vectorField newFaceCentres(tgtMesh_.areaCentres());
// volume: cells, area: faces
distMap_.distributeCellData(oldFaceCentres);
vectorField diff(newFaceCentres - oldFaceCentres);
Pout<< "diff faces: " << diff << endl;
vectorField oldEdgeCentres
(
faMeshTools::flattenEdgeField(srcMesh_.edgeCentres())
);
vectorField newEdgeCentres
(
faMeshTools::flattenEdgeField(tgtMesh_.edgeCentres())
);
Pout<< "distributed edges: " << oldEdgeCentres.size() << " from "
<< srcMesh.nEdges() << " to " << tgtMesh.nEdges() << endl;
// volume: faces, area: edges
distMap_.distributeFaceData(oldEdgeCentres);
diff = (newEdgeCentres - oldEdgeCentres);
Pout<< "diff edges: " << diff << endl;
Info<< "Patch edge maps" << endl;
forAll(patchEdgeMaps_, patchi)
{
if (patchEdgeMaps_.set(patchi))
{
Pout<< "patch " << patchi << " : "
<< patchEdgeMaps_[patchi].info() << endl;
}
}
Info<< nl << "Detailed patch maps" << endl;
forAll(patchEdgeMaps_, patchi)
{
if (patchEdgeMaps_.set(patchi))
{
Info<< "patch " << patchi << " : "
<< patchEdgeMaps_[patchi] << endl;
}
}
}
#endif
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::label Foam::faMeshDistributor::distributeAllFields
(
const IOobjectList& objects,
const wordRes& selected
) const
{
label nTotal = 0;
nTotal += distributeAreaFields<scalar>(objects, selected);
nTotal += distributeAreaFields<vector>(objects, selected);
nTotal += distributeAreaFields<symmTensor>(objects, selected);
nTotal += distributeAreaFields<sphericalTensor>(objects, selected);
nTotal += distributeAreaFields<tensor>(objects, selected);
nTotal += distributeEdgeFields<scalar>(objects, selected);
nTotal += distributeEdgeFields<vector>(objects, selected);
nTotal += distributeEdgeFields<symmTensor>(objects, selected);
nTotal += distributeEdgeFields<sphericalTensor>(objects, selected);
nTotal += distributeEdgeFields<tensor>(objects, selected);
return nTotal;
}
// ************************************************************************* //

View File

@ -0,0 +1,241 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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::faMeshDistributor
Description
Holds a reference to the original mesh (the baseMesh)
and optionally to a subset of that mesh (the subMesh)
with mapping lists for points, faces, and cells.
SourceFiles
faMeshDistributor.C
faMeshDistributorNew.C
faMeshDistributorTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef Foam_faMeshDistributor_H
#define Foam_faMeshDistributor_H
#include "faMesh.H"
#include "mapDistributePolyMesh.H"
#include "areaFieldsFwd.H"
#include "edgeFieldsFwd.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward Declarations
class IOobjectList;
/*---------------------------------------------------------------------------*\
Class faMeshDistributor Declaration
\*---------------------------------------------------------------------------*/
class faMeshDistributor
{
// Private Data
//- The source mesh reference
const faMesh& srcMesh_;
//- The destination mesh reference
const faMesh& tgtMesh_;
//- Distribution map reference (faMesh)
const mapDistributePolyMesh& distMap_;
//- Internal edge mapper
mutable std::unique_ptr<mapDistributeBase> internalEdgeMap_;
//- Patch edge mappers
mutable PtrList<mapDistributeBase> patchEdgeMaps_;
//- Do I need to write (eg, master only for reconstruct)
bool isWriteProc_;
// Private Member Functions
//- Construct internal edge mapping
void createInternalEdgeMap() const;
//- Construct per-patch edge mapping
void createPatchMaps() const;
static mapDistributePolyMesh createReconstructMap
(
const faMesh& mesh,
const autoPtr<faMesh>& baseMeshPtr,
const labelUList& faceProcAddr,
const labelUList& edgeProcAddr,
const labelUList& pointProcAddr,
const labelUList& boundaryProcAddr
);
//- No copy construct
faMeshDistributor(const faMeshDistributor&) = delete;
//- No copy assignment
void operator=(const faMeshDistributor&) = delete;
public:
//- Output verbosity when writing
static int verbose_;
// Constructors
//- Construct from components
faMeshDistributor
(
const faMesh& srcMesh,
const faMesh& tgtMesh,
const mapDistributePolyMesh& faDistMap,
const bool isWriteProc = false
);
// Static Methods
//- Distribute mesh according to the given (volume) mesh distribution.
// Uses 'tgtPolyMesh' for the new mesh
static mapDistributePolyMesh distribute
(
const faMesh& oldMesh,
const mapDistributePolyMesh& distMap, //! From polyMesh
const polyMesh& tgtPolyMesh,
autoPtr<faMesh>& newMeshPtr
);
//- Distribute mesh according to the given (volume) mesh distribution.
// Re-uses polyMesh from oldMesh for the new mesh
static mapDistributePolyMesh distribute
(
const faMesh& oldMesh,
const mapDistributePolyMesh& distMap, //! From polyMesh
autoPtr<faMesh>& newMeshPtr
);
// Member Functions
//- Get status of write enabled (on this proc)
bool isWriteProc() const noexcept
{
return isWriteProc_;
}
//- Change status of write enabled (on this proc)
bool isWriteProc(const bool on) noexcept
{
bool old(isWriteProc_);
isWriteProc_ = on;
return old;
}
// Field Mapping
//- Read, distribute and write all/selected point field types
//- (scalar, vector, ... types)
label distributeAllFields
(
const IOobjectList& objects,
const wordRes& selectedFields = wordRes()
) const;
//- Distribute area field
template<class Type>
tmp<GeometricField<Type, faPatchField, areaMesh>>
distributeField
(
const GeometricField<Type, faPatchField, areaMesh>& fld
) const;
//- Distribute edge field
template<class Type>
tmp<GeometricField<Type, faePatchField, edgeMesh>>
distributeField
(
const GeometricField<Type, faePatchField, edgeMesh>& fld
) const;
//- Read and distribute area field
template<class Type>
tmp<GeometricField<Type, faPatchField, areaMesh>>
distributeAreaField
(
const IOobject& fieldObject
) const;
//- Read and distribute edge field
template<class Type>
tmp<GeometricField<Type, faePatchField, edgeMesh>>
distributeEdgeField
(
const IOobject& fieldObject
) const;
//- Read, distribute and write all/selected area fields
template<class Type>
label distributeAreaFields
(
const IOobjectList& objects,
const wordRes& selectedFields = wordRes()
) const;
//- Read, distribute and write all/selected area fields
template<class Type>
label distributeEdgeFields
(
const IOobjectList& objects,
const wordRes& selectedFields = wordRes()
) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "faMeshDistributorTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,916 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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 "faMeshDistributor.H"
#include "globalIndex.H"
#include "BitOps.H"
#include "ListOps.H"
#include "mapDistributePolyMesh.H"
#include "processorFaPatch.H"
#include "labelPairHashes.H"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
Foam::mapDistributePolyMesh
Foam::faMeshDistributor::distribute
(
const faMesh& oldMesh,
const mapDistributePolyMesh& distMap,
const polyMesh& tgtPolyMesh,
autoPtr<faMesh>& newMeshPtr
)
{
newMeshPtr.reset(nullptr);
const uindirectPrimitivePatch& oldAreaPatch = oldMesh.patch();
// Original (patch) sizes before any changes
const label nOldPoints = oldAreaPatch.nPoints();
const label nOldEdges = oldAreaPatch.nEdges();
const label nOldFaces = oldAreaPatch.nFaces();
// ------------------------
// Step 1: The face mapping
// ------------------------
// Relatively straightforward.
// - a subset of face selections on the polyMesh faceMap
mapDistributeBase faFaceMap(distMap.faceMap());
{
// Retain faces needed for the faMesh - preserve original order
// Note can use compactLocalData without problem since
// finiteArea is only defined on real boundary faces so there
// is no danger of sending an internal or processor face.
labelList oldToNewSub;
labelList oldToNewConstruct;
faFaceMap.compactLocalData
(
oldMesh.faceLabels(),
oldToNewSub,
oldToNewConstruct,
distMap.nOldFaces(),
UPstream::msgType()
);
// The receiving side:
// Mapped faces (>= 0) are the polyMesh face labels that define
// the faMesh. Since the compact order is implicitly sorted in
// ascending order, it tends to form contiguous ranges on the
// polyPatches, which serves our purpose nicely.
labelList newFaceLabels
(
ListOps::findIndices(oldToNewConstruct, labelRange::ge0())
);
// Set up to read-if-present
IOobject io(tgtPolyMesh);
io.readOpt(IOobject::READ_IF_PRESENT);
newMeshPtr.reset
(
new faMesh(tgtPolyMesh, std::move(newFaceLabels), io)
);
}
// The face map is now complete.
// The new faMesh and the corresponding primitive patch
auto& newMesh = newMeshPtr();
const uindirectPrimitivePatch& newAreaPatch = newMesh.patch();
// ------------------------
// Step 2: The edge mapping
// ------------------------
// Use globally unique addressing to identify both sides of the edges.
// A local bookkeeping struct of (face0 face1 edge0 edge1)
// selected for a stable and unique sort
struct faceEdgeTuple : public FixedList<label, 4>
{
// Inherit constructors
using FixedList<label, 4>::FixedList;
// Default construct as 'invalid'
faceEdgeTuple() : FixedList<label, 4>(-1) {}
// Is empty if face indices are negative
bool empty() const
{
return (face0() < 0 && face1() < 0);
}
// Global face numbers are the first sort index
label face0() const { return (*this)[0]; }
label face1() const { return (*this)[1]; }
// Additional sorting based on edges
label edge0() const { return (*this)[2]; }
label edge1() const { return (*this)[3]; }
label getFace(int i) const { return (*this)[(i ? 1 : 0)]; }
label getEdge(int i) const { return (*this)[(i ? 3 : 2)]; }
labelPair getFaces() const { return labelPair(face0(), face1()); }
labelPair getPair0() const { return labelPair(face0(), edge0()); }
// labelPair getPair1() const { return labelPair(face1(), edge1()); }
// Canonically sorted order
void canonical()
{
if (face1() >= 0 && face0() >= face1())
{
std::swap((*this)[0], (*this)[1]);
std::swap((*this)[2], (*this)[3]);
}
}
// Slot a face-edge pair into a free location in the tuple
void add(const labelPair& faceEdge)
{
if ((*this)[0] < 0) // face0
{
(*this)[0] = faceEdge.first(); // face
(*this)[2] = faceEdge.second(); // edge
}
else if ((*this)[1] < 0) // face1
{
(*this)[1] = faceEdge.first(); // face
(*this)[3] = faceEdge.second(); // edge
}
}
// Combine operation
void combine(const faceEdgeTuple& y)
{
auto& x = *this;
if (y.empty() || x == y)
{
// Nothing to do
}
else if (x.empty())
{
x = y;
}
else // Both non-empty, but non-identical (should not occur)
{
FatalErrorInFunction
<< "Unexpected edge matching: "
<< x << " vs. " << y << endl
<< exit(FatalError);
}
}
// Combine operation
void operator()(faceEdgeTuple& x, const faceEdgeTuple& y) const
{
x.combine(y);
}
};
// ------------------------
// (Edge mapping)
// ------------------------
// 1.
// Create a list of destination edges for each face,
// appended by a unique face identifier.
// Using global face numbering from the *target* mesh.
const globalIndex uniqFaceIndex(newAreaPatch.nFaces());
labelListList dstFaceEdgeIds(newAreaPatch.nFaces());
forAll(newAreaPatch.faceEdges(), facei)
{
const labelList& fEdges = newAreaPatch.faceEdges()[facei];
labelList& dstEdges = dstFaceEdgeIds[facei];
dstEdges.resize(fEdges.size() + 1);
// Leading entries are the destination (patch) edge indices
labelSubList(dstEdges, fEdges.size()) = fEdges;
// Last entry is the face id
dstEdges.last() = uniqFaceIndex.toGlobal(facei);
}
// Send back to the original mesh locations
faFaceMap.reverseDistribute(nOldFaces, dstFaceEdgeIds);
// 2.
// Walk all original faces and their edges to generate a edge lookup
// table with the destination face/edge information.
// Eg ((globFacei, localEdgei), (globFacei, localEdgei))
// NB: currently no provision for face flips, which would potentially
// reverse the local edge order.
List<faceEdgeTuple> halfEdgeLookup(nOldEdges, faceEdgeTuple());
forAll(oldAreaPatch.faceEdges(), facei)
{
const labelList& fEdges = oldAreaPatch.faceEdges()[facei];
// The corresponding destination edges (+ uniqFacei).
const labelList& dstFaceEdges = dstFaceEdgeIds[facei];
// Last entry has the unique destination face id
const label uniqFacei = dstFaceEdges.last();
forAll(fEdges, faceEdgei)
{
const label srcEdgei = fEdges[faceEdgei];
const label dstEdgei = dstFaceEdges[faceEdgei];
halfEdgeLookup[srcEdgei].add(labelPair(uniqFacei, dstEdgei));
}
}
// 3.
// Add patch indices - encoded as '-(patchId + 2)' for
// non-processor boundaries (will be needed later).
// Also record which procs get patches from here [proc] -> [patches]
// Use for building patchMap
Map<labelHashSet> patchMapInfo;
label nNonProcessor(0);
{
const faBoundaryMesh& oldBndMesh = oldMesh.boundary();
forAll(oldBndMesh, patchi)
{
const faPatch& fap = oldBndMesh[patchi];
if (isA<processorFaPatch>(fap))
{
break;
}
++nNonProcessor;
// Encoded as -(patchId + 2)
const labelPair encodedPatchId(-(patchi+2), -(patchi+2));
for (const label srcEdgei : fap.edgeLabels())
{
faceEdgeTuple& facePairings = halfEdgeLookup[srcEdgei];
facePairings.add(encodedPatchId);
label dstFacei = facePairings.face0();
label proci = uniqFaceIndex.whichProcID(dstFacei);
patchMapInfo(proci).insert(patchi);
}
}
Pstream::broadcast(nNonProcessor);
}
// Processor-processor connections
if (Pstream::parRun())
{
const label startOfRequests = Pstream::nRequests();
const faBoundaryMesh& oldBndMesh = oldMesh.boundary();
// Setup sends
for (const faPatch& fap : oldBndMesh)
{
const auto* fapp = isA<processorFaPatch>(fap);
if (fapp)
{
// Send (dstFacei dstEdgei) per patch edge.
// Since we are walking a boundary edge, the first location
// from the previously established lookup provides
// our information.
List<labelPair> edgeTuples(fap.edgeLabels().size());
label edgeTuplei = 0;
for (const label edgei : fap.edgeLabels())
{
edgeTuples[edgeTuplei] = halfEdgeLookup[edgei].getPair0();
++edgeTuplei;
}
fapp->send<labelPair>
(
Pstream::commsTypes::nonBlocking,
edgeTuples
);
}
}
// Wait for all to finish
Pstream::waitRequests(startOfRequests);
// Receive values
for (const faPatch& fap : oldBndMesh)
{
const auto* fapp = isA<processorFaPatch>(fap);
if (fapp)
{
// Receive (dstFacei dstEdgei) per patch edge.
// - slot into the second location of the lookup
List<labelPair> edgeTuples(fap.edgeLabels().size());
fapp->receive<labelPair>
(
Pstream::commsTypes::nonBlocking,
edgeTuples
);
label edgeTuplei = 0;
for (const label srcEdgei : fap.edgeLabels())
{
halfEdgeLookup[srcEdgei].add(edgeTuples[edgeTuplei]);
++edgeTuplei;
}
}
}
}
// Globally consistent order
for (auto& tuple : halfEdgeLookup)
{
tuple.canonical();
}
// Now ready to actually construct the edgeMap
mapDistributeBase faEdgeMap
(
newAreaPatch.nEdges(), // constructSize
labelListList(), // subMap
labelListList(), // constructMap
false, // subHasFlip
false, // constructHasFlip
faFaceMap.comm()
);
{
// Pass 1.
// Count the number of edges to be sent to each proc
labelList nProcEdges(Pstream::nProcs(faFaceMap.comm()), Zero);
forAll(halfEdgeLookup, srcEdgei)
{
const faceEdgeTuple& facePairings = halfEdgeLookup[srcEdgei];
labelPair dstProcs(-1, -1);
for (int sidei = 0; sidei < 2; ++sidei)
{
const label dstFacei = facePairings.getFace(sidei);
//const label dstEdgei = facePairings.getEdge(sidei);
if (dstFacei < 0)
{
continue;
}
label proci = uniqFaceIndex.whichProcID(dstFacei);
dstProcs[sidei] = proci;
if (proci != -1 && dstProcs[0] != dstProcs[1])
{
++nProcEdges[proci];
}
}
}
auto& edgeSubMap = faEdgeMap.subMap();
auto& edgeCnstrMap = faEdgeMap.constructMap();
edgeSubMap.resize(nProcEdges.size());
edgeCnstrMap.resize(nProcEdges.size());
labelListList remoteEdges(nProcEdges.size());
forAll(nProcEdges, proci)
{
edgeSubMap[proci].resize(nProcEdges[proci], -1);
remoteEdges[proci].resize(nProcEdges[proci], -1);
}
// Pass 2.
// Fill in the maps
nProcEdges = Zero; // Reset counter
forAll(halfEdgeLookup, srcEdgei)
{
const faceEdgeTuple& facePairings = halfEdgeLookup[srcEdgei];
labelPair dstProcs(-1, -1);
for (int sidei = 0; sidei < 2; ++sidei)
{
const label dstFacei = facePairings.getFace(sidei);
const label dstEdgei = facePairings.getEdge(sidei);
if (dstFacei < 0)
{
continue;
}
label proci = uniqFaceIndex.whichProcID(dstFacei);
dstProcs[sidei] = proci;
if (proci != -1 && dstProcs[0] != dstProcs[1])
{
edgeSubMap[proci][nProcEdges[proci]] = srcEdgei;
remoteEdges[proci][nProcEdges[proci]] = dstEdgei;
++nProcEdges[proci];
}
}
}
// The remoteEdges are what we know locally about what will be
// received, but not what is actually received.
// So need an all-to-all exchange
Pstream::exchange<labelList, label>
(
remoteEdges,
edgeCnstrMap,
UPstream::msgType(),
faEdgeMap.comm()
);
}
// The edge map is now complete [in PrimitivePatch edge order]
if (oldMesh.hasInternalEdgeLabels())
{
// If there are gaps in the edge numbering or the
// internal edge labels are out of sequence would
// have to use compactLocalData etc before sending
// But just issue an error for now
FatalErrorInFunction
<< "Originating faMesh has gaps in the edge addressing"
<< " this is currently unsupported"
<< abort(FatalError);
}
// ------------------------
// Patch edge labels
// ------------------------
faPatchList newFaPatches;
// Distribute the edge lookups.
// Needs full version for the combine operation
mapDistributeBase::distribute<faceEdgeTuple, faceEdgeTuple, identityOp>
(
Pstream::commsTypes::nonBlocking,
List<labelPair>::null(),
faEdgeMap.constructSize(),
faEdgeMap.subMap(),
faEdgeMap.subHasFlip(),
faEdgeMap.constructMap(),
faEdgeMap.constructHasFlip(),
halfEdgeLookup,
faceEdgeTuple(), // nullValue
faceEdgeTuple(), // CombineOp
identityOp(), // NegateOp
UPstream::msgType(),
faEdgeMap.comm()
);
{
// Pass 1.
// Count the number of edges for each patch type
Map<label> nNonProcEdges(2*nNonProcessor);
LabelPairMap<label> nProcEdges(2*nNonProcessor);
forAll(halfEdgeLookup, edgei)
{
const auto& tuple = halfEdgeLookup[edgei];
labelPair target(tuple.getFaces());
if (target[1] < -1)
{
// Neighbour face was patchId encoded value
label patchi = mag(target[1])-2;
++nNonProcEdges(patchi);
}
else if (target[0] >= 0 && target[1] >= 0)
{
// From global face to proc id
target[0] = uniqFaceIndex.whichProcID(target[0]);
target[1] = uniqFaceIndex.whichProcID(target[1]);
// A connection between different procs but involving
// myProc?
if
(
target[0] != target[1]
&&
(
target[0] == Pstream::myProcNo()
|| target[1] == Pstream::myProcNo()
)
)
{
++nProcEdges(target);
}
}
}
label nPatches = (nNonProcessor + nProcEdges.size());
newFaPatches.resize(nPatches);
labelList nEdgeLabels(nPatches, Zero);
labelListList newEdgeLabels(nPatches);
LabelPairMap<label> procPairToPatchId(2*nProcEdges.size());
// Map processor-pair to index in patches
{
nPatches = nNonProcessor;
for (const labelPair& twoProcs : nProcEdges.sortedToc())
{
procPairToPatchId.set(twoProcs, nPatches);
++nPatches;
}
}
// Presize edgeLabels arrays
{
nPatches = 0;
for (label patchi = 0; patchi < nNonProcessor; ++patchi)
{
label nLabels = nNonProcEdges.lookup(nPatches, 0);
nEdgeLabels[nPatches] = nLabels;
newEdgeLabels[nPatches].resize(nLabels);
++nPatches;
}
// Processor patches
for (const labelPair& twoProcs : nProcEdges.sortedToc())
{
label nLabels = nProcEdges.lookup(twoProcs, 0);
nEdgeLabels[nPatches] = nLabels;
newEdgeLabels[nPatches].resize(nLabels);
++nPatches;
}
}
nEdgeLabels = Zero;
// Populate edgeLabels arrays - walk in canonically sorted
// order to ensure that both sides of processor edges
// correspond.
const labelList order(Foam::sortedOrder(halfEdgeLookup));
for (const label edgei : order)
{
const auto& tuple = halfEdgeLookup[edgei];
labelPair target(tuple.getFaces());
label patchi = -1;
if (target[1] < -1)
{
// Neighbour face was patchId encoded value
patchi = mag(target[1])-2;
}
else if (target[0] >= 0 && target[1] >= 0)
{
// From global face to proc id
target[0] = uniqFaceIndex.whichProcID(target[0]);
target[1] = uniqFaceIndex.whichProcID(target[1]);
// A connection between different procs but involving
// myProc?
if
(
target[0] != target[1]
&&
(
target[0] == Pstream::myProcNo()
|| target[1] == Pstream::myProcNo()
)
)
{
patchi = procPairToPatchId.lookup(target, -1);
}
}
if (patchi >= 0)
{
const label idx = nEdgeLabels[patchi]++;
newEdgeLabels[patchi][idx] = edgei;
}
}
// Clone all non-processor patches
nPatches = 0;
for (label patchi = 0; patchi < nNonProcessor; ++patchi)
{
newFaPatches.set
(
nPatches,
oldMesh.boundary()[patchi].clone
(
newMesh.boundary(),
newEdgeLabels[nPatches], // edgeLabels
nPatches,
oldMesh.boundary()[patchi].ngbPolyPatchIndex()
)
);
++nPatches;
}
// Any processor patches
for (const labelPair& twoProcs : nProcEdges.sortedToc())
{
label nbrProcNo =
(
twoProcs[1] == Pstream::myProcNo()
? twoProcs[0] : twoProcs[1]
);
newFaPatches.set
(
nPatches,
new processorFaPatch
(
newEdgeLabels[nPatches], // edgeLabels
nPatches,
newMesh.boundary(),
-1, // nbrPolyPatchi
Pstream::myProcNo(),
nbrProcNo
)
);
++nPatches;
}
}
newMesh.addFaPatches(newFaPatches);
newMesh.init(true);
// At this stage we now have a complete mapping overview in
// terms of the PrimitivePatch edge ordering which now must be
// changed into faMesh edge ordering.
{
labelList oldToNewSub;
labelList oldToNewConstruct;
// Assume we use all patch edges for the faMesh too.
oldToNewSub.resize(oldAreaPatch.nEdges(), -1);
oldToNewConstruct.resize(newAreaPatch.nEdges(), -1);
// Remap old edges
label nEdges = 0;
// Internal edgeLabels
for
(
label edgei = 0;
edgei < oldAreaPatch.nInternalEdges();
++edgei
)
{
oldToNewSub[edgei] = nEdges++;
}
// Boundary edgeLabels
for (const faPatch& fap : oldMesh.boundary())
{
for (const label edgei : fap.edgeLabels())
{
oldToNewSub[edgei] = nEdges++;
}
}
// New edges
nEdges = 0;
// Internal edgeLabels
for
(
label edgei = 0;
edgei < newAreaPatch.nInternalEdges();
++edgei
)
{
oldToNewConstruct[edgei] = nEdges++;
}
// Boundary edgeLabels
for (const faPatch& fap : newMesh.boundary())
{
for (const label edgei : fap.edgeLabels())
{
oldToNewConstruct[edgei] = nEdges++;
}
}
mapDistributeBase::renumberMap
(
faEdgeMap.subMap(),
oldToNewSub,
faEdgeMap.subHasFlip()
);
mapDistributeBase::renumberMap
(
faEdgeMap.constructMap(),
oldToNewConstruct,
faEdgeMap.constructHasFlip()
);
}
// ------------------------
// Patch mapping
// ------------------------
mapDistributeBase faPatchMap
(
newMesh.boundary().size(), // constructSize
labelListList(), // subMap
labelListList(), // constructMap
false, // subHasFlip
false, // constructHasFlip
faFaceMap.comm()
);
// For patch maps, would normally transcribe from patchMapInfo
// gathered earlier. However, existing practice (APR-2022) for
// faMesh decomposition is to map all non-processor patches
{
// Map all non-processor patches
const label nProcs = UPstream::nProcs(faPatchMap.comm());
faPatchMap.subMap().resize(nProcs, identity(nNonProcessor));
faPatchMap.constructMap().resize(nProcs, identity(nNonProcessor));
}
/// {
/// // Transcribe from patchMapInfo gathered earlier.
/// // - transform Map of labelHashSet to labelListList
///
/// labelListList sendToRemote(Pstream::nProcs(faPatchMap.comm()));
///
/// forAllConstIters(patchMapInfo, iter)
/// {
/// const label proci = iter.key();
/// sendToRemote[proci] = iter.val().sortedToc();
/// }
///
/// auto& patchSubMap = faPatchMap.subMap();
/// auto& patchCnstrMap = faPatchMap.constructMap();
///
/// patchSubMap = sendToRemote;
/// patchCnstrMap.resize(patchSubMap.size());
///
/// // Change sendToRemote into recv-from-remote by using
/// // all-to-all exchange
///
/// Pstream::exchange<labelList, label>
/// (
/// sendToRemote,
/// patchCnstrMap,
/// UPstream::msgType(),
/// faPatchMap.comm()
/// );
/// }
// ------------------------
// Point mapping
// ------------------------
mapDistributeBase faPointMap(distMap.pointMap());
{
// Retain meshPoints needed for the faMesh - preserve original order
// Need both sides (local/remote) for correct compaction maps
// without dangling points.
labelList oldToNewSub;
labelList oldToNewConstruct;
faPointMap.compactData
(
oldAreaPatch.meshPoints(),
newAreaPatch.meshPoints(),
oldToNewSub,
oldToNewConstruct,
distMap.nOldPoints(),
UPstream::msgType()
);
}
return mapDistributePolyMesh
(
// Mesh before changes
nOldPoints,
nOldEdges, // area: nOldEdges (volume: nOldFaces)
nOldFaces, // area: nOldFaces (volume: nOldCells)
labelList(oldMesh.boundary().patchStarts()),
labelList(), // oldPatchNMeshPoints [unused]
mapDistribute(std::move(faPointMap)),
mapDistribute(std::move(faEdgeMap)), // area: edgeMap (volume: faceMap)
mapDistribute(std::move(faFaceMap)), // area: faceMap (volume: cellMap)
mapDistribute(std::move(faPatchMap))
);
}
Foam::mapDistributePolyMesh
Foam::faMeshDistributor::distribute
(
const faMesh& oldMesh,
const mapDistributePolyMesh& distMap,
autoPtr<faMesh>& newMeshPtr
)
{
return faMeshDistributor::distribute
(
oldMesh,
distMap,
oldMesh.mesh(), // polyMesh
newMeshPtr
);
}
// ************************************************************************* //

View File

@ -0,0 +1,428 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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 "Time.H"
#include "emptyFaPatchField.H"
#include "emptyFaePatchField.H"
#include "IOobjectList.H"
#include "polyMesh.H"
#include "polyPatch.H"
#include "processorFaPatch.H"
#include "mapDistribute.H"
#include "mapDistributePolyMesh.H"
#include "areaFields.H"
#include "edgeFields.H"
#include "distributedFieldMapper.H"
#include "distributedFaPatchFieldMapper.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::faPatchField, Foam::areaMesh>>
Foam::faMeshDistributor::distributeField
(
const GeometricField<Type, faPatchField, areaMesh>& fld
) const
{
typedef typename
GeometricField<Type, faPatchField, areaMesh>::Patch
PatchFieldType;
if (tgtMesh_.boundary().size() && patchEdgeMaps_.empty())
{
createPatchMaps();
}
// Create internalField by remote mapping
const distributedFieldMapper mapper
(
labelUList::null(),
distMap_.cellMap() // area: faceMap (volume: cellMap)
);
DimensionedField<Type, areaMesh> internalField
(
IOobject
(
fld.name(),
tgtMesh_.time().timeName(),
fld.local(),
tgtMesh_.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
tgtMesh_,
fld.dimensions(),
Field<Type>(fld.internalField(), mapper)
);
internalField.oriented() = fld.oriented();
// Create patchFields by remote mapping
PtrList<PatchFieldType> newPatchFields(tgtMesh_.boundary().size());
const auto& bfld = fld.boundaryField();
forAll(bfld, patchi)
{
if (patchEdgeMaps_.set(patchi))
{
// Clone local patch field
const distributedFaPatchFieldMapper mapper
(
labelUList::null(),
patchEdgeMaps_[patchi]
);
// Map into local copy
newPatchFields.set
(
patchi,
PatchFieldType::New
(
bfld[patchi],
tgtMesh_.boundary()[patchi],
DimensionedField<Type, areaMesh>::null(),
mapper
)
);
}
}
// Add empty patchFields on remaining patches (this also handles
// e.g. processorPatchFields or any other constraint type patches)
forAll(newPatchFields, patchi)
{
if (!newPatchFields.set(patchi))
{
newPatchFields.set
(
patchi,
PatchFieldType::New
(
emptyFaPatchField<Type>::typeName,
tgtMesh_.boundary()[patchi],
DimensionedField<Type, areaMesh>::null()
)
);
}
}
auto tresult = tmp<GeometricField<Type, faPatchField, areaMesh>>::New
(
std::move(internalField),
newPatchFields
);
auto& result = tresult.ref();
result.boundaryFieldRef().template evaluateCoupled<processorFaPatch>();
return tresult;
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::faePatchField, Foam::edgeMesh>>
Foam::faMeshDistributor::distributeField
(
const GeometricField<Type, faePatchField, edgeMesh>& fld
) const
{
typedef typename
GeometricField<Type, faePatchField, edgeMesh>::Patch
PatchFieldType;
if (!internalEdgeMap_)
{
createInternalEdgeMap();
}
// Create internalField by remote mapping
const distributedFieldMapper mapper
(
labelUList::null(),
*(internalEdgeMap_)
);
DimensionedField<Type, edgeMesh> internalField
(
IOobject
(
fld.name(),
tgtMesh_.time().timeName(),
fld.local(),
tgtMesh_.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
tgtMesh_,
fld.dimensions(),
Field<Type>(fld.internalField(), mapper)
);
internalField.oriented() = fld.oriented();
// Create patchFields by remote mapping
PtrList<PatchFieldType> newPatchFields(tgtMesh_.boundary().size());
const auto& bfld = fld.boundaryField();
forAll(bfld, patchi)
{
if (patchEdgeMaps_.set(patchi))
{
// Clone local patch field
const distributedFaPatchFieldMapper mapper
(
labelUList::null(),
patchEdgeMaps_[patchi]
);
// Map into local copy
newPatchFields.set
(
patchi,
PatchFieldType::New
(
bfld[patchi],
tgtMesh_.boundary()[patchi],
DimensionedField<Type, edgeMesh>::null(),
mapper
)
);
}
}
// Add empty patchFields on remaining patches (this also handles
// e.g. processorPatchFields or any other constraint type patches)
forAll(newPatchFields, patchi)
{
if (!newPatchFields.set(patchi))
{
newPatchFields.set
(
patchi,
PatchFieldType::New
(
emptyFaePatchField<Type>::typeName,
tgtMesh_.boundary()[patchi],
DimensionedField<Type, edgeMesh>::null()
)
);
}
}
return tmp<GeometricField<Type, faePatchField, edgeMesh>>::New
(
std::move(internalField),
newPatchFields
);
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::faPatchField, Foam::areaMesh>>
Foam::faMeshDistributor::distributeAreaField
(
const IOobject& fieldObject
) const
{
// Read field
GeometricField<Type, faPatchField, areaMesh> fld
(
fieldObject,
srcMesh_
);
// Redistribute
return distributeField(fld);
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::faePatchField, Foam::edgeMesh>>
Foam::faMeshDistributor::distributeEdgeField
(
const IOobject& fieldObject
) const
{
// Read field
GeometricField<Type, faePatchField, edgeMesh> fld
(
fieldObject,
srcMesh_
);
// Redistribute
return distributeField(fld);
}
template<class Type>
Foam::label Foam::faMeshDistributor::distributeAreaFields
(
const IOobjectList& objects,
const wordRes& selectedFields
) const
{
typedef GeometricField<Type, faPatchField, areaMesh> fieldType;
label nFields = 0;
for
(
const IOobject& io :
(
selectedFields.empty()
? objects.sorted<fieldType>()
: objects.sorted<fieldType>(selectedFields)
)
)
{
if (verbose_)
{
if (!nFields)
{
Info<< " Reconstructing "
<< fieldType::typeName << "s\n" << nl;
}
Info<< " " << io.name() << nl;
}
++nFields;
tmp<fieldType> tfld(distributeAreaField<Type>(io));
if (isWriteProc_)
{
tfld().write();
}
}
if (nFields && verbose_) Info<< endl;
return nFields;
}
template<class Type>
Foam::label Foam::faMeshDistributor::distributeEdgeFields
(
const IOobjectList& objects,
const wordRes& selectedFields
) const
{
typedef GeometricField<Type, faePatchField, edgeMesh> fieldType;
label nFields = 0;
for
(
const IOobject& io :
(
selectedFields.empty()
? objects.sorted<fieldType>()
: objects.sorted<fieldType>(selectedFields)
)
)
{
if (verbose_)
{
if (!nFields)
{
Info<< " Reconstructing "
<< fieldType::typeName << "s\n" << nl;
}
Info<< " " << io.name() << nl;
}
++nFields;
tmp<fieldType> tfld(distributeEdgeField<Type>(io));
if (isWriteProc_)
{
tfld().write();
}
}
if (nFields && verbose_) Info<< endl;
return nFields;
}
#if 0
template<class Type>
void Foam::faMeshDistributor::redistributeAndWrite
(
PtrList<GeometricField<Type, faPatchField, areaMesh>>& flds
) const
{
for (auto& fld : flds)
{
Pout<< "process: " << fld.name() << endl;
tmp<GeometricField<Type, faPatchField, areaMesh>> tfld =
this->distributeField(fld);
if (isWriteProc_)
{
tfld().write();
}
}
}
template<class Type>
void Foam::faMeshDistributor::redistributeAndWrite
(
PtrList<GeometricField<Type, faePatchField, edgeMesh>>& flds
) const
{
for (auto& fld : flds)
{
tmp<GeometricField<Type, faePatchField, edgeMesh>> tfld =
this->distributeField(fld);
if (isWriteProc_)
{
tfld().write();
}
}
}
#endif
// ************************************************************************* //

View File

@ -186,6 +186,16 @@ public:
const bool allowUnmapped = false
);
//- Map edge field.
// Optionally allow unmapped faces not to produce a warning
template<class Type>
static tmp<GeometricField<Type, faePatchField, edgeMesh>>
interpolate
(
const GeometricField<Type, faePatchField, edgeMesh>&,
const faMesh& sMesh
);
// Field Mapping
@ -198,6 +208,15 @@ public:
const GeometricField<Type, faPatchField, areaMesh>&,
const bool allowUnmapped = false
) const;
//- Map edge field.
template<class Type>
tmp<GeometricField<Type, faePatchField, edgeMesh>>
interpolate
(
const GeometricField<Type, faePatchField, edgeMesh>&,
const bool allowUnmapped = false
) const;
};

View File

@ -144,6 +144,88 @@ Foam::faMeshSubset::interpolate
}
template<class Type>
Foam::tmp
<
Foam::GeometricField<Type, Foam::faePatchField, Foam::edgeMesh>
>
Foam::faMeshSubset::interpolate
(
const GeometricField<Type, faePatchField, edgeMesh>& vf,
const faMesh& sMesh
)
{
// 1. Create the complete field with dummy patch fields
PtrList<faePatchField<Type>> patchFields(sMesh.boundary().size());
forAll(patchFields, patchi)
{
patchFields.set
(
patchi,
faePatchField<Type>::New
(
calculatedFaePatchField<Type>::typeName,
sMesh.boundary()[patchi],
DimensionedField<Type, edgeMesh>::null()
)
);
}
auto tresult = tmp<GeometricField<Type, faePatchField, edgeMesh>>::New
(
IOobject
(
"subset"+vf.name(),
sMesh.time().timeName(),
sMesh.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
sMesh,
vf.dimensions(),
Field<Type>(),
// Field<Type>
// (
// vf.primitiveField(),
// SubList<label>(edgeMap, sMesh.nInternalEdges())
// ),
patchFields
);
auto& result = tresult.ref();
result.oriented() = vf.oriented();
// 2. Change the faePatchFields to the correct type using a mapper
// constructor (with reference to the now correct internal field)
auto& bf = result.boundaryFieldRef();
forAll(bf, patchi)
{
// Construct addressing
const faPatch& subPatch = sMesh.boundary()[patchi];
labelList directAddressing;
directFaPatchFieldMapper mapper(directAddressing);
bf.set
(
patchi,
faePatchField<Type>::New
(
vf.boundaryField()[patchi],
subPatch,
result(),
mapper
)
);
}
return tresult;
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
@ -166,4 +248,24 @@ Foam::faMeshSubset::interpolate
}
template<class Type>
Foam::tmp
<
Foam::GeometricField<Type, Foam::faePatchField, Foam::edgeMesh>
>
Foam::faMeshSubset::interpolate
(
const GeometricField<Type, faePatchField, edgeMesh>& vf,
const bool allowUnmapped
) const
{
if (subMeshPtr_)
{
return interpolate(vf, *subMeshPtr_);
}
return vf;
}
// ************************************************************************* //

View File

@ -2,7 +2,14 @@ decompositionInformation.C
decompositionModel.C
dimFieldDecomposer.C
fvFieldDecomposer.C
fvFieldDecomposerCache.C
pointFieldDecomposer.C
pointFieldDecomposerCache.C
lagrangianFieldDecomposer.C
lagrangianFieldDecomposerCache.C
LIB = $(FOAM_LIBBIN)/libdecompose

View File

@ -32,12 +32,12 @@ Description
SourceFiles
dimFieldDecomposer.C
dimFieldDecomposerFields.C
dimFieldDecomposerTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef dimFieldDecomposer_H
#define dimFieldDecomposer_H
#ifndef Foam_dimFieldDecomposer_H
#define Foam_dimFieldDecomposer_H
#include "fvMesh.H"
#include "surfaceFields.H"
@ -121,7 +121,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "dimFieldDecomposerFields.C"
#include "dimFieldDecomposerTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -47,8 +47,8 @@ Foam::dimFieldDecomposer::decomposeField
IOobject
(
field.name(),
procMesh_.time().timeName(),
procMesh_,
procMesh_.thisDb().time().timeName(),
procMesh_.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE,
false

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd.
Copyright (C) 2021-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -28,6 +28,11 @@ License
#include "fvFieldDecomposer.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
int Foam::fvFieldDecomposer::verbose_ = 1;
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fvFieldDecomposer::patchFieldDecomposer::patchFieldDecomposer
@ -95,7 +100,7 @@ processorVolPatchFieldDecomposer
Foam::fvFieldDecomposer::processorVolPatchFieldDecomposer::
processorVolPatchFieldDecomposer
(
const fvMesh& mesh,
const polyMesh& mesh,
const labelUList& addressingSlice
)
:

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd.
Copyright (C) 2021-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -32,12 +32,13 @@ Description
SourceFiles
fvFieldDecomposer.C
fvFieldDecomposerFields.C
fvFieldDecomposerCache.C
fvFieldDecomposerTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef fvFieldDecomposer_H
#define fvFieldDecomposer_H
#ifndef Foam_fvFieldDecomposer_H
#define Foam_fvFieldDecomposer_H
#include "fvMesh.H"
#include "fvPatchFieldMapper.H"
@ -48,6 +49,9 @@ SourceFiles
namespace Foam
{
// Forward Declarations
class IOobjectList;
/*---------------------------------------------------------------------------*\
Class fvFieldDecomposer Declaration
\*---------------------------------------------------------------------------*/
@ -56,6 +60,8 @@ class fvFieldDecomposer
{
public:
// Public Classes
//- Patch field decomposer class
class patchFieldDecomposer
:
@ -126,7 +132,7 @@ public:
//- Construct given addressing from complete mesh
processorVolPatchFieldDecomposer
(
const fvMesh& mesh,
const polyMesh& mesh,
const labelUList& addressingSlice
);
@ -232,13 +238,24 @@ private:
PtrList<scalarField> faceSign_;
// Private Member Functions
//- No copy construct
fvFieldDecomposer(const fvFieldDecomposer&) = delete;
//- No copy assignment
void operator=(const fvFieldDecomposer&) = delete;
public:
//- No copy construct
fvFieldDecomposer(const fvFieldDecomposer&) = delete;
// Public Classes
class fieldsCache;
//- No copy assignment
void operator=(const fvFieldDecomposer&) = delete;
// Static Data
//- Output verbosity when writing
static int verbose_;
// Constructors
@ -336,6 +353,69 @@ public:
};
/*---------------------------------------------------------------------------*\
Class fvFieldDecomposer::fieldsCache Declaration
\*---------------------------------------------------------------------------*/
class fvFieldDecomposer::fieldsCache
{
// Private Data
class privateCache;
//- All field and field-field types for lagrangian
std::unique_ptr<privateCache> cache_;
// Private Member Functions
//- No copy construct
fieldsCache(const fieldsCache&) = delete;
//- No copy assignment
void operator=(const fieldsCache&) = delete;
public:
// Constructors
//- Default construct
fieldsCache();
//- Destructor
~fieldsCache();
// Member Functions
//- No fields
bool empty() const;
//- Total number of fields
label size() const;
//- Clear out
void clear();
//- Read all fields given mesh and objects
void readAllFields
(
const fvMesh& mesh,
const IOobjectList& objects
);
//- Decompose and write all fields
void decomposeAllFields
(
const fvFieldDecomposer& decomposer,
bool report = false
) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
@ -343,7 +423,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "fvFieldDecomposerFields.C"
#include "fvFieldDecomposerTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -0,0 +1,228 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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 "fvFieldDecomposer.H"
#include "fieldsDistributor.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "IOobjectList.H"
#include "PtrListOps.H"
// * * * * * * * * * * * * * * * * Declarations * * * * * * * * * * * * * * //
namespace Foam
{
// All volume internal types
class fvFieldDecomposer::fieldsCache::privateCache
{
public:
#undef declareField
#define declareField(Type) \
PtrList<DimensionedField<Type, volMesh>> Type##DimFields_; \
PtrList<GeometricField<Type, fvPatchField, volMesh>> Type##VolFields_; \
PtrList<GeometricField<Type, fvsPatchField, surfaceMesh>> Type##SurfFields_;
declareField(scalar);
declareField(vector);
declareField(sphericalTensor);
declareField(symmTensor);
declareField(tensor);
#undef declareField
label size() const noexcept
{
label count = 0;
#undef doLocalCode
#define doLocalCode(Type) \
{ \
count += Type##DimFields_.size(); \
count += Type##VolFields_.size(); \
count += Type##SurfFields_.size(); \
}
doLocalCode(scalar);
doLocalCode(vector);
doLocalCode(sphericalTensor);
doLocalCode(symmTensor);
doLocalCode(tensor);
#undef doLocalCode
return count;
}
bool empty() const noexcept { return !size(); }
void readAll(const fvMesh& mesh, const IOobjectList& objects)
{
#undef doLocalCode
#define doLocalCode(Type) \
{ \
fieldsDistributor::readFields \
( \
mesh, \
objects, \
Type##DimFields_ \
); \
fieldsDistributor::readFields \
( \
mesh, \
objects, \
Type##VolFields_, \
false /* readOldTime = false */ \
); \
fieldsDistributor::readFields \
( \
mesh, \
objects, \
Type##SurfFields_, \
false /* readOldTime = false */ \
); \
}
doLocalCode(scalar);
doLocalCode(vector);
doLocalCode(sphericalTensor);
doLocalCode(symmTensor);
doLocalCode(tensor);
#undef doLocalCode
}
template<class GeoField>
static void decompose
(
const fvFieldDecomposer& decomposer,
const PtrList<GeoField>& fields,
bool report
)
{
if (!fields.empty())
{
if (report)
{
Info<< " "
<< pTraits<typename GeoField::value_type>::typeName
<< "s: "
<< flatOutput(PtrListOps::names(fields)) << nl;
}
decomposer.decomposeFields(fields);
}
}
void decomposeAll
(
const fvFieldDecomposer& decomposer,
bool report
) const
{
#undef doLocalCode
#define doLocalCode(Flavour) \
{ \
decompose(decomposer, scalar##Flavour##Fields_, report); \
decompose(decomposer, vector##Flavour##Fields_, report); \
decompose(decomposer, sphericalTensor##Flavour##Fields_, report); \
decompose(decomposer, symmTensor##Flavour##Fields_, report); \
decompose(decomposer, tensor##Flavour##Fields_, report); \
}
doLocalCode(Vol);
doLocalCode(Surf);
doLocalCode(Dim);
#undef doLocalCode
}
};
} // End namespace Foam
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fvFieldDecomposer::fieldsCache::fieldsCache()
:
cache_(new privateCache)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
// Destructor not in header (used incomplete type)
Foam::fvFieldDecomposer::fieldsCache::~fieldsCache()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::fvFieldDecomposer::fieldsCache::empty() const
{
return (!cache_ || cache_->empty());
}
Foam::label Foam::fvFieldDecomposer::fieldsCache::size() const
{
return (cache_ ? cache_->size() : label(0));
}
void Foam::fvFieldDecomposer::fieldsCache::clear()
{
cache_.reset(new privateCache);
}
void Foam::fvFieldDecomposer::fieldsCache::readAllFields
(
const fvMesh& mesh,
const IOobjectList& objects
)
{
if (cache_)
{
cache_->readAll(mesh, objects);
}
}
void Foam::fvFieldDecomposer::fieldsCache::decomposeAllFields
(
const fvFieldDecomposer& decomposer,
bool report
) const
{
if (cache_)
{
cache_->decomposeAll(decomposer, report);
}
}
// ************************************************************************* //

View File

@ -32,6 +32,8 @@ License
#include "processorCyclicFvPatchField.H"
#include "processorCyclicFvsPatchField.H"
#include "emptyFvPatchFields.H"
#include "volFields.H"
#include "surfaceFields.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
@ -52,8 +54,8 @@ Foam::fvFieldDecomposer::decomposeField
IOobject
(
field.name(),
procMesh_.time().timeName(),
procMesh_,
procMesh_.thisDb().time().timeName(),
procMesh_.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE,
false
@ -100,8 +102,8 @@ Foam::fvFieldDecomposer::decomposeField
IOobject
(
field.name(),
procMesh_.time().timeName(),
procMesh_,
procMesh_.thisDb().time().timeName(),
procMesh_.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
@ -118,7 +120,7 @@ Foam::fvFieldDecomposer::decomposeField
// 2. Change the fvPatchFields to the correct type using a mapper
// constructor (with reference to the now correct internal field)
typename VolFieldType::Boundary& bf = resF.boundaryFieldRef();
auto& bf = resF.boundaryFieldRef();
forAll(bf, patchi)
{
@ -272,8 +274,8 @@ Foam::fvFieldDecomposer::decomposeField
IOobject
(
field.name(),
procMesh_.time().timeName(),
procMesh_,
procMesh_.thisDb().time().timeName(),
procMesh_.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
@ -289,7 +291,7 @@ Foam::fvFieldDecomposer::decomposeField
// 2. Change the fvsPatchFields to the correct type using a mapper
// constructor (with reference to the now correct internal field)
typename SurfaceFieldType::Boundary& bf = resF.boundaryFieldRef();
auto& bf = resF.boundaryFieldRef();
forAll(boundaryAddressing_, patchi)
{

View File

@ -94,7 +94,7 @@ Foam::lagrangianFieldDecomposer::lagrangianFieldDecomposer
}
}
particleIndices_.setSize(pi);
particleIndices_.resize(pi);
IOPosition<Cloud<passiveParticle>>(positions_).write();
}

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -31,12 +32,14 @@ Description
SourceFiles
lagrangianFieldDecomposer.C
lagrangianFieldDecomposerFields.C
lagrangianFieldDecomposerCache.C
lagrangianFieldDecomposerReadFields.C
lagrangianFieldDecomposerTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef lagrangianFieldDecomposer_H
#define lagrangianFieldDecomposer_H
#ifndef Foam_lagrangianFieldDecomposer_H
#define Foam_lagrangianFieldDecomposer_H
#include "Cloud.H"
#include "CompactIOField.H"
@ -48,6 +51,7 @@ SourceFiles
namespace Foam
{
// Forward Declarations
class IOobjectList;
/*---------------------------------------------------------------------------*\
@ -56,7 +60,7 @@ class IOobjectList;
class lagrangianFieldDecomposer
{
// Private data
// Private Data
//- Reference to processor mesh
const polyMesh& procMesh_;
@ -79,6 +83,10 @@ class lagrangianFieldDecomposer
public:
// Public Classes
class fieldsCache;
// Constructors
//- Construct from components
@ -94,29 +102,29 @@ public:
);
// Member Functions
// Field Reading
// Read the fields and hold on the pointer list
//- Read the fields and store on the pointer list
template<class Type>
static void readFields
(
const label cloudI,
const label cloudi,
const IOobjectList& lagrangianObjects,
PtrList<PtrList<IOField<Type>>>& lagrangianFields
PtrList<PtrList<IOField<Type>>>& cloudFields
);
//- Read the field-fields and store on the pointer list
template<class Type>
static void readFieldFields
(
const label cloudI,
const label cloudi,
const IOobjectList& lagrangianObjects,
PtrList
<
PtrList<CompactIOField<Field<Type>, Type>>
>& lagrangianFields
PtrList<PtrList<CompactIOField<Field<Type>, Type>>>& cloudFields
);
// Member Functions
//- Decompose volume field
template<class Type>
tmp<IOField<Type>> decomposeField
@ -149,6 +157,77 @@ public:
};
/*---------------------------------------------------------------------------*\
Class lagrangianFieldDecomposer::fieldsCache Declaration
\*---------------------------------------------------------------------------*/
class lagrangianFieldDecomposer::fieldsCache
{
// Private Data
class privateCache;
//- All field and field-field types for lagrangian
std::unique_ptr<privateCache> cache_;
// Private Member Functions
//- No copy construct
fieldsCache(const fieldsCache&) = delete;
//- No copy assignment
void operator=(const fieldsCache&) = delete;
public:
// Constructors
//- Default construct (no clouds)
fieldsCache();
//- Construct for given number of clouds
explicit fieldsCache(const label nClouds);
//- Destructor
~fieldsCache();
// Member Functions
//- No clouds
bool empty() const;
//- Number of clouds
label size() const;
//- Clear out
void clear();
//- Resize for the number of clouds
void resize(const label nClouds);
//- Read all fields and field-fields for given cloud and objects
void readAllFields
(
const label cloudi,
const IOobjectList& lagrangianObjects
);
//- Decompose and write all fields and field-fields for given cloud
void decomposeAllFields
(
const label cloudi,
const fileName& cloudDir,
const lagrangianFieldDecomposer& decomposer,
bool report = false
) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
@ -156,7 +235,8 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "lagrangianFieldDecomposerFields.C"
#include "lagrangianFieldDecomposerReadFields.C"
#include "lagrangianFieldDecomposerTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -0,0 +1,241 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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 "lagrangianFieldDecomposer.H"
#include "labelIOField.H"
#include "labelFieldIOField.H"
#include "scalarIOField.H"
#include "scalarFieldIOField.H"
#include "vectorIOField.H"
#include "vectorFieldIOField.H"
#include "sphericalTensorIOField.H"
#include "sphericalTensorFieldIOField.H"
#include "symmTensorIOField.H"
#include "symmTensorFieldIOField.H"
#include "tensorIOField.H"
#include "tensorFieldIOField.H"
// * * * * * * * * * * * * * * * * Declarations * * * * * * * * * * * * * * //
namespace Foam
{
// All lagrangian field/field-field types
class lagrangianFieldDecomposer::fieldsCache::privateCache
{
public:
#undef declareField
#define declareField(Type) \
PtrList<PtrList<IOField<Type>>> Type##Fields_; \
PtrList<PtrList<CompactIOField<Field<Type>, Type>>> Type##FieldFields_;
declareField(label);
declareField(scalar);
declareField(vector);
declareField(sphericalTensor);
declareField(symmTensor);
declareField(tensor);
#undef declareField
bool empty() const noexcept { return labelFields_.empty(); }
label size() const noexcept { return labelFields_.size(); }
void resize(const label len)
{
#undef doLocalCode
#define doLocalCode(Type) \
{ \
Type##Fields_.resize(len); \
Type##FieldFields_.resize(len); \
}
doLocalCode(label);
doLocalCode(scalar);
doLocalCode(vector);
doLocalCode(sphericalTensor);
doLocalCode(symmTensor);
doLocalCode(tensor);
#undef doLocalCode
}
void readAll(const label cloudi, const IOobjectList& lagrangianObjects)
{
#undef doLocalCode
#define doLocalCode(Type) \
{ \
lagrangianFieldDecomposer::readFields \
( \
cloudi, \
lagrangianObjects, \
Type##Fields_ \
); \
lagrangianFieldDecomposer::readFieldFields \
( \
cloudi, \
lagrangianObjects, \
Type##FieldFields_ \
); \
}
doLocalCode(label);
doLocalCode(scalar);
doLocalCode(vector);
doLocalCode(sphericalTensor);
doLocalCode(symmTensor);
doLocalCode(tensor);
#undef doLocalCode
}
void decomposeAll
(
const label cloudi,
const fileName& cloudDir,
const lagrangianFieldDecomposer& decomposer,
bool report /* unused */
) const
{
#undef doLocalCode
#define doLocalCode(Type) \
{ \
decomposer.decomposeFields \
( \
cloudDir, \
Type##Fields_[cloudi] \
); \
decomposer.decomposeFieldFields \
( \
cloudDir, \
Type##FieldFields_[cloudi] \
); \
}
doLocalCode(label);
doLocalCode(scalar);
doLocalCode(vector);
doLocalCode(sphericalTensor);
doLocalCode(symmTensor);
doLocalCode(tensor);
#undef doLocalCode
}
};
} // End namespace Foam
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::lagrangianFieldDecomposer::fieldsCache::fieldsCache()
:
cache_(new privateCache)
{}
Foam::lagrangianFieldDecomposer::fieldsCache::fieldsCache
(
const label nClouds
)
:
cache_(new privateCache)
{
cache_->resize(nClouds);
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
// Destructor not in header (used incomplete type)
Foam::lagrangianFieldDecomposer::fieldsCache::~fieldsCache()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::lagrangianFieldDecomposer::fieldsCache::empty() const
{
return (!cache_ || cache_->empty());
}
Foam::label Foam::lagrangianFieldDecomposer::fieldsCache::size() const
{
return (cache_ ? cache_->size() : label(0));
}
void Foam::lagrangianFieldDecomposer::fieldsCache::clear()
{
cache_.reset(new privateCache);
}
void Foam::lagrangianFieldDecomposer::fieldsCache::resize
(
const label nClouds
)
{
if (cache_)
{
cache_->resize(nClouds);
}
}
void Foam::lagrangianFieldDecomposer::fieldsCache::readAllFields
(
const label cloudi,
const IOobjectList& lagrangianObjects
)
{
if (cache_)
{
cache_->readAll(cloudi, lagrangianObjects);
}
}
void Foam::lagrangianFieldDecomposer::fieldsCache::decomposeAllFields
(
const label cloudi,
const fileName& cloudDir,
const lagrangianFieldDecomposer& decomposer,
bool report
) const
{
if (cache_)
{
cache_->decomposeAll(cloudi, cloudDir, decomposer, report);
}
}
// ************************************************************************* //

View File

@ -0,0 +1,108 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2022 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 "lagrangianFieldDecomposer.H"
#include "IOobjectList.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
void Foam::lagrangianFieldDecomposer::readFields
(
const label cloudi,
const IOobjectList& lagrangianObjects,
PtrList<PtrList<IOField<Type>>>& lagrangianFields
)
{
// List of lagrangian field objects
UPtrList<const IOobject> fieldObjects
(
lagrangianObjects.sorted<IOField<Type>>()
);
lagrangianFields.set
(
cloudi,
new PtrList<IOField<Type>>(fieldObjects.size())
);
label fieldi = 0;
for (const IOobject& io : fieldObjects)
{
lagrangianFields[cloudi].set(fieldi++, new IOField<Type>(io));
}
}
template<class Type>
void Foam::lagrangianFieldDecomposer::readFieldFields
(
const label cloudi,
const IOobjectList& lagrangianObjects,
PtrList<PtrList<CompactIOField<Field<Type>, Type>>>& lagrangianFields
)
{
// List of lagrangian field objects
UPtrList<const IOobject> fieldObjects;
fieldObjects.append
(
lagrangianObjects.sorted<IOField<Field<Type>>>()
);
fieldObjects.append
(
lagrangianObjects.sorted<CompactIOField<Field<Type>, Type>>()
);
Foam::sort(fieldObjects, nameOp<IOobject>());
lagrangianFields.set
(
cloudi,
new PtrList<CompactIOField<Field<Type>, Type>>(fieldObjects.size())
);
label fieldi = 0;
for (const IOobject& io : fieldObjects)
{
lagrangianFields[cloudi].set
(
fieldi++,
new CompactIOField<Field<Type>, Type>(io)
);
}
}
// ************************************************************************* //

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -30,95 +31,6 @@ License
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
void Foam::lagrangianFieldDecomposer::readFields
(
const label cloudI,
const IOobjectList& lagrangianObjects,
PtrList<PtrList<IOField<Type>>>& lagrangianFields
)
{
// Search list of objects for lagrangian fields
IOobjectList lagrangianTypeObjects
(
lagrangianObjects.lookupClass(IOField<Type>::typeName)
);
lagrangianFields.set
(
cloudI,
new PtrList<IOField<Type>>
(
lagrangianTypeObjects.size()
)
);
label lagrangianFieldi = 0;
forAllConstIters(lagrangianTypeObjects, iter)
{
lagrangianFields[cloudI].set
(
lagrangianFieldi++,
new IOField<Type>(*iter())
);
}
}
template<class Type>
void Foam::lagrangianFieldDecomposer::readFieldFields
(
const label cloudI,
const IOobjectList& lagrangianObjects,
PtrList<PtrList<CompactIOField<Field<Type>, Type>>>& lagrangianFields
)
{
// Search list of objects for lagrangian fields
IOobjectList lagrangianTypeObjectsA
(
lagrangianObjects.lookupClass(IOField<Field<Type>>::typeName)
);
IOobjectList lagrangianTypeObjectsB
(
lagrangianObjects.lookupClass
(
CompactIOField<Field<Type>,
Type>::typeName
)
);
lagrangianFields.set
(
cloudI,
new PtrList<CompactIOField<Field<Type>, Type>>
(
lagrangianTypeObjectsA.size() + lagrangianTypeObjectsB.size()
)
);
label lagrangianFieldi = 0;
forAllConstIters(lagrangianTypeObjectsA, iter)
{
lagrangianFields[cloudI].set
(
lagrangianFieldi++,
new CompactIOField<Field<Type>, Type>(*iter())
);
}
forAllConstIters(lagrangianTypeObjectsB, iter)
{
lagrangianFields[cloudI].set
(
lagrangianFieldi++,
new CompactIOField<Field<Type>, Type>(*iter())
);
}
}
template<class Type>
Foam::tmp<Foam::IOField<Type>>
Foam::lagrangianFieldDecomposer::decomposeField
@ -127,9 +39,6 @@ Foam::lagrangianFieldDecomposer::decomposeField
const IOField<Type>& field
) const
{
// Create and map the internal field values
Field<Type> procField(field, particleIndices_);
// Create the field for the processor
return tmp<IOField<Type>>::New
(
@ -143,7 +52,8 @@ Foam::lagrangianFieldDecomposer::decomposeField
IOobject::NO_WRITE,
false
),
procField
// Mapping internal field values
Field<Type>(field, particleIndices_)
);
}
@ -156,9 +66,6 @@ Foam::lagrangianFieldDecomposer::decomposeFieldField
const CompactIOField<Field<Type>, Type>& field
) const
{
// Create and map the internal field values
Field<Field<Type>> procField(field, particleIndices_);
// Create the field for the processor
return tmp<CompactIOField<Field<Type>, Type>>::New
(
@ -172,7 +79,8 @@ Foam::lagrangianFieldDecomposer::decomposeFieldField
IOobject::NO_WRITE,
false
),
procField
// Mapping internal field values
Field<Field<Type>>(field, particleIndices_)
);
}
@ -184,13 +92,11 @@ void Foam::lagrangianFieldDecomposer::decomposeFields
const PtrList<GeoField>& fields
) const
{
//if (particleIndices_.size())
const bool existsOnProc = (particleIndices_.size() > 0);
for (const GeoField& fld : fields)
{
bool valid = particleIndices_.size() > 0;
forAll(fields, fieldi)
{
decomposeField(cloudName, fields[fieldi])().write(valid);
}
decomposeField(cloudName, fld)().write(existsOnProc);
}
}
@ -202,13 +108,11 @@ void Foam::lagrangianFieldDecomposer::decomposeFieldFields
const PtrList<GeoField>& fields
) const
{
//if (particleIndices_.size())
const bool existsOnProc = (particleIndices_.size() > 0);
for (const GeoField& fld : fields)
{
bool valid = particleIndices_.size() > 0;
forAll(fields, fieldi)
{
decomposeFieldField(cloudName, fields[fieldi])().write(valid);
}
decomposeFieldField(cloudName, fld)().write(existsOnProc);
}
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd.
Copyright (C) 2021-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -32,12 +32,13 @@ Description
SourceFiles
pointFieldDecomposer.C
pointFieldDecomposerFields.C
pointFieldDecomposerCache.C
pointFieldDecomposerTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef pointFieldDecomposer_H
#define pointFieldDecomposer_H
#ifndef Foam_pointFieldDecomposer_H
#define Foam_pointFieldDecomposer_H
#include "pointMesh.H"
#include "pointPatchFieldMapperPatchRef.H"
@ -48,6 +49,9 @@ SourceFiles
namespace Foam
{
// Forward Declarations
class IOobjectList;
/*---------------------------------------------------------------------------*\
Class pointFieldDecomposer Declaration
\*---------------------------------------------------------------------------*/
@ -56,6 +60,8 @@ class pointFieldDecomposer
{
public:
// Public Classes
//- Point patch field decomposer class
class patchFieldDecomposer
:
@ -122,13 +128,18 @@ private:
PtrList<patchFieldDecomposer> patchFieldDecomposerPtrs_;
// Private Member Functions
//- No copy construct
pointFieldDecomposer(const pointFieldDecomposer&) = delete;
//- No copy assignment
void operator=(const pointFieldDecomposer&) = delete;
public:
//- No copy construct
pointFieldDecomposer(const pointFieldDecomposer&) = delete;
//- No copy assignment
void operator=(const pointFieldDecomposer&) = delete;
// Public Classes
class fieldsCache;
// Constructors
@ -184,6 +195,69 @@ public:
};
/*---------------------------------------------------------------------------*\
Class pointFieldDecomposer::fieldsCache Declaration
\*---------------------------------------------------------------------------*/
class pointFieldDecomposer::fieldsCache
{
// Private Data
class privateCache;
//- All field and field-field types for lagrangian
std::unique_ptr<privateCache> cache_;
// Private Member Functions
//- No copy construct
fieldsCache(const fieldsCache&) = delete;
//- No copy assignment
void operator=(const fieldsCache&) = delete;
public:
// Constructors
//- Default construct
fieldsCache();
//- Destructor
~fieldsCache();
// Member Functions
//- No fields
bool empty() const;
//- Total number of fields
label size() const;
//- Clear out
void clear();
//- Read all fields given mesh and objects
void readAllFields
(
const pointMesh& mesh,
const IOobjectList& objects
);
//- Decompose and write all fields
void decomposeAllFields
(
const pointFieldDecomposer& decomposer,
bool report = false
) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
@ -191,7 +265,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "pointFieldDecomposerFields.C"
#include "pointFieldDecomposerTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -0,0 +1,208 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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 "pointFieldDecomposer.H"
#include "fieldsDistributor.H"
#include "pointFields.H"
#include "IOobjectList.H"
#include "PtrListOps.H"
// * * * * * * * * * * * * * * * * Declarations * * * * * * * * * * * * * * //
namespace Foam
{
// All point field types
class pointFieldDecomposer::fieldsCache::privateCache
{
public:
#undef declareField
#define declareField(Type) \
PtrList<GeometricField<Type, pointPatchField, pointMesh>> Type##Fields_;
declareField(scalar);
declareField(vector);
declareField(sphericalTensor);
declareField(symmTensor);
declareField(tensor);
#undef declareField
label size() const noexcept
{
label count = 0;
#undef doLocalCode
#define doLocalCode(Type) \
{ \
count += Type##Fields_.size(); \
}
doLocalCode(scalar);
doLocalCode(vector);
doLocalCode(sphericalTensor);
doLocalCode(symmTensor);
doLocalCode(tensor);
#undef doLocalCode
return count;
}
bool empty() const noexcept { return !size(); }
void readAll(const pointMesh& mesh, const IOobjectList& objects)
{
#undef doLocalCode
#define doLocalCode(Type) \
{ \
fieldsDistributor::readFields \
( \
mesh, \
objects, \
Type##Fields_, \
false /* readOldTime = false */ \
); \
}
doLocalCode(scalar);
doLocalCode(vector);
doLocalCode(sphericalTensor);
doLocalCode(symmTensor);
doLocalCode(tensor);
#undef doLocalCode
}
template<class GeoField>
static void decompose
(
const pointFieldDecomposer& decomposer,
const PtrList<GeoField>& fields,
bool report
)
{
if (!fields.empty())
{
if (report)
{
Info<< " "
<< pTraits<typename GeoField::value_type>::typeName
<< "s: "
<< flatOutput(PtrListOps::names(fields)) << nl;
}
decomposer.decomposeFields(fields);
}
}
void decomposeAll
(
const pointFieldDecomposer& decomposer,
bool report
) const
{
#undef doLocalCode
#define doLocalCode(Type) \
{ \
decompose(decomposer, Type##Fields_, report); \
}
doLocalCode(scalar);
doLocalCode(vector);
doLocalCode(sphericalTensor);
doLocalCode(symmTensor);
doLocalCode(tensor);
#undef doLocalCode
}
};
} // End namespace Foam
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::pointFieldDecomposer::fieldsCache::fieldsCache()
:
cache_(new privateCache)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
// Destructor not in header (used incomplete type)
Foam::pointFieldDecomposer::fieldsCache::~fieldsCache()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::pointFieldDecomposer::fieldsCache::empty() const
{
return (!cache_ || cache_->empty());
}
Foam::label Foam::pointFieldDecomposer::fieldsCache::size() const
{
return (cache_ ? cache_->size() : label(0));
}
void Foam::pointFieldDecomposer::fieldsCache::clear()
{
cache_.reset(new privateCache);
}
void Foam::pointFieldDecomposer::fieldsCache::readAllFields
(
const pointMesh& mesh,
const IOobjectList& objects
)
{
if (cache_)
{
cache_->readAll(mesh, objects);
}
}
void Foam::pointFieldDecomposer::fieldsCache::decomposeAllFields
(
const pointFieldDecomposer& decomposer,
bool report
) const
{
if (cache_)
{
cache_->decomposeAll(decomposer, report);
}
}
// ************************************************************************* //

View File

@ -82,8 +82,8 @@ Foam::pointFieldDecomposer::decomposeField
IOobject
(
field.name(),
procMesh_().time().timeName(),
procMesh_(),
procMesh_.thisDb().time().timeName(),
procMesh_.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE,
false

View File

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

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2021 OpenCFD Ltd.
Copyright (C) 2021-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -36,12 +36,13 @@ Author
SourceFiles
faFieldDecomposer.C
faFieldDecomposerFields.C
fvFieldDecomposerCache.C
faFieldDecomposerTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef faFieldDecomposer_H
#define faFieldDecomposer_H
#ifndef Foam_faFieldDecomposer_H
#define Foam_faFieldDecomposer_H
#include "faMesh.H"
#include "faPatchFieldMapper.H"
@ -63,6 +64,8 @@ class faFieldDecomposer
{
public:
// Public Classes
//- Patch field decomposer class
class patchFieldDecomposer
:
@ -270,13 +273,17 @@ private:
public:
// Public Classes
class fieldsCache;
// Constructors
//- Construct without mappers, added later with reset()
faFieldDecomposer
(
const Foam::zero,
const faMesh& procMesh,
const faMesh& procMesh, // Target mesh
const labelList& edgeAddressing,
const labelList& faceAddressing,
const labelList& boundaryAddressing
@ -285,8 +292,8 @@ public:
//- Construct from components using information from the complete mesh
faFieldDecomposer
(
const faMesh& completeMesh,
const faMesh& procMesh,
const faMesh& completeMesh, // Source mesh
const faMesh& procMesh, // Target mesh
const labelList& edgeAddressing,
const labelList& faceAddressing,
const labelList& boundaryAddressing
@ -302,7 +309,7 @@ public:
const labelUList& edgeNeigbour,
// Addressing for processor mesh
const faMesh& procMesh,
const faMesh& procMesh, // Target mesh
const labelList& edgeAddressing,
const labelList& faceAddressing,
const labelList& boundaryAddressing
@ -358,7 +365,7 @@ public:
// Reading helpers
//- Read the fields and hold on the pointer list
//- Read the fields and store on the pointer list
template
<
class Type,
@ -373,7 +380,7 @@ public:
const bool readOldTime
);
//- Read fields and hold on the pointer list
//- Read fields and store on the pointer list
template<class Mesh, class GeoField>
static void readFields
(
@ -384,6 +391,70 @@ public:
};
/*---------------------------------------------------------------------------*\
Class faFieldDecomposer::fieldsCache Declaration
\*---------------------------------------------------------------------------*/
class faFieldDecomposer::fieldsCache
{
// Private Data
class privateCache;
//- All field and field-field types for lagrangian
std::unique_ptr<privateCache> cache_;
// Private Member Functions
//- No copy construct
fieldsCache(const fieldsCache&) = delete;
//- No copy assignment
void operator=(const fieldsCache&) = delete;
public:
// Constructors
//- Default construct
fieldsCache();
//- Destructor
~fieldsCache();
// Member Functions
//- No fields
bool empty() const;
//- Number of fields
label size() const;
//- Clear out
void clear();
//- Read all fields given mesh and objects
void readAllFields
(
const faMesh& mesh,
const IOobjectList& objects
);
//- Decompose and write all fields
void decomposeAllFields
(
const faFieldDecomposer& decomposer,
bool report = false
) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
@ -391,8 +462,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "faFieldDecomposerFields.C"
#include "faFieldDecomposerReadFields.C"
#include "faFieldDecomposerTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -0,0 +1,221 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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 "fieldsDistributor.H"
#include "areaFields.H"
#include "edgeFields.H"
#include "IOobjectList.H"
#include "PtrListOps.H"
// * * * * * * * * * * * * * * * * Declarations * * * * * * * * * * * * * * //
namespace Foam
{
// All area/edge field types
class faFieldDecomposer::fieldsCache::privateCache
{
public:
#undef declareField
#define declareField(Type) \
PtrList<GeometricField<Type, faPatchField, areaMesh>> Type##AreaFields_; \
PtrList<GeometricField<Type, faePatchField, edgeMesh>> Type##EdgeFields_;
declareField(scalar);
declareField(vector);
declareField(sphericalTensor);
declareField(symmTensor);
declareField(tensor);
#undef declareField
label size() const noexcept
{
label count = 0;
#undef doLocalCode
#define doLocalCode(Type) \
{ \
count += Type##AreaFields_.size(); \
count += Type##EdgeFields_.size(); \
}
doLocalCode(scalar);
doLocalCode(vector);
doLocalCode(sphericalTensor);
doLocalCode(symmTensor);
doLocalCode(tensor);
#undef doLocalCode
return count;
}
bool empty() const noexcept { return !size(); }
void readAll(const faMesh& mesh, const IOobjectList& objects)
{
#undef doLocalCode
#define doLocalCode(Type) \
{ \
fieldsDistributor::readFields \
( \
mesh, \
objects, \
Type##AreaFields_ \
); \
fieldsDistributor::readFields \
( \
mesh, \
objects, \
Type##AreaFields_, \
false /* readOldTime = false */ \
); \
fieldsDistributor::readFields \
( \
mesh, \
objects, \
Type##EdgeFields_, \
false /* readOldTime = false */ \
); \
}
doLocalCode(scalar);
doLocalCode(vector);
doLocalCode(sphericalTensor);
doLocalCode(symmTensor);
doLocalCode(tensor);
#undef doLocalCode
}
template<class GeoField>
static void decompose
(
const faFieldDecomposer& decomposer,
const PtrList<GeoField>& fields,
bool report
)
{
if (!fields.empty())
{
if (report)
{
Info<< " "
<< pTraits<typename GeoField::value_type>::typeName
<< "s: "
<< flatOutput(PtrListOps::names(fields)) << nl;
}
decomposer.decomposeFields(fields);
}
}
void decomposeAll(const faFieldDecomposer& decomposer, bool report) const
{
#undef doLocalCode
#define doLocalCode(Flavour) \
{ \
decompose(decomposer, scalar##Flavour##Fields_, report); \
decompose(decomposer, vector##Flavour##Fields_, report); \
decompose(decomposer, sphericalTensor##Flavour##Fields_, report); \
decompose(decomposer, symmTensor##Flavour##Fields_, report); \
decompose(decomposer, tensor##Flavour##Fields_, report); \
}
doLocalCode(Area);
doLocalCode(Edge);
#undef doLocalCode
}
};
} // End namespace Foam
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::faFieldDecomposer::fieldsCache::fieldsCache()
:
cache_(new privateCache)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
// Destructor not in header (used incomplete type)
Foam::faFieldDecomposer::fieldsCache::~fieldsCache()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::faFieldDecomposer::fieldsCache::empty() const
{
return (!cache_ || cache_->empty());
}
Foam::label Foam::faFieldDecomposer::fieldsCache::size() const
{
return (cache_ ? cache_->size() : label(0));
}
void Foam::faFieldDecomposer::fieldsCache::clear()
{
cache_.reset(new privateCache);
}
void Foam::faFieldDecomposer::fieldsCache::readAllFields
(
const faMesh& mesh,
const IOobjectList& objects
)
{
if (cache_)
{
cache_->readAll(mesh, objects);
}
}
void Foam::faFieldDecomposer::fieldsCache::decomposeAllFields
(
const faFieldDecomposer& decomposer,
bool report
) const
{
if (cache_)
{
cache_->decomposeAll(decomposer, report);
}
}
// ************************************************************************* //

View File

@ -1,92 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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>());
// 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 |
-------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2021 OpenCFD Ltd.
Copyright (C) 2021-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,6 +27,8 @@ License
\*---------------------------------------------------------------------------*/
#include "faFieldDecomposer.H"
#include "GeometricField.H"
#include "IOobjectList.H"
#include "processorFaPatchField.H"
#include "processorFaePatchField.H"
@ -89,8 +91,8 @@ Foam::faFieldDecomposer::decomposeField
IOobject
(
field.name(),
procMesh_.time().timeName(),
procMesh_(),
procMesh_.thisDb().time().timeName(),
procMesh_.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
@ -200,8 +202,8 @@ Foam::faFieldDecomposer::decomposeField
IOobject
(
field.name(),
procMesh_.time().timeName(),
procMesh_(),
procMesh_.thisDb().time().timeName(),
procMesh_.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE
),

View File

@ -47,16 +47,16 @@ void Foam::faMeshDecomposition::distributeFaces()
cpuTime decompositionTime;
for (label procI = 0; procI < nProcs(); procI++)
for (label proci = 0; proci < nProcs(); ++proci)
{
Time processorDb
(
Time::controlDictName,
time().rootPath(),
time().caseName()/("processor" + Foam::name(procI))
time().caseName()/("processor" + Foam::name(proci))
);
polyMesh procMesh
polyMesh procFvMesh
(
IOobject
(
@ -66,6 +66,24 @@ void Foam::faMeshDecomposition::distributeFaces()
)
);
IOobject ioAddr
(
"procAddressing",
"constant",
polyMesh::meshSubDir,
procFvMesh,
IOobject::MUST_READ,
IOobject::NO_WRITE,
false // not registered
);
// faceProcAddressing (polyMesh)
ioAddr.rename("faceProcAddressing");
labelIOList fvFaceProcAddressing(ioAddr);
labelHashSet faceProcAddressingHash(2*fvFaceProcAddressing.size());
// If faMesh's fvPatch is a part of the global face zones, faces of that
// patch will be present on all processors. Because of that, looping
// through faceProcAddressing will decompose global faMesh faces to the
@ -76,77 +94,31 @@ void Foam::faMeshDecomposition::distributeFaces()
// Vanja Skuric, 2016-04-21
if (hasGlobalFaceZones_)
{
labelList faceProcAddressing
(
labelIOList
(
IOobject
(
"faceProcAddressing",
"constant",
procMesh.meshSubDir,
procMesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
)
)
);
const label ownerSize =
(
labelIOList
(
IOobject
(
"owner",
"constant",
procMesh.meshSubDir,
procMesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
)
)
).size();
labelHashSet faceProcAddressingHash(ownerSize);
// owner (polyMesh)
ioAddr.rename("owner");
const label ownerSize = labelIOList(ioAddr).size();
for (int i = 0; i < ownerSize; ++i)
{
faceProcAddressingHash.insert(faceProcAddressing[i]);
}
forAll(faceLabels(), faceI)
{
if (faceProcAddressingHash.found(faceLabels()[faceI] + 1))
{
faceToProc_[faceI] = procI;
}
faceProcAddressingHash.insert(fvFaceProcAddressing[i]);
}
}
else
{
labelHashSet faceProcAddressingHash
faceProcAddressingHash.insert
(
labelIOList
(
IOobject
(
"faceProcAddressing",
"constant",
procMesh.meshSubDir,
procMesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
)
)
static_cast<labelList&>(fvFaceProcAddressing)
);
}
forAll(faceLabels(), faceI)
forAll(faceLabels(), facei)
{
// With +1 for lookup in faceMap with flip encoding
const label index = (faceLabels()[facei] + 1);
if (faceProcAddressingHash.found(index))
{
if (faceProcAddressingHash.found(faceLabels()[faceI] + 1))
{
faceToProc_[faceI] = procI;
}
faceToProc_[facei] = proci;
}
}
}
@ -276,40 +248,37 @@ void Foam::faMeshDecomposition::decomposeMesh()
)
);
labelIOList fvPointProcAddressing
IOobject ioAddr
(
IOobject
(
"pointProcAddressing",
"constant",
procFvMesh.meshSubDir,
procFvMesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
)
"procAddressing",
"constant",
polyMesh::meshSubDir,
procFvMesh,
IOobject::MUST_READ,
IOobject::NO_WRITE,
false // not registered
);
// pointProcAddressing (polyMesh)
ioAddr.rename("pointProcAddressing");
labelIOList fvPointProcAddressing(ioAddr);
Map<label> fvFaceProcAddressingHash;
{
labelIOList fvFaceProcAddressing
(
IOobject
(
"faceProcAddressing",
"constant",
procFvMesh.meshSubDir,
procFvMesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
)
);
// faceProcAddressing (polyMesh)
ioAddr.rename("faceProcAddressing");
labelIOList fvFaceProcAddressing(ioAddr);
forAll(fvFaceProcAddressing, faceI)
fvFaceProcAddressingHash.resize(2*fvFaceProcAddressing.size());
forAll(fvFaceProcAddressing, facei)
{
fvFaceProcAddressingHash.insert
(
fvFaceProcAddressing[faceI], faceI
fvFaceProcAddressing[facei],
facei
);
}
};
@ -365,17 +334,16 @@ void Foam::faMeshDecomposition::decomposeMesh()
const uindirectPrimitivePatch& procPatch = procMesh.patch();
const vectorField& procPoints = procPatch.localPoints();
const labelList& procMeshPoints = procPatch.meshPoints();
const edgeList& procEdges = procPatch.edges();
labelList& curPatchPointAddressing = procPatchPointAddressing_[procI];
curPatchPointAddressing.setSize(procPoints.size(), -1);
curPatchPointAddressing.resize(procMeshPoints.size(), -1);
forAll(procPoints, pointI)
forAll(procMeshPoints, pointi)
{
curPatchPointAddressing[pointI] =
map[fvPointProcAddressing[procMeshPoints[pointI]]];
curPatchPointAddressing[pointi] =
map[fvPointProcAddressing[procMeshPoints[pointi]]];
}
labelList& curPatchEdgeAddressing = procPatchEdgeAddressing_[procI];
@ -1154,9 +1122,12 @@ bool Foam::faMeshDecomposition::writeDecomposition()
sharedPointLookup.insert(globallySharedPoints_[pointi], pointi);
}
label maxProcFaces = 0;
label totProcFaces = 0;
label maxProcEdges = 0;
label totProcEdges = 0;
label maxProcPatches = 0;
label maxProcEdges = 0;
label totProcPatches = 0;
// Write out the meshes
for (label procI = 0; procI < nProcs(); procI++)
@ -1193,7 +1164,7 @@ bool Foam::faMeshDecomposition::writeDecomposition()
(
"boundaryProcAddressing",
"constant",
procFvMesh.meshSubDir,
polyMesh::meshSubDir,
procFvMesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
@ -1286,19 +1257,35 @@ bool Foam::faMeshDecomposition::writeDecomposition()
procMesh.write();
Info<< endl
<< "Processor " << procI << nl
<< " Number of faces = " << procMesh.nFaces()
<< endl;
// Statistics
Info<< nl << "Processor " << procI;
if (procMesh.nFaces())
{
Info<< nl << " ";
}
else
{
Info<< ": ";
}
Info<< "Number of faces = " << procMesh.nFaces() << nl;
if (procMesh.nFaces())
{
Info<< " Number of points = " << procMesh.nPoints() << nl;
}
totProcFaces += procMesh.nFaces();
maxProcFaces = max(maxProcFaces, procMesh.nFaces());
label nBoundaryEdges = 0;
label nProcPatches = 0;
label nProcEdges = 0;
forAll(procMesh.boundary(), patchi)
for (const faPatch& fap : procMesh.boundary())
{
const auto* ppp =
isA<processorFaPatch>(procMesh.boundary()[patchi]);
const auto* ppp = isA<processorFaPatch>(fap);
if (ppp)
{
@ -1306,92 +1293,93 @@ bool Foam::faMeshDecomposition::writeDecomposition()
Info<< " Number of edges shared with processor "
<< procPatch.neighbProcNo() << " = "
<< procPatch.size() << endl;
<< procPatch.size() << nl;
nProcEdges += procPatch.size();
++nProcPatches;
}
else
{
nBoundaryEdges += procMesh.boundary()[patchi].size();
nBoundaryEdges += fap.size();
}
}
Info<< " Number of processor patches = " << nProcPatches << nl
<< " Number of processor edges = " << nProcEdges << nl
<< " Number of boundary edges = " << nBoundaryEdges << endl;
if (procMesh.nFaces() && (nBoundaryEdges || nProcEdges))
{
Info<< " Number of processor patches = " << nProcPatches << nl
<< " Number of processor edges = " << nProcEdges << nl
<< " Number of boundary edges = " << nBoundaryEdges << nl;
}
totProcEdges += nProcEdges;
maxProcPatches = max(maxProcPatches, nProcPatches);
totProcPatches += nProcPatches;
maxProcEdges = max(maxProcEdges, nProcEdges);
maxProcPatches = max(maxProcPatches, nProcPatches);
// create and write the addressing information
labelIOList pointProcAddressing
(
IOobject
(
"pointProcAddressing",
"constant",
procMesh.meshSubDir,
procFvMesh,
IOobject::NO_READ,
IOobject::NO_WRITE
),
procPatchPointAddressing_[procI]
);
pointProcAddressing.write();
// Write the addressing information
labelIOList edgeProcAddressing
IOobject ioAddr
(
IOobject
(
"edgeProcAddressing",
"constant",
procMesh.meshSubDir,
procFvMesh,
IOobject::NO_READ,
IOobject::NO_WRITE
),
procEdgeAddressing_[procI]
"procAddressing",
"constant",
faMesh::meshSubDir,
procMesh.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE,
false // not registered
);
edgeProcAddressing.write();
labelIOList faceProcAddressing
(
IOobject
(
"faceProcAddressing",
"constant",
procMesh.meshSubDir,
procFvMesh,
IOobject::NO_READ,
IOobject::NO_WRITE
),
procFaceAddressing_[procI]
);
faceProcAddressing.write();
// pointProcAddressing
ioAddr.rename("pointProcAddressing");
IOListRef<label>(ioAddr, procPatchPointAddressing_[procI]).write();
labelIOList boundaryProcAddressing
(
IOobject
(
"boundaryProcAddressing",
"constant",
procMesh.meshSubDir,
procFvMesh,
IOobject::NO_READ,
IOobject::NO_WRITE
),
procBoundaryAddressing_[procI]
);
boundaryProcAddressing.write();
// edgeProcAddressing
ioAddr.rename("edgeProcAddressing");
IOListRef<label>(ioAddr, procEdgeAddressing_[procI]).write();
// faceProcAddressing
ioAddr.rename("faceProcAddressing");
IOListRef<label>(ioAddr, procFaceAddressing_[procI]).write();
// boundaryProcAddressing
ioAddr.rename("boundaryProcAddressing");
IOListRef<label>(ioAddr, procBoundaryAddressing_[procI]).write();
}
// Summary stats
Info<< nl
<< "Number of processor edges = " << totProcEdges/2 << nl
<< "Max number of processor patches = " << maxProcPatches << nl
<< "Max number of faces between processors = " << maxProcEdges
<< endl;
<< "Number of processor edges = " << (totProcEdges/2) << nl
<< "Max number of faces = " << maxProcFaces;
if (maxProcFaces != totProcFaces)
{
scalar avgValue = scalar(totProcFaces)/nProcs_;
Info<< " (" << 100.0*(maxProcFaces-avgValue)/avgValue
<< "% above average " << avgValue << ')';
}
Info<< nl;
Info<< "Max number of processor patches = " << maxProcPatches;
if (totProcPatches)
{
scalar avgValue = scalar(totProcPatches)/nProcs_;
Info<< " (" << 100.0*(maxProcPatches-avgValue)/avgValue
<< "% above average " << avgValue << ')';
}
Info<< nl;
Info<< "Max number of edges between processors = " << maxProcEdges;
if (totProcEdges)
{
scalar avgValue = scalar(totProcEdges)/nProcs_;
Info<< " (" << 100.0*(maxProcEdges-avgValue)/avgValue
<< "% above average " << avgValue << ')';
}
Info<< nl << endl;
return true;
}

View File

@ -39,8 +39,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef faMeshDecomposition_H
#define faMeshDecomposition_H
#ifndef Foam_faMeshDecomposition_H
#define Foam_faMeshDecomposition_H
#include "polyMesh.H"
#include "faMesh.H"

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -26,6 +27,13 @@ License
\*---------------------------------------------------------------------------*/
#include "faFieldReconstructor.H"
#include "areaFields.H"
#include "edgeFields.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
int Foam::faFieldReconstructor::verbose_ = 1;
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
@ -42,8 +50,42 @@ Foam::faFieldReconstructor::faFieldReconstructor
procMeshes_(procMeshes),
edgeProcAddressing_(edgeProcAddressing),
faceProcAddressing_(faceProcAddressing),
boundaryProcAddressing_(boundaryProcAddressing)
boundaryProcAddressing_(boundaryProcAddressing),
nReconstructed_(0)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::label Foam::faFieldReconstructor::reconstructAllFields
(
const IOobjectList& objects,
const wordRes& selected
)
{
label nTotal = 0;
do
{
#undef doLocalCode
#define doLocalCode(Method) \
{ \
nTotal += this->Method <scalar> (objects, selected); \
nTotal += this->Method <vector> (objects, selected); \
nTotal += this->Method <sphericalTensor> (objects, selected); \
nTotal += this->Method <symmTensor> (objects, selected); \
nTotal += this->Method <tensor> (objects, selected); \
}
doLocalCode(reconstructAreaFields);
doLocalCode(reconstructEdgeFields);
#undef doLocalCode
}
while (false);
return nTotal;
}
// ************************************************************************* //

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -35,12 +36,12 @@ Author
SourceFiles
faFieldReconstructor.C
faFieldReconstructorFields.C
faFieldReconstructorTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef faFieldReconstructor_H
#define faFieldReconstructor_H
#ifndef Foam_faFieldReconstructor_H
#define Foam_faFieldReconstructor_H
#include "PtrList.H"
#include "faMesh.H"
@ -59,7 +60,7 @@ namespace Foam
class faFieldReconstructor
{
// Private data
// Private Data
//- Reconstructed mesh reference
faMesh& mesh_;
@ -76,6 +77,9 @@ class faFieldReconstructor
//- List of processor boundary addressing lists
const PtrList<labelIOList>& boundaryProcAddressing_;
//- Number of fields reconstructed
label nReconstructed_;
// Private Member Functions
@ -88,6 +92,8 @@ class faFieldReconstructor
public:
// Public Classes
class faPatchFieldReconstructor
:
public faPatchFieldMapper
@ -111,7 +117,7 @@ public:
{}
// Member functions
// Member Functions
virtual label size() const
{
@ -140,13 +146,19 @@ public:
};
// Static Data
//- Output verbosity when writing
static int verbose_;
// Constructors
//- Construct from components
faFieldReconstructor
(
faMesh& mesh,
const PtrList<faMesh>& procMeshes,
faMesh& mesh, // Target mesh
const PtrList<faMesh>& procMeshes, // Source meshes
const PtrList<labelIOList>& edgeProcAddressing,
const PtrList<labelIOList>& faceProcAddressing,
const PtrList<labelIOList>& boundaryProcAddressing
@ -155,34 +167,80 @@ public:
// Member Functions
//- Return number of fields reconstructed
label nReconstructed() const noexcept
{
return nReconstructed_;
}
//- Reconstruct area field
template<class Type>
tmp<GeometricField<Type, faPatchField, areaMesh>>
reconstructFaAreaField
reconstructField
(
const IOobject& fieldIoObject
);
const IOobject& fieldObject,
const PtrList<GeometricField<Type, faPatchField, areaMesh>>&
) const;
//- Read and reconstruct area field
template<class Type>
tmp<GeometricField<Type, faPatchField, areaMesh>>
reconstructAreaField(const IOobject& fieldObject);
//- Reconstruct edge field
template<class Type>
tmp<GeometricField<Type, faePatchField, edgeMesh>>
reconstructFaEdgeField
reconstructField
(
const IOobject& fieldIoObject
const IOobject& fieldObject,
const PtrList<GeometricField<Type, faePatchField, edgeMesh>>&
) const;
//- Read and reconstruct edge field
template<class Type>
tmp<GeometricField<Type, faePatchField, edgeMesh>>
reconstructEdgeField(const IOobject& fieldObject);
//- Read, reconstruct and write specified area fields
template<class Type>
label reconstructAreaFields
(
const UPtrList<const IOobject>& fieldObjects
);
//- Reconstruct and write all area fields
//- Read, reconstruct and write specified edge fields
template<class Type>
void reconstructFaAreaFields
label reconstructEdgeFields
(
const IOobjectList& objects
const UPtrList<const IOobject>& fieldObjects
);
//- Reconstruct and write all area fields
//- Read, reconstruct and write all/selected area fields
// An empty wordRes corresponds to select ALL.
template<class Type>
void reconstructFaEdgeFields
label reconstructAreaFields
(
const IOobjectList& objects
const IOobjectList& objects,
const wordRes& selectedFields = wordRes()
);
//- Read, reconstruct and write all/selected edge fields
// An empty wordRes corresponds to select ALL.
template<class Type>
label reconstructEdgeFields
(
const IOobjectList& objects,
const wordRes& selectedFields = wordRes()
);
//- Reconstruct all supported area/edge field types
label reconstructAllFields
(
const IOobjectList& objects,
const wordRes& selectedFields = wordRes()
);
};
@ -194,7 +252,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "faFieldReconstructorFields.C"
# include "faFieldReconstructorTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2018 OpenCFD Ltd.
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -38,37 +38,12 @@ License
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::faPatchField, Foam::areaMesh>>
Foam::faFieldReconstructor::reconstructFaAreaField
Foam::faFieldReconstructor::reconstructField
(
const IOobject& fieldIoObject
)
const IOobject& fieldObject,
const PtrList<GeometricField<Type, faPatchField, areaMesh>>& procFields
) const
{
// Read the field for all the processors
PtrList<GeometricField<Type, faPatchField, areaMesh>> procFields
(
procMeshes_.size()
);
forAll(procMeshes_, procI)
{
procFields.set
(
procI,
new GeometricField<Type, faPatchField, areaMesh>
(
IOobject
(
fieldIoObject.name(),
procMeshes_[procI].time().timeName(),
procMeshes_[procI](),
IOobject::MUST_READ,
IOobject::NO_WRITE
),
procMeshes_[procI]
)
);
}
// Create the internalField
Field<Type> internalField(mesh_.nFaces());
@ -278,9 +253,9 @@ Foam::faFieldReconstructor::reconstructFaAreaField
(
IOobject
(
fieldIoObject.name(),
mesh_.time().timeName(),
mesh_(),
fieldObject.name(),
mesh_.thisDb().time().timeName(),
mesh_.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
@ -294,38 +269,12 @@ Foam::faFieldReconstructor::reconstructFaAreaField
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::faePatchField, Foam::edgeMesh>>
Foam::faFieldReconstructor::reconstructFaEdgeField
Foam::faFieldReconstructor::reconstructField
(
const IOobject& fieldIoObject
)
const IOobject& fieldObject,
const PtrList<GeometricField<Type, faePatchField, edgeMesh>>& procFields
) const
{
// Read the field for all the processors
PtrList<GeometricField<Type, faePatchField, edgeMesh>> procFields
(
procMeshes_.size()
);
forAll(procMeshes_, procI)
{
procFields.set
(
procI,
new GeometricField<Type, faePatchField, edgeMesh>
(
IOobject
(
fieldIoObject.name(),
procMeshes_[procI].time().timeName(),
procMeshes_[procI](),
IOobject::MUST_READ,
IOobject::NO_WRITE
),
procMeshes_[procI]
)
);
}
// Create the internalField
Field<Type> internalField(mesh_.nInternalEdges());
@ -555,9 +504,9 @@ Foam::faFieldReconstructor::reconstructFaEdgeField
(
IOobject
(
fieldIoObject.name(),
mesh_.time().timeName(),
mesh_(),
fieldObject.name(),
mesh_.thisDb().time().timeName(),
mesh_.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
@ -569,58 +518,209 @@ Foam::faFieldReconstructor::reconstructFaEdgeField
}
// Reconstruct and write all area fields
template<class Type>
void Foam::faFieldReconstructor::reconstructFaAreaFields
Foam::tmp<Foam::GeometricField<Type, Foam::faPatchField, Foam::areaMesh>>
Foam::faFieldReconstructor::reconstructAreaField
(
const IOobjectList& objects
const IOobject& fieldObject
)
{
const word& clsName =
GeometricField<Type, faPatchField, areaMesh>::typeName;
// Read the field for all the processors
PtrList<GeometricField<Type, faPatchField, areaMesh>> procFields
(
procMeshes_.size()
);
const wordList fieldNames = objects.sortedNames(clsName);
if (fieldNames.size())
forAll(procMeshes_, proci)
{
Info<< " Reconstructing " << clsName << "s\n" << endl;
procFields.set
(
proci,
new GeometricField<Type, faPatchField, areaMesh>
(
IOobject
(
fieldObject.name(),
procMeshes_[proci].thisDb().time().timeName(),
procMeshes_[proci].thisDb(),
IOobject::MUST_READ,
IOobject::NO_WRITE
),
procMeshes_[proci]
)
);
}
for (const word& fieldName : fieldNames)
{
Info << " " << fieldName << endl;
reconstructFaAreaField<Type>(*(objects[fieldName]))().write();
}
if (fieldNames.size()) Info<< endl;
return reconstructField
(
IOobject
(
fieldObject.name(),
mesh_.thisDb().time().timeName(),
mesh_.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
procFields
);
}
// Reconstruct and write all edge fields
template<class Type>
void Foam::faFieldReconstructor::reconstructFaEdgeFields
Foam::tmp<Foam::GeometricField<Type, Foam::faePatchField, Foam::edgeMesh>>
Foam::faFieldReconstructor::reconstructEdgeField
(
const IOobjectList& objects
const IOobject& fieldObject
)
{
const word& clsName =
GeometricField<Type, faePatchField, edgeMesh>::typeName;
// Read the field for all the processors
PtrList<GeometricField<Type, faePatchField, edgeMesh>> procFields
(
procMeshes_.size()
);
const wordList fieldNames = objects.sortedNames(clsName);
if (fieldNames.size())
forAll(procMeshes_, proci)
{
Info<< " Reconstructing " << clsName << "s\n" << endl;
procFields.set
(
proci,
new GeometricField<Type, faePatchField, edgeMesh>
(
IOobject
(
fieldObject.name(),
procMeshes_[proci].thisDb().time().timeName(),
procMeshes_[proci].thisDb(),
IOobject::MUST_READ,
IOobject::NO_WRITE
),
procMeshes_[proci]
)
);
}
for (const word& fieldName : fieldNames)
{
Info << " " << fieldName << endl;
return reconstructField
(
IOobject
(
fieldObject.name(),
mesh_.thisDb().time().timeName(),
mesh_.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
procFields
);
}
reconstructFaEdgeField<Type>(*(objects[fieldName]))().write();
template<class Type>
Foam::label Foam::faFieldReconstructor::reconstructAreaFields
(
const UPtrList<const IOobject>& fieldObjects
)
{
typedef GeometricField<Type, faPatchField, areaMesh> fieldType;
label nFields = 0;
for (const IOobject& io : fieldObjects)
{
if (io.isHeaderClass<fieldType>())
{
if (verbose_)
{
if (!nFields)
{
Info<< " Reconstructing "
<< fieldType::typeName << "s\n" << nl;
}
Info<< " " << io.name() << endl;
}
++nFields;
reconstructAreaField<Type>(io)().write();
++nReconstructed_;
}
}
if (fieldNames.size()) Info<< endl;
if (verbose_ && nFields) Info<< endl;
return nFields;
}
template<class Type>
Foam::label Foam::faFieldReconstructor::reconstructEdgeFields
(
const UPtrList<const IOobject>& fieldObjects
)
{
typedef GeometricField<Type, faePatchField, edgeMesh> fieldType;
label nFields = 0;
for (const IOobject& io : fieldObjects)
{
if (io.isHeaderClass<fieldType>())
{
if (verbose_)
{
if (!nFields)
{
Info<< " Reconstructing "
<< fieldType::typeName << "s\n" << nl;
}
Info<< " " << io.name() << endl;
}
++nFields;
reconstructEdgeField<Type>(io)().write();
++nReconstructed_;
}
}
if (verbose_ && nFields) Info<< endl;
return nFields;
}
template<class Type>
Foam::label Foam::faFieldReconstructor::reconstructAreaFields
(
const IOobjectList& objects,
const wordRes& selectedFields
)
{
typedef GeometricField<Type, faPatchField, areaMesh> fieldType;
return reconstructAreaFields<Type>
(
(
selectedFields.empty()
? objects.sorted<fieldType>()
: objects.sorted<fieldType>(selectedFields)
)
);
}
template<class Type>
Foam::label Foam::faFieldReconstructor::reconstructEdgeFields
(
const IOobjectList& objects,
const wordRes& selectedFields
)
{
typedef GeometricField<Type, faePatchField, edgeMesh> fieldType;
return reconstructEdgeFields<Type>
(
(
selectedFields.empty()
? objects.sorted<fieldType>()
: objects.sorted<fieldType>(selectedFields)
)
);
}

View File

@ -77,7 +77,7 @@ void Foam::faMeshReconstructor::calcAddressing
for (label& facei : faFaceProcAddr_)
{
// Use finiteVolume info, ignoring face flips
facei = mag(fvFaceProcAddr[facei] - 1);
facei = mag(fvFaceProcAddr[facei])-1;
}
@ -449,7 +449,7 @@ void Foam::faMeshReconstructor::initPatch() const
void Foam::faMeshReconstructor::createMesh()
{
const Time& runTime = procMesh_.mesh().time();
const Time& runTime = procMesh_.thisDb().time();
// Time for non-parallel case (w/o functionObjects or libs)
serialRunTime_ = Time::New(runTime.globalPath().toAbsolute());
@ -654,7 +654,7 @@ void Foam::faMeshReconstructor::writeAddressing(const word& timeName) const
"procAddressing",
timeName,
faMesh::meshSubDir,
procMesh_.mesh(), // The polyMesh
procMesh_.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE,
false // not registered
@ -662,19 +662,19 @@ void Foam::faMeshReconstructor::writeAddressing(const word& timeName) const
// boundaryProcAddressing
ioAddr.rename("boundaryProcAddressing");
labelIOList(ioAddr, faBoundaryProcAddr_).write();
IOListRef<label>(ioAddr, faBoundaryProcAddr_).write();
// faceProcAddressing
ioAddr.rename("faceProcAddressing");
labelIOList(ioAddr, faFaceProcAddr_).write();
IOListRef<label>(ioAddr, faFaceProcAddr_).write();
// pointProcAddressing
ioAddr.rename("pointProcAddressing");
labelIOList(ioAddr, faPointProcAddr_).write();
IOListRef<label>(ioAddr, faPointProcAddr_).write();
// edgeProcAddressing
ioAddr.rename("edgeProcAddressing");
labelIOList(ioAddr, faEdgeProcAddr_).write();
IOListRef<label>(ioAddr, faEdgeProcAddr_).write();
}
@ -699,7 +699,7 @@ void Foam::faMeshReconstructor::writeMesh(const word& timeName) const
IOobject io(fullMesh.boundary());
io.rename("faceLabels");
labelIOList(io, singlePatchFaceLabels_).write();
IOListRef<label>(io, singlePatchFaceLabels_).write();
fullMesh.boundary().write();

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,102 +28,50 @@ License
#include "processorFaMeshes.H"
#include "Time.H"
#include "OSspecific.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::processorFaMeshes::read()
{
forAll(fvMeshes_, procI)
forAll(fvMeshes_, proci)
{
meshes_.set
meshes_.set(proci, new faMesh(fvMeshes_[proci]));
// Read the addressing information
IOobject ioAddr
(
procI,
new faMesh(fvMeshes_[procI])
"procAddressing",
"constant", // Placeholder
faMesh::meshSubDir,
meshes_[proci].thisDb(),
IOobject::MUST_READ,
IOobject::NO_WRITE
);
pointProcAddressing_.set
(
procI,
new labelIOList
(
IOobject
(
"pointProcAddressing",
meshes_[procI].time().findInstance
(
meshes_[procI].meshDir(),
"pointProcAddressing"
),
meshes_[procI].meshSubDir,
fvMeshes_[procI],
IOobject::MUST_READ,
IOobject::NO_WRITE
)
)
);
const auto& runTime = meshes_[proci].thisDb().time();
const auto& meshDir = meshes_[proci].meshDir();
edgeProcAddressing_.set
(
procI,
new labelIOList
(
IOobject
(
"edgeProcAddressing",
meshes_[procI].time().findInstance
(
meshes_[procI].meshDir(),
"edgeProcAddressing"
),
meshes_[procI].meshSubDir,
fvMeshes_[procI],
IOobject::MUST_READ,
IOobject::NO_WRITE
)
)
);
// pointProcAddressing (faMesh)
ioAddr.rename("pointProcAddressing");
ioAddr.instance() = runTime.findInstance(meshDir, ioAddr.name());
pointProcAddressing_.set(proci, new labelIOList(ioAddr));
faceProcAddressing_.set
(
procI,
new labelIOList
(
IOobject
(
"faceProcAddressing",
meshes_[procI].time().findInstance
(
meshes_[procI].meshDir(),
"faceProcAddressing"
),
meshes_[procI].meshSubDir,
fvMeshes_[procI],
IOobject::MUST_READ,
IOobject::NO_WRITE
)
)
);
// edgeProcAddressing (faMesh)
ioAddr.rename("edgeProcAddressing");
ioAddr.instance() = runTime.findInstance(meshDir, ioAddr.name());
edgeProcAddressing_.set(proci, new labelIOList(ioAddr));
boundaryProcAddressing_.set
(
procI,
new labelIOList
(
IOobject
(
"boundaryProcAddressing",
meshes_[procI].time().findInstance
(
meshes_[procI].meshDir(),
"faceProcAddressing"
),
meshes_[procI].meshSubDir,
fvMeshes_[procI],
IOobject::MUST_READ,
IOobject::NO_WRITE
)
)
);
// faceProcAddressing (faMesh)
ioAddr.rename("faceProcAddressing");
ioAddr.instance() = runTime.findInstance(meshDir, ioAddr.name());
faceProcAddressing_.set(proci, new labelIOList(ioAddr));
// boundaryProcAddressing (faMesh)
ioAddr.rename("boundaryProcAddressing");
ioAddr.instance() = runTime.findInstance(meshDir, ioAddr.name());
boundaryProcAddressing_.set(proci, new labelIOList(ioAddr));
}
}
@ -131,11 +80,11 @@ void Foam::processorFaMeshes::read()
Foam::processorFaMeshes::processorFaMeshes
(
const UPtrList<fvMesh>& processorFvMeshes
const UPtrList<fvMesh>& procFvMeshes
)
:
fvMeshes_(processorFvMeshes),
meshes_(processorFvMeshes.size()),
fvMeshes_(procFvMeshes),
meshes_(procFvMeshes.size()),
pointProcAddressing_(meshes_.size()),
edgeProcAddressing_(meshes_.size()),
faceProcAddressing_(meshes_.size()),
@ -145,4 +94,40 @@ Foam::processorFaMeshes::processorFaMeshes
}
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
void Foam::processorFaMeshes::removeFiles(const faMesh& mesh)
{
IOobject ioAddr
(
"procAddressing",
mesh.facesInstance(),
faMesh::meshSubDir,
mesh.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE,
false // not registered
);
// procAddressing
rm(ioAddr.objectPath());
// pointProcAddressing
ioAddr.rename("pointProcAddressing");
rm(ioAddr.objectPath());
// edgeProcAddressing
ioAddr.rename("edgeProcAddressing");
rm(ioAddr.objectPath());
// faceProcAddressing
ioAddr.rename("faceProcAddressing");
rm(ioAddr.objectPath());
// boundaryProcAddressing
ioAddr.rename("boundaryProcAddressing");
rm(ioAddr.objectPath());
}
// ************************************************************************* //

View File

@ -37,8 +37,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef processorFaMeshes_H
#define processorFaMeshes_H
#ifndef Foam_processorFaMeshes_H
#define Foam_processorFaMeshes_H
#include "PtrList.H"
#include "faMesh.H"
@ -57,7 +57,7 @@ namespace Foam
class processorFaMeshes
{
// Private data
// Private Data
//- List of processor finite volume meshes
const UPtrList<fvMesh>& fvMeshes_;
@ -95,40 +95,44 @@ public:
// Constructors
//- Construct from components
explicit processorFaMeshes(const UPtrList<fvMesh>& processorFvMeshes);
explicit processorFaMeshes(const UPtrList<fvMesh>& procFvMeshes);
// Member Functions
const PtrList<faMesh>& meshes() const
const PtrList<faMesh>& meshes() const noexcept
{
return meshes_;
}
PtrList<faMesh>& meshes()
PtrList<faMesh>& meshes() noexcept
{
return meshes_;
}
const PtrList<labelIOList>& pointProcAddressing() const
const PtrList<labelIOList>& pointProcAddressing() const noexcept
{
return pointProcAddressing_;
}
PtrList<labelIOList>& edgeProcAddressing()
PtrList<labelIOList>& edgeProcAddressing() noexcept
{
return edgeProcAddressing_;
}
const PtrList<labelIOList>& faceProcAddressing() const
const PtrList<labelIOList>& faceProcAddressing() const noexcept
{
return faceProcAddressing_;
}
const PtrList<labelIOList>& boundaryProcAddressing() const
const PtrList<labelIOList>& boundaryProcAddressing() const noexcept
{
return boundaryProcAddressing_;
}
//- Helper: remove all procAddressing files from mesh instance
static void removeFiles(const faMesh& mesh);
};

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -26,6 +27,13 @@ License
\*---------------------------------------------------------------------------*/
#include "fvFieldReconstructor.H"
#include "volFields.H"
#include "surfaceFields.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
int Foam::fvFieldReconstructor::verbose_ = 1;
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
@ -71,4 +79,38 @@ Foam::fvFieldReconstructor::fvFieldReconstructor
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::label Foam::fvFieldReconstructor::reconstructAllFields
(
const IOobjectList& objects,
const wordRes& selected
)
{
label nTotal = 0;
do
{
#undef doLocalCode
#define doLocalCode(Method) \
{ \
nTotal += this->Method <scalar> (objects, selected); \
nTotal += this->Method <vector> (objects, selected); \
nTotal += this->Method <sphericalTensor> (objects, selected); \
nTotal += this->Method <symmTensor> (objects, selected); \
nTotal += this->Method <tensor> (objects, selected); \
}
doLocalCode(reconstructInternalFields);
doLocalCode(reconstructVolumeFields);
doLocalCode(reconstructSurfaceFields);
#undef doLocalCode
}
while (false);
return nTotal;
}
// ************************************************************************* //

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018 OpenCFD Ltd.
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -32,12 +32,12 @@ Description
SourceFiles
fvFieldReconstructor.C
fvFieldReconstructorFields.C
fvFieldReconstructorTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef fvFieldReconstructor_H
#define fvFieldReconstructor_H
#ifndef Foam_fvFieldReconstructor_H
#define Foam_fvFieldReconstructor_H
#include "PtrList.H"
#include "fvMesh.H"
@ -56,7 +56,7 @@ namespace Foam
class fvFieldReconstructor
{
// Private data
// Private Data
//- Reconstructed mesh reference
fvMesh& mesh_;
@ -88,6 +88,8 @@ class fvFieldReconstructor
public:
// Public Classes
//- Mapper for sizing only - does not do any actual mapping.
class fvPatchFieldReconstructor
:
@ -130,6 +132,12 @@ public:
};
// Static Data
//- Output verbosity when writing
static int verbose_;
// Constructors
//- Construct from components
@ -146,7 +154,7 @@ public:
// Member Functions
//- Return number of fields reconstructed
label nReconstructed() const
label nReconstructed() const noexcept
{
return nReconstructed_;
}
@ -154,76 +162,74 @@ public:
//- Reconstruct volume internal field
template<class Type>
tmp<DimensionedField<Type, volMesh>>
reconstructFvVolumeInternalField
reconstructField
(
const IOobject& fieldIoObject,
const IOobject& fieldObject,
const PtrList<DimensionedField<Type, volMesh>>& procFields
) const;
//- Read and reconstruct volume internal field
template<class Type>
tmp<DimensionedField<Type, volMesh>>
reconstructFvVolumeInternalField(const IOobject& fieldIoObject) const;
reconstructInternalField(const IOobject& fieldObject) const;
//- Reconstruct volume field
template<class Type>
tmp<GeometricField<Type, fvPatchField, volMesh>>
reconstructFvVolumeField
reconstructField
(
const IOobject& fieldIoObject,
const IOobject& fieldObject,
const PtrList<GeometricField<Type, fvPatchField, volMesh>>&
) const;
//- Read and reconstruct volume field
template<class Type>
tmp<GeometricField<Type, fvPatchField, volMesh>>
reconstructFvVolumeField(const IOobject& fieldIoObject) const;
reconstructVolumeField(const IOobject& fieldObject) const;
//- Reconstruct surface field
template<class Type>
tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
reconstructFvSurfaceField
reconstructField
(
const IOobject& fieldIoObject,
const IOobject& fieldObject,
const PtrList<GeometricField<Type, fvsPatchField, surfaceMesh>>&
) const;
//- Read and reconstruct surface field
template<class Type>
tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
reconstructFvSurfaceField(const IOobject& fieldIoObject) const;
reconstructSurfaceField(const IOobject& fieldObject) const;
//- Read, reconstruct and write specified volume internal fields
template<class Type>
label reconstructFvVolumeInternalFields
label reconstructInternalFields
(
const IOobjectList& objects,
const UList<word>& fieldNames
const UPtrList<const IOobject>& fieldObjects
);
//- Read, reconstruct and write specified volume fields
template<class Type>
label reconstructFvVolumeFields
label reconstructVolumeFields
(
const IOobjectList& objects,
const UList<word>& fieldNames
const UPtrList<const IOobject>& fieldObjects
);
//- Read, reconstruct and write specified surface fields
template<class Type>
label reconstructFvSurfaceFields
label reconstructSurfaceFields
(
const IOobjectList& objects,
const UList<word>& fieldNames
const UPtrList<const IOobject>& fieldObjects
);
//- Read, reconstruct and write all/selected volume internal fields
// An empty wordRes corresponds to select ALL.
template<class Type>
label reconstructFvVolumeInternalFields
label reconstructInternalFields
(
const IOobjectList& objects,
const wordRes& selectedFields = wordRes()
@ -232,7 +238,7 @@ public:
//- Read, reconstruct and write all/selected volume fields
// An empty wordRes corresponds to select ALL.
template<class Type>
label reconstructFvVolumeFields
label reconstructVolumeFields
(
const IOobjectList& objects,
const wordRes& selectedFields = wordRes()
@ -241,40 +247,17 @@ public:
//- Read, reconstruct and write all/selected surface fields
// An empty wordRes corresponds to select ALL.
template<class Type>
label reconstructFvSurfaceFields
label reconstructSurfaceFields
(
const IOobjectList& objects,
const wordRes& selectedFields = wordRes()
);
//- Read, reconstruct and write all/selected volume internal fields
// An empty wordHashSet corresponds to select ALL.
// \note this may be removed in the future (2018-11)
template<class Type>
label reconstructFvVolumeInternalFields
//- Reconstruct all known field types
label reconstructAllFields
(
const IOobjectList& objects,
const wordHashSet& selectedFields
);
//- Read, reconstruct and write all/selected volume fields
// An empty wordHashSet corresponds to select ALL.
// \note this may be removed in the future (2018-11)
template<class Type>
label reconstructFvVolumeFields
(
const IOobjectList& objects,
const wordHashSet& selectedFields
);
//- Read, reconstruct and write all/selected surface fields
// An empty wordHashSet corresponds to select ALL.
// \note this may be removed in the future (2018-11)
template<class Type>
label reconstructFvSurfaceFields
(
const IOobjectList& objects,
const wordHashSet& selectedFields
const wordRes& selectedFields = wordRes()
);
};
@ -286,7 +269,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "fvFieldReconstructorFields.C"
#include "fvFieldReconstructorTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018 OpenCFD Ltd.
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -38,9 +38,9 @@ License
template<class Type>
Foam::tmp<Foam::DimensionedField<Type, Foam::volMesh>>
Foam::fvFieldReconstructor::reconstructFvVolumeInternalField
Foam::fvFieldReconstructor::reconstructField
(
const IOobject& fieldIoObject,
const IOobject& fieldObject,
const PtrList<DimensionedField<Type, volMesh>>& procFields
) const
{
@ -61,7 +61,7 @@ Foam::fvFieldReconstructor::reconstructFvVolumeInternalField
auto tfield = tmp<DimensionedField<Type, volMesh>>::New
(
fieldIoObject,
fieldObject,
mesh_,
procFields[0].dimensions(),
internalField
@ -73,59 +73,11 @@ Foam::fvFieldReconstructor::reconstructFvVolumeInternalField
}
template<class Type>
Foam::tmp<Foam::DimensionedField<Type, Foam::volMesh>>
Foam::fvFieldReconstructor::reconstructFvVolumeInternalField
(
const IOobject& fieldIoObject
) const
{
// Read the field for all the processors
PtrList<DimensionedField<Type, volMesh>> procFields
(
procMeshes_.size()
);
forAll(procMeshes_, proci)
{
procFields.set
(
proci,
new DimensionedField<Type, volMesh>
(
IOobject
(
fieldIoObject.name(),
procMeshes_[proci].time().timeName(),
procMeshes_[proci],
IOobject::MUST_READ,
IOobject::NO_WRITE
),
procMeshes_[proci]
)
);
}
return reconstructFvVolumeInternalField
(
IOobject
(
fieldIoObject.name(),
mesh_.time().timeName(),
mesh_,
IOobject::NO_READ,
IOobject::NO_WRITE
),
procFields
);
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh>>
Foam::fvFieldReconstructor::reconstructFvVolumeField
Foam::fvFieldReconstructor::reconstructField
(
const IOobject& fieldIoObject,
const IOobject& fieldObject,
const PtrList<GeometricField<Type, fvPatchField, volMesh>>& procFields
) const
{
@ -137,8 +89,7 @@ Foam::fvFieldReconstructor::reconstructFvVolumeField
forAll(procFields, proci)
{
const GeometricField<Type, fvPatchField, volMesh>& procField =
procFields[proci];
const auto& procField = procFields[proci];
// Set the cell values in the reconstructed field
internalField.rmap
@ -287,7 +238,7 @@ Foam::fvFieldReconstructor::reconstructFvVolumeField
// setting the internalField and patchFields
auto tfield = tmp<GeometricField<Type, fvPatchField, volMesh>>::New
(
fieldIoObject,
fieldObject,
mesh_,
procFields[0].dimensions(),
internalField,
@ -300,59 +251,11 @@ Foam::fvFieldReconstructor::reconstructFvVolumeField
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh>>
Foam::fvFieldReconstructor::reconstructFvVolumeField
(
const IOobject& fieldIoObject
) const
{
// Read the field for all the processors
PtrList<GeometricField<Type, fvPatchField, volMesh>> procFields
(
procMeshes_.size()
);
forAll(procMeshes_, proci)
{
procFields.set
(
proci,
new GeometricField<Type, fvPatchField, volMesh>
(
IOobject
(
fieldIoObject.name(),
procMeshes_[proci].time().timeName(),
procMeshes_[proci],
IOobject::MUST_READ,
IOobject::NO_WRITE
),
procMeshes_[proci]
)
);
}
return reconstructFvVolumeField
(
IOobject
(
fieldIoObject.name(),
mesh_.time().timeName(),
mesh_,
IOobject::NO_READ,
IOobject::NO_WRITE
),
procFields
);
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::fvsPatchField, Foam::surfaceMesh>>
Foam::fvFieldReconstructor::reconstructFvSurfaceField
Foam::fvFieldReconstructor::reconstructField
(
const IOobject& fieldIoObject,
const IOobject& fieldObject,
const PtrList<GeometricField<Type, fvsPatchField, surfaceMesh>>& procFields
) const
{
@ -365,8 +268,7 @@ Foam::fvFieldReconstructor::reconstructFvSurfaceField
forAll(procMeshes_, proci)
{
const GeometricField<Type, fvsPatchField, surfaceMesh>& procField =
procFields[proci];
const auto& procField = procFields[proci];
// Set the face values in the reconstructed field
@ -529,7 +431,7 @@ Foam::fvFieldReconstructor::reconstructFvSurfaceField
// setting the internalField and patchFields
auto tfield = tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>::New
(
fieldIoObject,
fieldObject,
mesh_,
procFields[0].dimensions(),
internalField,
@ -543,10 +445,106 @@ Foam::fvFieldReconstructor::reconstructFvSurfaceField
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::fvsPatchField, Foam::surfaceMesh>>
Foam::fvFieldReconstructor::reconstructFvSurfaceField
Foam::tmp<Foam::DimensionedField<Type, Foam::volMesh>>
Foam::fvFieldReconstructor::reconstructInternalField
(
const IOobject& fieldIoObject
const IOobject& fieldObject
) const
{
// Read the field for all the processors
PtrList<DimensionedField<Type, volMesh>> procFields
(
procMeshes_.size()
);
forAll(procMeshes_, proci)
{
procFields.set
(
proci,
new DimensionedField<Type, volMesh>
(
IOobject
(
fieldObject.name(),
procMeshes_[proci].thisDb().time().timeName(),
procMeshes_[proci].thisDb(),
IOobject::MUST_READ,
IOobject::NO_WRITE
),
procMeshes_[proci]
)
);
}
return reconstructField
(
IOobject
(
fieldObject.name(),
mesh_.thisDb().time().timeName(),
mesh_.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
procFields
);
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh>>
Foam::fvFieldReconstructor::reconstructVolumeField
(
const IOobject& fieldObject
) const
{
// Read the field for all the processors
PtrList<GeometricField<Type, fvPatchField, volMesh>> procFields
(
procMeshes_.size()
);
forAll(procMeshes_, proci)
{
procFields.set
(
proci,
new GeometricField<Type, fvPatchField, volMesh>
(
IOobject
(
fieldObject.name(),
procMeshes_[proci].thisDb().time().timeName(),
procMeshes_[proci].thisDb(),
IOobject::MUST_READ,
IOobject::NO_WRITE
),
procMeshes_[proci]
)
);
}
return reconstructField
(
IOobject
(
fieldObject.name(),
mesh_.thisDb().time().timeName(),
mesh_.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
procFields
);
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::fvsPatchField, Foam::surfaceMesh>>
Foam::fvFieldReconstructor::reconstructSurfaceField
(
const IOobject& fieldObject
) const
{
// Read the field for all the processors
@ -564,9 +562,9 @@ Foam::fvFieldReconstructor::reconstructFvSurfaceField
(
IOobject
(
fieldIoObject.name(),
procMeshes_[proci].time().timeName(),
procMeshes_[proci],
fieldObject.name(),
procMeshes_[proci].thisDb().time().timeName(),
procMeshes_[proci].thisDb(),
IOobject::MUST_READ,
IOobject::NO_WRITE
),
@ -575,13 +573,13 @@ Foam::fvFieldReconstructor::reconstructFvSurfaceField
);
}
return reconstructFvSurfaceField
return reconstructField
(
IOobject
(
fieldIoObject.name(),
mesh_.time().timeName(),
mesh_,
fieldObject.name(),
mesh_.thisDb().time().timeName(),
mesh_.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
@ -591,103 +589,113 @@ Foam::fvFieldReconstructor::reconstructFvSurfaceField
template<class Type>
Foam::label Foam::fvFieldReconstructor::reconstructFvVolumeInternalFields
Foam::label Foam::fvFieldReconstructor::reconstructInternalFields
(
const IOobjectList& objects,
const UList<word>& fieldNames
const UPtrList<const IOobject>& fieldObjects
)
{
typedef DimensionedField<Type, volMesh> fieldType;
label nFields = 0;
for (const word& fieldName : fieldNames)
{
const IOobject* io = objects.cfindObject<fieldType>(fieldName);
if (io)
{
if (!nFields++)
{
Info<< " Reconstructing "
<< fieldType::typeName << "s\n" << nl;
}
Info<< " " << fieldName << endl;
reconstructFvVolumeInternalField<Type>(*io)().write();
for (const IOobject& io : fieldObjects)
{
if (io.isHeaderClass<fieldType>())
{
if (verbose_)
{
if (!nFields)
{
Info<< " Reconstructing "
<< fieldType::typeName << "s\n" << nl;
}
Info<< " " << io.name() << endl;
}
++nFields;
reconstructInternalField<Type>(io)().write();
++nReconstructed_;
}
}
if (nFields) Info<< endl;
if (verbose_ && nFields) Info<< endl;
return nFields;
}
template<class Type>
Foam::label Foam::fvFieldReconstructor::reconstructFvVolumeFields
Foam::label Foam::fvFieldReconstructor::reconstructVolumeFields
(
const IOobjectList& objects,
const UList<word>& fieldNames
const UPtrList<const IOobject>& fieldObjects
)
{
typedef GeometricField<Type, fvPatchField, volMesh> fieldType;
label nFields = 0;
for (const word& fieldName : fieldNames)
{
const IOobject* io = objects.cfindObject<fieldType>(fieldName);
if (io)
{
if (!nFields++)
{
Info<< " Reconstructing "
<< fieldType::typeName << "s\n" << nl;
}
Info<< " " << fieldName << endl;
reconstructFvVolumeField<Type>(*io)().write();
for (const IOobject& io : fieldObjects)
{
if (io.isHeaderClass<fieldType>())
{
if (verbose_)
{
if (!nFields)
{
Info<< " Reconstructing "
<< fieldType::typeName << "s\n" << nl;
}
Info<< " " << io.name() << endl;
}
++nFields;
reconstructVolumeField<Type>(io)().write();
++nReconstructed_;
}
}
if (nFields) Info<< endl;
if (verbose_ && nFields) Info<< endl;
return nFields;
}
template<class Type>
Foam::label Foam::fvFieldReconstructor::reconstructFvSurfaceFields
Foam::label Foam::fvFieldReconstructor::reconstructSurfaceFields
(
const IOobjectList& objects,
const UList<word>& fieldNames
const UPtrList<const IOobject>& fieldObjects
)
{
typedef GeometricField<Type, fvsPatchField, surfaceMesh> fieldType;
label nFields = 0;
for (const word& fieldName : fieldNames)
{
const IOobject* io = objects.cfindObject<fieldType>(fieldName);
if (io)
{
if (!nFields++)
{
Info<< " Reconstructing "
<< fieldType::typeName << "s\n" << nl;
}
Info<< " " << fieldName << endl;
reconstructFvSurfaceField<Type>(*io)().write();
for (const IOobject& io : fieldObjects)
{
if (io.isHeaderClass<fieldType>())
{
if (verbose_)
{
if (!nFields)
{
Info<< " Reconstructing "
<< fieldType::typeName << "s\n" << nl;
}
Info<< " " << io.name() << endl;
}
++nFields;
reconstructSurfaceField<Type>(io)().write();
++nReconstructed_;
}
}
if (nFields) Info<< endl;
if (verbose_ && nFields) Info<< endl;
return nFields;
}
template<class Type>
Foam::label Foam::fvFieldReconstructor::reconstructFvVolumeInternalFields
Foam::label Foam::fvFieldReconstructor::reconstructInternalFields
(
const IOobjectList& objects,
const wordRes& selectedFields
@ -695,19 +703,19 @@ Foam::label Foam::fvFieldReconstructor::reconstructFvVolumeInternalFields
{
typedef DimensionedField<Type, volMesh> fieldType;
const wordList fieldNames =
return reconstructInternalFields<Type>
(
selectedFields.empty()
? objects.sortedNames<fieldType>()
: objects.sortedNames<fieldType>(selectedFields)
(
selectedFields.empty()
? objects.sorted<fieldType>()
: objects.sorted<fieldType>(selectedFields)
)
);
return reconstructFvVolumeInternalFields<Type>(objects, fieldNames);
}
template<class Type>
Foam::label Foam::fvFieldReconstructor::reconstructFvVolumeFields
Foam::label Foam::fvFieldReconstructor::reconstructVolumeFields
(
const IOobjectList& objects,
const wordRes& selectedFields
@ -715,19 +723,19 @@ Foam::label Foam::fvFieldReconstructor::reconstructFvVolumeFields
{
typedef GeometricField<Type, fvPatchField, volMesh> fieldType;
const wordList fieldNames =
return reconstructVolumeFields<Type>
(
selectedFields.empty()
? objects.sortedNames<fieldType>()
: objects.sortedNames<fieldType>(selectedFields)
(
selectedFields.empty()
? objects.sorted<fieldType>()
: objects.sorted<fieldType>(selectedFields)
)
);
return reconstructFvVolumeFields<Type>(objects, fieldNames);
}
template<class Type>
Foam::label Foam::fvFieldReconstructor::reconstructFvSurfaceFields
Foam::label Foam::fvFieldReconstructor::reconstructSurfaceFields
(
const IOobjectList& objects,
const wordRes& selectedFields
@ -735,74 +743,14 @@ Foam::label Foam::fvFieldReconstructor::reconstructFvSurfaceFields
{
typedef GeometricField<Type, fvsPatchField, surfaceMesh> fieldType;
const wordList fieldNames =
return reconstructSurfaceFields<Type>
(
selectedFields.empty()
? objects.sortedNames<fieldType>()
: objects.sortedNames<fieldType>(selectedFields)
(
selectedFields.empty()
? objects.sorted<fieldType>()
: objects.sorted<fieldType>(selectedFields)
)
);
return reconstructFvSurfaceFields<Type>(objects, fieldNames);
}
template<class Type>
Foam::label Foam::fvFieldReconstructor::reconstructFvVolumeInternalFields
(
const IOobjectList& objects,
const wordHashSet& selectedFields
)
{
typedef DimensionedField<Type, volMesh> fieldType;
const wordList fieldNames =
(
selectedFields.empty()
? objects.sortedNames<fieldType>()
: objects.sortedNames<fieldType>(selectedFields)
);
return reconstructFvVolumeInternalFields<Type>(objects, fieldNames);
}
template<class Type>
Foam::label Foam::fvFieldReconstructor::reconstructFvVolumeFields
(
const IOobjectList& objects,
const wordHashSet& selectedFields
)
{
typedef GeometricField<Type, fvPatchField, volMesh> fieldType;
const wordList fieldNames =
(
selectedFields.empty()
? objects.sortedNames<fieldType>()
: objects.sortedNames<fieldType>(selectedFields)
);
return reconstructFvVolumeField<Type>(objects, fieldNames);
}
template<class Type>
Foam::label Foam::fvFieldReconstructor::reconstructFvSurfaceFields
(
const IOobjectList& objects,
const wordHashSet& selectedFields
)
{
typedef GeometricField<Type, fvsPatchField, surfaceMesh> fieldType;
const wordList fieldNames =
(
selectedFields.empty()
? objects.sortedNames<fieldType>()
: objects.sortedNames<fieldType>(selectedFields)
);
return reconstructFvSurfaceFields<Type>(objects, fieldNames);
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2018,2021 OpenCFD Ltd.
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -29,6 +29,11 @@ License
#include "lagrangianReconstructor.H"
#include "passivePositionParticleCloud.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
int Foam::lagrangianReconstructor::verbose_ = 1;
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::lagrangianReconstructor::lagrangianReconstructor
@ -142,4 +147,44 @@ Foam::label Foam::lagrangianReconstructor::reconstructPositions
}
void Foam::lagrangianReconstructor::reconstructAllFields
(
const word& cloudName,
const IOobjectList& cloudObjs,
const wordRes& selectedFields
)
{
do
{
#undef doLocalCode
#define doLocalCode(Type) \
{ \
this->reconstructFields<Type> \
( \
cloudName, \
cloudObjs, \
selectedFields \
); \
\
this->reconstructFieldFields<Type> \
( \
cloudName, \
cloudObjs, \
selectedFields \
); \
}
doLocalCode(label);
doLocalCode(scalar);
doLocalCode(vector);
doLocalCode(sphericalTensor);
doLocalCode(symmTensor);
doLocalCode(tensor);
#undef doLocalCode
}
while (false);
}
// ************************************************************************* //

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018 OpenCFD Ltd.
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -32,12 +32,12 @@ Description
SourceFiles
lagrangianReconstructor.C
lagrangianReconstructorFields.C
lagrangianReconstructorTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef lagrangianReconstructor_H
#define lagrangianReconstructor_H
#ifndef Foam_lagrangianReconstructor_H
#define Foam_lagrangianReconstructor_H
#include "cloud.H"
#include "polyMesh.H"
@ -56,7 +56,7 @@ namespace Foam
class lagrangianReconstructor
{
// Private data
// Private Data
//- Mesh reference
const fvMesh& mesh_;
@ -82,6 +82,12 @@ class lagrangianReconstructor
public:
// Static Data
//- Output verbosity when writing
static int verbose_;
// Constructors
//- Construct from components
@ -101,7 +107,8 @@ public:
//- Reconstruct a single field for given cloud
template<class Type>
tmp<IOField<Type>> reconstructField
tmp<IOField<Type>>
reconstructField
(
const word& cloudName,
const word& fieldName
@ -109,7 +116,8 @@ public:
//- Reconstruct a single field-field for given cloud
template<class Type>
tmp<CompactIOField<Field<Type>, Type>> reconstructFieldField
tmp<CompactIOField<Field<Type>, Type>>
reconstructFieldField
(
const word& cloudName,
const word& fieldName
@ -120,8 +128,7 @@ public:
label reconstructFields
(
const word& cloudName,
const IOobjectList& objects,
const UList<word>& fieldNames
const UPtrList<const IOobject>& fieldObjects
);
//- Reconstruct multiple fields for given cloud
@ -141,6 +148,14 @@ public:
const IOobjectList& objects,
const wordRes& selectedFields = wordRes()
);
//- Reconstruct all fields for known cloud field types
void reconstructAllFields
(
const word& cloudName,
const IOobjectList& cloudObjs,
const wordRes& selectedFields = wordRes()
);
};
@ -151,7 +166,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "lagrangianReconstructorFields.C"
#include "lagrangianReconstructorTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -153,30 +153,33 @@ template<class Type>
Foam::label Foam::lagrangianReconstructor::reconstructFields
(
const word& cloudName,
const IOobjectList& objects,
const UList<word>& fieldNames
const UPtrList<const IOobject>& fieldObjects
)
{
typedef IOField<Type> fieldType;
label nFields = 0;
for (const word& fieldName : fieldNames)
{
const IOobject* io = objects.cfindObject<fieldType>(fieldName);
if (io)
{
if (nFields++)
{
Info<< " Reconstructing lagrangian "
<< fieldType::typeName << "s\n" << nl;
}
Info<< " " << fieldName << endl;
reconstructField<Type>(cloudName, fieldName)().write();
for (const IOobject& io : fieldObjects)
{
if (io.isHeaderClass<fieldType>())
{
if (verbose_)
{
if (!nFields)
{
Info<< " Reconstructing lagrangian "
<< fieldType::typeName << "s\n" << nl;
}
Info<< " " << io.name() << endl;
}
++nFields;
reconstructField<Type>(cloudName, io.name())().write();
}
}
if (nFields) Info<< endl;
if (verbose_ && nFields) Info<< endl;
return nFields;
}
@ -191,14 +194,15 @@ Foam::label Foam::lagrangianReconstructor::reconstructFields
{
typedef IOField<Type> fieldType;
const wordList fieldNames =
return reconstructFields<Type>
(
selectedFields.empty()
? objects.sortedNames<fieldType>()
: objects.sortedNames<fieldType>(selectedFields)
cloudName,
(
selectedFields.empty()
? objects.sorted<fieldType>()
: objects.sorted<fieldType>(selectedFields)
)
);
return reconstructFields<Type>(cloudName, objects, fieldNames);
}
@ -211,38 +215,41 @@ Foam::label Foam::lagrangianReconstructor::reconstructFieldFields
)
{
typedef CompactIOField<Field<Type>, Type> fieldType;
typedef IOField<Field<Type>> fieldTypeB;
wordList fieldNames =
(
selectedFields.empty()
? objects.names<fieldType>()
: objects.names<fieldType>(selectedFields)
);
UPtrList<const IOobject> fieldObjects;
// Append IOField Field names
fieldNames.append
(
objects.empty()
? objects.names<IOField<Field<Type>>>()
: objects.names<IOField<Field<Type>>>(selectedFields)
);
Foam::sort(fieldNames);
label nFields = 0;
for (const word& fieldName : fieldNames)
if (selectedFields.empty())
{
if (!nFields++)
{
Info<< " Reconstructing lagrangian "
<< fieldType::typeName << "s\n" << nl;
}
Info<< " " << fieldName << endl;
reconstructFieldField<Type>(cloudName, fieldName)().write();
fieldObjects.append(objects.sorted<fieldType>());
fieldObjects.append(objects.sorted<fieldTypeB>());
}
else
{
fieldObjects.append(objects.sorted<fieldType>(selectedFields));
fieldObjects.append(objects.sorted<fieldTypeB>(selectedFields));
}
if (nFields) Info<< endl;
Foam::sort(fieldObjects, nameOp<IOobject>());
label nFields = 0;
for (const IOobject& io : fieldObjects)
{
if (verbose_)
{
if (!nFields)
{
Info<< " Reconstructing lagrangian "
<< fieldType::typeName << "s\n" << nl;
}
Info<< " " << io.name() << endl;
}
++nFields;
reconstructFieldField<Type>(cloudName, io.name())().write();
}
if (verbose_ && nFields) Info<< endl;
return nFields;
}

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -26,6 +27,12 @@ License
\*---------------------------------------------------------------------------*/
#include "pointFieldReconstructor.H"
#include "pointFields.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
int Foam::pointFieldReconstructor::verbose_ = 1;
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
@ -95,4 +102,24 @@ Foam::pointFieldReconstructor::pointFieldReconstructor
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::label Foam::pointFieldReconstructor::reconstructAllFields
(
const IOobjectList& objects,
const wordRes& selected
)
{
label nTotal = 0;
nTotal += reconstructPointFields<scalar>(objects, selected);
nTotal += reconstructPointFields<vector>(objects, selected);
nTotal += reconstructPointFields<symmTensor>(objects, selected);
nTotal += reconstructPointFields<sphericalTensor>(objects, selected);
nTotal += reconstructPointFields<tensor>(objects, selected);
return nTotal;
}
// ************************************************************************* //

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018 OpenCFD Ltd.
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -32,12 +32,12 @@ Description
SourceFiles
pointFieldReconstructor.C
pointFieldReconstructorFields.C
pointFieldReconstructorTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef pointFieldReconstructor_H
#define pointFieldReconstructor_H
#ifndef Foam_pointFieldReconstructor_H
#define Foam_pointFieldReconstructor_H
#include "pointMesh.H"
#include "pointFields.H"
@ -55,7 +55,7 @@ namespace Foam
class pointFieldReconstructor
{
// Private data
// Private Data
//- Reconstructed mesh reference
const pointMesh& mesh_;
@ -87,6 +87,8 @@ class pointFieldReconstructor
public:
// Public Classes
class pointPatchFieldReconstructor
:
public pointPatchFieldMapper
@ -128,6 +130,12 @@ public:
};
// Static Data
//- Output verbosity when writing
static int verbose_;
// Constructors
//- Construct from components
@ -143,41 +151,48 @@ public:
// Member Functions
//- Return number of fields reconstructed
label nReconstructed() const
label nReconstructed() const noexcept
{
return nReconstructed_;
}
//- Reconstruct field
template<class Type>
tmp<GeometricField<Type, pointPatchField, pointMesh>>
reconstructField(const IOobject& fieldIoObject);
//- Reconstruct and write specified fields
template<class Type>
label reconstructFields
reconstructField
(
const IOobjectList& objects,
const UList<word>& fieldNames
const IOobject& fieldObject,
const PtrList<GeometricField<Type, pointPatchField, pointMesh>>&
) const;
//- Read and reconstruct point field
template<class Type>
tmp<GeometricField<Type, pointPatchField, pointMesh>>
reconstructPointField(const IOobject& fieldObject);
//- Reconstruct and write specified point fields
template<class Type>
label reconstructPointFields
(
const UPtrList<const IOobject>& fieldObjects
);
//- Reconstruct and write all or selected fields
//- Reconstruct and write all or selected point fields
// An empty wordRes corresponds to select ALL.
template<class Type>
label reconstructFields
label reconstructPointFields
(
const IOobjectList& objects,
const wordRes& selectedFields = wordRes()
);
//- Reconstruct and write all or selected fields
// An empty wordHashSet corresponds to select ALL.
// \note this may be removed in the future (2018-11)
template<class Type>
label reconstructFields
//- Reconstruct and write all known field types
label reconstructAllFields
(
const IOobjectList& objects,
const wordHashSet& selectedFields
const wordRes& selectedFields = wordRes()
);
};
@ -189,7 +204,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "pointFieldReconstructorFields.C"
#include "pointFieldReconstructorTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018 OpenCFD Ltd.
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -32,34 +32,13 @@ License
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::pointPatchField, Foam::pointMesh>>
Foam::pointFieldReconstructor::reconstructField(const IOobject& fieldIoObject)
Foam::pointFieldReconstructor::reconstructField
(
const IOobject& fieldObject,
const PtrList<GeometricField<Type, pointPatchField, pointMesh>>& procFields
) const
{
// Read the field for all the processors
PtrList<GeometricField<Type, pointPatchField, pointMesh>> procFields
(
procMeshes_.size()
);
forAll(procMeshes_, proci)
{
procFields.set
(
proci,
new GeometricField<Type, pointPatchField, pointMesh>
(
IOobject
(
fieldIoObject.name(),
procMeshes_[proci]().time().timeName(),
procMeshes_[proci](),
IOobject::MUST_READ,
IOobject::NO_WRITE
),
procMeshes_[proci]
)
);
}
typedef GeometricField<Type, pointPatchField, pointMesh> fieldType;
// Create the internalField
Field<Type> internalField(mesh_.size());
@ -70,8 +49,7 @@ Foam::pointFieldReconstructor::reconstructField(const IOobject& fieldIoObject)
forAll(procMeshes_, proci)
{
const GeometricField<Type, pointPatchField, pointMesh>&
procField = procFields[proci];
const auto& procField = procFields[proci];
// Get processor-to-global addressing for use in rmap
const labelList& procToGlobalAddr = pointProcAddressing_[proci];
@ -120,13 +98,13 @@ Foam::pointFieldReconstructor::reconstructField(const IOobject& fieldIoObject)
// Construct and write the field
// setting the internalField and patchFields
return tmp<GeometricField<Type, pointPatchField, pointMesh>>::New
return tmp<fieldType>::New
(
IOobject
(
fieldIoObject.name(),
mesh_().time().timeName(),
mesh_(),
fieldObject.name(),
mesh_.thisDb().time().timeName(),
mesh_.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
@ -139,39 +117,89 @@ Foam::pointFieldReconstructor::reconstructField(const IOobject& fieldIoObject)
template<class Type>
Foam::label Foam::pointFieldReconstructor::reconstructFields
Foam::tmp<Foam::GeometricField<Type, Foam::pointPatchField, Foam::pointMesh>>
Foam::pointFieldReconstructor::reconstructPointField
(
const IOobjectList& objects,
const UList<word>& fieldNames
const IOobject& fieldObject
)
{
typedef GeometricField<Type, pointPatchField, pointMesh> fieldType;
// Read the field for all the processors
PtrList<fieldType> procFields(procMeshes_.size());
forAll(procMeshes_, proci)
{
procFields.set
(
proci,
new fieldType
(
IOobject
(
fieldObject.name(),
procMeshes_[proci].thisDb().time().timeName(),
procMeshes_[proci].thisDb(),
IOobject::MUST_READ,
IOobject::NO_WRITE
),
procMeshes_[proci]
)
);
}
return reconstructField
(
IOobject
(
fieldObject.name(),
mesh_.thisDb().time().timeName(),
mesh_.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
procFields
);
}
template<class Type>
Foam::label Foam::pointFieldReconstructor::reconstructPointFields
(
const UPtrList<const IOobject>& fieldObjects
)
{
typedef GeometricField<Type, pointPatchField, pointMesh> fieldType;
label nFields = 0;
for (const word& fieldName : fieldNames)
{
const IOobject* io = objects.cfindObject<fieldType>(fieldName);
if (io)
{
if (!nFields++)
{
Info<< " Reconstructing "
<< fieldType::typeName << "s\n" << nl;
}
Info<< " " << fieldName << endl;
reconstructField<Type>(*io)().write();
for (const IOobject& io : fieldObjects)
{
if (io.isHeaderClass<fieldType>())
{
if (verbose_)
{
if (!nFields)
{
Info<< " Reconstructing "
<< fieldType::typeName << "s\n" << nl;
}
Info<< " " << io.name() << endl;
}
++nFields;
reconstructPointField<Type>(io)().write();
++nReconstructed_;
}
}
if (nFields) Info<< endl;
if (verbose_ && nFields) Info<< endl;
return nFields;
}
template<class Type>
Foam::label Foam::pointFieldReconstructor::reconstructFields
Foam::label Foam::pointFieldReconstructor::reconstructPointFields
(
const IOobjectList& objects,
const wordRes& selectedFields
@ -179,34 +207,14 @@ Foam::label Foam::pointFieldReconstructor::reconstructFields
{
typedef GeometricField<Type, pointPatchField, pointMesh> fieldType;
const wordList fieldNames =
return reconstructPointFields<Type>
(
selectedFields.empty()
? objects.sortedNames<fieldType>()
: objects.sortedNames<fieldType>(selectedFields)
(
selectedFields.empty()
? objects.sorted<fieldType>()
: objects.sorted<fieldType>(selectedFields)
)
);
return reconstructFields<Type>(objects, fieldNames);
}
template<class Type>
Foam::label Foam::pointFieldReconstructor::reconstructFields
(
const IOobjectList& objects,
const wordHashSet& selectedFields
)
{
typedef GeometricField<Type, pointPatchField, pointMesh> fieldType;
const wordList fieldNames =
(
selectedFields.empty()
? objects.sortedNames<fieldType>()
: objects.sortedNames<fieldType>(selectedFields)
);
return reconstructFields<Type>(objects, fieldNames);
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2016 OpenCFD Ltd.
Copyright (C) 2016-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -28,8 +28,9 @@ License
#include "processorMeshes.H"
#include "Time.H"
#include "IndirectList.H"
#include "primitiveMesh.H"
#include "topoSet.H"
#include "OSspecific.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -70,73 +71,33 @@ void Foam::processorMeshes::read()
)
);
pointProcAddressing_.set
// Read the addressing information
IOobject ioAddr
(
proci,
new labelIOList
(
IOobject
(
"pointProcAddressing",
meshes_[proci].facesInstance(),
meshes_[proci].meshSubDir,
meshes_[proci],
IOobject::MUST_READ,
IOobject::NO_WRITE
)
)
"procAddressing",
meshes_[proci].facesInstance(),
polyMesh::meshSubDir,
meshes_[proci].thisDb(),
IOobject::MUST_READ,
IOobject::NO_WRITE
);
faceProcAddressing_.set
(
proci,
new labelIOList
(
IOobject
(
"faceProcAddressing",
meshes_[proci].facesInstance(),
meshes_[proci].meshSubDir,
meshes_[proci],
IOobject::MUST_READ,
IOobject::NO_WRITE
)
)
);
// pointProcAddressing (polyMesh)
ioAddr.rename("pointProcAddressing");
pointProcAddressing_.set(proci, new labelIOList(ioAddr));
cellProcAddressing_.set
(
proci,
new labelIOList
(
IOobject
(
"cellProcAddressing",
meshes_[proci].facesInstance(),
meshes_[proci].meshSubDir,
meshes_[proci],
IOobject::MUST_READ,
IOobject::NO_WRITE
)
)
);
// faceProcAddressing (polyMesh)
ioAddr.rename("faceProcAddressing");
faceProcAddressing_.set(proci, new labelIOList(ioAddr));
boundaryProcAddressing_.set
(
proci,
new labelIOList
(
IOobject
(
"boundaryProcAddressing",
meshes_[proci].facesInstance(),
meshes_[proci].meshSubDir,
meshes_[proci],
IOobject::MUST_READ,
IOobject::NO_WRITE
)
)
);
// cellProcAddressing (polyMesh)
ioAddr.rename("cellProcAddressing");
cellProcAddressing_.set(proci, new labelIOList(ioAddr));
// boundaryProcAddressing (polyMesh)
ioAddr.rename("boundaryProcAddressing");
boundaryProcAddressing_.set(proci, new labelIOList(ioAddr));
}
}
@ -163,17 +124,17 @@ Foam::processorMeshes::processorMeshes
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::fvMesh::readUpdateState Foam::processorMeshes::readUpdate()
Foam::polyMesh::readUpdateState Foam::processorMeshes::readUpdate()
{
fvMesh::readUpdateState stat = fvMesh::UNCHANGED;
polyMesh::readUpdateState stat = polyMesh::UNCHANGED;
forAll(databases_, proci)
{
// Check if any new meshes need to be read.
fvMesh::readUpdateState procStat = meshes_[proci].readUpdate();
polyMesh::readUpdateState procStat = meshes_[proci].readUpdate();
/*
if (procStat != fvMesh::UNCHANGED)
if (procStat != polyMesh::UNCHANGED)
{
Info<< "Processor " << proci
<< " at time " << databases_[proci].timeName()
@ -183,7 +144,7 @@ Foam::fvMesh::readUpdateState Foam::processorMeshes::readUpdate()
*/
// Combine into overall mesh change status
if (stat == fvMesh::UNCHANGED)
if (stat == polyMesh::UNCHANGED)
{
stat = procStat;
}
@ -203,8 +164,8 @@ Foam::fvMesh::readUpdateState Foam::processorMeshes::readUpdate()
if
(
stat == fvMesh::TOPO_CHANGE
|| stat == fvMesh::TOPO_PATCH_CHANGE
stat == polyMesh::TOPO_CHANGE
|| stat == polyMesh::TOPO_PATCH_CHANGE
)
{
// Reread all meshes and addressing
@ -231,7 +192,7 @@ void Foam::processorMeshes::reconstructPoints(fvMesh& mesh)
"points",
meshes_[proci].time().timeName(),
polyMesh::meshSubDir,
meshes_[proci],
meshes_[proci].thisDb(),
IOobject::MUST_READ,
IOobject::NO_WRITE,
false
@ -247,23 +208,19 @@ void Foam::processorMeshes::reconstructPoints(fvMesh& mesh)
{
const vectorField& procPoints = procsPoints[proci];
// Set the cell values in the reconstructed field
const labelList& pointProcAddr = pointProcAddressing_[proci];
const labelList& pointProcAddressingI = pointProcAddressing_[proci];
if (pointProcAddressingI.size() != procPoints.size())
if (pointProcAddr.size() != procPoints.size())
{
FatalErrorInFunction
<< "problem :"
<< " pointProcAddressingI:" << pointProcAddressingI.size()
<< " pointProcAddr:" << pointProcAddr.size()
<< " procPoints:" << procPoints.size()
<< abort(FatalError);
}
forAll(pointProcAddressingI, pointi)
{
newPoints[pointProcAddressingI[pointi]] = procPoints[pointi];
}
UIndirectList<point>(newPoints, pointProcAddr) = procPoints;
// or: newPoints.rmap(procPoints, pointProcAddr)
}
mesh.movePoints(newPoints);
@ -273,59 +230,35 @@ void Foam::processorMeshes::reconstructPoints(fvMesh& mesh)
void Foam::processorMeshes::removeFiles(const polyMesh& mesh)
{
fileName pointPath
IOobject ioAddr
(
IOobject
(
"pointProcAddressing",
mesh.facesInstance(),
mesh.meshSubDir,
mesh
).objectPath()
"procAddressing",
mesh.facesInstance(),
polyMesh::meshSubDir,
mesh.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE,
false // not registered
);
if (topoSet::debug) DebugVar(pointPath);
rm(pointPath);
rm
(
IOobject
(
"faceProcAddressing",
mesh.facesInstance(),
mesh.meshSubDir,
mesh
).objectPath()
);
rm
(
IOobject
(
"cellProcAddressing",
mesh.facesInstance(),
mesh.meshSubDir,
mesh
).objectPath()
);
rm
(
IOobject
(
"boundaryProcAddressing",
mesh.facesInstance(),
mesh.meshSubDir,
mesh
).objectPath()
);
rm
(
IOobject
(
"procAddressing",
mesh.facesInstance(),
mesh.meshSubDir,
mesh
).objectPath()
);
// procAddressing
rm(ioAddr.objectPath());
// pointProcAddressing
ioAddr.rename("pointProcAddressing");
rm(ioAddr.objectPath());
// faceProcAddressing
ioAddr.rename("faceProcAddressing");
rm(ioAddr.objectPath());
// cellProcAddressing
ioAddr.rename("cellProcAddressing");
rm(ioAddr.objectPath());
// boundaryProcAddressing
ioAddr.rename("boundaryProcAddressing");
rm(ioAddr.objectPath());
}

View File

@ -35,8 +35,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef processorMeshes_H
#define processorMeshes_H
#ifndef Foam_processorMeshes_H
#define Foam_processorMeshes_H
#include "PtrList.H"
#include "fvMesh.H"
@ -54,7 +54,7 @@ namespace Foam
class processorMeshes
{
// Private data
// Private Data
const word meshName_;
@ -104,41 +104,42 @@ public:
// Member Functions
//- Update the meshes based on the mesh files saved in time directories
fvMesh::readUpdateState readUpdate();
polyMesh::readUpdateState readUpdate();
//- Reconstruct point position after motion in parallel
void reconstructPoints(fvMesh&);
const PtrList<fvMesh>& meshes() const
const PtrList<fvMesh>& meshes() const noexcept
{
return meshes_;
}
PtrList<fvMesh>& meshes()
PtrList<fvMesh>& meshes() noexcept
{
return meshes_;
}
const PtrList<labelIOList>& pointProcAddressing() const
const PtrList<labelIOList>& pointProcAddressing() const noexcept
{
return pointProcAddressing_;
}
PtrList<labelIOList>& faceProcAddressing()
PtrList<labelIOList>& faceProcAddressing() noexcept
{
return faceProcAddressing_;
}
const PtrList<labelIOList>& cellProcAddressing() const
const PtrList<labelIOList>& cellProcAddressing() const noexcept
{
return cellProcAddressing_;
}
const PtrList<labelIOList>& boundaryProcAddressing() const
const PtrList<labelIOList>& boundaryProcAddressing() const noexcept
{
return boundaryProcAddressing_;
}
//- Helper: remove all procAddressing files from mesh instance
static void removeFiles(const polyMesh& mesh);
};

View File

@ -22,7 +22,7 @@ referenceLevel 0;
boundaryField
{
fontAndBack
frontAndBack
{
type empty;
}

View File

@ -18,7 +18,8 @@ solvers
{
Cs
{
solver PBiCG;
//solver PBiCG;
solver PBiCGStab;
preconditioner DILU;
minIter 0;
maxIter 2000;