ENH: parallel: overhaul of parallel mapping

- redistributePar to have almost (complete) functionality of decomposePar+reconstructPar
- low-level distributed Field mapping
- support for mapping surfaceFields (including flipping faces)
- support for decomposing/reconstructing refinement data
This commit is contained in:
mattijs
2015-11-17 15:05:05 +00:00
parent 09dec5263b
commit 916dcb8685
205 changed files with 21665 additions and 4196 deletions

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -202,6 +202,7 @@ void subsetSurfaceFields
(
const fvMesh& mesh,
const fvMesh& subMesh,
const labelList& cellMap,
const labelList& faceMap,
const labelHashSet& addedPatches
)
@ -225,6 +226,7 @@ void subsetSurfaceFields
fld,
subMesh,
patchMap,
cellMap,
faceMap
)
);
@ -830,6 +832,7 @@ void createAndWriteRegion
(
mesh,
newMesh(),
map().cellMap(),
map().faceMap(),
addedPatches
);
@ -837,6 +840,7 @@ void createAndWriteRegion
(
mesh,
newMesh(),
map().cellMap(),
map().faceMap(),
addedPatches
);
@ -844,6 +848,7 @@ void createAndWriteRegion
(
mesh,
newMesh(),
map().cellMap(),
map().faceMap(),
addedPatches
);
@ -851,6 +856,7 @@ void createAndWriteRegion
(
mesh,
newMesh(),
map().cellMap(),
map().faceMap(),
addedPatches
);
@ -858,6 +864,7 @@ void createAndWriteRegion
(
mesh,
newMesh(),
map().cellMap(),
map().faceMap(),
addedPatches
);

View File

@ -2,6 +2,7 @@ EXE_INC = \
-I$(LIB_SRC)/parallel/decompose/decompose/lnInclude \
-I$(LIB_SRC)/parallel/decompose/decompositionMethods/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/regionModels/regionModel/lnInclude
@ -12,5 +13,6 @@ EXE_LIBS = \
-lgenericPatchFields \
-ldecompositionMethods -L$(FOAM_LIBBIN)/dummy -lmetisDecomp -lscotchDecomp \
-llagrangian \
-ldynamicMesh \
-lmeshTools \
-lregionModels

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -96,6 +96,7 @@ Usage
#include "fvFieldDecomposer.H"
#include "pointFieldDecomposer.H"
#include "lagrangianFieldDecomposer.H"
#include "decompositionModel.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -142,6 +143,12 @@ int main(int argc, char *argv[])
);
argList::noParallel();
Foam::argList::addOption
(
"decomposeParDict",
"file",
"read decomposePar dictionary from specified location"
);
#include "addRegionOption.H"
argList::addBoolOption
(
@ -199,6 +206,17 @@ int main(int argc, char *argv[])
instantList times = timeSelector::selectIfPresent(runTime, args);
// Allow override of decomposeParDict location
fileName decompDictFile;
if (args.optionReadIfPresent("decomposeParDict", decompDictFile))
{
if (isDir(decompDictFile))
{
decompDictFile = decompDictFile/"decomposeParDict";
}
}
wordList regionNames;
wordList regionDirs;
if (allRegions)
@ -260,21 +278,27 @@ int main(int argc, char *argv[])
++nProcs;
}
// get requested numberOfSubdomains
// get requested numberOfSubdomains. Note: have no mesh yet so
// cannot use decompositionModel::New
const label nDomains = readLabel
(
IOdictionary
(
IOobject
decompositionModel::selectIO
(
"decomposeParDict",
runTime.time().system(),
regionDir, // use region if non-standard
runTime,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE,
false
IOobject
(
"decomposeParDict",
runTime.time().system(),
regionDir, // use region if non-standard
runTime,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE,
false
),
decompDictFile
)
).lookup("numberOfSubdomains")
);
@ -288,8 +312,7 @@ int main(int argc, char *argv[])
<< nProcs << " domains"
<< nl
<< "instead of " << nDomains
<< " domains as specified in decomposeParDict"
<< nl
<< " domains as specified in decomposeParDict" << nl
<< exit(FatalError);
}
}
@ -351,7 +374,8 @@ int main(int argc, char *argv[])
IOobject::NO_READ,
IOobject::NO_WRITE,
false
)
),
decompDictFile
);
// Decompose the mesh
@ -447,15 +471,15 @@ int main(int argc, char *argv[])
// Construct the vol fields
// ~~~~~~~~~~~~~~~~~~~~~~~~
PtrList<volScalarField> volScalarFields;
readFields(mesh, objects, volScalarFields);
readFields(mesh, objects, volScalarFields, false);
PtrList<volVectorField> volVectorFields;
readFields(mesh, objects, volVectorFields);
readFields(mesh, objects, volVectorFields, false);
PtrList<volSphericalTensorField> volSphericalTensorFields;
readFields(mesh, objects, volSphericalTensorFields);
readFields(mesh, objects, volSphericalTensorFields, false);
PtrList<volSymmTensorField> volSymmTensorFields;
readFields(mesh, objects, volSymmTensorFields);
readFields(mesh, objects, volSymmTensorFields, false);
PtrList<volTensorField> volTensorFields;
readFields(mesh, objects, volTensorFields);
readFields(mesh, objects, volTensorFields, false);
// Construct the dimensioned fields
@ -476,15 +500,15 @@ int main(int argc, char *argv[])
// Construct the surface fields
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PtrList<surfaceScalarField> surfaceScalarFields;
readFields(mesh, objects, surfaceScalarFields);
readFields(mesh, objects, surfaceScalarFields, false);
PtrList<surfaceVectorField> surfaceVectorFields;
readFields(mesh, objects, surfaceVectorFields);
readFields(mesh, objects, surfaceVectorFields, false);
PtrList<surfaceSphericalTensorField> surfaceSphericalTensorFields;
readFields(mesh, objects, surfaceSphericalTensorFields);
readFields(mesh, objects, surfaceSphericalTensorFields, false);
PtrList<surfaceSymmTensorField> surfaceSymmTensorFields;
readFields(mesh, objects, surfaceSymmTensorFields);
readFields(mesh, objects, surfaceSymmTensorFields, false);
PtrList<surfaceTensorField> surfaceTensorFields;
readFields(mesh, objects, surfaceTensorFields);
readFields(mesh, objects, surfaceTensorFields, false);
// Construct the point fields
@ -492,15 +516,15 @@ int main(int argc, char *argv[])
const pointMesh& pMesh = pointMesh::New(mesh);
PtrList<pointScalarField> pointScalarFields;
readFields(pMesh, objects, pointScalarFields);
readFields(pMesh, objects, pointScalarFields, false);
PtrList<pointVectorField> pointVectorFields;
readFields(pMesh, objects, pointVectorFields);
readFields(pMesh, objects, pointVectorFields, false);
PtrList<pointSphericalTensorField> pointSphericalTensorFields;
readFields(pMesh, objects, pointSphericalTensorFields);
readFields(pMesh, objects, pointSphericalTensorFields, false);
PtrList<pointSymmTensorField> pointSymmTensorFields;
readFields(pMesh, objects, pointSymmTensorFields);
readFields(pMesh, objects, pointSymmTensorFields, false);
PtrList<pointTensorField> pointTensorFields;
readFields(pMesh, objects, pointTensorFields);
readFields(pMesh, objects, pointTensorFields, false);
// Construct the Lagrangian fields
@ -820,16 +844,6 @@ int main(int argc, char *argv[])
processorDb.setTime(runTime);
// remove files remnants that can cause horrible problems
// - mut and nut are used to mark the new turbulence models,
// their existence prevents old models from being upgraded
{
fileName timeDir(processorDb.path()/processorDb.timeName());
rm(timeDir/"mut");
rm(timeDir/"nut");
}
// read the mesh
if (!procMeshList.set(procI))
{

View File

@ -17,11 +17,61 @@ FoamFile
numberOfSubdomains 2;
// Optional decomposition constraints
//constraints
//{
// preserveBaffles
// {
// //- Keep owner and neighbour of baffles on same processor (i.e.
// // keep it detectable as a baffle). Baffles are two boundary face
// // sharing the same points
// type preserveBaffles;
// }
// preserveFaceZones
// {
// //- Keep owner and neighbour on same processor for faces in zones
// type preserveFaceZones;
// zones (".*");
// }
// preservePatches
// {
// //- Keep owner and neighbour on same processor for faces in patches
// // (only makes sense for cyclic patches. Not suitable for e.g.
// // cyclicAMI since these are not coupled on the patch level. Use
// // singleProcessorFaceSets for those)
// type preservePatches;
// patches (".*");
// }
// singleProcessorFaceSets
// {
// //- Keep all of faceSet on a single processor. This puts all cells
// // connected with a point, edge or face on the same processor.
// // (just having face connected cells might not guarantee a balanced
// // decomposition)
// // The processor can be -1 (the decompositionMethod chooses the
// // processor for a good load balance) or explicitly provided (upsets
// // balance)
// type singleProcessorFaceSets;
// singleProcessorFaceSets ((f1 -1));
// }
// refinementHistory
// {
// //- Decompose cells such that all cell originating from single cell
// // end up on same processor
// type refinementHistory;
// }
//}
// Deprecated form of specifying decomposition constraints:
//- Keep owner and neighbour on same processor for faces in zones:
// preserveFaceZones (heater solid1 solid3);
//- Keep owner and neighbour on same processor for faces in patches:
// (makes sense only for cyclic patches)
// (makes sense only for cyclic patches. Not suitable for e.g. cyclicAMI
// since these are not coupled on the patch level. Use
// singleProcessorFaceSets for those)
//preservePatches (cyclic_half0 cyclic_half1);
//- Keep all of faceSet on a single processor. This puts all cells
@ -32,12 +82,13 @@ numberOfSubdomains 2;
// for a good load balance) or explicitly provided (upsets balance).
//singleProcessorFaceSets ((f0 -1));
//- Keep owner and neighbour of baffles on same processor (i.e. keep it
// detectable as a baffle). Baffles are two boundary face sharing the
// same points.
//preserveBaffles true;
//- Use the volScalarField named here as a weight for each cell in the
// decomposition. For example, use a particle population field to decompose
// for a balanced number of particles in a lagrangian simulation.

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -31,14 +31,14 @@ License
#include "fvMesh.H"
#include "OSspecific.H"
#include "Map.H"
#include "globalMeshData.H"
#include "DynamicList.H"
#include "fvFieldDecomposer.H"
#include "IOobjectList.H"
#include "cellSet.H"
#include "faceSet.H"
#include "pointSet.H"
#include "uniformDimensionedFields.H"
#include "decompositionModel.H"
#include "hexRef8Data.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@ -69,7 +69,12 @@ void Foam::domainDecomposition::mark
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::domainDecomposition::domainDecomposition(const IOobject& io)
// from components
Foam::domainDecomposition::domainDecomposition
(
const IOobject& io,
const fileName& decompDictFile
)
:
fvMesh(io),
facesInstancePointsPtr_
@ -90,18 +95,18 @@ Foam::domainDecomposition::domainDecomposition(const IOobject& io)
)
: NULL
),
decompositionDict_
decompDictFile_(decompDictFile),
nProcs_
(
IOobject
readInt
(
"decomposeParDict",
time().system(),
*this,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE
decompositionModel::New
(
*this,
decompDictFile
).lookup("numberOfSubdomains")
)
),
nProcs_(readInt(decompositionDict_.lookup("numberOfSubdomains"))),
distributed_(false),
cellToProc_(nCells()),
procPointAddressing_(nProcs_),
@ -115,7 +120,11 @@ Foam::domainDecomposition::domainDecomposition(const IOobject& io)
procProcessorPatchSubPatchIDs_(nProcs_),
procProcessorPatchSubPatchStarts_(nProcs_)
{
decompositionDict_.readIfPresent("distributed", distributed_);
decompositionModel::New
(
*this,
decompDictFile
).readIfPresent("distributed", distributed_);
}
@ -195,57 +204,20 @@ bool Foam::domainDecomposition::writeDecomposition(const bool decomposeSets)
}
autoPtr<labelIOList> cellLevelPtr;
{
IOobject io
// Load refinement data (if any)
hexRef8Data baseMeshData
(
IOobject
(
"cellLevel",
"dummy",
facesInstance(),
polyMesh::meshSubDir,
*this,
IOobject::MUST_READ,
IOobject::NO_WRITE
);
if (io.headerOk())
{
Info<< "Reading hexRef8 data : " << io.name() << endl;
cellLevelPtr.reset(new labelIOList(io));
}
}
autoPtr<labelIOList> pointLevelPtr;
{
IOobject io
(
"pointLevel",
facesInstance(),
polyMesh::meshSubDir,
*this,
IOobject::MUST_READ,
IOobject::NO_WRITE
);
if (io.headerOk())
{
Info<< "Reading hexRef8 data : " << io.name() << endl;
pointLevelPtr.reset(new labelIOList(io));
}
}
autoPtr<uniformDimensionedScalarField> level0EdgePtr;
{
IOobject io
(
"level0Edge",
facesInstance(),
polyMesh::meshSubDir,
*this,
IOobject::MUST_READ,
IOobject::NO_WRITE
);
if (io.headerOk())
{
Info<< "Reading hexRef8 data : " << io.name() << endl;
level0EdgePtr.reset(new uniformDimensionedScalarField(io));
}
}
IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE,
false
)
);
@ -816,8 +788,8 @@ bool Foam::domainDecomposition::writeDecomposition(const bool decomposeSets)
}
}
// Set the precision of the points data to 10
IOstream::defaultPrecision(10);
// Set the precision of the points data to be min 10
IOstream::defaultPrecision(max(10u, IOstream::defaultPrecision()));
procMesh.write();
@ -887,64 +859,23 @@ bool Foam::domainDecomposition::writeDecomposition(const bool decomposeSets)
}
// hexRef8 data
if (cellLevelPtr.valid())
{
labelIOList
// Optional hexRef8 data
hexRef8Data
(
IOobject
(
IOobject
(
cellLevelPtr().name(),
facesInstance(),
polyMesh::meshSubDir,
procMesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
UIndirectList<label>
(
cellLevelPtr(),
procCellAddressing_[procI]
)()
).write();
}
if (pointLevelPtr.valid())
{
labelIOList
(
IOobject
(
pointLevelPtr().name(),
facesInstance(),
polyMesh::meshSubDir,
procMesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
UIndirectList<label>
(
pointLevelPtr(),
procPointAddressing_[procI]
)()
).write();
}
if (level0EdgePtr.valid())
{
uniformDimensionedScalarField
(
IOobject
(
level0EdgePtr().name(),
facesInstance(),
polyMesh::meshSubDir,
procMesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
level0EdgePtr()
).write();
}
"dummy",
facesInstance(),
polyMesh::meshSubDir,
procMesh,
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
baseMeshData,
procCellAddressing_[procI],
procPointAddressing_[procI]
).write();
// Statistics

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -61,8 +61,8 @@ class domainDecomposition
//- Optional: points at the facesInstance
autoPtr<pointIOField> facesInstancePointsPtr_;
//- Mesh decomposition control dictionary
IOdictionary decompositionDict_;
//- Optional non-standard file for decomposeParDict
const fileName decompDictFile_;
//- Number of processors in decomposition
label nProcs_;
@ -159,8 +159,13 @@ public:
// Constructors
//- Construct from IOobject
domainDecomposition(const IOobject& io);
//- Construct from IOobjects (for mesh and optional non-standard
// decomposeParDict location)
domainDecomposition
(
const IOobject& io,
const fileName& decompDictFile = ""
);
//- Destructor

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -30,6 +30,7 @@ License
#include "regionSplit.H"
#include "Tuple2.H"
#include "faceSet.H"
#include "decompositionModel.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -39,15 +40,17 @@ void Foam::domainDecomposition::distributeCells()
cpuTime decompositionTime;
autoPtr<decompositionMethod> decomposePtr = decompositionMethod::New
const decompositionModel& method = decompositionModel::New
(
decompositionDict_
*this,
decompDictFile_
);
scalarField cellWeights;
if (decompositionDict_.found("weightField"))
if (method.found("weightField"))
{
word weightName = decompositionDict_.lookup("weightField");
word weightName = method.lookup("weightField");
volScalarField weights
(
@ -64,7 +67,7 @@ void Foam::domainDecomposition::distributeCells()
cellWeights = weights.internalField();
}
cellToProc_ = decomposePtr().decompose(*this, cellWeights);
cellToProc_ = method.decomposer().decompose(*this, cellWeights);
Info<< "\nFinished decomposition in "
<< decompositionTime.elapsedCpuTime()

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -23,10 +23,48 @@ License
\*---------------------------------------------------------------------------*/
#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 GeomField
IOobjectList fieldObjects(objects.lookupClass(GeoField::typeName));
// Remove the cellDist field
IOobjectList::iterator celDistIter = fieldObjects.find("cellDist");
if (celDistIter != fieldObjects.end())
{
fieldObjects.erase(celDistIter);
}
// Get sorted set of names (different processors might read objects in
// different order)
const wordList masterNames(fieldObjects.sortedNames());
// Construct the fields
fields.setSize(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
(
@ -38,24 +76,21 @@ void Foam::readFields
// Search list of objects for fields of type GeomField
IOobjectList fieldObjects(objects.lookupClass(GeoField::typeName));
// Remove the cellDist field
IOobjectList::iterator celDistIter = fieldObjects.find("cellDist");
if (celDistIter != fieldObjects.end())
{
fieldObjects.erase(celDistIter);
}
// Construct the fields
fields.setSize(fieldObjects.size());
label fieldI = 0;
forAllIter(IOobjectList, fieldObjects, iter)
// Get sorted set of names (different processors might read objects in
// different order)
const wordList masterNames(fieldObjects.sortedNames());
// Construct the fields
fields.setSize(masterNames.size());
forAll(masterNames, i)
{
fields.set
(
fieldI++,
new GeoField(*iter(), mesh)
);
const IOobject& io = *fieldObjects[masterNames[i]];
fields.set(i, new GeoField(io, mesh));
}
}

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -41,6 +41,16 @@ SourceFiles
namespace Foam
{
// 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
);
// Read the fields and hold on the pointer list
template<class Mesh, class GeoField>
void readFields

View File

@ -1,6 +1,7 @@
EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/parallel/reconstruct/reconstruct/lnInclude \
-I$(LIB_SRC)/regionModels/regionModel/lnInclude
@ -9,6 +10,7 @@ EXE_LIBS = \
-lfiniteVolume \
-lgenericPatchFields \
-llagrangian \
-ldynamicMesh \
-lmeshTools \
-lreconstruct \
-lregionModels

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -45,6 +45,8 @@ Description
#include "faceSet.H"
#include "pointSet.H"
#include "hexRef8Data.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
bool haveAllTimes
@ -865,6 +867,78 @@ int main(int argc, char *argv[])
pointSets[i].write();
}
}
// Reconstruct refinement data
{
PtrList<hexRef8Data> procData(procMeshes.meshes().size());
forAll(procMeshes.meshes(), procI)
{
const fvMesh& procMesh = procMeshes.meshes()[procI];
procData.set
(
procI,
new hexRef8Data
(
IOobject
(
"dummy",
procMesh.time().timeName(),
polyMesh::meshSubDir,
procMesh,
IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE,
false
)
)
);
}
// Combine individual parts
const PtrList<labelIOList>& cellAddr =
procMeshes.cellProcAddressing();
UPtrList<const labelList> cellMaps(cellAddr.size());
forAll(cellAddr, i)
{
cellMaps.set(i, &cellAddr[i]);
}
const PtrList<labelIOList>& pointAddr =
procMeshes.pointProcAddressing();
UPtrList<const labelList> pointMaps(pointAddr.size());
forAll(pointAddr, i)
{
pointMaps.set(i, &pointAddr[i]);
}
UPtrList<const hexRef8Data> procRefs(procData.size());
forAll(procData, i)
{
procRefs.set(i, &procData[i]);
}
hexRef8Data
(
IOobject
(
"dummy",
mesh.time().timeName(),
polyMesh::meshSubDir,
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
cellMaps,
pointMaps,
procRefs
).write();
}
}
}
@ -882,7 +956,7 @@ int main(int argc, char *argv[])
}
}
Info<< "End.\n" << endl;
Info<< "\nEnd\n" << endl;
return 0;
}

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -899,7 +899,7 @@ int main(int argc, char *argv[])
}
Info<< "End.\n" << endl;
Info<< "\nEnd\n" << endl;
return 0;
}

View File

@ -1,3 +1,5 @@
parLagrangianRedistributor.C
parFvFieldReconstructor.C
loadOrCreateMesh.C
redistributePar.C

View File

@ -1,13 +1,17 @@
EXE_INC = \
-I$(LIB_SRC)/parallel/decompose/decompositionMethods/lnInclude \
-I$(LIB_SRC)/parallel/decompose/decompose/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude
EXE_LIBS = \
-lfiniteVolume \
-lgenericPatchFields \
-ldecompositionMethods \
-L$(FOAM_LIBBIN)/dummy -lptscotchDecomp \
-L$(FOAM_LIBBIN)/dummy -lptscotchDecomp -lscotchDecomp \
-ldecompose \
-lmeshTools \
-llagrangian \
-ldynamicMesh

View File

@ -0,0 +1,131 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 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::distributedUnallocatedDirectFieldMapper
Description
FieldMapper with direct mapping from remote quantities.
\*---------------------------------------------------------------------------*/
#ifndef distributedUnallocatedDirectFieldMapper_H
#define distributedUnallocatedDirectFieldMapper_H
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class distributedUnallocatedDirectFieldMapper Declaration
\*---------------------------------------------------------------------------*/
class distributedUnallocatedDirectFieldMapper
:
public FieldMapper
{
const labelUList& directAddressing_;
const mapDistributeBase& distMap_;
bool hasUnmapped_;
public:
// Constructors
//- Construct given addressing
distributedUnallocatedDirectFieldMapper
(
const labelUList& directAddressing,
const mapDistributeBase& distMap
)
:
directAddressing_(directAddressing),
distMap_(distMap),
hasUnmapped_(false)
{
if
(
notNull(directAddressing_)
&& directAddressing_.size()
&& min(directAddressing_) < 0
)
{
hasUnmapped_ = true;
}
}
//- Destructor
virtual ~distributedUnallocatedDirectFieldMapper()
{}
// Member Functions
virtual label size() const
{
return
(
notNull(directAddressing_)
? directAddressing_.size()
: distMap_.constructSize()
);
}
virtual bool direct() const
{
return true;
}
virtual bool distributed() const
{
return true;
}
virtual const mapDistributeBase& distributeMap() const
{
return distMap_;
}
virtual bool hasUnmapped() const
{
return hasUnmapped_;
}
virtual const labelUList& directAddressing() const
{
return directAddressing_;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,133 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 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::distributedUnallocatedDirectFvPatchFieldMapper
Description
FieldMapper with direct mapping from remote quantities.
\*---------------------------------------------------------------------------*/
#ifndef distributedUnallocatedDirectFvPatchFieldMapper_H
#define distributedUnallocatedDirectFvPatchFieldMapper_H
#include "fvPatchFieldMapper.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class distributedUnallocatedDirectFvPatchFieldMapper Declaration
\*---------------------------------------------------------------------------*/
class distributedUnallocatedDirectFvPatchFieldMapper
:
public fvPatchFieldMapper
{
const labelUList& directAddressing_;
const mapDistributeBase& distMap_;
bool hasUnmapped_;
public:
// Constructors
//- Construct given addressing
distributedUnallocatedDirectFvPatchFieldMapper
(
const labelUList& directAddressing,
const mapDistributeBase& distMap
)
:
directAddressing_(directAddressing),
distMap_(distMap),
hasUnmapped_(false)
{
if
(
notNull(directAddressing_)
&& directAddressing_.size()
&& min(directAddressing_) < 0
)
{
hasUnmapped_ = true;
}
}
//- Destructor
virtual ~distributedUnallocatedDirectFvPatchFieldMapper()
{}
// Member Functions
virtual label size() const
{
return
(
notNull(directAddressing_)
? directAddressing_.size()
: distMap_.constructSize()
);
}
virtual bool direct() const
{
return true;
}
virtual bool distributed() const
{
return true;
}
virtual const mapDistributeBase& distributeMap() const
{
return distMap_;
}
virtual bool hasUnmapped() const
{
return hasUnmapped_;
}
virtual const labelUList& directAddressing() const
{
return directAddressing_;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2012-2014 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,14 +27,15 @@ License
#include "processorPolyPatch.H"
#include "processorCyclicPolyPatch.H"
#include "Time.H"
#include "IOPtrList.H"
//#include "IOPtrList.H"
#include "polyBoundaryMeshEntries.H"
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
namespace Foam
{
defineTemplateTypeNameAndDebug(IOPtrList<entry>, 0);
}
//namespace Foam
//{
// defineTemplateTypeNameAndDebug(IOPtrList<entry>, 0);
//}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -46,6 +47,9 @@ Foam::autoPtr<Foam::fvMesh> Foam::loadOrCreateMesh
const IOobject& io
)
{
// Region name
// ~~~~~~~~~~~
fileName meshSubDir;
if (io.name() == polyMesh::defaultRegion)
@ -58,24 +62,52 @@ Foam::autoPtr<Foam::fvMesh> Foam::loadOrCreateMesh
}
// Scatter master patches
// Patch types
// ~~~~~~~~~~~
// Read and scatter master patches (without reading master mesh!)
PtrList<entry> patchEntries;
if (Pstream::master())
{
// Read PtrList of dictionary as dictionary.
const word oldTypeName = IOPtrList<entry>::typeName;
const_cast<word&>(IOPtrList<entry>::typeName) = word::null;
IOPtrList<entry> dictList
//// Read PtrList of dictionary as dictionary.
//const word oldTypeName = IOPtrList<entry>::typeName;
//const_cast<word&>(IOPtrList<entry>::typeName) = word::null;
//IOPtrList<entry> dictList
//(
// IOobject
// (
// "boundary",
// io.time().findInstance
// (
// meshSubDir,
// "boundary",
// IOobject::MUST_READ
// ),
// meshSubDir,
// io.db(),
// IOobject::MUST_READ,
// IOobject::NO_WRITE,
// false
// )
//);
//const_cast<word&>(IOPtrList<entry>::typeName) = oldTypeName;
//// Fake type back to what was in field
//const_cast<word&>(dictList.type()) = dictList.headerClassName();
//
//patchEntries.transfer(dictList);
const fileName facesInstance = io.time().findInstance
(
meshSubDir,
"faces",
IOobject::MUST_READ
);
patchEntries = polyBoundaryMeshEntries
(
IOobject
(
"boundary",
io.time().findInstance
(
meshSubDir,
"boundary",
IOobject::MUST_READ
),
facesInstance,
meshSubDir,
io.db(),
IOobject::MUST_READ,
@ -83,11 +115,6 @@ Foam::autoPtr<Foam::fvMesh> Foam::loadOrCreateMesh
false
)
);
const_cast<word&>(IOPtrList<entry>::typeName) = oldTypeName;
// Fake type back to what was in field
const_cast<word&>(dictList.type()) = dictList.headerClassName();
patchEntries.transfer(dictList);
// Send patches
for
@ -110,8 +137,16 @@ Foam::autoPtr<Foam::fvMesh> Foam::loadOrCreateMesh
// Dummy meshes
// ~~~~~~~~~~~~
// Check who has a mesh
const bool haveMesh = isDir(io.time().path()/io.instance()/meshSubDir);
//const bool haveMesh = isDir(io.time().path()/io.instance()/meshSubDir);
const bool haveMesh = isFile
(
io.time().path()/io.instance()/meshSubDir/"faces"
);
if (!haveMesh)
{
@ -164,6 +199,7 @@ Foam::autoPtr<Foam::fvMesh> Foam::loadOrCreateMesh
patches.setSize(nPatches);
dummyMesh.addFvPatches(patches, false); // no parallel comms
// Add some dummy zones so upon reading it does not read them
// from the undecomposed case. Should be done as extra argument to
// regIOobject::readStream?
@ -202,6 +238,9 @@ Foam::autoPtr<Foam::fvMesh> Foam::loadOrCreateMesh
)
);
dummyMesh.addZones(pz, fz, cz);
dummyMesh.pointZones().clear();
dummyMesh.faceZones().clear();
dummyMesh.cellZones().clear();
//Pout<< "Writing dummy mesh to " << dummyMesh.polyMesh::objectPath()
// << endl;
dummyMesh.write();
@ -209,11 +248,19 @@ Foam::autoPtr<Foam::fvMesh> Foam::loadOrCreateMesh
Pstream::parRun() = oldParRun;
}
// Read mesh
// ~~~~~~~~~
// Now all processors have a (possibly zero size) mesh so read in
// parallel
//Pout<< "Reading mesh from " << io.objectPath() << endl;
autoPtr<fvMesh> meshPtr(new fvMesh(io));
fvMesh& mesh = meshPtr();
// Sync patches
// ~~~~~~~~~~~~
@ -327,17 +374,17 @@ Foam::autoPtr<Foam::fvMesh> Foam::loadOrCreateMesh
}
if (!haveMesh)
{
// We created a dummy mesh file above. Delete it.
const fileName meshFiles = io.time().path()/io.instance()/meshSubDir;
//Pout<< "Removing dummy mesh " << meshFiles << endl;
mesh.removeFiles();
rmDir(meshFiles);
}
// if (!haveMesh)
// {
// // We created a dummy mesh file above. Delete it.
// const fileName meshFiles = io.time().path()/io.instance()/meshSubDir;
// //Pout<< "Removing dummy mesh " << meshFiles << endl;
// mesh.removeFiles();
// rmDir(meshFiles);
// }
//
// Force recreation of globalMeshData.
mesh.clearOut();
// mesh.clearOut();
mesh.globalData();

View File

@ -0,0 +1,113 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 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 "parFvFieldReconstructor.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::parFvFieldReconstructor::createPatchFaceMaps()
{
const fvBoundaryMesh& fvb = procMesh_.boundary();
patchFaceMaps_.setSize(fvb.size());
forAll(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;
}
// Copy face map
patchFaceMaps_.set
(
patchI,
new mapDistributeBase(distMap_.faceMap())
);
// Compact out unused elements
labelList oldToNewSub;
labelList oldToNewConstruct;
patchFaceMaps_[patchI].compact
(
faceIsUsed,
procMesh_.nFaces(), // maximum index of subMap
oldToNewSub,
oldToNewConstruct,
UPstream::msgType()
);
//Pout<< "patchMap:" << patchFaceMaps_[patchI] << endl;
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::parFvFieldReconstructor::parFvFieldReconstructor
(
fvMesh& baseMesh,
const fvMesh& procMesh,
const mapDistributePolyMesh& distMap,
const bool isWriteProc
)
:
baseMesh_(baseMesh),
procMesh_(procMesh),
distMap_(distMap),
isWriteProc_(isWriteProc)
{
createPatchFaceMaps();
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::parFvFieldReconstructor::reconstructPoints()
{
// Reconstruct the points for moving mesh cases and write
// them out
distributedUnallocatedDirectFieldMapper mapper
(
labelUList::null(),
distMap_.pointMap()
);
pointField basePoints(procMesh_.points(), mapper);
baseMesh_.movePoints(basePoints);
if (Pstream::master())
{
baseMesh_.write();
}
}
// ************************************************************************* //

View File

@ -0,0 +1,194 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 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::parFvFieldReconstructor
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.
SourceFiles
parFvFieldReconstructor.C
parFvFieldReconstructorReconstructFields.C
\*---------------------------------------------------------------------------*/
#ifndef parFvFieldReconstructor_H
#define parFvFieldReconstructor_H
#include "PtrList.H"
#include "fvMesh.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
class mapDistributePolyMesh;
class mapDistributeBase;
class IOobjectList;
/*---------------------------------------------------------------------------*\
Class parFvFieldReconstructor Declaration
\*---------------------------------------------------------------------------*/
class parFvFieldReconstructor
{
// Private data
//- Reconstructed mesh reference
fvMesh& baseMesh_;
//- Processor mesh reference
const fvMesh& procMesh_;
//- Distribution map reference
const mapDistributePolyMesh& distMap_;
//- Do I need to to write (usually master only)
const bool isWriteProc_;
//- Patch mappers
PtrList<mapDistributeBase> patchFaceMaps_;
// Private Member Functions
//- Construct per-patch addressing
void createPatchFaceMaps();
//- Disallow default bitwise copy construct
parFvFieldReconstructor(const parFvFieldReconstructor&);
//- Disallow default bitwise assignment
void operator=(const parFvFieldReconstructor&);
public:
// Constructors
//- Construct from components
parFvFieldReconstructor
(
fvMesh& baseMesh,
const fvMesh& procMesh,
const mapDistributePolyMesh& distMap,
const bool isWriteProc
);
// Member Functions
//- Reconstruct volume internal field
template<class Type>
tmp<DimensionedField<Type, volMesh> >
reconstructFvVolumeInternalField
(
const DimensionedField<Type, volMesh>&
) const;
//- Read and reconstruct volume internal field
template<class Type>
tmp<DimensionedField<Type, volMesh> >
reconstructFvVolumeInternalField(const IOobject& fieldIoObject) const;
//- Reconstruct volume field
template<class Type>
tmp<GeometricField<Type, fvPatchField, volMesh> >
reconstructFvVolumeField
(
const GeometricField<Type, fvPatchField, volMesh>& fld
) const;
//- Read and reconstruct volume field
template<class Type>
tmp<GeometricField<Type, fvPatchField, volMesh> >
reconstructFvVolumeField(const IOobject& fieldIoObject) const;
//- Reconstruct surface field
template<class Type>
tmp<GeometricField<Type, fvsPatchField, surfaceMesh> >
reconstructFvSurfaceField
(
const GeometricField<Type, fvsPatchField, surfaceMesh>&
) const;
//- Read and reconstruct surface field
template<class Type>
tmp<GeometricField<Type, fvsPatchField, surfaceMesh> >
reconstructFvSurfaceField(const IOobject& fieldIoObject) const;
//- Read, reconstruct and write all/selected volume internal fields
template<class Type>
void reconstructFvVolumeInternalFields
(
const IOobjectList& objects,
const HashSet<word>& selectedFields
) const;
//- Read, reconstruct and write all/selected volume fields
template<class Type>
void reconstructFvVolumeFields
(
const IOobjectList& objects,
const HashSet<word>& selectedFields
) const;
//- Read, reconstruct and write all/selected surface fields
template<class Type>
void reconstructFvSurfaceFields
(
const IOobjectList& objects,
const HashSet<word>& selectedFields
) const;
//- Helper: reconstruct and write mesh points
// (note: should be moved to something like processorMeshes class)
void reconstructPoints();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "parFvFieldReconstructorReconstructFields.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,543 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 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 "parFvFieldReconstructor.H"
#include "Time.H"
#include "PtrList.H"
#include "fvPatchFields.H"
#include "emptyFvPatch.H"
#include "emptyFvPatchField.H"
#include "emptyFvsPatchField.H"
#include "IOobjectList.H"
#include "mapDistributePolyMesh.H"
#include "processorFvPatch.H"
#include "directFvPatchFieldMapper.H"
#include "distributedUnallocatedDirectFieldMapper.H"
#include "distributedUnallocatedDirectFvPatchFieldMapper.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
Foam::tmp<Foam::DimensionedField<Type, Foam::volMesh> >
Foam::parFvFieldReconstructor::reconstructFvVolumeInternalField
(
const DimensionedField<Type, volMesh>& fld
) const
{
distributedUnallocatedDirectFieldMapper 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
);
return tmp<DimensionedField<Type, volMesh> >
(
new DimensionedField<Type, volMesh>
(
baseIO,
baseMesh_,
fld.dimensions(),
internalField
)
);
}
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
(
const GeometricField<Type, fvPatchField, volMesh>& fld
) const
{
// Create the internalField by remote mapping
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
distributedUnallocatedDirectFieldMapper mapper
(
labelUList::null(),
distMap_.cellMap()
);
Field<Type> internalField(fld.internalField(), mapper);
// Create the patchFields by remote mapping
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Note: patchFields still on mesh, not baseMesh
PtrList<fvPatchField<Type> > patchFields(fld.mesh().boundary().size());
const typename GeometricField
<
Type,
fvPatchField,
volMesh
>::GeometricBoundaryField& bfld = fld.boundaryField();
forAll(bfld, patchI)
{
if (patchFaceMaps_.set(patchI))
{
// Clone local patch field
patchFields.set(patchI, bfld[patchI].clone());
distributedUnallocatedDirectFvPatchFieldMapper mapper
(
labelUList::null(),
patchFaceMaps_[patchI]
);
// Map into local copy
patchFields[patchI].autoMap(mapper);
}
}
PtrList<fvPatchField<Type> > basePatchFields
(
baseMesh_.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)
{
if (patchFields.set(patchI))
{
const fvPatch& basePatch = baseMesh_.boundary()[patchI];
const fvPatchField<Type>& pfld = patchFields[patchI];
labelList dummyMap(identity(pfld.size()));
directFvPatchFieldMapper dummyMapper(dummyMap);
basePatchFields.set
(
patchI,
fvPatchField<Type>::New
(
pfld,
basePatch,
DimensionedField<Type, volMesh>::null(),
dummyMapper
)
);
}
}
// Add some empty patches on remaining patches (tbd.probably processor
// patches)
forAll(basePatchFields, patchI)
{
if (patchI >= patchFields.size() || !patchFields.set(patchI))
{
basePatchFields.set
(
patchI,
fvPatchField<Type>::New
(
emptyFvPatchField<Type>::typeName,
baseMesh_.boundary()[patchI],
DimensionedField<Type, volMesh>::null()
)
);
}
}
// Construct a volField
IOobject baseIO
(
fld.name(),
baseMesh_.time().timeName(),
fld.local(),
baseMesh_,
IOobject::NO_READ,
IOobject::NO_WRITE
);
return tmp<GeometricField<Type, fvPatchField, volMesh> >
(
new GeometricField<Type, fvPatchField, volMesh>
(
baseIO,
baseMesh_,
fld.dimensions(),
internalField,
basePatchFields
)
);
}
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
(
const GeometricField<Type, fvsPatchField, surfaceMesh>& fld
) const
{
// Create the internalField by remote mapping
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
distributedUnallocatedDirectFieldMapper mapper
(
labelUList::null(),
distMap_.faceMap()
);
// Create flat field of internalField + all patch fields
Field<Type> flatFld(fld.mesh().nFaces(), pTraits<Type>::zero);
SubList<Type>(flatFld, fld.internalField().size()).assign
(
fld.internalField()
);
forAll(fld.boundaryField(), patchI)
{
const fvsPatchField<Type>& fvp = fld.boundaryField()[patchI];
SubList<Type>(flatFld, fvp.size(), fvp.patch().start()).assign(fvp);
}
// Map all faces
Field<Type> internalField(flatFld, mapper);
// Trim to internal faces (note: could also have special mapper)
internalField.setSize
(
min
(
internalField.size(),
baseMesh_.nInternalFaces()
)
);
// Create the patchFields by remote mapping
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Note: patchFields still on mesh, not baseMesh
PtrList<fvsPatchField<Type> > patchFields(fld.mesh().boundary().size());
const typename GeometricField
<
Type,
fvsPatchField,
surfaceMesh
>::GeometricBoundaryField& bfld = fld.boundaryField();
forAll(bfld, patchI)
{
if (patchFaceMaps_.set(patchI))
{
// Clone local patch field
patchFields.set(patchI, bfld[patchI].clone());
distributedUnallocatedDirectFvPatchFieldMapper mapper
(
labelUList::null(),
patchFaceMaps_[patchI]
);
// Map into local copy
patchFields[patchI].autoMap(mapper);
}
}
PtrList<fvsPatchField<Type> > basePatchFields
(
baseMesh_.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)
{
if (patchFields.set(patchI))
{
const fvPatch& basePatch = baseMesh_.boundary()[patchI];
const fvsPatchField<Type>& pfld = patchFields[patchI];
labelList dummyMap(identity(pfld.size()));
directFvPatchFieldMapper dummyMapper(dummyMap);
basePatchFields.set
(
patchI,
fvsPatchField<Type>::New
(
pfld,
basePatch,
DimensionedField<Type, surfaceMesh>::null(),
dummyMapper
)
);
}
}
// Add some empty patches on remaining patches (tbd.probably processor
// patches)
forAll(basePatchFields, patchI)
{
if (patchI >= patchFields.size() || !patchFields.set(patchI))
{
basePatchFields.set
(
patchI,
fvsPatchField<Type>::New
(
emptyFvsPatchField<Type>::typeName,
baseMesh_.boundary()[patchI],
DimensionedField<Type, surfaceMesh>::null()
)
);
}
}
// Construct a volField
IOobject baseIO
(
fld.name(),
baseMesh_.time().timeName(),
fld.local(),
baseMesh_,
IOobject::NO_READ,
IOobject::NO_WRITE
);
return tmp<GeometricField<Type, fvsPatchField, surfaceMesh> >
(
new GeometricField<Type, fvsPatchField, surfaceMesh>
(
baseIO,
baseMesh_,
fld.dimensions(),
internalField,
basePatchFields
)
);
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::fvsPatchField, Foam::surfaceMesh> >
Foam::parFvFieldReconstructor::reconstructFvSurfaceField
(
const IOobject& fieldIoObject
) const
{
// Read the field
GeometricField<Type, fvsPatchField, surfaceMesh> fld
(
fieldIoObject,
procMesh_
);
return reconstructFvSurfaceField(fld);
}
template<class Type>
void Foam::parFvFieldReconstructor::reconstructFvVolumeInternalFields
(
const IOobjectList& objects,
const HashSet<word>& selectedFields
) const
{
const word& fieldClassName = DimensionedField<Type, volMesh>::typeName;
IOobjectList fields = objects.lookupClass(fieldClassName);
if (fields.size())
{
Info<< " Reconstructing " << fieldClassName << "s\n" << endl;
forAllConstIter(IOobjectList, fields, fieldIter)
{
if
(
selectedFields.empty()
|| selectedFields.found(fieldIter()->name())
)
{
Info<< " " << fieldIter()->name() << endl;
tmp<DimensionedField<Type, volMesh> > tfld
(
reconstructFvVolumeInternalField<Type>(*fieldIter())
);
if (isWriteProc_)
{
tfld().write();
}
}
}
Info<< endl;
}
}
template<class Type>
void Foam::parFvFieldReconstructor::reconstructFvVolumeFields
(
const IOobjectList& objects,
const HashSet<word>& selectedFields
) const
{
const word& fieldClassName =
GeometricField<Type, fvPatchField, volMesh>::typeName;
IOobjectList fields = objects.lookupClass(fieldClassName);
if (fields.size())
{
Info<< " Reconstructing " << fieldClassName << "s\n" << endl;
forAllConstIter(IOobjectList, fields, fieldIter)
{
const word& name = fieldIter()->name();
if
(
(selectedFields.empty() || selectedFields.found(name))
&& name != "cellDist"
)
{
Info<< " " << name << endl;
tmp<GeometricField<Type, fvPatchField, volMesh> > tfld
(
reconstructFvVolumeField<Type>(*fieldIter())
);
if (isWriteProc_)
{
tfld().write();
}
}
}
Info<< endl;
}
}
template<class Type>
void Foam::parFvFieldReconstructor::reconstructFvSurfaceFields
(
const IOobjectList& objects,
const HashSet<word>& selectedFields
) const
{
const word& fieldClassName =
GeometricField<Type, fvsPatchField, surfaceMesh>::typeName;
IOobjectList fields = objects.lookupClass(fieldClassName);
if (fields.size())
{
Info<< " Reconstructing " << fieldClassName << "s\n" << endl;
forAllConstIter(IOobjectList, fields, fieldIter)
{
if
(
selectedFields.empty()
|| selectedFields.found(fieldIter()->name())
)
{
Info<< " " << fieldIter()->name() << endl;
tmp<GeometricField<Type, fvsPatchField, surfaceMesh> > tfld
(
reconstructFvSurfaceField<Type>(*fieldIter())
);
if (isWriteProc_)
{
tfld().write();
}
}
}
Info<< endl;
}
}
// ************************************************************************* //

View File

@ -0,0 +1,321 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 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 "ListOps.H"
#include "parLagrangianRedistributor.H"
#include "passiveParticleCloud.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::parLagrangianRedistributor::parLagrangianRedistributor
(
const fvMesh& srcMesh,
const fvMesh& tgtMesh,
const label nSrcCells,
const mapDistributePolyMesh& distMap
)
:
srcMesh_(srcMesh),
tgtMesh_(tgtMesh),
distMap_(distMap)
{
const mapDistribute& cellMap = distMap_.cellMap();
// Get destination processors and cells
destinationProcID_ = labelList(tgtMesh_.nCells(), Pstream::myProcNo());
cellMap.reverseDistribute(nSrcCells, destinationProcID_);
destinationCell_ = identity(tgtMesh_.nCells());
cellMap.reverseDistribute(nSrcCells, destinationCell_);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// Find all clouds (on all processors) and for each cloud all the objects.
// Result will be synchronised on all processors
void Foam::parLagrangianRedistributor::findClouds
(
const fvMesh& mesh,
wordList& cloudNames,
List<wordList>& objectNames
)
{
fileNameList localCloudDirs
(
readDir
(
mesh.time().timePath()
/ mesh.dbDir()
/ cloud::prefix,
fileName::DIRECTORY
)
);
cloudNames.setSize(localCloudDirs.size());
forAll(localCloudDirs, i)
{
cloudNames[i] = localCloudDirs[i];
}
// Synchronise cloud names
Pstream::combineGather(cloudNames, ListUniqueEqOp<word>());
Pstream::combineScatter(cloudNames);
objectNames.setSize(cloudNames.size());
forAll(localCloudDirs, i)
{
// Do local scan for valid cloud objects
IOobjectList sprayObjs
(
mesh,
mesh.time().timeName(),
cloud::prefix/localCloudDirs[i]
);
if (sprayObjs.lookup(word("positions")))
{
// One of the objects is positions so must be valid cloud
label cloudI = findIndex(cloudNames, localCloudDirs[i]);
objectNames[cloudI].setSize(sprayObjs.size());
label objectI = 0;
forAllConstIter(IOobjectList, sprayObjs, iter)
{
const word& name = iter.key();
if (name != "positions")
{
objectNames[cloudI][objectI++] = name;
}
}
objectNames[cloudI].setSize(objectI);
}
}
// Synchronise objectNames
forAll(objectNames, cloudI)
{
Pstream::combineGather(objectNames[cloudI], ListUniqueEqOp<word>());
Pstream::combineScatter(objectNames[cloudI]);
}
}
Foam::autoPtr<Foam::mapDistributeBase>
Foam::parLagrangianRedistributor::redistributeLagrangianPositions
(
passiveParticleCloud& lpi
) const
{
//Debug(lpi.size());
labelListList subMap;
// Allocate transfer buffers
PstreamBuffers pBufs(Pstream::nonBlocking);
{
// List of lists of particles to be transfered for all of the
// neighbour processors
List<IDLList<passiveParticle> > particleTransferLists
(
Pstream::nProcs()
);
// Per particle the destination processor
labelList destProc(lpi.size());
label particleI = 0;
forAllIter(passiveParticleCloud, lpi, iter)
{
passiveParticle& ppi = iter();
label destProcI = destinationProcID_[ppi.cell()];
label destCellI = destinationCell_[ppi.cell()];
ppi.cell() = destCellI;
destProc[particleI++] = destProcI;
//Pout<< "Sending particle:" << ppi << " to processor " << destProcI
// << " to cell " << destCellI << endl;
particleTransferLists[destProcI].append(lpi.remove(&ppi));
}
// Per processor the indices of the particles to send
subMap = invertOneToMany(Pstream::nProcs(), destProc);
// Stream into send buffers
forAll(particleTransferLists, procI)
{
//Pout<< "To proc " << procI << " sending "
// << particleTransferLists[procI] << endl;
if (particleTransferLists[procI].size())
{
UOPstream particleStream(procI, pBufs);
particleStream << particleTransferLists[procI];
}
}
}
// Start sending. Sets number of bytes transferred
labelListList allNTrans(Pstream::nProcs());
pBufs.finishedSends(allNTrans);
{
// Temporarily rename original cloud so we can construct a new one
// (to distribute the positions) without getting a duplicate
// registration warning
const word cloudName = lpi.name();
lpi.rename(cloudName + "_old");
// New cloud on tgtMesh
passiveParticleCloud lagrangianPositions
(
tgtMesh_,
cloudName,
IDLList<passiveParticle>()
);
// Retrieve from receive buffers
forAll(allNTrans, procI)
{
label nRec = allNTrans[procI][Pstream::myProcNo()];
//Pout<< "From processor " << procI << " receiving bytes " << nRec
// << endl;
if (nRec)
{
UIPstream particleStream(procI, pBufs);
IDLList<passiveParticle> newParticles
(
particleStream,
passiveParticle::iNew(tgtMesh_)
);
forAllIter
(
IDLList<passiveParticle>,
newParticles,
newpIter
)
{
passiveParticle& newp = newpIter();
lagrangianPositions.addParticle(newParticles.remove(&newp));
}
}
}
//OFstream::debug = 1;
//Debug(lagrangianPositions.size());
IOPosition<passiveParticleCloud>(lagrangianPositions).write();
//OFstream::debug = 0;
// Restore cloud name
lpi.rename(cloudName);
}
// Work the send indices (subMap) into a mapDistributeBase
labelListList sizes(Pstream::nProcs());
labelList& nsTransPs = sizes[Pstream::myProcNo()];
nsTransPs.setSize(Pstream::nProcs());
forAll(subMap, sendProcI)
{
nsTransPs[sendProcI] = subMap[sendProcI].size();
}
// Send sizes across. Note: blocks.
combineReduce(sizes, Pstream::listEq());
labelListList constructMap(Pstream::nProcs());
label constructSize = 0;
forAll(constructMap, procI)
{
label nRecv = sizes[procI][UPstream::myProcNo()];
labelList& map = constructMap[procI];
map.setSize(nRecv);
forAll(map, i)
{
map[i] = constructSize++;
}
}
// Construct map
return autoPtr<mapDistributeBase>
(
new mapDistributeBase
(
constructSize,
subMap.xfer(),
constructMap.xfer()
)
);
}
Foam::autoPtr<Foam::mapDistributeBase>
Foam::parLagrangianRedistributor::redistributeLagrangianPositions
(
const word& cloudName
) const
{
(void)srcMesh_.tetBasePtIs();
(void)tgtMesh_.tetBasePtIs();
// Temporarily: override master-only checking
regIOobject::fileCheckTypes oldCheckType =
regIOobject::fileModificationChecking;
if (oldCheckType == regIOobject::timeStampMaster)
{
regIOobject::fileModificationChecking = regIOobject::timeStamp;
}
else if (oldCheckType == regIOobject::inotifyMaster)
{
regIOobject::fileModificationChecking = regIOobject::inotify;
}
// Load cloud and send particle
passiveParticleCloud lpi(srcMesh_, cloudName, false);
regIOobject::fileModificationChecking = oldCheckType;
return redistributeLagrangianPositions(lpi);
}
// ************************************************************************* //

View File

@ -0,0 +1,186 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 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::parLagrangianRedistributor
Description
Lagrangian field redistributor.
Runs in parallel. Redistributes from fromMesh to toMesh.
SourceFiles
parLagrangianRedistributor.C
parLagrangianRedistributorRedistributeFields.C
\*---------------------------------------------------------------------------*/
#ifndef parLagrangianRedistributor_H
#define parLagrangianRedistributor_H
#include "PtrList.H"
#include "fvMesh.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
class mapDistributePolyMesh;
class mapDistributeBase;
class IOobjectList;
class passiveParticleCloud;
/*---------------------------------------------------------------------------*\
Class parLagrangianRedistributor Declaration
\*---------------------------------------------------------------------------*/
class parLagrangianRedistributor
{
// Private data
//- Source mesh reference
const fvMesh& srcMesh_;
//- Destination mesh reference
const fvMesh& tgtMesh_;
//- Distribution map reference
const mapDistributePolyMesh& distMap_;
//- For every src cell the target processor
labelList destinationProcID_;
//- For every src cell the target cell
labelList destinationCell_;
// Private Member Functions
//- Disallow default bitwise copy construct
parLagrangianRedistributor(const parLagrangianRedistributor&);
//- Disallow default bitwise assignment
void operator=(const parLagrangianRedistributor&);
public:
// Constructors
//- Construct from components
parLagrangianRedistributor
(
const fvMesh& srcMesh,
const fvMesh& tgtMesh,
const label nOldCells,
const mapDistributePolyMesh& distMap
);
// Member Functions
//- Find all clouds (on all processors) and for each cloud all
// the objects. Result will be synchronised on all processors
static void findClouds
(
const fvMesh&,
wordList& cloudNames,
List<wordList>& objectNames
);
//- Redistribute and write lagrangian positions
autoPtr<mapDistributeBase> redistributeLagrangianPositions
(
passiveParticleCloud& 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
(
const IOobjectList& objects,
const HashSet<word>& selectedFields
);
//- Read, redistribute and write all/selected lagrangian fields
template<class Type>
void redistributeLagrangianFields
(
const mapDistributeBase& map,
const word& cloudName,
const IOobjectList& objects,
const HashSet<word>& selectedFields
) const;
//- Read, redistribute and write all/selected lagrangian fieldFields
template<class Type>
void redistributeLagrangianFieldFields
(
const mapDistributeBase& map,
const word& cloudName,
const IOobjectList& objects,
const HashSet<word>& selectedFields
) const;
//- Read and store all fields of a cloud
template<class Container>
static void readLagrangianFields
(
const passiveParticleCloud& cloud,
const IOobjectList& objects,
const HashSet<word>& selectedFields
);
//- Redistribute and write stored lagrangian fields
template<class Container>
void redistributeStoredLagrangianFields
(
const mapDistributeBase& map,
passiveParticleCloud& cloud
) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "parLagrangianRedistributorRedistributeFields.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,320 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 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 "parLagrangianRedistributor.H"
#include "Time.H"
#include "IOobjectList.H"
#include "mapDistributePolyMesh.H"
#include "cloud.H"
#include "CompactIOField.H"
#include "passiveParticleCloud.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Container>
Foam::wordList Foam::parLagrangianRedistributor::filterObjects
(
const IOobjectList& objects,
const HashSet<word>& selectedFields
)
{
const word fieldClassName(Container::typeName);
// Parallel synchronise
wordList fieldNames(objects.names(fieldClassName));
Pstream::combineGather(fieldNames, ListUniqueEqOp<word>());
Pstream::combineScatter(fieldNames);
if (!selectedFields.empty())
{
DynamicList<word> selectedNames(fieldNames.size());
forAll(fieldNames, i)
{
if (selectedFields.found(fieldNames[i]))
{
selectedNames.append(fieldNames[i]);
}
}
fieldNames.transfer(selectedNames);
}
return fieldNames;
}
template<class Type>
void Foam::parLagrangianRedistributor::redistributeLagrangianFields
(
const mapDistributeBase& map,
const word& cloudName,
const IOobjectList& objects,
const HashSet<word>& selectedFields
) const
{
const wordList objectNames
(
filterObjects<IOField<Type> >
(
objects,
selectedFields
)
);
if (objectNames.size())
{
const word fieldClassName(IOField<Type>::typeName);
Info<< " Redistributing lagrangian "
<< fieldClassName << "s\n" << endl;
forAll(objectNames, i)
{
Info<< " " << objectNames[i] << endl;
// Read if present
IOField<Type> field
(
IOobject
(
objectNames[i],
srcMesh_.time().timeName(),
cloud::prefix/cloudName,
srcMesh_,
IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE,
false
),
0
);
map.distribute(field);
if (field.size())
{
IOField<Type>
(
IOobject
(
objectNames[i],
tgtMesh_.time().timeName(),
cloud::prefix/cloudName,
tgtMesh_,
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
xferMove<Field<Type> >(field)
).write();
}
}
Info<< endl;
}
}
template<class Type>
void Foam::parLagrangianRedistributor::redistributeLagrangianFieldFields
(
const mapDistributeBase& map,
const word& cloudName,
const IOobjectList& objects,
const HashSet<word>& selectedFields
) const
{
wordList objectNames
(
filterObjects<CompactIOField<Field<Type>, Type> >
(
objects,
selectedFields
)
);
// Append IOField names
{
const wordList ioFieldNames
(
filterObjects<IOField<Field<Type> > >
(
objects,
selectedFields
)
);
objectNames.append(ioFieldNames);
}
if (objectNames.size())
{
const word fieldClassName(CompactIOField<Field<Type>, Type>::typeName);
Info<< " Redistributing lagrangian "
<< fieldClassName << "s\n" << endl;
forAll(objectNames, i)
{
Info<< " " << objectNames[i] << endl;
// Read if present
CompactIOField<Field<Type>, Type > field
(
IOobject
(
objectNames[i],
srcMesh_.time().timeName(),
cloud::prefix/cloudName,
srcMesh_,
IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE,
false
),
0
);
// Distribute
map.distribute(field);
// Write
if (field.size())
{
CompactIOField<Field<Type>, Type>
(
IOobject
(
objectNames[i],
tgtMesh_.time().timeName(),
cloud::prefix/cloudName,
tgtMesh_,
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
xferMove<Field<Field<Type> > >(field)
).write();
}
}
}
}
template<class Container>
void Foam::parLagrangianRedistributor::readLagrangianFields
(
const passiveParticleCloud& cloud,
const IOobjectList& objects,
const HashSet<word>& selectedFields
)
{
const wordList objectNames
(
filterObjects<Container>
(
objects,
selectedFields
)
);
if (objectNames.size())
{
const word fieldClassName(Container::typeName);
Info<< " Reading lagrangian "
<< fieldClassName << "s\n" << endl;
forAll(objectNames, i)
{
Info<< " " << objectNames[i] << endl;
// Read if present
Container* fieldPtr = new Container
(
IOobject
(
objectNames[i],
cloud.time().timeName(),
cloud,
IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE
),
0
);
fieldPtr->store();
}
}
}
template<class Container>
void Foam::parLagrangianRedistributor::redistributeStoredLagrangianFields
(
const mapDistributeBase& map,
passiveParticleCloud& cloud
) const
{
HashTable<Container*> fields
(
cloud.lookupClass<Container >()
);
if (fields.size())
{
const word fieldClassName(Container::typeName);
Info<< " Redistributing lagrangian "
<< fieldClassName << "s\n" << endl;
forAllIter(typename HashTable<Container*>, fields, iter)
{
Container& field = *iter();
Info<< " " << field.name() << endl;
map.distribute(field);
if (field.size())
{
Container
(
IOobject
(
field.name(),
tgtMesh_.time().timeName(),
cloud::prefix/cloud.name(),
tgtMesh_,
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
xferMove<Field<typename Container::value_type> >(field)
).write();
}
}
}
}
// ************************************************************************* //

View File

@ -0,0 +1,112 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 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::unmappedPassiveParticleCloud
Description
passiveParticleCloud but with autoMap and writing disabled. Only used
for its objectRegistry to store lagrangian fields
SourceFiles
unmappedPassiveParticleCloud.C
\*---------------------------------------------------------------------------*/
#ifndef unmappedPassiveParticleCloud_H
#define unmappedPassiveParticleCloud_H
#include "passiveParticleCloud.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class unmappedPassiveParticleCloud Declaration
\*---------------------------------------------------------------------------*/
class unmappedPassiveParticleCloud
:
public passiveParticleCloud
{
public:
// Constructors
//- Construct given mesh
unmappedPassiveParticleCloud
(
const polyMesh& mesh,
const word& cloudName = "defaultCloud",
bool readFields = true
)
:
passiveParticleCloud(mesh, cloudName, readFields)
{}
//- Construct from mesh, cloud name, and a list of particles
unmappedPassiveParticleCloud
(
const polyMesh& mesh,
const word& cloudName,
const IDLList<passiveParticle>& particles
)
:
passiveParticleCloud(mesh, cloudName, particles)
{}
//- Destructor
virtual ~unmappedPassiveParticleCloud()
{}
//- Switch off remapping of cells of particles when
// mesh topology changes
virtual void autoMap(const mapPolyMesh&)
{}
//- Switch off writing the objects
virtual bool writeObject
(
IOstream::streamFormat fmt,
IOstream::versionNumber ver,
IOstream::compressionType cmp
) const
{
return true;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,12 +1,14 @@
EXE_INC = \
/* -DFULLDEBUG -g -O0 */ \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/sampling/lnInclude \
-I$(LIB_SRC)/lagrangian/basic/lnInclude
EXE_LIBS = \
-lfiniteVolume \
-ldynamicMesh \
-lmeshTools \
-lsampling \
-lgenericPatchFields \

View File

@ -2,12 +2,14 @@ EXE_INC = \
-I$(WM_THIRD_PARTY_DIR)/tecio/tecsrc/lnInclude \
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude
EXE_LIBS = \
-llagrangian \
-lfiniteVolume \
-ldynamicMesh \
-lgenericPatchFields \
-lmeshTools \
-L$(FOAM_EXT_LIBBIN) -ltecio

View File

@ -1,10 +1,12 @@
EXE_INC = \
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude
EXE_LIBS = \
-lfiniteVolume \
-ldynamicMesh \
-llagrangian \
-lgenericPatchFields \
-lmeshTools

View File

@ -3,6 +3,7 @@
EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
-I../../vtkPV4Readers/lnInclude \
-I../PV4FoamReader \
@ -15,6 +16,7 @@ EXE_INC = \
LIB_LIBS = \
-lmeshTools \
-lfiniteVolume \
-ldynamicMesh \
-lgenericPatchFields \
-llagrangian \
-L$(FOAM_LIBBIN) -lvtkPV4Readers \

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -41,7 +41,8 @@ void mapConsistentMesh
(
const fvMesh& meshSource,
const fvMesh& meshTarget,
const meshToMesh::interpolationMethod& mapMethod,
const word& mapMethod,
const word& AMIMapMethod,
const bool subtract,
const HashSet<word>& selectedFields,
const bool noLagrangian
@ -50,7 +51,7 @@ void mapConsistentMesh
Info<< nl << "Consistently creating and mapping fields for time "
<< meshSource.time().timeName() << nl << endl;
meshToMesh interp(meshSource, meshTarget, mapMethod);
meshToMesh interp(meshSource, meshTarget, mapMethod, AMIMapMethod);
if (subtract)
{
@ -79,7 +80,8 @@ void mapSubMesh
const fvMesh& meshTarget,
const HashTable<word>& patchMap,
const wordList& cuttingPatches,
const meshToMesh::interpolationMethod& mapMethod,
const word& mapMethod,
const word& AMIMapMethod,
const bool subtract,
const HashSet<word>& selectedFields,
const bool noLagrangian
@ -93,6 +95,7 @@ void mapSubMesh
meshSource,
meshTarget,
mapMethod,
AMIMapMethod,
patchMap,
cuttingPatches
);
@ -184,7 +187,14 @@ int main(int argc, char *argv[])
(
"mapMethod",
"word",
"specify the mapping method"
"specify the mapping method "
"(direct|mapNearest|cellVolumeWeight|correctedCellVolumeWeight)"
);
argList::addOption
(
"patchMapMethod",
"word",
"specify the patch mapping method (direct|mapNearest|faceAreaWeight)"
);
argList::addBoolOption
(
@ -231,15 +241,46 @@ int main(int argc, char *argv[])
const bool consistent = args.optionFound("consistent");
meshToMesh::interpolationMethod mapMethod =
meshToMesh::imCellVolumeWeight;
if (args.optionFound("mapMethod"))
word mapMethod = meshToMesh::interpolationMethodNames_
[
meshToMesh::imCellVolumeWeight
];
if (args.optionReadIfPresent("mapMethod", mapMethod))
{
mapMethod = meshToMesh::interpolationMethodNames_[args["mapMethod"]];
Info<< "Mapping method: " << mapMethod << endl;
}
Info<< "Mapping method: "
<< meshToMesh::interpolationMethodNames_[mapMethod] << endl;
word patchMapMethod;
if (meshToMesh::interpolationMethodNames_.found(mapMethod))
{
// Lookup corresponding AMI method
meshToMesh::interpolationMethod method =
meshToMesh::interpolationMethodNames_[mapMethod];
patchMapMethod = AMIPatchToPatchInterpolation::interpolationMethodToWord
(
meshToMesh::interpolationMethodAMI(method)
);
}
// Optionally override
if (args.optionFound("patchMapMethod"))
{
patchMapMethod = args["patchMapMethod"];
Info<< "Patch mapping method: " << patchMapMethod << endl;
}
if (patchMapMethod.empty())
{
FatalErrorIn(args.executable())
<< "No valid patchMapMethod for method " << mapMethod
<< ". Please supply one through the 'patchMapMethod' option"
<< exit(FatalError);
}
const bool subtract = args.optionFound("subtract");
@ -304,8 +345,9 @@ int main(int argc, char *argv[])
)
);
Info<< "Source mesh size: " << meshSource.nCells() << tab
<< "Target mesh size: " << meshTarget.nCells() << nl << endl;
Info<< "Source mesh size: " << meshSource.globalData().nTotalCells() << tab
<< "Target mesh size: " << meshTarget.globalData().nTotalCells()
<< nl << endl;
if (consistent)
{
@ -314,6 +356,7 @@ int main(int argc, char *argv[])
meshSource,
meshTarget,
mapMethod,
patchMapMethod,
subtract,
selectedFields,
noLagrangian
@ -328,6 +371,7 @@ int main(int argc, char *argv[])
patchMap,
addProcessorPatches(meshTarget, cuttingPatches),
mapMethod,
patchMapMethod,
subtract,
selectedFields,
noLagrangian