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

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -22,15 +22,15 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::weightedFvPatchFieldMapper
Foam::distributedUnallocatedDirectFvPatchFieldMapper
Description
FieldMapper with weighted mapping.
FieldMapper with direct mapping from remote quantities.
\*---------------------------------------------------------------------------*/
#ifndef weightedFvPatchFieldMapper_H
#define weightedFvPatchFieldMapper_H
#ifndef distributedUnallocatedDirectFvPatchFieldMapper_H
#define distributedUnallocatedDirectFvPatchFieldMapper_H
#include "fvPatchFieldMapper.H"
@ -40,16 +40,16 @@ namespace Foam
{
/*---------------------------------------------------------------------------*\
Class weightedFvPatchFieldMapper Declaration
Class distributedUnallocatedDirectFvPatchFieldMapper Declaration
\*---------------------------------------------------------------------------*/
class weightedFvPatchFieldMapper
class distributedUnallocatedDirectFvPatchFieldMapper
:
public fvPatchFieldMapper
{
const labelListList& addressing_;
const labelUList& directAddressing_;
const scalarListList& weights_;
const mapDistributeBase& distMap_;
bool hasUnmapped_;
@ -58,27 +58,29 @@ public:
// Constructors
//- Construct given addressing
weightedFvPatchFieldMapper
distributedUnallocatedDirectFvPatchFieldMapper
(
const labelListList& addressing,
const scalarListList& weights
const labelUList& directAddressing,
const mapDistributeBase& distMap
)
:
addressing_(addressing),
weights_(weights),
directAddressing_(directAddressing),
distMap_(distMap),
hasUnmapped_(false)
{
forAll(addressing_, i)
if
(
notNull(directAddressing_)
&& directAddressing_.size()
&& min(directAddressing_) < 0
)
{
if (addressing_[i].size() == 0)
{
hasUnmapped_ = true;
}
hasUnmapped_ = true;
}
}
//- Destructor
virtual ~weightedFvPatchFieldMapper()
virtual ~distributedUnallocatedDirectFvPatchFieldMapper()
{}
@ -86,12 +88,27 @@ public:
virtual label size() const
{
return addressing().size();
return
(
notNull(directAddressing_)
? directAddressing_.size()
: distMap_.constructSize()
);
}
virtual bool direct() const
{
return false;
return true;
}
virtual bool distributed() const
{
return true;
}
virtual const mapDistributeBase& distributeMap() const
{
return distMap_;
}
virtual bool hasUnmapped() const
@ -99,16 +116,10 @@ public:
return hasUnmapped_;
}
virtual const labelListList& addressing() const
virtual const labelUList& directAddressing() const
{
return addressing_;
return directAddressing_;
}
virtual const scalarListList& weights() const
{
return weights_;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

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

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.
@ -52,7 +52,10 @@ cleanTimeDirectories()
rm -rf ./${timeDir} ./-${timeDir} > /dev/null 2>&1
zeros="0$zeros"
done
rm -rf ./[1-9]* ./-[1-9]* ./log ./log.* ./log-* ./logSummary.* ./.fxLock ./*.xml ./ParaView* ./paraFoam* ./*.OpenFOAM ./*.blockMesh ./.setSet > /dev/null 2>&1
rm -rf \
./[1-9]* ./-[1-9]* ./log ./log.* ./log-* ./logSummary.* \
./.fxLock ./*.xml ./ParaView* ./paraFoam* ./*.OpenFOAM ./*.blockMesh \
./.setSet > /dev/null 2>&1
}
@ -68,6 +71,33 @@ cleanDynamicCode()
}
cleanSnappyFiles()
{
rm -f \
constant/polyMesh/cellLevel \
constant/polyMesh/pointLevel \
constant/polyMesh/refinementHistory \
constant/polyMesh/level0Edge \
constant/polyMesh/surfaceIndex > /dev/null 2>&1
rm -f \
processor*/constant/polyMesh/cellLevel \
processor*/constant/polyMesh/pointLevel \
processor*/constant/polyMesh/refinementHistory \
processor*/constant/polyMesh/level0Edge \
processor*/constant/polyMesh/surfaceIndex > /dev/null 2>&1
rm -f \
constant/cellLevel \
constant/pointLevel \
0/cellLevel \
0/pointLevel > /dev/null 2>&1
rm -f \
processor*/constant/cellLevel \
processor*/constant/pointLevel \
processor*/0/cellLevel \
processor*/0/pointLevel > /dev/null 2>&1
}
cleanCase()
{
cleanTimeDirectories
@ -83,26 +113,25 @@ cleanCase()
rm -rf cuttingPlane > /dev/null 2>&1
rm -rf system/machines > /dev/null 2>&1
# From mpirunDebug
rm -f gdbCommands mpirun.schema
cleanSnappyFiles
if [ -d constant/polyMesh ]
then
(cd constant/polyMesh && \
rm -rf \
allOwner* cell* face* meshModifiers* \
owner* neighbour* point* edge* \
cellLevel* pointLevel* refinementHistory* level0Edge* surfaceIndex* sets \
owner* neighbour* point* edge* sets \
> /dev/null 2>&1 \
)
fi
(cd constant && \
rm -rf \
cellToRegion cellLevel* pointLevel* \
> /dev/null 2>&1 \
)
(cd constant && rm -rf cellToRegion > /dev/null 2>&1)
rm -rf constant/tetDualMesh > /dev/null 2>&1
rm -rf VTK > /dev/null 2>&1
rm -f 0/cellLevel 0/pointLevel 0/cellDist constant/cellDecomposition
rm -f 0/cellDist constant/cellDecomposition
if [ -e constant/polyMesh/blockMeshDict.m4 ]
then

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.
@ -40,28 +40,46 @@ getApplication()
runApplication()
{
APP_LOGFILE=''
if [ "$1" = "-l" ]
then
APP_LOGFILE=$2
shift 2
fi
APP_RUN=$1
APP_NAME=${1##*/}
shift
if [ -f log.$APP_NAME ]
APP_LOGFILE=${APP_LOGFILE:="log.$APP_NAME"}
if [ -f $APP_LOGFILE ]
then
echo "$APP_NAME already run on $PWD: remove log file to re-run"
echo "$APP_NAME already run on $PWD: remove log file $APP_LOGFILE to re-run"
else
echo "Running $APP_RUN on $PWD"
$APP_RUN "$@" > log.$APP_NAME 2>&1
$APP_RUN "$@" > $APP_LOGFILE 2>&1
fi
}
runParallel()
{
APP_LOGFILE=''
if [ "$1" = "-l" ]
then
APP_LOGFILE=$2
shift 2
fi
APP_RUN=$1
APP_NAME=${1##*/}
shift
if [ -f log.$APP_NAME ]
APP_LOGFILE=${APP_LOGFILE:="log.$APP_NAME"}
if [ -f $APP_LOGFILE ]
then
echo "$APP_NAME already run on $PWD: remove log file to re-run"
echo "$APP_NAME already run on $PWD: remove log file $APP_LOGFILE to re-run"
else
nProcs=$1
shift
@ -70,9 +88,9 @@ runParallel()
#if [ "$WM_SCHEDULER" ]
#then
# echo "$PWD: $WM_SCHEDULER -np $nProcs" 1>&2
# $WM_SCHEDULER -np $nProcs "( mpirun -np $nProcs $APP_RUN -parallel "$@" < /dev/null > log.$APP_NAME 2>&1 )"
# $WM_SCHEDULER -np $nProcs "( mpirun -np $nProcs $APP_RUN -parallel "$@" < /dev/null > $APP_LOGFILE 2>&1 )"
#else
( mpirun -np $nProcs $APP_RUN -parallel "$@" < /dev/null > log.$APP_NAME 2>&1 )
( mpirun -np $nProcs $APP_RUN -parallel "$@" < /dev/null > $APP_LOGFILE 2>&1 )
#fi
fi
}

View File

@ -91,6 +91,9 @@ $(strings)/wordRe/wordRe.C
$(strings)/lists/hashedWordList.C
$(strings)/stringOps/stringOps.C
ops = primitives/ops
$(ops)/flipOp.C
primitives/hashes/Hasher/Hasher.C
sha1 = primitives/hashes/SHA1
@ -505,6 +508,7 @@ $(mapPolyMesh)/mapPolyMesh.C
$(mapPolyMesh)/faceMapper/faceMapper.C
$(mapPolyMesh)/cellMapper/cellMapper.C
$(mapPolyMesh)/mapDistribute/mapDistribute.C
$(mapPolyMesh)/mapDistribute/mapDistributeBase.C
$(mapPolyMesh)/mapDistribute/mapDistributePolyMesh.C
$(mapPolyMesh)/mapDistribute/IOmapDistribute.C
$(mapPolyMesh)/mapAddedPolyMesh.C
@ -618,6 +622,8 @@ $(derivedPointPatchFields)/codedFixedValue/codedFixedValuePointPatchFields.C
fields/GeometricFields/pointFields/pointFields.C
fields/ReadFields/ReadFields.C
meshes/bandCompression/bandCompression.C
meshes/preservePatchTypes/preservePatchTypes.C

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.
@ -57,22 +57,41 @@ const Foam::NamedEnum<Foam::UPstream::commsTypes, 3>
void Foam::UPstream::setParRun(const label nProcs)
{
parRun_ = true;
// Redo worldComm communicator (this has been created at static
// initialisation time)
freeCommunicator(UPstream::worldComm);
label comm = allocateCommunicator(-1, identity(nProcs), true);
if (comm != UPstream::worldComm)
if (nProcs == 0)
{
FatalErrorIn("UPstream::setParRun(const label)")
<< "problem : comm:" << comm
<< " UPstream::worldComm:" << UPstream::worldComm
<< Foam::exit(FatalError);
}
parRun_ = false;
freeCommunicator(UPstream::worldComm);
label comm = allocateCommunicator(-1, labelList(1, label(0)), false);
if (comm != UPstream::worldComm)
{
FatalErrorIn("UPstream::setParRun(const label)")
<< "problem : comm:" << comm
<< " UPstream::worldComm:" << UPstream::worldComm
<< Foam::exit(FatalError);
}
Pout.prefix() = '[' + name(myProcNo(Pstream::worldComm)) + "] ";
Perr.prefix() = '[' + name(myProcNo(Pstream::worldComm)) + "] ";
Pout.prefix() = "";
Perr.prefix() = "";
}
else
{
parRun_ = true;
// Redo worldComm communicator (this has been created at static
// initialisation time)
freeCommunicator(UPstream::worldComm);
label comm = allocateCommunicator(-1, identity(nProcs), true);
if (comm != UPstream::worldComm)
{
FatalErrorIn("UPstream::setParRun(const label)")
<< "problem : comm:" << comm
<< " UPstream::worldComm:" << UPstream::worldComm
<< Foam::exit(FatalError);
}
Pout.prefix() = '[' + name(myProcNo(Pstream::worldComm)) + "] ";
Perr.prefix() = '[' + name(myProcNo(Pstream::worldComm)) + "] ";
}
}

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.
@ -197,9 +197,6 @@ private:
// Private Member Functions
//- Set data for parallel running
static void setParRun(const label nProcs);
//- Calculate linear communication schedule
static List<commsStruct> calcLinearComm(const label nProcs);
@ -383,6 +380,10 @@ public:
return parRun_;
}
//- Set data for parallel running. Special case nProcs=0 to switch off
// parallel running
static void setParRun(const label nProcs);
//- Number of processes in parallel run
static label nProcs(const label communicator = 0)
{

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.
@ -55,7 +55,7 @@ void Pstream::combineGather
const label comm
)
{
if (UPstream::nProcs(comm) > 1)
if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
{
// Get my communication order
const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
@ -182,7 +182,7 @@ void Pstream::combineScatter
const label comm
)
{
if (UPstream::nProcs(comm) > 1)
if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
{
// Get my communication order
const UPstream::commsStruct& myComm = comms[UPstream::myProcNo(comm)];
@ -287,7 +287,7 @@ void Pstream::listCombineGather
const label comm
)
{
if (UPstream::nProcs(comm) > 1)
if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
{
// Get my communication order
const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
@ -421,7 +421,7 @@ void Pstream::listCombineScatter
const label comm
)
{
if (UPstream::nProcs(comm) > 1)
if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
{
// Get my communication order
const UPstream::commsStruct& myComm = comms[UPstream::myProcNo(comm)];
@ -540,7 +540,7 @@ void Pstream::mapCombineGather
const label comm
)
{
if (UPstream::nProcs(comm) > 1)
if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
{
// Get my communication order
const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
@ -640,7 +640,7 @@ void Pstream::mapCombineScatter
const label comm
)
{
if (UPstream::nProcs(comm) > 1)
if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
{
// Get my communication order
const UPstream::commsStruct& myComm = comms[UPstream::myProcNo(comm)];

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.
@ -75,14 +75,15 @@ void Foam::Pstream::exchange
// Send sizes across. Note: blocks.
combineReduce(sizes, UPstream::listEq(), tag, comm);
if (UPstream::nProcs(comm) > 1)
recvBufs.setSize(sendBufs.size());
if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
{
label startOfRequests = Pstream::nRequests();
// Set up receives
// ~~~~~~~~~~~~~~~
recvBufs.setSize(sendBufs.size());
forAll(sizes, procI)
{
label nRecv = sizes[procI][UPstream::myProcNo(comm)];

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.
@ -52,7 +52,7 @@ void Pstream::gather
const label comm
)
{
if (UPstream::nProcs(comm) > 1)
if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
{
// Get my communication order
const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
@ -151,7 +151,7 @@ void Pstream::scatter
const label comm
)
{
if (UPstream::nProcs(comm) > 1)
if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
{
// Get my communication order
const commsStruct& myComm = comms[UPstream::myProcNo(comm)];

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.
@ -53,7 +53,7 @@ void Pstream::gatherList
const label comm
)
{
if (UPstream::nProcs(comm) > 1)
if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
{
if (Values.size() != UPstream::nProcs(comm))
{
@ -212,7 +212,7 @@ void Pstream::scatterList
const label comm
)
{
if (UPstream::nProcs(comm) > 1)
if (UPstream::parRun() && UPstream::nProcs(comm) > 1)
{
if (Values.size() != UPstream::nProcs(comm))
{

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -54,7 +54,7 @@ class TimePaths
bool processorCase_;
const fileName rootPath_;
fileName globalCaseName_;
const fileName case_;
fileName case_;
const word system_;
const word constant_;
@ -111,6 +111,12 @@ public:
return case_;
}
//- Return case name
fileName& caseName()
{
return case_;
}
//- Return system name
const word& system() const
{

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.
@ -200,7 +200,7 @@ public:
dictionary();
//- Construct top-level empty dictionary with given name
dictionary(const fileName& name);
explicit dictionary(const fileName& name);
//- Construct given the entry name, parent dictionary and Istream,
// reading entries until lastEntry or EOF

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.
@ -35,7 +35,7 @@ Foam::Istream& Foam::regIOobject::readStream()
{
if (IFstream::debug)
{
Info<< "regIOobject::readStream() : "
Pout<< "regIOobject::readStream() : "
<< "reading object " << name()
<< " from file " << objectPath()
<< endl;
@ -112,7 +112,7 @@ Foam::Istream& Foam::regIOobject::readStream(const word& expectName)
{
if (IFstream::debug)
{
Info<< "regIOobject::readStream(const word&) : "
Pout<< "regIOobject::readStream(const word&) : "
<< "reading object " << name()
<< " from file " << objectPath()
<< endl;
@ -149,7 +149,7 @@ void Foam::regIOobject::close()
{
if (IFstream::debug)
{
Info<< "regIOobject::close() : "
Pout<< "regIOobject::close() : "
<< "finished reading " << filePath()
<< endl;
}
@ -288,7 +288,7 @@ bool Foam::regIOobject::readIfModified()
if (modified())
{
const fileName& fName = time().getFile(watchIndex_);
Info<< "regIOobject::readIfModified() : " << nl
Pout<< "regIOobject::readIfModified() : " << nl
<< " Re-reading object " << name()
<< " from file " << fName << endl;
return read();

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.
@ -40,7 +40,7 @@ if (&(df1).mesh() != &(df2).mesh()) \
FatalErrorIn("checkField(df1, df2, op)") \
<< "different mesh for fields " \
<< (df1).name() << " and " << (df2).name() \
<< " during operatrion " << op \
<< " during operation " << op \
<< abort(FatalError); \
}

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.
@ -149,6 +149,15 @@ public:
const word& fieldDictEntry="value"
);
//- Construct from dictionary
DimensionedField
(
const IOobject&,
const Mesh& mesh,
const dictionary& fieldDict,
const word& fieldDictEntry="value"
);
//- Construct as copy
DimensionedField
(

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -80,6 +80,24 @@ Foam::DimensionedField<Type, GeoMesh>::DimensionedField
}
template<class Type, class GeoMesh>
Foam::DimensionedField<Type, GeoMesh>::DimensionedField
(
const IOobject& io,
const Mesh& mesh,
const dictionary& fieldDict,
const word& fieldDictEntry
)
:
regIOobject(io),
Field<Type>(0),
mesh_(mesh),
dimensions_(dimless)
{
readField(fieldDict, fieldDictEntry);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type, class GeoMesh>

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.
@ -27,6 +27,8 @@ License
#include "FieldM.H"
#include "dictionary.H"
#include "contiguous.H"
#include "mapDistributeBase.H"
#include "flipOp.H"
// * * * * * * * * * * * * * * * Static Members * * * * * * * * * * * * * * //
@ -115,12 +117,13 @@ template<class Type>
Foam::Field<Type>::Field
(
const UList<Type>& mapF,
const FieldMapper& mapper
const FieldMapper& mapper,
const bool applyFlip
)
:
List<Type>(mapper.size())
{
map(mapF, mapper);
map(mapF, mapper, applyFlip);
}
@ -129,12 +132,13 @@ Foam::Field<Type>::Field
(
const UList<Type>& mapF,
const FieldMapper& mapper,
const Type& defaultValue
const Type& defaultValue,
const bool applyFlip
)
:
List<Type>(mapper.size(), defaultValue)
{
map(mapF, mapper);
map(mapF, mapper, applyFlip);
}
@ -143,12 +147,13 @@ Foam::Field<Type>::Field
(
const UList<Type>& mapF,
const FieldMapper& mapper,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const bool applyFlip
)
:
List<Type>(defaultValues)
{
map(mapF, mapper);
map(mapF, mapper, applyFlip);
}
@ -156,12 +161,13 @@ template<class Type>
Foam::Field<Type>::Field
(
const tmp<Field<Type> >& tmapF,
const FieldMapper& mapper
const FieldMapper& mapper,
const bool applyFlip
)
:
List<Type>(mapper.size())
{
map(tmapF, mapper);
map(tmapF, mapper, applyFlip);
}
@ -170,12 +176,13 @@ Foam::Field<Type>::Field
(
const tmp<Field<Type> >& tmapF,
const FieldMapper& mapper,
const Type& defaultValue
const Type& defaultValue,
const bool applyFlip
)
:
List<Type>(mapper.size(), defaultValue)
{
map(tmapF, mapper);
map(tmapF, mapper, applyFlip);
}
@ -184,12 +191,13 @@ Foam::Field<Type>::Field
(
const tmp<Field<Type> >& tmapF,
const FieldMapper& mapper,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const bool applyFlip
)
:
List<Type>(defaultValues)
{
map(tmapF, mapper);
map(tmapF, mapper, applyFlip);
}
@ -443,21 +451,57 @@ template<class Type>
void Foam::Field<Type>::map
(
const UList<Type>& mapF,
const FieldMapper& mapper
const FieldMapper& mapper,
const bool applyFlip
)
{
if
(
mapper.direct()
&& notNull(mapper.directAddressing())
&& mapper.directAddressing().size()
)
if (mapper.distributed())
{
map(mapF, mapper.directAddressing());
// Fetch remote parts of mapF
const mapDistributeBase& distMap = mapper.distributeMap();
Field<Type> newMapF(mapF);
if (applyFlip)
{
distMap.distribute(newMapF);
}
else
{
distMap.distribute(newMapF, noOp());
}
if (mapper.direct() && notNull(mapper.directAddressing()))
{
map(newMapF, mapper.directAddressing());
}
else if (!mapper.direct())
{
map(newMapF, mapper.addressing(), mapper.weights());
}
else if (mapper.direct() && isNull(mapper.directAddressing()))
{
// Special case, no local mapper. Assume ordering already correct
// from distribution. Note: this behaviour is different compared
// to local mapper.
this->transfer(newMapF);
this->setSize(mapper.size());
}
}
else if (!mapper.direct() && mapper.addressing().size())
else
{
map(mapF, mapper.addressing(), mapper.weights());
if
(
mapper.direct()
&& notNull(mapper.directAddressing())
&& mapper.directAddressing().size()
)
{
map(mapF, mapper.directAddressing());
}
else if (!mapper.direct() && mapper.addressing().size())
{
map(mapF, mapper.addressing(), mapper.weights());
}
}
}
@ -466,10 +510,11 @@ template<class Type>
void Foam::Field<Type>::map
(
const tmp<Field<Type> >& tmapF,
const FieldMapper& mapper
const FieldMapper& mapper,
const bool applyFlip
)
{
map(tmapF(), mapper);
map(tmapF(), mapper, applyFlip);
tmapF.clear();
}
@ -477,25 +522,62 @@ void Foam::Field<Type>::map
template<class Type>
void Foam::Field<Type>::autoMap
(
const FieldMapper& mapper
const FieldMapper& mapper,
const bool applyFlip
)
{
if
(
(
mapper.direct()
&& notNull(mapper.directAddressing())
&& mapper.directAddressing().size()
)
|| (!mapper.direct() && mapper.addressing().size())
)
if (mapper.distributed())
{
// Fetch remote parts of *this
const mapDistributeBase& distMap = mapper.distributeMap();
Field<Type> fCpy(*this);
map(fCpy, mapper);
if (applyFlip)
{
distMap.distribute(fCpy);
}
else
{
distMap.distribute(fCpy, noOp());
}
if
(
(mapper.direct()
&& notNull(mapper.directAddressing()))
|| !mapper.direct()
)
{
this->map(fCpy, mapper);
}
else if (mapper.direct() && isNull(mapper.directAddressing()))
{
// Special case, no local mapper. Assume ordering already correct
// from distribution. Note: this behaviour is different compared
// to local mapper.
this->transfer(fCpy);
this->setSize(mapper.size());
}
}
else
{
this->setSize(mapper.size());
if
(
(
mapper.direct()
&& notNull(mapper.directAddressing())
&& mapper.directAddressing().size()
)
|| (!mapper.direct() && mapper.addressing().size())
)
{
Field<Type> fCpy(*this);
map(fCpy, mapper);
}
else
{
this->setSize(mapper.size());
}
}
}

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.
@ -157,7 +157,8 @@ public:
Field
(
const UList<Type>& mapF,
const FieldMapper& map
const FieldMapper& map,
const bool applyFlip = true
);
//- Construct by mapping from the given field
@ -165,7 +166,8 @@ public:
(
const UList<Type>& mapF,
const FieldMapper& map,
const Type& defaultValue
const Type& defaultValue,
const bool applyFlip = true
);
//- Construct by mapping from the given field
@ -173,14 +175,16 @@ public:
(
const UList<Type>& mapF,
const FieldMapper& map,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const bool applyFlip = true
);
//- Construct by mapping from the given tmp field
Field
(
const tmp<Field<Type> >& tmapF,
const FieldMapper& map
const FieldMapper& map,
const bool applyFlip = true
);
//- Construct by mapping from the given tmp field. Supplied uniform
@ -189,7 +193,8 @@ public:
(
const tmp<Field<Type> >& tmapF,
const FieldMapper& map,
const Type& defaultValue
const Type& defaultValue,
const bool applyFlip = true
);
//- Construct by mapping from the given tmp field. Supplied values
@ -198,7 +203,8 @@ public:
(
const tmp<Field<Type> >& tmapF,
const FieldMapper& map,
const UList<Type>& defaultValues
const UList<Type>& defaultValues,
const bool applyFlip = true
);
//- Construct as copy
@ -269,20 +275,23 @@ public:
void map
(
const UList<Type>& mapF,
const FieldMapper& map
const FieldMapper& map,
const bool applyFlip = true
);
//- Map from the given tmp field
void map
(
const tmp<Field<Type> >& tmapF,
const FieldMapper& map
const FieldMapper& map,
const bool applyFlip = true
);
//- Map from self
void autoMap
(
const FieldMapper& map
const FieldMapper& map,
const bool applyFlip = true
);
//- 1 to 1 reverse-map from the given field

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -37,6 +37,8 @@ Description
namespace Foam
{
class mapDistributeBase;
/*---------------------------------------------------------------------------*\
Class FieldMapper Declaration
\*---------------------------------------------------------------------------*/
@ -64,6 +66,19 @@ public:
virtual bool direct() const = 0;
virtual bool distributed() const
{
return false;
}
virtual const mapDistributeBase& distributeMap() const
{
FatalErrorIn("FieldMapper::distributeMap() const")
<< "attempt to access null distributeMap"
<< abort(FatalError);
return *reinterpret_cast<mapDistributeBase*>(NULL);
}
//- Are there unmapped values? I.e. do all size() elements get
// get value
virtual bool hasUnmapped() const = 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.
@ -37,7 +37,7 @@ if ((gf1).mesh() != (gf2).mesh()) \
FatalErrorIn("checkField(gf1, gf2, op)") \
<< "different mesh for fields " \
<< (gf1).name() << " and " << (gf2).name() \
<< " during operatrion " << op \
<< " during operation " << op \
<< abort(FatalError); \
}
@ -319,7 +319,8 @@ template<class Type, template<class> class PatchField, class GeoMesh>
Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
(
const IOobject& io,
const Mesh& mesh
const Mesh& mesh,
const bool readOldTime
)
:
DimensionedField<Type, GeoMesh>(io, mesh, dimless, false),
@ -344,7 +345,10 @@ Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
<< exit(FatalIOError);
}
readOldTimeIfPresent();
if (readOldTime)
{
readOldTimeIfPresent();
}
if (debug)
{
@ -384,8 +388,6 @@ Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
<< exit(FatalIOError);
}
readOldTimeIfPresent();
if (debug)
{
Info<< "Finishing dictionary-construct of "
@ -600,7 +602,7 @@ Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
if (debug)
{
Info<< "GeometricField<Type, PatchField, GeoMesh>::GeometricField : "
"constructing as copy resetting IO params"
"constructing as copy resetting IO params and patch type"
<< endl << this->info() << endl;
}

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.
@ -337,7 +337,8 @@ public:
GeometricField
(
const IOobject&,
const Mesh&
const Mesh&,
const bool readOldTime = true
);
//- Construct from dictionary

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -32,19 +32,16 @@ License
// Read all fields of type. Returns names of fields read. Guarantees all
// processors to read fields in same order.
template<class GeoField, class Mesh>
Foam::wordList Foam::ReadFields
Foam::wordList Foam::fieldNames
(
const Mesh& mesh,
const IOobjectList& objects,
PtrList<GeoField>& fields,
const IOobjectList& fieldObjects,
const bool syncPar
)
{
// Search list of objects for wanted type
IOobjectList fieldObjects(objects.lookupClass(GeoField::typeName));
wordList masterNames(fieldObjects.names());
// Get sorted field names. Sorting needed in parallel since different
// processors (using different file servers) might pick up the files
// in different order.
wordList masterNames(fieldObjects.sortedNames());
if (syncPar && Pstream::parRun())
{
@ -64,9 +61,7 @@ Foam::wordList Foam::ReadFields
{
FatalErrorIn
(
"ReadFields<class GeoField, class Mesh>"
"(const Mesh&, const IOobjectList&, PtrList<GeoField>&"
", const bool)"
"fieldNames(const IOobjectList&, const bool syncPar)"
) << "Fields not synchronised across processors." << endl
<< "Master has fields " << masterNames
<< " processor " << Pstream::myProcNo()
@ -82,9 +77,7 @@ Foam::wordList Foam::ReadFields
{
FatalErrorIn
(
"ReadFields<class GeoField, class Mesh>"
"(const Mesh&, const IOobjectList&, PtrList<GeoField>&"
", const bool)"
"fieldNames(const IOobjectList&, const bol syncPar)"
) << "Fields not synchronised across processors." << endl
<< "Master has fields " << masterNames
<< " processor " << Pstream::myProcNo()
@ -92,169 +85,8 @@ Foam::wordList Foam::ReadFields
}
}
fields.setSize(masterNames.size());
// Make sure to read in masterNames order.
forAll(masterNames, i)
{
Info<< "Reading " << GeoField::typeName << ' ' << masterNames[i]
<< endl;
const IOobject& io = *fieldObjects[masterNames[i]];
fields.set
(
i,
new GeoField
(
IOobject
(
io.name(),
io.instance(),
io.local(),
io.db(),
IOobject::MUST_READ,
IOobject::AUTO_WRITE,
io.registerObject()
),
mesh
)
);
}
return masterNames;
}
template<class GeoField>
void Foam::ReadFields
(
const word& fieldName,
const typename GeoField::Mesh& mesh,
const wordList& timeNames,
objectRegistry& fieldsCache
)
{
// Collect all times that are no longer used
{
HashSet<word> usedTimes(timeNames);
DynamicList<word> unusedTimes(fieldsCache.size());
forAllIter(objectRegistry, fieldsCache, timeIter)
{
const word& tm = timeIter.key();
if (!usedTimes.found(tm))
{
unusedTimes.append(tm);
}
}
//Info<< "Unloading times " << unusedTimes << endl;
forAll(unusedTimes, i)
{
objectRegistry& timeCache = const_cast<objectRegistry&>
(
fieldsCache.lookupObject<objectRegistry>(unusedTimes[i])
);
fieldsCache.checkOut(timeCache);
}
}
// Load any new fields
forAll(timeNames, i)
{
const word& tm = timeNames[i];
// Create if not found
if (!fieldsCache.found(tm))
{
//Info<< "Creating registry for time " << tm << endl;
// Create objectRegistry if not found
objectRegistry* timeCachePtr = new objectRegistry
(
IOobject
(
tm,
tm,
fieldsCache,
IOobject::NO_READ,
IOobject::NO_WRITE
)
);
timeCachePtr->store();
}
// Obtain cache for current time
const objectRegistry& timeCache =
fieldsCache.lookupObject<objectRegistry>
(
tm
);
// Store field if not found
if (!timeCache.found(fieldName))
{
//Info<< "Loading field " << fieldName
// << " for time " << tm << endl;
GeoField loadedFld
(
IOobject
(
fieldName,
tm,
mesh.thisDb(),
IOobject::MUST_READ,
IOobject::NO_WRITE,
false
),
mesh
);
// Transfer to timeCache (new objectRegistry and store flag)
GeoField* fldPtr = new GeoField
(
IOobject
(
fieldName,
tm,
timeCache,
IOobject::NO_READ,
IOobject::NO_WRITE
),
loadedFld
);
fldPtr->store();
}
}
}
template<class GeoField>
void Foam::ReadFields
(
const word& fieldName,
const typename GeoField::Mesh& mesh,
const wordList& timeNames,
const word& registryName
)
{
ReadFields<GeoField>
(
fieldName,
mesh,
timeNames,
const_cast<objectRegistry&>
(
mesh.thisDb().subRegistry(registryName, true)
)
);
}
// ************************************************************************* //

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -29,6 +29,7 @@ Description
SourceFiles
ReadFields.C
ReadFieldsTemplates.C
\*---------------------------------------------------------------------------*/
@ -37,6 +38,7 @@ SourceFiles
#include "PtrList.H"
#include "wordList.H"
#include "GeometricField.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -45,7 +47,23 @@ namespace Foam
class IOobjectList;
//- Helper routine to read fields
//- Get sorted names of fields of type. If syncPar and running in parallel
// check for identical names
wordList fieldNames(const IOobjectList& objects, const bool syncPar);
//- Helper routine to read Geometric fields
template<class Type, template<class> class PatchField, class GeoMesh>
wordList ReadFields
(
const typename GeoMesh::Mesh& mesh,
const IOobjectList& objects,
PtrList<GeometricField<Type, PatchField, GeoMesh> >& fields,
const bool syncPar = true,
const bool readOldTime = false
);
//- Helper routine to read other mesh fields
template<class GeoField, class Mesh>
wordList ReadFields
(
@ -55,6 +73,16 @@ wordList ReadFields
const bool syncPar = true
);
//- Helper routine to read non-mesh fields (e.g. uniformDimensionedField like
// 'g')
template<class GeoField>
wordList ReadFields
(
const IOobjectList& objects,
PtrList<GeoField>& fields,
const bool syncPar = true
);
//- Helper routine to read GeometricFields. The fieldsCache is per time
// an objectRegistry of all stored fields
template<class GeoField>
@ -82,7 +110,7 @@ static void ReadFields
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "ReadFields.C"
# include "ReadFieldsTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -0,0 +1,314 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2014 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 "ReadFields.H"
#include "HashSet.H"
#include "IOobjectList.H"
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
// Read all GeometricFields of type. Returns names of fields read. Guarantees
// all processors to read fields in same order.
template<class Type, template<class> class PatchField, class GeoMesh>
Foam::wordList Foam::ReadFields
(
const typename GeoMesh::Mesh& mesh,
const IOobjectList& objects,
PtrList<GeometricField<Type, PatchField, GeoMesh> >& fields,
const bool syncPar,
const bool readOldTime
)
{
typedef GeometricField<Type, PatchField, GeoMesh> GeoField;
// Search list of objects for wanted type
IOobjectList fieldObjects(objects.lookupClass(GeoField::typeName));
const wordList masterNames(fieldNames(fieldObjects, syncPar));
fields.setSize(masterNames.size());
// Make sure to read in masterNames order.
forAll(masterNames, i)
{
Info<< "Reading " << GeoField::typeName << ' ' << masterNames[i]
<< endl;
const IOobject& io = *fieldObjects[masterNames[i]];
fields.set
(
i,
new GeoField
(
IOobject
(
io.name(),
io.instance(),
io.local(),
io.db(),
IOobject::MUST_READ,
IOobject::AUTO_WRITE,
io.registerObject()
),
mesh,
readOldTime
)
);
}
return masterNames;
}
// Read all fields of type. Returns names of fields read. Guarantees all
// processors to read fields in same order.
template<class GeoField, class Mesh>
Foam::wordList Foam::ReadFields
(
const Mesh& mesh,
const IOobjectList& objects,
PtrList<GeoField>& fields,
const bool syncPar
)
{
// Search list of objects for wanted type
IOobjectList fieldObjects(objects.lookupClass(GeoField::typeName));
const wordList masterNames(fieldNames(fieldObjects, syncPar));
fields.setSize(masterNames.size());
// Make sure to read in masterNames order.
forAll(masterNames, i)
{
Info<< "Reading " << GeoField::typeName << ' ' << masterNames[i]
<< endl;
const IOobject& io = *fieldObjects[masterNames[i]];
fields.set
(
i,
new GeoField
(
IOobject
(
io.name(),
io.instance(),
io.local(),
io.db(),
IOobject::MUST_READ,
IOobject::AUTO_WRITE,
io.registerObject()
),
mesh
)
);
}
return masterNames;
}
// Read all (non-mesh) fields of type. Returns names of fields read. Guarantees
// all processors to read fields in same order.
template<class GeoField>
Foam::wordList Foam::ReadFields
(
const IOobjectList& objects,
PtrList<GeoField>& fields,
const bool syncPar
)
{
// Search list of objects for wanted type
IOobjectList fieldObjects(objects.lookupClass(GeoField::typeName));
const wordList masterNames(fieldNames(fieldObjects, syncPar));
fields.setSize(masterNames.size());
// Make sure to read in masterNames order.
forAll(masterNames, i)
{
Info<< "Reading " << GeoField::typeName << ' ' << masterNames[i]
<< endl;
const IOobject& io = *fieldObjects[masterNames[i]];
fields.set
(
i,
new GeoField
(
IOobject
(
io.name(),
io.instance(),
io.local(),
io.db(),
IOobject::MUST_READ,
IOobject::AUTO_WRITE,
io.registerObject()
)
)
);
}
return masterNames;
}
template<class GeoField>
void Foam::ReadFields
(
const word& fieldName,
const typename GeoField::Mesh& mesh,
const wordList& timeNames,
objectRegistry& fieldsCache
)
{
// Collect all times that are no longer used
{
HashSet<word> usedTimes(timeNames);
DynamicList<word> unusedTimes(fieldsCache.size());
forAllIter(objectRegistry, fieldsCache, timeIter)
{
const word& tm = timeIter.key();
if (!usedTimes.found(tm))
{
unusedTimes.append(tm);
}
}
//Info<< "Unloading times " << unusedTimes << endl;
forAll(unusedTimes, i)
{
objectRegistry& timeCache = const_cast<objectRegistry&>
(
fieldsCache.lookupObject<objectRegistry>(unusedTimes[i])
);
fieldsCache.checkOut(timeCache);
}
}
// Load any new fields
forAll(timeNames, i)
{
const word& tm = timeNames[i];
// Create if not found
if (!fieldsCache.found(tm))
{
//Info<< "Creating registry for time " << tm << endl;
// Create objectRegistry if not found
objectRegistry* timeCachePtr = new objectRegistry
(
IOobject
(
tm,
tm,
fieldsCache,
IOobject::NO_READ,
IOobject::NO_WRITE
)
);
timeCachePtr->store();
}
// Obtain cache for current time
const objectRegistry& timeCache =
fieldsCache.lookupObject<objectRegistry>
(
tm
);
// Store field if not found
if (!timeCache.found(fieldName))
{
//Info<< "Loading field " << fieldName
// << " for time " << tm << endl;
GeoField loadedFld
(
IOobject
(
fieldName,
tm,
mesh.thisDb(),
IOobject::MUST_READ,
IOobject::NO_WRITE,
false
),
mesh
);
// Transfer to timeCache (new objectRegistry and store flag)
GeoField* fldPtr = new GeoField
(
IOobject
(
fieldName,
tm,
timeCache,
IOobject::NO_READ,
IOobject::NO_WRITE
),
loadedFld
);
fldPtr->store();
}
}
}
template<class GeoField>
void Foam::ReadFields
(
const word& fieldName,
const typename GeoField::Mesh& mesh,
const wordList& timeNames,
const word& registryName
)
{
ReadFields<GeoField>
(
fieldName,
mesh,
timeNames,
const_cast<objectRegistry&>
(
mesh.thisDb().subRegistry(registryName, true)
)
);
}
// ************************************************************************* //

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -103,7 +103,7 @@ bool Foam::UniformDimensionedField<Type>::writeData(Ostream& os) const
os.writeKeyword("value") << this->value()/multiplier << token::END_STATEMENT
<< nl << nl;
return (os.good());
return os.good();
}

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.
@ -64,6 +64,17 @@ Foam::argList::initValidTables::initValidTables()
);
validParOptions.set("roots", "(dir1 .. dirN)");
argList::addOption
(
"decomposeParDict", "file",
"read decomposePar dictionary from specified location"
);
validParOptions.set
(
"decomposeParDict",
"file"
);
argList::addBoolOption
(
"noFunctionObjects",
@ -147,6 +158,7 @@ void Foam::argList::noParallel()
{
removeOption("parallel");
removeOption("roots");
removeOption("decomposeParDict");
validParOptions.clear();
}
@ -601,13 +613,23 @@ void Foam::argList::parse
}
else
{
source = rootPath_/globalCase_/"system/decomposeParDict";
source = rootPath_/globalCase_/"system"/"decomposeParDict";
// Override with -decomposeParDict
if (options_.found("decomposeParDict"))
{
source = options_["decomposeParDict"];
if (isDir(source))
{
source = source/"decomposeParDict";
}
}
IFstream decompDictStream(source);
if (!decompDictStream.good())
{
FatalError
<< "Cannot read "
<< "Cannot read decomposeParDict from "
<< decompDictStream.name()
<< exit(FatalError);
}
@ -770,9 +792,6 @@ void Foam::argList::parse
if (Pstream::master())
{
slaveProcs.setSize(Pstream::nProcs() - 1);
string slaveMachine;
label slavePid;
label procI = 0;
for
(
@ -782,15 +801,30 @@ void Foam::argList::parse
)
{
IPstream fromSlave(Pstream::scheduled, slave);
fromSlave >> slaveMachine >> slavePid;
string slaveBuild;
string slaveMachine;
label slavePid;
fromSlave >> slaveBuild >> slaveMachine >> slavePid;
slaveProcs[procI++] = slaveMachine + "." + name(slavePid);
// Check build string to make sure all processors are running
// the same build
if (slaveBuild != Foam::FOAMbuild)
{
FatalErrorIn(executable())
<< "Master is running version " << Foam::FOAMbuild
<< "; slave " << procI << " is running version "
<< slaveBuild
<< exit(FatalError);
}
}
}
else
{
OPstream toMaster(Pstream::scheduled, Pstream::masterNo());
toMaster << hostName() << pid();
toMaster << string(Foam::FOAMbuild) << hostName() << pid();
}
}

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2014 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -72,7 +72,7 @@ Foam::IOmapDistribute::IOmapDistribute
:
regIOobject(io)
{
// Temporary warning
// Temporary warning
if (io.readOpt() == IOobject::MUST_READ_IF_MODIFIED)
{
WarningIn("IOmapDistribute::IOmapDistribute(const IOobject&)")

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.
@ -118,6 +118,12 @@ Note:
+------+ 0
When constructing from components optionally a 'flip' on
the maps can be specified. This will interpret the map
values as index+flip, similar to e.g. faceProcAddressing. The flip
will only be applied to fieldTypes (scalar, vector, .. triad)
SourceFiles
mapDistribute.C
mapDistributeTemplates.C
@ -127,12 +133,8 @@ SourceFiles
#ifndef mapDistribute_H
#define mapDistribute_H
#include "mapDistributeBase.H"
#include "transformList.H"
#include "labelList.H"
#include "labelPair.H"
#include "Pstream.H"
#include "boolList.H"
#include "Map.H"
#include "vectorTensorTransform.H"
#include "coupledPolyPatch.H"
@ -141,81 +143,27 @@ SourceFiles
namespace Foam
{
class mapPolyMesh;
class globalIndex;
class PstreamBuffers;
class globalIndexAndTransform;
//class vectorTensorTransform;
/*---------------------------------------------------------------------------*\
Class mapDistribute Declaration
\*---------------------------------------------------------------------------*/
class mapDistribute
:
public mapDistributeBase
{
// Private data
//- Size of reconstructed data
label constructSize_;
//- For every globalIndexAndTransform::transformPermutations
// gives the elements that need to be transformed
labelListList transformElements_;
//- Maps from subsetted data back to original data
labelListList subMap_;
//- Maps from subsetted data to new reconstructed data
labelListList constructMap_;
// Optional transformation
//- For every globalIndexAndTransform::transformPermutations
// gives the elements that need to be transformed
labelListList transformElements_;
//- Destination in constructMap for transformed elements
labelList transformStart_;
//- Schedule
mutable autoPtr<List<labelPair> > schedulePtr_;
// Private Member Functions
static void checkReceivedSize
(
const label procI,
const label expectedSize,
const label receivedSize
);
void calcCompactAddressing
(
const globalIndex& globalNumbering,
const labelList& elements,
List<Map<label> >& compactMap
) const;
void calcCompactAddressing
(
const globalIndex& globalNumbering,
const labelListList& elements,
List<Map<label> >& compactMap
) const;
void exchangeAddressing
(
const int tag,
const globalIndex& globalNumbering,
labelList& elements,
List<Map<label> >& compactMap,
labelList& compactStart
);
void exchangeAddressing
(
const int tag,
const globalIndex& globalNumbering,
labelListList& elements,
List<Map<label> >& compactMap,
labelList& compactStart
);
//- Destination in constructMap for transformed elements
labelList transformStart_;
// Private Member Functions
//- Helper function: copy transformElements without transformation
template<class T>
@ -241,7 +189,6 @@ class mapDistribute
const TransformOp& top
) const;
public:
// Public classes
@ -358,7 +305,6 @@ public:
};
// Declare name of the class and its debug switch
ClassName("mapDistribute");
@ -373,7 +319,9 @@ public:
(
const label constructSize,
const Xfer<labelListList>& subMap,
const Xfer<labelListList>& constructMap
const Xfer<labelListList>& constructMap,
const bool subHasFlip = false,
const bool constructHasFlip = false
);
//- Construct from components
@ -383,7 +331,9 @@ public:
const Xfer<labelListList>& subMap,
const Xfer<labelListList>& constructMap,
const Xfer<labelListList>& transformElements,
const Xfer<labelList>& transformStart
const Xfer<labelList>& transformStart,
const bool subHasFlip = false,
const bool constructHasFlip = false
);
//- Construct from reverse addressing: per data item the send
@ -453,47 +403,22 @@ public:
//- Construct copy
mapDistribute(const mapDistribute&);
//- Construct from Istream
mapDistribute(Istream&);
//- Clone
autoPtr<mapDistribute> clone() const;
//- Destructor
virtual ~mapDistribute()
{}
// Member Functions
// Access
//- Constructed data size
label constructSize() const
{
return constructSize_;
}
//- Constructed data size
label& constructSize()
{
return constructSize_;
}
//- From subsetted data back to original data
const labelListList& subMap() const
{
return subMap_;
}
//- From subsetted data back to original data
labelListList& subMap()
{
return subMap_;
}
//- From subsetted data to new reconstructed data
const labelListList& constructMap() const
{
return constructMap_;
}
//- From subsetted data to new reconstructed data
labelListList& constructMap()
{
return constructMap_;
}
//- For every globalIndexAndTransform::transformPermutations
// gives the elements that need to be transformed
const labelListList& transformElements() const
@ -510,17 +435,6 @@ public:
//- Find transform from transformElements
label whichTransform(const label index) const;
//- Calculate a schedule. See above.
static List<labelPair> schedule
(
const labelListList& subMap,
const labelListList& constructMap,
const int tag
);
//- Return a schedule. Demand driven. See above.
const List<labelPair>& schedule() const;
// Other
@ -530,53 +444,25 @@ public:
//- Transfer contents to the Xfer container
Xfer<mapDistribute> xfer();
//- Helper for construct from globalIndex. Renumbers element
// (in globalIndex numbering) into compact indices.
static label renumber
(
const globalIndex&,
const List<Map<label> >& compactMap,
const label globalElement
);
//- Compact maps. Gets per field a bool whether it is used (locally)
// and works out itself what this side and sender side can remove
// from maps.
void compact
(
const boolList& elemIsUsed,
const int tag = UPstream::msgType()
);
//- Distribute data. Note:schedule only used for Pstream::scheduled
// for now, all others just use send-to-all, receive-from-all.
//- Distribute data using default commsType.
template<class T>
static void distribute
void distribute
(
const Pstream::commsTypes commsType,
const List<labelPair>& schedule,
const label constructSize,
const labelListList& subMap,
const labelListList& constructMap,
List<T>&,
List<T>& fld,
const bool dummyTransform = true,
const int tag = UPstream::msgType()
);
) const;
//- Distribute data. If multiple processors writing to same
// position adds contributions using cop.
template<class T, class CombineOp>
static void distribute
//- Distribute data using default commsType.
template<class T, class negateOp>
void distribute
(
const Pstream::commsTypes commsType,
const List<labelPair>& schedule,
const label constructSize,
const labelListList& subMap,
const labelListList& constructMap,
List<T>&,
const CombineOp& cop,
const T& nullValue,
List<T>& fld,
const negateOp& negOp,
const bool dummyTransform = true,
const int tag = UPstream::msgType()
);
) const;
//- Distribute data using default commsType.
template<class T>
@ -587,25 +473,6 @@ public:
const int tag = UPstream::msgType()
) const;
//- Distribute data using default commsType.
template<class T>
void distribute
(
List<T>& fld,
const bool dummyTransform = true,
const int tag = UPstream::msgType()
) const;
//- Same but with transforms
template<class T, class TransformOp>
void distribute
(
const globalIndexAndTransform&,
List<T>& fld,
const TransformOp& top,
const int tag = UPstream::msgType()
) const;
//- Reverse distribute data using default commsType.
template<class T>
void reverseDistribute
@ -616,17 +483,6 @@ public:
const int tag = UPstream::msgType()
) const;
//- Same but with transforms
template<class T, class TransformOp>
void reverseDistribute
(
const globalIndexAndTransform&,
const label constructSize,
List<T>& fld,
const TransformOp& top,
const int tag = UPstream::msgType()
) const;
//- Reverse distribute data using default commsType.
// Since constructSize might be larger than supplied size supply
// a nullValue
@ -640,7 +496,28 @@ public:
const int tag = UPstream::msgType()
) const;
//- Same but with transforms
//- Distribute with transforms
template<class T, class TransformOp>
void distribute
(
const globalIndexAndTransform&,
List<T>& fld,
const TransformOp& top,
const int tag = UPstream::msgType()
) const;
//- Reverse distribute with transforms
template<class T, class TransformOp>
void reverseDistribute
(
const globalIndexAndTransform&,
const label constructSize,
List<T>& fld,
const TransformOp& top,
const int tag = UPstream::msgType()
) const;
//- Reverse distribute with transforms
template<class T, class TransformOp>
void reverseDistribute
(
@ -652,13 +529,6 @@ public:
const int tag = UPstream::msgType()
) const;
//- Do all sends using PstreamBuffers
template<class T>
void send(PstreamBuffers&, const List<T>&) const;
//- Do all receives using PstreamBuffers
template<class T>
void receive(PstreamBuffers&, List<T>&) const;
//- Debug: print layout. Can only be used on maps with sorted
// storage (local data first, then non-local data)
void printLayout(Ostream& os) const;
@ -676,7 +546,6 @@ public:
void operator=(const mapDistribute&);
// IOstream operators
//- Read dictionary from Istream
@ -688,6 +557,7 @@ public:
};
// Template specialisation for primitives that do not need transform
template<>
void mapDistribute::transform::operator()
(

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,485 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::mapDistributeBase
Description
Class containing processor-to-processor mapping information.
We store mapping from the bits-to-send to the complete starting list
(subXXXMap) and from the received bits to their location in the new
list (constructXXXMap).
Note:
Schedule is a list of processor pairs (one send, one receive. One of
them will be myself) which forms a scheduled (i.e. non-buffered) exchange.
See distribute on how to use it.
Note2: number of items sent on one processor have to equal the number
of items received on the other processor.
To aid constructing these maps there are the constructors from global
numbering, either with or without transforms.
Constructors using compact numbering: layout is
- all my own elements first (whether used or not)
- followed by used-only remote elements sorted by remote processor.
So e.g 4 procs and on proc 1 the compact
table will first have all globalIndex.localSize() elements from proc1
followed by used-only elements of proc0, proc2, proc3.
The constructed mapDistributeBase sends the local elements from and
receives the remote elements into their compact position.
compactMap[procI] is the position of elements from procI in the compact
map. compactMap[myProcNo()] is empty since trivial addressing.
It rewrites the input global indices into indices into the constructed
data.
When constructing from components optionally a 'flip' on
the maps can be specified. This will interpret the map
values as index+flip, similar to e.g. faceProcAddressing. The flip
will only be applied to fieldTypes (scalar, vector, .. triad)
SourceFiles
mapDistributeBase.C
mapDistributeBaseTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef mapDistributeBase_H
#define mapDistributeBase_H
#include "labelList.H"
#include "labelPair.H"
#include "Pstream.H"
#include "boolList.H"
#include "Map.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
class mapPolyMesh;
class globalIndex;
class PstreamBuffers;
/*---------------------------------------------------------------------------*\
Class mapDistributeBase Declaration
\*---------------------------------------------------------------------------*/
class mapDistributeBase
{
protected:
// Protected data
//- Size of reconstructed data
label constructSize_;
//- Maps from subsetted data back to original data
labelListList subMap_;
//- Maps from subsetted data to new reconstructed data
labelListList constructMap_;
//- Whether subMap includes flip or not
bool subHasFlip_;
//- Whether constructMap includes flip or not
bool constructHasFlip_;
//- Schedule
mutable autoPtr<List<labelPair> > schedulePtr_;
// Private Member Functions
static void checkReceivedSize
(
const label procI,
const label expectedSize,
const label receivedSize
);
void calcCompactAddressing
(
const globalIndex& globalNumbering,
const labelList& elements,
List<Map<label> >& compactMap
) const;
void calcCompactAddressing
(
const globalIndex& globalNumbering,
const labelListList& elements,
List<Map<label> >& compactMap
) const;
void exchangeAddressing
(
const int tag,
const globalIndex& globalNumbering,
labelList& elements,
List<Map<label> >& compactMap,
labelList& compactStart
);
void exchangeAddressing
(
const int tag,
const globalIndex& globalNumbering,
labelListList& elements,
List<Map<label> >& compactMap,
labelList& compactStart
);
template<class T, class CombineOp, class negateOp>
static void flipAndCombine
(
const UList<label>& map,
const bool hasFlip,
const UList<T>& rhs,
const CombineOp& cop,
const negateOp& negOp,
List<T>& lhs
);
template<class T, class negateOp>
static T accessAndFlip
(
const UList<T>& fld,
const label index,
const bool hasFlip,
const negateOp& negOp
);
public:
// Declare name of the class and its debug switch
ClassName("mapDistributeBase");
// Constructors
//- Construct null
mapDistributeBase();
//- Construct from components
mapDistributeBase
(
const label constructSize,
const Xfer<labelListList>& subMap,
const Xfer<labelListList>& constructMap,
const bool subHasFlip = false,
const bool constructHasFlip = false
);
//- Construct from reverse addressing: per data item the send
// processor and the receive processor. (note: data is not stored
// sorted per processor so cannot use printLayout).
mapDistributeBase
(
const labelList& sendProcs,
const labelList& recvProcs
);
//- Construct from list of (possibly) remote elements in globalIndex
// numbering (or -1). Determines compact numbering (see above) and
// distribute map to get data into this ordering and renumbers the
// elements to be in compact numbering.
mapDistributeBase
(
const globalIndex&,
labelList& elements,
List<Map<label> >& compactMap,
const int tag = Pstream::msgType()
);
//- Special variant that works with the info sorted into bins
// according to local indices. E.g. think cellCells where
// cellCells[localCellI] is a list of global cells
mapDistributeBase
(
const globalIndex&,
labelListList& cellCells,
List<Map<label> >& compactMap,
const int tag = Pstream::msgType()
);
//- Construct by transferring parameter content
mapDistributeBase(const Xfer<mapDistributeBase>&);
//- Construct copy
mapDistributeBase(const mapDistributeBase&);
//- Construct from Istream
mapDistributeBase(Istream&);
// Member Functions
// Access
//- Constructed data size
label constructSize() const
{
return constructSize_;
}
//- Constructed data size
label& constructSize()
{
return constructSize_;
}
//- From subsetted data back to original data
const labelListList& subMap() const
{
return subMap_;
}
//- From subsetted data back to original data
labelListList& subMap()
{
return subMap_;
}
//- From subsetted data to new reconstructed data
const labelListList& constructMap() const
{
return constructMap_;
}
//- From subsetted data to new reconstructed data
labelListList& constructMap()
{
return constructMap_;
}
//- Does subMap include a sign
bool subHasFlip() const
{
return subHasFlip_;
}
//- Does subMap include a sign
bool& subHasFlip()
{
return subHasFlip_;
}
//- Does constructMap include a sign
bool constructHasFlip() const
{
return constructHasFlip_;
}
//- Does constructMap include a sign
bool& constructHasFlip()
{
return constructHasFlip_;
}
//- Calculate a schedule. See above.
static List<labelPair> schedule
(
const labelListList& subMap,
const labelListList& constructMap,
const int tag
);
//- Return a schedule. Demand driven. See above.
const List<labelPair>& schedule() const;
// Other
//- Transfer the contents of the argument and annul the argument.
void transfer(mapDistributeBase&);
//- Transfer contents to the Xfer container
Xfer<mapDistributeBase> xfer();
//- Helper for construct from globalIndex. Renumbers element
// (in globalIndex numbering) into compact indices.
static label renumber
(
const globalIndex&,
const List<Map<label> >& compactMap,
const label globalElement
);
//- Compact maps. Gets per field a bool whether it is used (locally)
// and works out itself what this side and sender side can remove
// from maps. Only compacts non-local elements (i.e. the stuff
// that gets sent over), does not change the local layout
void compact
(
const boolList& elemIsUsed,
const int tag = UPstream::msgType()
);
//- Compact all maps and layout. Returns compaction maps for
// subMap and constructMap
void compact
(
const boolList& elemIsUsed,
const label localSize, // max index for subMap
labelList& oldToNewSub,
labelList& oldToNewConstruct,
const int tag = UPstream::msgType()
);
//- Distribute data. Note:schedule only used for Pstream::scheduled
// for now, all others just use send-to-all, receive-from-all.
template<class T, class negateOp>
static void distribute
(
const Pstream::commsTypes commsType,
const List<labelPair>& schedule,
const label constructSize,
const labelListList& subMap,
const bool subHasFlip,
const labelListList& constructMap,
const bool constructHasFlip,
List<T>&,
const negateOp& negOp,
const int tag = UPstream::msgType()
);
//- Distribute data. If multiple processors writing to same
// position adds contributions using cop.
template<class T, class CombineOp, class negateOp>
static void distribute
(
const Pstream::commsTypes commsType,
const List<labelPair>& schedule,
const label constructSize,
const labelListList& subMap,
const bool subHasFlip,
const labelListList& constructMap,
const bool constructHasFlip,
List<T>&,
const CombineOp& cop,
const negateOp& negOp,
const T& nullValue,
const int tag = UPstream::msgType()
);
//- Distribute data using default commsType.
template<class T>
void distribute
(
List<T>& fld,
const int tag = UPstream::msgType()
) const;
//- Distribute data using default commsType.
template<class T, class negateOp>
void distribute
(
List<T>& fld,
const negateOp& negOp,
const int tag = UPstream::msgType()
) const;
//- Distribute data using default commsType.
template<class T>
void distribute
(
DynamicList<T>& fld,
const int tag = UPstream::msgType()
) const;
//- Reverse distribute data using default commsType.
template<class T>
void reverseDistribute
(
const label constructSize,
List<T>&,
const int tag = UPstream::msgType()
) const;
//- Reverse distribute data using default commsType.
// Since constructSize might be larger than supplied size supply
// a nullValue
template<class T>
void reverseDistribute
(
const label constructSize,
const T& nullValue,
List<T>& fld,
const int tag = UPstream::msgType()
) const;
//- Do all sends using PstreamBuffers
template<class T>
void send(PstreamBuffers&, const List<T>&) const;
//- Do all receives using PstreamBuffers
template<class T>
void receive(PstreamBuffers&, List<T>&) const;
//- Debug: print layout. Can only be used on maps with sorted
// storage (local data first, then non-local data)
void printLayout(Ostream& os) const;
//- Correct for topo change.
void updateMesh(const mapPolyMesh&)
{
notImplemented
(
"mapDistributeBase::updateMesh(const mapPolyMesh&)"
);
}
// Member Operators
void operator=(const mapDistributeBase&);
// IOstream operators
//- Read dictionary from Istream
friend Istream& operator>>(Istream&, mapDistributeBase&);
//- Write dictionary to Ostream
friend Ostream& operator<<(Ostream&, const mapDistributeBase&);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "mapDistributeBaseTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -26,37 +26,53 @@ License
#include "mapDistributePolyMesh.H"
#include "polyMesh.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::mapDistributePolyMesh::calcPatchSizes()
{
oldPatchSizes_.setSize(oldPatchStarts_.size());
// Calculate old patch sizes
for (label patchI = 0; patchI < oldPatchStarts_.size() - 1; patchI++)
if (oldPatchStarts_.size())
{
oldPatchSizes_[patchI] =
oldPatchStarts_[patchI + 1] - oldPatchStarts_[patchI];
}
// Calculate old patch sizes
for (label patchI = 0; patchI < oldPatchStarts_.size() - 1; patchI++)
{
oldPatchSizes_[patchI] =
oldPatchStarts_[patchI + 1] - oldPatchStarts_[patchI];
}
// Set the last one by hand
const label lastPatchID = oldPatchStarts_.size() - 1;
// Set the last one by hand
const label lastPatchID = oldPatchStarts_.size() - 1;
oldPatchSizes_[lastPatchID] = nOldFaces_ - oldPatchStarts_[lastPatchID];
oldPatchSizes_[lastPatchID] = nOldFaces_ - oldPatchStarts_[lastPatchID];
if (min(oldPatchSizes_) < 0)
{
FatalErrorIn("mapDistributePolyMesh::calcPatchSizes()")
<< "Calculated negative old patch size:" << oldPatchSizes_ << nl
<< "Error in mapping data" << abort(FatalError);
if (min(oldPatchSizes_) < 0)
{
FatalErrorIn("mapDistributePolyMesh::calcPatchSizes()")
<< "Calculated negative old patch size:" << oldPatchSizes_ << nl
<< "Error in mapping data" << abort(FatalError);
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
//- Construct from components
Foam::mapDistributePolyMesh::mapDistributePolyMesh()
:
nOldPoints_(0),
nOldFaces_(0),
nOldCells_(0),
oldPatchSizes_(0),
oldPatchStarts_(0),
oldPatchNMeshPoints_(0),
pointMap_(),
faceMap_(),
cellMap_(),
patchMap_()
{}
Foam::mapDistributePolyMesh::mapDistributePolyMesh
(
const polyMesh& mesh,
@ -78,10 +94,12 @@ Foam::mapDistributePolyMesh::mapDistributePolyMesh
const Xfer<labelListList>& constructPointMap,
const Xfer<labelListList>& constructFaceMap,
const Xfer<labelListList>& constructCellMap,
const Xfer<labelListList>& constructPatchMap
const Xfer<labelListList>& constructPatchMap,
const bool subFaceHasFlip,
const bool constructFaceHasFlip
)
:
mesh_(mesh),
nOldPoints_(nOldPoints),
nOldFaces_(nOldFaces),
nOldCells_(nOldCells),
@ -89,7 +107,14 @@ Foam::mapDistributePolyMesh::mapDistributePolyMesh
oldPatchStarts_(oldPatchStarts),
oldPatchNMeshPoints_(oldPatchNMeshPoints),
pointMap_(mesh.nPoints(), subPointMap, constructPointMap),
faceMap_(mesh.nFaces(), subFaceMap, constructFaceMap),
faceMap_
(
mesh.nFaces(),
subFaceMap,
constructFaceMap,
subFaceHasFlip,
constructFaceHasFlip
),
cellMap_(mesh.nCells(), subCellMap, constructCellMap),
patchMap_(mesh.boundaryMesh().size(), subPatchMap, constructPatchMap)
{
@ -97,8 +122,84 @@ Foam::mapDistributePolyMesh::mapDistributePolyMesh
}
Foam::mapDistributePolyMesh::mapDistributePolyMesh
(
// mesh before changes
const label nOldPoints,
const label nOldFaces,
const label nOldCells,
const Xfer<labelList>& oldPatchStarts,
const Xfer<labelList>& oldPatchNMeshPoints,
// how to transfer pieces of mesh
const Xfer<mapDistribute>& pointMap,
const Xfer<mapDistribute>& faceMap,
const Xfer<mapDistribute>& cellMap,
const Xfer<mapDistribute>& patchMap
)
:
nOldPoints_(nOldPoints),
nOldFaces_(nOldFaces),
nOldCells_(nOldCells),
oldPatchSizes_(oldPatchStarts().size()),
oldPatchStarts_(oldPatchStarts),
oldPatchNMeshPoints_(oldPatchNMeshPoints),
pointMap_(pointMap),
faceMap_(faceMap),
cellMap_(cellMap),
patchMap_(patchMap)
{
calcPatchSizes();
}
Foam::mapDistributePolyMesh::mapDistributePolyMesh
(
const Xfer<mapDistributePolyMesh>& map
)
:
nOldPoints_(map().nOldPoints_),
nOldFaces_(map().nOldFaces_),
nOldCells_(map().nOldCells_),
oldPatchSizes_(map().oldPatchSizes_.xfer()),
oldPatchStarts_(map().oldPatchStarts_.xfer()),
oldPatchNMeshPoints_(map().oldPatchNMeshPoints_.xfer()),
pointMap_(map().pointMap_.xfer()),
faceMap_(map().faceMap_.xfer()),
cellMap_(map().cellMap_.xfer()),
patchMap_(map().patchMap_.xfer())
{}
Foam::mapDistributePolyMesh::mapDistributePolyMesh(Istream& is)
{
is >> *this;
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::mapDistributePolyMesh::transfer(mapDistributePolyMesh& rhs)
{
nOldPoints_ = rhs.nOldPoints_;
nOldFaces_ = rhs.nOldFaces_;
nOldCells_ = rhs.nOldCells_;
oldPatchSizes_.transfer(rhs.oldPatchSizes_);
oldPatchStarts_.transfer(rhs.oldPatchStarts_);
oldPatchNMeshPoints_.transfer(rhs.oldPatchNMeshPoints_);
pointMap_.transfer(rhs.pointMap_);
faceMap_.transfer(rhs.faceMap_);
cellMap_.transfer(rhs.cellMap_);
patchMap_.transfer(rhs.patchMap_);
}
Foam::Xfer<Foam::mapDistributePolyMesh> Foam::mapDistributePolyMesh::xfer()
{
return xferMove(*this);
}
void Foam::mapDistributePolyMesh::distributePointIndices(labelList& lst) const
{
// Construct boolList from selected elements
@ -187,10 +288,61 @@ void Foam::mapDistributePolyMesh::distributePatchIndices(labelList& lst) const
}
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
void Foam::mapDistributePolyMesh::operator=(const mapDistributePolyMesh& rhs)
{
nOldPoints_ = rhs.nOldPoints_;
nOldFaces_ = rhs.nOldFaces_;
nOldCells_ = rhs.nOldCells_;
oldPatchSizes_ = rhs.oldPatchSizes_;
oldPatchStarts_ = rhs.oldPatchStarts_;
oldPatchNMeshPoints_ = rhs.oldPatchNMeshPoints_;
pointMap_ = rhs.pointMap_;
faceMap_ = rhs.faceMap_;
cellMap_ = rhs.cellMap_;
patchMap_ = rhs.patchMap_;
}
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * Istream Operator * * * * * * * * * * * * * * //
Foam::Istream& Foam::operator>>(Istream& is, mapDistributePolyMesh& map)
{
is.fatalCheck("operator>>(Istream&, mapDistributePolyMesh&)");
is >> map.nOldPoints_
>> map.nOldFaces_
>> map.nOldCells_
>> map.oldPatchSizes_
>> map.oldPatchStarts_
>> map.oldPatchNMeshPoints_
>> map.pointMap_
>> map.faceMap_
>> map.cellMap_
>> map.patchMap_;
return is;
}
// * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * * //
Foam::Ostream& Foam::operator<<(Ostream& os, const mapDistributePolyMesh& map)
{
os << map.nOldPoints_
<< token::SPACE << map.nOldFaces_
<< token::SPACE << map.nOldCells_ << token::NL
<< map.oldPatchSizes_ << token::NL
<< map.oldPatchStarts_ << token::NL
<< map.oldPatchNMeshPoints_ << token::NL
<< map.pointMap_ << token::NL
<< map.faceMap_ << token::NL
<< map.cellMap_ << token::NL
<< map.patchMap_;
return os;
}
// ************************************************************************* //

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.
@ -52,46 +52,43 @@ class mapPolyMesh;
class polyMesh;
/*---------------------------------------------------------------------------*\
Class mapDistributePolyMesh Declaration
Class mapDistributePolyMesh Declaration
\*---------------------------------------------------------------------------*/
class mapDistributePolyMesh
{
// Private data
const polyMesh& mesh_;
//- Number of old live points
const label nOldPoints_;
label nOldPoints_;
//- Number of old live faces
const label nOldFaces_;
label nOldFaces_;
//- Number of old live cells
const label nOldCells_;
label nOldCells_;
//- List of the old patch sizes
labelList oldPatchSizes_;
//- List of the old patch start labels
const labelList oldPatchStarts_;
labelList oldPatchStarts_;
//- List of numbers of mesh points per old patch
const labelList oldPatchNMeshPoints_;
labelList oldPatchNMeshPoints_;
//- Point distribute map
const mapDistribute pointMap_;
mapDistribute pointMap_;
//- Face distribute map
const mapDistribute faceMap_;
mapDistribute faceMap_;
//- Cell distribute map
const mapDistribute cellMap_;
mapDistribute cellMap_;
//- Patch distribute map
const mapDistribute patchMap_;
mapDistribute patchMap_;
// Private Member Functions
@ -101,14 +98,14 @@ class mapDistributePolyMesh
//- Disallow default bitwise copy construct
mapDistributePolyMesh(const mapDistributePolyMesh&);
//- Disallow default bitwise assignment
void operator=(const mapDistributePolyMesh&);
public:
// Constructors
//- Construct null
mapDistributePolyMesh();
//- Construct from components. Note that mesh has to be changed already
// since uses mesh.nPoints etc as the new size.
mapDistributePolyMesh
@ -132,19 +129,40 @@ public:
const Xfer<labelListList>& constructPointMap,
const Xfer<labelListList>& constructFaceMap,
const Xfer<labelListList>& constructCellMap,
const Xfer<labelListList>& constructPatchMap
const Xfer<labelListList>& constructPatchMap,
const bool subFaceHasFlip = false,
const bool constructFaceHasFlip = false
);
//- Construct from components
mapDistributePolyMesh
(
// mesh before changes
const label nOldPoints,
const label nOldFaces,
const label nOldCells,
const Xfer<labelList>& oldPatchStarts,
const Xfer<labelList>& oldPatchNMeshPoints,
// how to subset pieces of mesh to send across
const Xfer<mapDistribute>& pointMap,
const Xfer<mapDistribute>& faceMap,
const Xfer<mapDistribute>& cellMap,
const Xfer<mapDistribute>& patchMap
);
//- Construct by transferring parameter content
mapDistributePolyMesh(const Xfer<mapDistributePolyMesh>&);
//- Construct from Istream
mapDistributePolyMesh(Istream&);
// Member Functions
// Access
const polyMesh& mesh() const
{
return mesh_;
}
//- Number of points in mesh before distribution
label nOldPoints() const
{
@ -206,7 +224,13 @@ public:
}
// Edit
// Other
//- Transfer the contents of the argument and annul the argument.
void transfer(mapDistributePolyMesh&);
//- Transfer contents to the Xfer container
Xfer<mapDistributePolyMesh> xfer();
//- Distribute list of point data
template<class T>
@ -254,6 +278,19 @@ public:
"mapDistributePolyMesh::updateMesh(const mapPolyMesh&)"
);
}
// Member operators
void operator=(const mapDistributePolyMesh&);
// IOstream operators
//- Read dictionary from Istream
friend Istream& operator>>(Istream&, mapDistributePolyMesh&);
//- Write dictionary to Ostream
friend Ostream& operator<<(Ostream&, const mapDistributePolyMesh&);
};

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -28,768 +28,10 @@ License
#include "PstreamCombineReduceOps.H"
#include "globalIndexAndTransform.H"
#include "transformField.H"
#include "flipOp.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// Distribute list.
template<class T>
void Foam::mapDistribute::distribute
(
const Pstream::commsTypes commsType,
const List<labelPair>& schedule,
const label constructSize,
const labelListList& subMap,
const labelListList& constructMap,
List<T>& field,
const int tag
)
{
if (!Pstream::parRun())
{
// Do only me to me.
const labelList& mySubMap = subMap[Pstream::myProcNo()];
List<T> subField(mySubMap.size());
forAll(mySubMap, i)
{
subField[i] = field[mySubMap[i]];
}
// Receive sub field from myself (subField)
const labelList& map = constructMap[Pstream::myProcNo()];
field.setSize(constructSize);
forAll(map, i)
{
field[map[i]] = subField[i];
}
return;
}
if (commsType == Pstream::blocking)
{
// Since buffered sending can reuse the field to collect the
// received data.
// Send sub field to neighbour
for (label domain = 0; domain < Pstream::nProcs(); domain++)
{
const labelList& map = subMap[domain];
if (domain != Pstream::myProcNo() && map.size())
{
OPstream toNbr(Pstream::blocking, domain, 0, tag);
toNbr << UIndirectList<T>(field, map);
}
}
// Subset myself
const labelList& mySubMap = subMap[Pstream::myProcNo()];
List<T> subField(mySubMap.size());
forAll(mySubMap, i)
{
subField[i] = field[mySubMap[i]];
}
// Receive sub field from myself (subField)
const labelList& map = constructMap[Pstream::myProcNo()];
field.setSize(constructSize);
forAll(map, i)
{
field[map[i]] = subField[i];
}
// Receive sub field from neighbour
for (label domain = 0; domain < Pstream::nProcs(); domain++)
{
const labelList& map = constructMap[domain];
if (domain != Pstream::myProcNo() && map.size())
{
IPstream fromNbr(Pstream::blocking, domain, 0, tag);
List<T> subField(fromNbr);
checkReceivedSize(domain, map.size(), subField.size());
forAll(map, i)
{
field[map[i]] = subField[i];
}
}
}
}
else if (commsType == Pstream::scheduled)
{
// Need to make sure I don't overwrite field with received data
// since the data might need to be sent to another processor. So
// allocate a new field for the results.
List<T> newField(constructSize);
// Subset myself
UIndirectList<T> subField(field, subMap[Pstream::myProcNo()]);
// Receive sub field from myself (subField)
const labelList& map = constructMap[Pstream::myProcNo()];
forAll(map, i)
{
newField[map[i]] = subField[i];
}
// Schedule will already have pruned 0-sized comms
forAll(schedule, i)
{
const labelPair& twoProcs = schedule[i];
// twoProcs is a swap pair of processors. The first one is the
// one that needs to send first and then receive.
label sendProc = twoProcs[0];
label recvProc = twoProcs[1];
if (Pstream::myProcNo() == sendProc)
{
// I am send first, receive next
{
OPstream toNbr(Pstream::scheduled, recvProc, 0, tag);
toNbr << UIndirectList<T>(field, subMap[recvProc]);
}
{
IPstream fromNbr(Pstream::scheduled, recvProc, 0, tag);
List<T> subField(fromNbr);
const labelList& map = constructMap[recvProc];
checkReceivedSize(recvProc, map.size(), subField.size());
forAll(map, i)
{
newField[map[i]] = subField[i];
}
}
}
else
{
// I am receive first, send next
{
IPstream fromNbr(Pstream::scheduled, sendProc, 0, tag);
List<T> subField(fromNbr);
const labelList& map = constructMap[sendProc];
checkReceivedSize(sendProc, map.size(), subField.size());
forAll(map, i)
{
newField[map[i]] = subField[i];
}
}
{
OPstream toNbr(Pstream::scheduled, sendProc, 0, tag);
toNbr << UIndirectList<T>(field, subMap[sendProc]);
}
}
}
field.transfer(newField);
}
else if (commsType == Pstream::nonBlocking)
{
label nOutstanding = Pstream::nRequests();
if (!contiguous<T>())
{
PstreamBuffers pBufs(Pstream::nonBlocking, tag);
// Stream data into buffer
for (label domain = 0; domain < Pstream::nProcs(); domain++)
{
const labelList& map = subMap[domain];
if (domain != Pstream::myProcNo() && map.size())
{
// Put data into send buffer
UOPstream toDomain(domain, pBufs);
toDomain << UIndirectList<T>(field, map);
}
}
// Start receiving. Do not block.
pBufs.finishedSends(false);
{
// Set up 'send' to myself
const labelList& mySubMap = subMap[Pstream::myProcNo()];
List<T> mySubField(mySubMap.size());
forAll(mySubMap, i)
{
mySubField[i] = field[mySubMap[i]];
}
// Combine bits. Note that can reuse field storage
field.setSize(constructSize);
// Receive sub field from myself
{
const labelList& map = constructMap[Pstream::myProcNo()];
forAll(map, i)
{
field[map[i]] = mySubField[i];
}
}
}
// Block ourselves, waiting only for the current comms
Pstream::waitRequests(nOutstanding);
// Consume
for (label domain = 0; domain < Pstream::nProcs(); domain++)
{
const labelList& map = constructMap[domain];
if (domain != Pstream::myProcNo() && map.size())
{
UIPstream str(domain, pBufs);
List<T> recvField(str);
checkReceivedSize(domain, map.size(), recvField.size());
forAll(map, i)
{
field[map[i]] = recvField[i];
}
}
}
}
else
{
// Set up sends to neighbours
List<List<T > > sendFields(Pstream::nProcs());
for (label domain = 0; domain < Pstream::nProcs(); domain++)
{
const labelList& map = subMap[domain];
if (domain != Pstream::myProcNo() && map.size())
{
List<T>& subField = sendFields[domain];
subField.setSize(map.size());
forAll(map, i)
{
subField[i] = field[map[i]];
}
OPstream::write
(
Pstream::nonBlocking,
domain,
reinterpret_cast<const char*>(subField.begin()),
subField.byteSize(),
tag
);
}
}
// Set up receives from neighbours
List<List<T > > recvFields(Pstream::nProcs());
for (label domain = 0; domain < Pstream::nProcs(); domain++)
{
const labelList& map = constructMap[domain];
if (domain != Pstream::myProcNo() && map.size())
{
recvFields[domain].setSize(map.size());
IPstream::read
(
Pstream::nonBlocking,
domain,
reinterpret_cast<char*>(recvFields[domain].begin()),
recvFields[domain].byteSize(),
tag
);
}
}
// Set up 'send' to myself
{
const labelList& map = subMap[Pstream::myProcNo()];
List<T>& subField = sendFields[Pstream::myProcNo()];
subField.setSize(map.size());
forAll(map, i)
{
subField[i] = field[map[i]];
}
}
// Combine bits. Note that can reuse field storage
field.setSize(constructSize);
// Receive sub field from myself (sendFields[Pstream::myProcNo()])
{
const labelList& map = constructMap[Pstream::myProcNo()];
const List<T>& subField = sendFields[Pstream::myProcNo()];
forAll(map, i)
{
field[map[i]] = subField[i];
}
}
// Wait for all to finish
Pstream::waitRequests(nOutstanding);
// Collect neighbour fields
for (label domain = 0; domain < Pstream::nProcs(); domain++)
{
const labelList& map = constructMap[domain];
if (domain != Pstream::myProcNo() && map.size())
{
const List<T>& subField = recvFields[domain];
checkReceivedSize(domain, map.size(), subField.size());
forAll(map, i)
{
field[map[i]] = subField[i];
}
}
}
}
}
else
{
FatalErrorIn("mapDistribute::distribute(..)")
<< "Unknown communication schedule " << commsType
<< abort(FatalError);
}
}
// Distribute list.
template<class T, class CombineOp>
void Foam::mapDistribute::distribute
(
const Pstream::commsTypes commsType,
const List<labelPair>& schedule,
const label constructSize,
const labelListList& subMap,
const labelListList& constructMap,
List<T>& field,
const CombineOp& cop,
const T& nullValue,
const int tag
)
{
if (!Pstream::parRun())
{
// Do only me to me.
const labelList& mySubMap = subMap[Pstream::myProcNo()];
List<T> subField(mySubMap.size());
forAll(mySubMap, i)
{
subField[i] = field[mySubMap[i]];
}
// Receive sub field from myself (subField)
const labelList& map = constructMap[Pstream::myProcNo()];
field.setSize(constructSize);
field = nullValue;
forAll(map, i)
{
cop(field[map[i]], subField[i]);
}
return;
}
if (commsType == Pstream::blocking)
{
// Since buffered sending can reuse the field to collect the
// received data.
// Send sub field to neighbour
for (label domain = 0; domain < Pstream::nProcs(); domain++)
{
const labelList& map = subMap[domain];
if (domain != Pstream::myProcNo() && map.size())
{
OPstream toNbr(Pstream::blocking, domain, 0, tag);
toNbr << UIndirectList<T>(field, map);
}
}
// Subset myself
const labelList& mySubMap = subMap[Pstream::myProcNo()];
List<T> subField(mySubMap.size());
forAll(mySubMap, i)
{
subField[i] = field[mySubMap[i]];
}
// Receive sub field from myself (subField)
const labelList& map = constructMap[Pstream::myProcNo()];
field.setSize(constructSize);
field = nullValue;
forAll(map, i)
{
cop(field[map[i]], subField[i]);
}
// Receive sub field from neighbour
for (label domain = 0; domain < Pstream::nProcs(); domain++)
{
const labelList& map = constructMap[domain];
if (domain != Pstream::myProcNo() && map.size())
{
IPstream fromNbr(Pstream::blocking, domain, 0, tag);
List<T> subField(fromNbr);
checkReceivedSize(domain, map.size(), subField.size());
forAll(map, i)
{
cop(field[map[i]], subField[i]);
}
}
}
}
else if (commsType == Pstream::scheduled)
{
// Need to make sure I don't overwrite field with received data
// since the data might need to be sent to another processor. So
// allocate a new field for the results.
List<T> newField(constructSize, nullValue);
// Subset myself
UIndirectList<T> subField(field, subMap[Pstream::myProcNo()]);
// Receive sub field from myself (subField)
const labelList& map = constructMap[Pstream::myProcNo()];
forAll(map, i)
{
cop(newField[map[i]], subField[i]);
}
// Schedule will already have pruned 0-sized comms
forAll(schedule, i)
{
const labelPair& twoProcs = schedule[i];
// twoProcs is a swap pair of processors. The first one is the
// one that needs to send first and then receive.
label sendProc = twoProcs[0];
label recvProc = twoProcs[1];
if (Pstream::myProcNo() == sendProc)
{
// I am send first, receive next
{
OPstream toNbr(Pstream::scheduled, recvProc, 0, tag);
toNbr << UIndirectList<T>(field, subMap[recvProc]);
}
{
IPstream fromNbr(Pstream::scheduled, recvProc, 0, tag);
List<T> subField(fromNbr);
const labelList& map = constructMap[recvProc];
checkReceivedSize(recvProc, map.size(), subField.size());
forAll(map, i)
{
cop(newField[map[i]], subField[i]);
}
}
}
else
{
// I am receive first, send next
{
IPstream fromNbr(Pstream::scheduled, sendProc, 0, tag);
List<T> subField(fromNbr);
const labelList& map = constructMap[sendProc];
checkReceivedSize(sendProc, map.size(), subField.size());
forAll(map, i)
{
cop(newField[map[i]], subField[i]);
}
}
{
OPstream toNbr(Pstream::scheduled, sendProc, 0, tag);
toNbr << UIndirectList<T>(field, subMap[sendProc]);
}
}
}
field.transfer(newField);
}
else if (commsType == Pstream::nonBlocking)
{
label nOutstanding = Pstream::nRequests();
if (!contiguous<T>())
{
PstreamBuffers pBufs(Pstream::nonBlocking, tag);
// Stream data into buffer
for (label domain = 0; domain < Pstream::nProcs(); domain++)
{
const labelList& map = subMap[domain];
if (domain != Pstream::myProcNo() && map.size())
{
// Put data into send buffer
UOPstream toDomain(domain, pBufs);
toDomain << UIndirectList<T>(field, map);
}
}
// Start receiving. Do not block.
pBufs.finishedSends(false);
{
// Set up 'send' to myself
List<T> mySubField(field, subMap[Pstream::myProcNo()]);
// Combine bits. Note that can reuse field storage
field.setSize(constructSize);
field = nullValue;
// Receive sub field from myself
{
const labelList& map = constructMap[Pstream::myProcNo()];
forAll(map, i)
{
cop(field[map[i]], mySubField[i]);
}
}
}
// Block ourselves, waiting only for the current comms
Pstream::waitRequests(nOutstanding);
// Consume
for (label domain = 0; domain < Pstream::nProcs(); domain++)
{
const labelList& map = constructMap[domain];
if (domain != Pstream::myProcNo() && map.size())
{
UIPstream str(domain, pBufs);
List<T> recvField(str);
checkReceivedSize(domain, map.size(), recvField.size());
forAll(map, i)
{
cop(field[map[i]], recvField[i]);
}
}
}
}
else
{
// Set up sends to neighbours
List<List<T > > sendFields(Pstream::nProcs());
for (label domain = 0; domain < Pstream::nProcs(); domain++)
{
const labelList& map = subMap[domain];
if (domain != Pstream::myProcNo() && map.size())
{
List<T>& subField = sendFields[domain];
subField.setSize(map.size());
forAll(map, i)
{
subField[i] = field[map[i]];
}
OPstream::write
(
Pstream::nonBlocking,
domain,
reinterpret_cast<const char*>(subField.begin()),
subField.size()*sizeof(T),
tag
);
}
}
// Set up receives from neighbours
List<List<T > > recvFields(Pstream::nProcs());
for (label domain = 0; domain < Pstream::nProcs(); domain++)
{
const labelList& map = constructMap[domain];
if (domain != Pstream::myProcNo() && map.size())
{
recvFields[domain].setSize(map.size());
UIPstream::read
(
Pstream::nonBlocking,
domain,
reinterpret_cast<char*>(recvFields[domain].begin()),
recvFields[domain].size()*sizeof(T),
tag
);
}
}
// Set up 'send' to myself
{
const labelList& map = subMap[Pstream::myProcNo()];
List<T>& subField = sendFields[Pstream::myProcNo()];
subField.setSize(map.size());
forAll(map, i)
{
subField[i] = field[map[i]];
}
}
// Combine bits. Note that can reuse field storage
field.setSize(constructSize);
field = nullValue;
// Receive sub field from myself (subField)
{
const labelList& map = constructMap[Pstream::myProcNo()];
const List<T>& subField = sendFields[Pstream::myProcNo()];
forAll(map, i)
{
cop(field[map[i]], subField[i]);
}
}
// Wait for all to finish
Pstream::waitRequests(nOutstanding);
// Collect neighbour fields
for (label domain = 0; domain < Pstream::nProcs(); domain++)
{
const labelList& map = constructMap[domain];
if (domain != Pstream::myProcNo() && map.size())
{
const List<T>& subField = recvFields[domain];
checkReceivedSize(domain, map.size(), subField.size());
forAll(map, i)
{
cop(field[map[i]], subField[i]);
}
}
}
}
}
else
{
FatalErrorIn("mapDistribute::distribute(..)")
<< "Unknown communication schedule " << commsType
<< abort(FatalError);
}
}
template<class T>
void Foam::mapDistribute::send(PstreamBuffers& pBufs, const List<T>& field)
const
{
// Stream data into buffer
for (label domain = 0; domain < Pstream::nProcs(); domain++)
{
const labelList& map = subMap_[domain];
if (map.size())
{
// Put data into send buffer
UOPstream toDomain(domain, pBufs);
toDomain << UIndirectList<T>(field, map);
}
}
// Start sending and receiving but do not block.
pBufs.finishedSends(false);
}
template<class T>
void Foam::mapDistribute::receive(PstreamBuffers& pBufs, List<T>& field) const
{
// Consume
field.setSize(constructSize_);
for (label domain = 0; domain < Pstream::nProcs(); domain++)
{
const labelList& map = constructMap_[domain];
if (map.size())
{
UIPstream str(domain, pBufs);
List<T> recvField(str);
if (recvField.size() != map.size())
{
FatalErrorIn
(
"template<class T>\n"
"void mapDistribute::receive\n"
"(\n"
" PstreamBuffers&,\n"
" List<T>&\n"
")\n"
) << "Expected from processor " << domain
<< " " << map.size() << " but received "
<< recvField.size() << " elements."
<< abort(FatalError);
}
forAll(map, i)
{
field[map[i]] = recvField[i];
}
}
}
}
// In case of no transform: copy elements
template<class T>
void Foam::mapDistribute::applyDummyTransforms(List<T>& field) const
@ -887,6 +129,39 @@ void Foam::mapDistribute::applyInverseTransforms
}
//- Distribute data using default commsType.
template<class T, class negateOp>
void Foam::mapDistribute::distribute
(
List<T>& fld,
const negateOp& negOp,
const bool dummyTransform,
const int tag
) const
{
mapDistributeBase::distribute(fld, negOp, tag);
//- Fill in transformed slots with copies
if (dummyTransform)
{
applyDummyTransforms(fld);
}
}
//- Distribute data using default commsType.
template<class T>
void Foam::mapDistribute::distribute
(
List<T>& fld,
const bool dummyTransform,
const int tag
) const
{
distribute(fld, flipOp(), dummyTransform, tag);
}
//- Distribute data using default commsType.
template<class T>
void Foam::mapDistribute::distribute
@ -906,63 +181,6 @@ void Foam::mapDistribute::distribute
}
//- Distribute data using default commsType.
template<class T>
void Foam::mapDistribute::distribute
(
List<T>& fld,
const bool dummyTransform,
const int tag
) const
{
if (Pstream::defaultCommsType == Pstream::nonBlocking)
{
distribute
(
Pstream::nonBlocking,
List<labelPair>(),
constructSize_,
subMap_,
constructMap_,
fld,
tag
);
}
else if (Pstream::defaultCommsType == Pstream::scheduled)
{
distribute
(
Pstream::scheduled,
schedule(),
constructSize_,
subMap_,
constructMap_,
fld,
tag
);
}
else
{
distribute
(
Pstream::blocking,
List<labelPair>(),
constructSize_,
subMap_,
constructMap_,
fld,
tag
);
}
//- Fill in transformed slots with copies
if (dummyTransform)
{
applyDummyTransforms(fld);
}
}
//- Reverse distribute data using default commsType.
template<class T>
void Foam::mapDistribute::reverseDistribute
@ -978,45 +196,7 @@ void Foam::mapDistribute::reverseDistribute
applyDummyInverseTransforms(fld);
}
if (Pstream::defaultCommsType == Pstream::nonBlocking)
{
distribute
(
Pstream::nonBlocking,
List<labelPair>(),
constructSize,
constructMap_,
subMap_,
fld,
tag
);
}
else if (Pstream::defaultCommsType == Pstream::scheduled)
{
distribute
(
Pstream::scheduled,
schedule(),
constructSize,
constructMap_,
subMap_,
fld,
tag
);
}
else
{
distribute
(
Pstream::blocking,
List<labelPair>(),
constructSize,
constructMap_,
subMap_,
fld,
tag
);
}
mapDistributeBase::reverseDistribute(constructSize, fld, tag);
}
@ -1038,51 +218,7 @@ void Foam::mapDistribute::reverseDistribute
applyDummyInverseTransforms(fld);
}
if (Pstream::defaultCommsType == Pstream::nonBlocking)
{
distribute
(
Pstream::nonBlocking,
List<labelPair>(),
constructSize,
constructMap_,
subMap_,
fld,
eqOp<T>(),
nullValue,
tag
);
}
else if (Pstream::defaultCommsType == Pstream::scheduled)
{
distribute
(
Pstream::scheduled,
schedule(),
constructSize,
constructMap_,
subMap_,
fld,
eqOp<T>(),
nullValue,
tag
);
}
else
{
distribute
(
Pstream::blocking,
List<labelPair>(),
constructSize,
constructMap_,
subMap_,
fld,
eqOp<T>(),
nullValue,
tag
);
}
mapDistributeBase::reverseDistribute(constructSize, nullValue, fld, tag);
}

View File

@ -0,0 +1,100 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::triPoints
Description
Triangle storage. Null constructable (unfortunately triangle<point, point>
is not)
SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef triPoints_H
#define triPoints_H
#include "FixedList.H"
#include "treeBoundBox.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class triPoints Declaration
\*---------------------------------------------------------------------------*/
class triPoints
:
public FixedList<point, 3>
{
public:
// Constructors
//- Construct null
inline triPoints()
{}
//- Construct from points
inline triPoints
(
const point& a,
const point& b,
const point& c
)
{
operator[](0) = a;
operator[](1) = b;
operator[](2) = c;
}
// Member Functions
//- Calculate the bounding box
inline treeBoundBox bounds() const
{
treeBoundBox bb(operator[](0), operator[](0));
for (label i = 1; i < size(); i++)
{
bb.min() = min(bb.min(), operator[](i));
bb.max() = max(bb.max(), operator[](i));
}
return bb;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,76 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "flipOp.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<>
Foam::scalar Foam::flipOp::operator()(const scalar& v) const
{
return -v;
}
template<> Foam::vector Foam::flipOp::operator()(const vector& v) const
{
return -v;
}
template<>Foam::sphericalTensor Foam::flipOp::operator()
(
const sphericalTensor& v
) const
{
return -v;
}
template<> Foam::symmTensor Foam::flipOp::operator()
(
const symmTensor& v
) const
{
return -v;
}
template<> Foam::tensor Foam::flipOp::operator()(const tensor& v) const
{
return -v;
}
template<> Foam::triad Foam::flipOp::operator()
(
const triad& v
) const
{
return -v;
}
// ************************************************************************* //

View File

@ -0,0 +1,103 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::flipOp
Description
Class containing functor to negate primitives. Dummy for all other types.
Used in mesh transformations where face can flip.
SourceFiles
flipOp.C
\*---------------------------------------------------------------------------*/
#ifndef flipOp_H
#define flipOp_H
#include "fieldTypes.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class flipOp Declaration
\*---------------------------------------------------------------------------*/
class flipOp
{
public:
template<class Type>
Type operator()(const Type& val) const
{
return val;
}
};
class noOp
{
public:
template<class Type>
Type operator()(const Type& val) const
{
return val;
}
};
class flipLabelOp
{
public:
label operator()(const label& val) const
{
return -val;
}
};
// Template specialisation for primitives that support negation
template<> scalar flipOp::operator()(const scalar&) const;
template<> vector flipOp::operator()(const vector&) const;
template<> sphericalTensor flipOp::operator()(const sphericalTensor&) const;
template<> symmTensor flipOp::operator()(const symmTensor&) const;
template<> tensor flipOp::operator()(const tensor&) const;
template<> triad flipOp::operator()(const triad&) const;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -28,17 +28,22 @@ polyTopoChange/polyTopoChange/addPatchCellLayer.C
polyTopoChange/polyTopoChange/pointEdgeCollapse/pointEdgeCollapse.C
polyTopoChange/polyTopoChange/edgeCollapser.C
polyTopoChange/polyTopoChange/faceCollapser.C
polyTopoChange/polyTopoChange/hexRef8.C
polyTopoChange/polyTopoChange/removeCells.C
polyTopoChange/polyTopoChange/removeFaces.C
polyTopoChange/polyTopoChange/refinementData.C
polyTopoChange/polyTopoChange/refinementDistanceData.C
polyTopoChange/polyTopoChange/refinementHistory.C
polyTopoChange/polyTopoChange/removePoints.C
polyTopoChange/polyTopoChange/combineFaces.C
polyTopoChange/polyTopoChange/duplicatePoints.C
polyTopoChange/polyTopoChange/tetDecomposer.C
hexRef8 = polyTopoChange/polyTopoChange/hexRef8
$(hexRef8)/hexRef8.C
$(hexRef8)/hexRef8Data.C
$(hexRef8)/refinementHistory.C
slidingInterface/slidingInterface.C
slidingInterface/slidingInterfaceProjectPoints.C
slidingInterface/coupleSlidingInterface.C
@ -78,11 +83,14 @@ polyTopoChange/repatchPolyTopoChanger/repatchPolyTopoChanger.C
fvMeshAdder/fvMeshAdder.C
fvMeshDistribute/fvMeshDistribute.C
fvMeshDistribute/IOmapDistributePolyMesh.C
polyMeshAdder/faceCoupleInfo.C
polyMeshAdder/polyMeshAdder.C
fvMeshTools/fvMeshTools.C
fvMeshSubset/fvMeshSubset.C
motionSmoother/motionSmoother.C
motionSmoother/motionSmootherAlgo.C
motionSmoother/motionSmootherAlgoCheck.C

View File

@ -0,0 +1,126 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "IOmapDistributePolyMesh.H"
/* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
namespace Foam
{
defineTypeNameAndDebug(IOmapDistributePolyMesh, 0);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::IOmapDistributePolyMesh::IOmapDistributePolyMesh(const IOobject& io)
:
regIOobject(io)
{
// Temporary warning
if (io.readOpt() == IOobject::MUST_READ_IF_MODIFIED)
{
WarningIn
(
"IOmapDistributePolyMesh::IOmapDistributePolyMesh(const IOobject&)"
) << "Specified IOobject::MUST_READ_IF_MODIFIED but class"
<< " does not support automatic rereading."
<< endl;
}
if
(
(
io.readOpt() == IOobject::MUST_READ
|| io.readOpt() == IOobject::MUST_READ_IF_MODIFIED
)
|| (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
)
{
readStream(typeName) >> *this;
close();
}
}
Foam::IOmapDistributePolyMesh::IOmapDistributePolyMesh
(
const IOobject& io,
const mapDistributePolyMesh& map
)
:
regIOobject(io)
{
// Temporary warning
if (io.readOpt() == IOobject::MUST_READ_IF_MODIFIED)
{
WarningIn
(
"IOmapDistributePolyMesh::IOmapDistributePolyMesh(const IOobject&)"
) << "Specified IOobject::MUST_READ_IF_MODIFIED but class"
<< " does not support automatic rereading."
<< endl;
}
if
(
(
io.readOpt() == IOobject::MUST_READ
|| io.readOpt() == IOobject::MUST_READ_IF_MODIFIED
)
|| (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
)
{
readStream(typeName) >> *this;
close();
}
else
{
mapDistributePolyMesh::operator=(map);
}
}
// * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * //
Foam::IOmapDistributePolyMesh::~IOmapDistributePolyMesh()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::IOmapDistributePolyMesh::readData(Istream& is)
{
return (is >> *this).good();
}
bool Foam::IOmapDistributePolyMesh::writeData(Ostream& os) const
{
return (os << *this).good();
}
// ************************************************************************* //

View File

@ -0,0 +1,95 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::IOmapDistributePolyMesh
Description
IOmapDistributePolyMesh is derived from mapDistributePolyMesh and
IOobject to give the mapDistributePolyMesh
automatic IO functionality via the objectRegistry.
SourceFiles
IOmapDistributePolyMesh.C
\*---------------------------------------------------------------------------*/
#ifndef IOmapDistributePolyMesh_H
#define IOmapDistributePolyMesh_H
#include "mapDistributePolyMesh.H"
#include "regIOobject.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class IOmapDistributePolyMesh Declaration
\*---------------------------------------------------------------------------*/
class IOmapDistributePolyMesh
:
public regIOobject,
public mapDistributePolyMesh
{
public:
//- Runtime type information
TypeName("mapDistributePolyMesh");
// Constructors
//- Construct given an IOobject
IOmapDistributePolyMesh(const IOobject&);
//- Construct given an IOobject and mapDistributePolyMesh
IOmapDistributePolyMesh(const IOobject&, const mapDistributePolyMesh&);
//- Destructor
virtual ~IOmapDistributePolyMesh();
// Member functions
//- ReadData function required for regIOobject read operation
virtual bool readData(Istream&);
//- WriteData function required for regIOobject write operation
virtual bool writeData(Ostream&) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

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.
@ -40,17 +40,129 @@ License
#include "syncTools.H"
#include "CompactListList.H"
#include "fvMeshTools.H"
#include "ListOps.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(fvMeshDistribute, 0);
//- Less function class that can be used for sorting processor patches
class lessProcPatches
{
const labelList& nbrProc_;
const labelList& referPatchID_;
public:
lessProcPatches( const labelList& nbrProc, const labelList& referPatchID)
:
nbrProc_(nbrProc),
referPatchID_(referPatchID)
{}
bool operator()(const label a, const label b)
{
if (nbrProc_[a] < nbrProc_[b])
{
return true;
}
else if (nbrProc_[a] > nbrProc_[b])
{
return false;
}
else
{
// Equal neighbour processor
return referPatchID_[a] < referPatchID_[b];
}
}
};
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::fvMeshDistribute::inplaceRenumberWithFlip
(
const labelUList& oldToNew,
const bool oldToNewHasFlip,
const bool lstHasFlip,
labelUList& lst
)
{
if (!lstHasFlip && !oldToNewHasFlip)
{
Foam::inplaceRenumber(oldToNew, lst);
}
else
{
// Either input data or map encodes sign so result encodes sign
forAll(lst, elemI)
{
// Extract old value and sign
label val = lst[elemI];
label sign = 1;
if (lstHasFlip)
{
if (val > 0)
{
val = val-1;
}
else if (val < 0)
{
val = -val-1;
sign = -1;
}
else
{
FatalErrorIn
(
"fvMeshDistribute::inplaceRenumberWithFlip(..)"
) << "Problem : zero value " << val
<< " at index " << elemI << " out of " << lst.size()
<< " list with flip bit" << exit(FatalError);
}
}
// Lookup new value and possibly change sign
label newVal = oldToNew[val];
if (oldToNewHasFlip)
{
if (newVal > 0)
{
newVal = newVal-1;
}
else if (newVal < 0)
{
newVal = -newVal-1;
sign = -sign;
}
else
{
FatalErrorIn
(
"fvMeshDistribute::inplaceRenumberWithFlip(..)"
) << "Problem : zero value " << newVal
<< " at index " << elemI << " out of "
<< oldToNew.size()
<< " list with flip bit" << exit(FatalError);
}
}
// Encode new value and sign
lst[elemI] = sign*(newVal+1);
}
}
}
Foam::labelList Foam::fvMeshDistribute::select
(
const bool selectEqual,
@ -277,6 +389,114 @@ Foam::label Foam::fvMeshDistribute::findNonEmptyPatch() const
}
Foam::tmp<Foam::surfaceScalarField> Foam::fvMeshDistribute::generateTestField
(
const fvMesh& mesh
)
{
vector testNormal(1, 1, 1);
testNormal /= mag(testNormal);
tmp<surfaceScalarField> tfld
(
new surfaceScalarField
(
IOobject
(
"myFlux",
mesh.time().timeName(),
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE
),
mesh,
dimensionedScalar("zero", dimless, 0.0)
)
);
surfaceScalarField& fld = tfld();
const surfaceVectorField n(mesh.Sf()/mesh.magSf());
forAll(fld, faceI)
{
fld[faceI] = (n[faceI] & testNormal);
}
forAll(fld.boundaryField(), patchI)
{
fvsPatchScalarField& fvp = fld.boundaryField()[patchI];
scalarField newPfld(fvp.size());
forAll(newPfld, i)
{
newPfld[i] = (n.boundaryField()[patchI][i] & testNormal);
}
fvp == newPfld;
}
return tfld;
}
void Foam::fvMeshDistribute::testField(const surfaceScalarField& fld)
{
const fvMesh& mesh = fld.mesh();
vector testNormal(1, 1, 1);
testNormal /= mag(testNormal);
const surfaceVectorField n(mesh.Sf()/mesh.magSf());
forAll(fld, faceI)
{
scalar cos = (n[faceI] & testNormal);
if (mag(cos-fld[faceI]) > 1e-6)
{
//FatalErrorIn
WarningIn
(
"fvMeshDistribute::testField(const surfaceScalarField&)"
) << "On internal face " << faceI << " at "
<< mesh.faceCentres()[faceI]
<< " the field value is " << fld[faceI]
<< " whereas cos angle of " << testNormal
<< " with mesh normal " << n[faceI]
<< " is " << cos
//<< exit(FatalError);
<< endl;
}
}
forAll(fld.boundaryField(), patchI)
{
const fvsPatchScalarField& fvp = fld.boundaryField()[patchI];
const fvsPatchVectorField& np = n.boundaryField()[patchI];
forAll(fvp, i)
{
scalar cos = (np[i] & testNormal);
if (mag(cos-fvp[i]) > 1e-6)
{
label faceI = fvp.patch().start()+i;
//FatalErrorIn
WarningIn
(
"fvMeshDistribute::testField(const surfaceScalarField&)"
) << "On face " << faceI
<< " on patch " << fvp.patch().name()
<< " at " << mesh.faceCentres()[faceI]
<< " the field value is " << fvp[i]
<< " whereas cos angle of " << testNormal
<< " with mesh normal " << np[i]
<< " is " << cos
//<< exit(FatalError);
<< endl;
}
}
}
}
// Delete all processor patches. Move any processor faces into the last
// non-processor patch.
Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::deleteProcPatches
@ -455,10 +675,15 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::repatch
forAll(constructFaceMap, procI)
{
inplaceRenumber(map().reverseFaceMap(), constructFaceMap[procI]);
inplaceRenumberWithFlip
(
map().reverseFaceMap(),
false,
true,
constructFaceMap[procI]
);
}
return map;
}
@ -886,18 +1111,52 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::doRemoveCells
meshMod
);
//// Generate test field
//tmp<surfaceScalarField> sfld(generateTestField(mesh_));
// Save internal fields (note: not as DimensionedFields since would
// get mapped)
PtrList<Field<scalar> > sFlds;
saveInternalFields(sFlds);
PtrList<Field<vector> > vFlds;
saveInternalFields(vFlds);
PtrList<Field<sphericalTensor> > sptFlds;
saveInternalFields(sptFlds);
PtrList<Field<symmTensor> > sytFlds;
saveInternalFields(sytFlds);
PtrList<Field<tensor> > tFlds;
saveInternalFields(tFlds);
// Change the mesh. No inflation. Note: no parallel comms allowed.
autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, false);
// Update fields
mesh_.updateMesh(map);
// Any exposed faces in a surfaceField will not be mapped. Map the value
// of these separately (until there is support in all PatchFields for
// mapping from internal faces ...)
mapExposedFaces(map(), sFlds);
mapExposedFaces(map(), vFlds);
mapExposedFaces(map(), sptFlds);
mapExposedFaces(map(), sytFlds);
mapExposedFaces(map(), tFlds);
//// Test test field
//testField(sfld);
// Move mesh (since morphing does not do this)
if (map().hasMotionPoints())
{
mesh_.movePoints(map().preMotionPoints());
}
return map;
}
@ -915,10 +1174,18 @@ void Foam::fvMeshDistribute::addProcPatches
// contain for all current boundary faces the global patchID (for non-proc
// patch) or the processor.
// Determine a visit order such that the processor patches get added
// in order of increasing neighbour processor (and for same neighbour
// processor (in case of processor cyclics) in order of increasing
// 'refer' patch)
labelList indices;
sortedOrder(nbrProc, indices, lessProcPatches(nbrProc, referPatchID));
procPatchID.setSize(Pstream::nProcs());
forAll(nbrProc, bFaceI)
forAll(indices, i)
{
label bFaceI = indices[i];
label procI = nbrProc[bFaceI];
if (procI != -1 && procI != Pstream::myProcNo())
@ -946,7 +1213,7 @@ void Foam::fvMeshDistribute::addProcPatches
mesh_.boundaryMesh().size(),
mesh_.boundaryMesh(),
Pstream::myProcNo(),
nbrProc[bFaceI]
procI
);
procPatchID[procI].insert
@ -989,7 +1256,7 @@ void Foam::fvMeshDistribute::addProcPatches
mesh_.boundaryMesh().size(),
mesh_.boundaryMesh(),
Pstream::myProcNo(),
nbrProc[bFaceI],
procI,
cycName,
pcPatch.transform()
);
@ -1524,7 +1791,33 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
const wordList surfTensors(mesh_.names(surfaceTensorField::typeName));
checkEqualWordList("surfaceTensorFields", surfTensors);
typedef volScalarField::DimensionedInternalField dimScalType;
const wordList dimScalars(mesh_.names(dimScalType::typeName));
checkEqualWordList("volScalarField::DimensionedInternalField", dimScalars);
typedef volVectorField::DimensionedInternalField dimVecType;
const wordList dimVectors(mesh_.names(dimVecType::typeName));
checkEqualWordList("volVectorField::DimensionedInternalField", dimVectors);
typedef volSphericalTensorField::DimensionedInternalField dimSphereType;
const wordList dimSphereTensors(mesh_.names(dimSphereType::typeName));
checkEqualWordList
(
"volSphericalTensorField::DimensionedInternalField",
dimSphereTensors
);
typedef volSymmTensorField::DimensionedInternalField dimSymmTensorType;
const wordList dimSymmTensors(mesh_.names(dimSymmTensorType::typeName));
checkEqualWordList
(
"volSymmTensorField::DimensionedInternalField",
dimSymmTensors
);
typedef volTensorField::DimensionedInternalField dimTensorType;
const wordList dimTensors(mesh_.names(dimTensorType::typeName));
checkEqualWordList("volTensorField::DimensionedInternalField", dimTensors);
// Find patch to temporarily put exposed and processor faces into.
@ -1650,10 +1943,13 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
);
subCellMap[recvProc] = subsetter.cellMap();
subFaceMap[recvProc] = renumber
subFaceMap[recvProc] = subsetter.faceFlipMap();
inplaceRenumberWithFlip
(
repatchFaceMap,
subsetter.faceMap()
false, // oldToNew has flip
true, // subFaceMap has flip
subFaceMap[recvProc]
);
subPointMap[recvProc] = subsetter.pointMap();
subPatchMap[recvProc] = subsetter.patchMap();
@ -1705,6 +2001,8 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
procSourceNewNbrProc,
str
);
// volFields
sendFields<volScalarField>(recvProc, volScalars, subsetter, str);
sendFields<volVectorField>(recvProc, volVectors, subsetter, str);
sendFields<volSphericalTensorField>
@ -1723,6 +2021,7 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
);
sendFields<volTensorField>(recvProc, volTensors, subsetter, str);
// surfaceFields
sendFields<surfaceScalarField>
(
recvProc,
@ -1758,6 +2057,43 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
subsetter,
str
);
// dimensionedFields
sendFields<volScalarField::DimensionedInternalField>
(
recvProc,
dimScalars,
subsetter,
str
);
sendFields<volVectorField::DimensionedInternalField>
(
recvProc,
dimVectors,
subsetter,
str
);
sendFields<volSphericalTensorField::DimensionedInternalField>
(
recvProc,
dimSphereTensors,
subsetter,
str
);
sendFields<volSymmTensorField::DimensionedInternalField>
(
recvProc,
dimSymmTensors,
subsetter,
str
);
sendFields<volTensorField::DimensionedInternalField>
(
recvProc,
dimTensors,
subsetter,
str
);
}
}
@ -1795,12 +2131,24 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
repatchFaceMap,
subMap().faceMap()
);
// Insert the sign bit from face flipping
labelList& faceMap = subFaceMap[Pstream::myProcNo()];
forAll(faceMap, faceI)
{
faceMap[faceI] += 1;
}
const labelHashSet& flip = subMap().flipFaceFlux();
forAllConstIter(labelHashSet, flip, iter)
{
label faceI = iter.key();
faceMap[faceI] = -faceMap[faceI];
}
subPointMap[Pstream::myProcNo()] = subMap().pointMap();
subPatchMap[Pstream::myProcNo()] = identity(patches.size());
// Initialize all addressing into current mesh
constructCellMap[Pstream::myProcNo()] = identity(mesh_.nCells());
constructFaceMap[Pstream::myProcNo()] = identity(mesh_.nFaces());
constructFaceMap[Pstream::myProcNo()] = identity(mesh_.nFaces()) + 1;
constructPointMap[Pstream::myProcNo()] = identity(mesh_.nPoints());
constructPatchMap[Pstream::myProcNo()] = identity(patches.size());
@ -1896,17 +2244,26 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
labelList domainSourceNewNbrProc;
autoPtr<fvMesh> domainMeshPtr;
PtrList<volScalarField> vsf;
PtrList<volVectorField> vvf;
PtrList<volSphericalTensorField> vsptf;
PtrList<volSymmTensorField> vsytf;
PtrList<volTensorField> vtf;
PtrList<surfaceScalarField> ssf;
PtrList<surfaceVectorField> svf;
PtrList<surfaceSphericalTensorField> ssptf;
PtrList<surfaceSymmTensorField> ssytf;
PtrList<surfaceTensorField> stf;
PtrList<volScalarField::DimensionedInternalField> dsf;
PtrList<volVectorField::DimensionedInternalField> dvf;
PtrList<volSphericalTensorField::DimensionedInternalField> dstf;
PtrList<volSymmTensorField::DimensionedInternalField> dsytf;
PtrList<volTensorField::DimensionedInternalField> dtf;
// Opposite of sendMesh
{
domainMeshPtr = receiveMesh
@ -1932,6 +2289,7 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
// of problems reading consecutive fields from single stream.
dictionary fieldDicts(str);
// Vol fields
receiveFields<volScalarField>
(
sendProc,
@ -1973,6 +2331,7 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
fieldDicts.subDict(volTensorField::typeName)
);
// Surface fields
receiveFields<surfaceScalarField>
(
sendProc,
@ -2013,12 +2372,70 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
stf,
fieldDicts.subDict(surfaceTensorField::typeName)
);
// Dimensioned fields
receiveFields<volScalarField::DimensionedInternalField>
(
sendProc,
dimScalars,
domainMesh,
dsf,
fieldDicts.subDict
(
volScalarField::DimensionedInternalField::typeName
)
);
receiveFields<volVectorField::DimensionedInternalField>
(
sendProc,
dimVectors,
domainMesh,
dvf,
fieldDicts.subDict
(
volVectorField::DimensionedInternalField::typeName
)
);
receiveFields<volSphericalTensorField::DimensionedInternalField>
(
sendProc,
dimSphereTensors,
domainMesh,
dstf,
fieldDicts.subDict
(
volSphericalTensorField::DimensionedInternalField::
typeName
)
);
receiveFields<volSymmTensorField::DimensionedInternalField>
(
sendProc,
dimSymmTensors,
domainMesh,
dsytf,
fieldDicts.subDict
(
volSymmTensorField::DimensionedInternalField::typeName
)
);
receiveFields<volTensorField::DimensionedInternalField>
(
sendProc,
dimTensors,
domainMesh,
dtf,
fieldDicts.subDict
(
volTensorField::DimensionedInternalField::typeName
)
);
}
const fvMesh& domainMesh = domainMeshPtr();
constructCellMap[sendProc] = identity(domainMesh.nCells());
constructFaceMap[sendProc] = identity(domainMesh.nFaces());
constructFaceMap[sendProc] = identity(domainMesh.nFaces()) + 1;
constructPointMap[sendProc] = identity(domainMesh.nPoints());
constructPatchMap[sendProc] =
identity(domainMesh.boundaryMesh().size());
@ -2129,28 +2546,76 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
domainSourceNewNbrProc
);
// Update all addressing so xxProcAddressing points to correct item
// in masterMesh.
// Update all addressing so xxProcAddressing points to correct
// item in masterMesh.
const labelList& oldCellMap = map().oldCellMap();
const labelList& oldFaceMap = map().oldFaceMap();
const labelList& oldPointMap = map().oldPointMap();
const labelList& oldPatchMap = map().oldPatchMap();
//Note: old mesh faces never flipped!
forAll(constructPatchMap, procI)
{
if (procI != sendProc && constructPatchMap[procI].size())
{
// Processor already in mesh (either myProcNo or received)
inplaceRenumber(oldCellMap, constructCellMap[procI]);
inplaceRenumber(oldFaceMap, constructFaceMap[procI]);
inplaceRenumberWithFlip
(
oldFaceMap,
false,
true,
constructFaceMap[procI]
);
inplaceRenumber(oldPointMap, constructPointMap[procI]);
inplaceRenumber(oldPatchMap, constructPatchMap[procI]);
}
}
labelHashSet flippedAddedFaces;
{
// Find out if any faces of domain mesh were flipped (boundary
// faces becoming internal)
label nBnd = domainMesh.nFaces()-domainMesh.nInternalFaces();
flippedAddedFaces.resize(nBnd/4);
for
(
label domainFaceI = domainMesh.nInternalFaces();
domainFaceI < domainMesh.nFaces();
domainFaceI++
)
{
label newFaceI = map().addedFaceMap()[domainFaceI];
label newCellI = mesh_.faceOwner()[newFaceI];
label domainCellI = domainMesh.faceOwner()[domainFaceI];
if (newCellI != map().addedCellMap()[domainCellI])
{
flippedAddedFaces.insert(domainFaceI);
}
}
}
// Added processor
inplaceRenumber(map().addedCellMap(), constructCellMap[sendProc]);
inplaceRenumber(map().addedFaceMap(), constructFaceMap[sendProc]);
// Add flip
forAllConstIter(labelHashSet, flippedAddedFaces, iter)
{
label domainFaceI = iter.key();
label& val = constructFaceMap[sendProc][domainFaceI];
val = -val;
}
inplaceRenumberWithFlip
(
map().addedFaceMap(),
false,
true, // constructFaceMap has flip sign
constructFaceMap[sendProc]
);
inplaceRenumber(map().addedPointMap(), constructPointMap[sendProc]);
inplaceRenumber(map().addedPatchMap(), constructPatchMap[sendProc]);
@ -2260,35 +2725,6 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
pTraits<tensor>::zero
);
initPatchFields<surfaceScalarField, processorFvsPatchField<scalar> >
(
pTraits<scalar>::zero
);
initPatchFields<surfaceVectorField, processorFvsPatchField<vector> >
(
pTraits<vector>::zero
);
initPatchFields
<
surfaceSphericalTensorField,
processorFvsPatchField<sphericalTensor>
>
(
pTraits<sphericalTensor>::zero
);
initPatchFields
<
surfaceSymmTensorField,
processorFvsPatchField<symmTensor>
>
(
pTraits<symmTensor>::zero
);
initPatchFields<surfaceTensorField, processorFvsPatchField<tensor> >
(
pTraits<tensor>::zero
);
mesh_.setInstance(mesh_.time().timeName());
@ -2332,7 +2768,10 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
constructPointMap.xfer(),
constructFaceMap.xfer(),
constructCellMap.xfer(),
constructPatchMap.xfer()
constructPatchMap.xfer(),
true, // subFaceMap has flip
true // constructFaceMap has flip
)
);
}

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.
@ -82,6 +82,14 @@ class fvMeshDistribute
// Private Member Functions
static void inplaceRenumberWithFlip
(
const labelUList& oldToNew,
const bool oldToNewHasFlip,
const bool lstHasFlip,
labelUList& lst
);
//- Find indices with value
static labelList select
(
@ -117,6 +125,21 @@ class fvMeshDistribute
const PtrList<FieldField<fvsPatchField, T> >& oldBflds
);
//- Save internal fields of surfaceFields
template<class T>
void saveInternalFields
(
PtrList<Field<T> >& iflds
) const;
//- Set value of patch faces resulting from internal faces
template<class T>
void mapExposedFaces
(
const mapPolyMesh& map,
const PtrList<Field<T> >& oldFlds
);
//- Init patch fields of certain type
template<class GeoField, class PatchFieldType>
void initPatchFields
@ -337,6 +360,12 @@ public:
//- Print some info on mesh.
static void printMeshInfo(const fvMesh&);
//- Generate a test field on faces
static tmp<surfaceScalarField> generateTestField(const fvMesh&);
//- Check whether field consistent with face orientation
static void testField(const surfaceScalarField&);
};

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.
@ -113,8 +113,7 @@ void Foam::fvMeshDistribute::mapBoundaryFields
forAllIter(typename HashTable<fldType*>, flds, iter)
{
fldType& fld = *iter();
typename fldType::GeometricBoundaryField& bfld =
fld.boundaryField();
typename fldType::GeometricBoundaryField& bfld = fld.boundaryField();
const FieldField<fvsPatchField, T>& oldBfld = oldBflds[fieldI++];
@ -145,6 +144,94 @@ void Foam::fvMeshDistribute::mapBoundaryFields
}
template<class T>
void Foam::fvMeshDistribute::saveInternalFields
(
PtrList<Field<T> >& iflds
) const
{
typedef GeometricField<T, fvsPatchField, surfaceMesh> fldType;
HashTable<const fldType*> flds
(
static_cast<const fvMesh&>(mesh_).objectRegistry::lookupClass<fldType>()
);
iflds.setSize(flds.size());
label i = 0;
forAllConstIter(typename HashTable<const fldType*>, flds, iter)
{
const fldType& fld = *iter();
iflds.set(i, fld.internalField().clone());
i++;
}
}
// Set boundary values of exposed internal faces
template<class T>
void Foam::fvMeshDistribute::mapExposedFaces
(
const mapPolyMesh& map,
const PtrList<Field<T> >& oldFlds
)
{
const labelList& faceMap = map.faceMap();
typedef GeometricField<T, fvsPatchField, surfaceMesh> fldType;
HashTable<fldType*> flds
(
mesh_.objectRegistry::lookupClass<fldType>()
);
if (flds.size() != oldFlds.size())
{
FatalErrorIn("fvMeshDistribute::mapExposedFaces(..)") << "problem"
<< abort(FatalError);
}
label fieldI = 0;
forAllIter(typename HashTable<fldType*>, flds, iter)
{
fldType& fld = *iter();
typename fldType::GeometricBoundaryField& bfld = fld.boundaryField();
const Field<T>& oldInternal = oldFlds[fieldI++];
// Pull from old internal field into bfld.
forAll(bfld, patchI)
{
fvsPatchField<T>& patchFld = bfld[patchI];
forAll(patchFld, i)
{
const label faceI = patchFld.patch().start()+i;
label oldFaceI = faceMap[faceI];
if (oldFaceI < oldInternal.size())
{
patchFld[i] = oldInternal[oldFaceI];
if (map.flipFaceFlux().found(faceI))
{
patchFld[i] = flipOp()(patchFld[i]);
}
}
}
}
}
}
// Init patch fields of certain type
template<class GeoField, class PatchFieldType>
void Foam::fvMeshDistribute::initPatchFields

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -34,6 +34,9 @@ Description
#include "emptyPolyPatch.H"
#include "demandDrivenData.H"
#include "cyclicPolyPatch.H"
#include "removeCells.H"
#include "polyTopoChange.H"
#include "mapPolyMesh.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -354,6 +357,39 @@ void Foam::fvMeshSubset::subsetZones()
}
Foam::labelList Foam::fvMeshSubset::getCellsToRemove
(
const labelList& region,
const label currentRegion
) const
{
// Count
label nKeep = 0;
forAll(region, cellI)
{
if (region[cellI] == currentRegion)
{
nKeep++;
}
}
// Collect cells to remove
label nRemove = baseMesh().nCells() - nKeep;
labelList cellsToRemove(nRemove);
nRemove = 0;
forAll(region, cellI)
{
if (region[cellI] != currentRegion)
{
cellsToRemove[nRemove++] = cellI;
}
}
return cellsToRemove;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// Construct from components
@ -364,7 +400,8 @@ Foam::fvMeshSubset::fvMeshSubset(const fvMesh& baseMesh)
pointMap_(0),
faceMap_(0),
cellMap_(0),
patchMap_(0)
patchMap_(0),
faceFlipMapPtr_()
{}
@ -404,6 +441,10 @@ void Foam::fvMeshSubset::setCellSubset
}
// Clear demand driven data
faceFlipMapPtr_.clear();
cellMap_ = globalCellMap.toc();
// Sort the cell map in the ascending order
@ -803,6 +844,8 @@ void Foam::fvMeshSubset::setLargeCellSubset
<< abort(FatalError);
}
// Clear demand driven data
faceFlipMapPtr_.clear();
// Get the cells for the current region.
cellMap_.setSize(oldCells.size());
@ -1371,6 +1414,68 @@ void Foam::fvMeshSubset::setLargeCellSubset
}
Foam::labelList Foam::fvMeshSubset::getExposedFaces
(
const labelList& region,
const label currentRegion,
const bool syncCouples
) const
{
// Collect cells to remove
labelList cellsToRemove(getCellsToRemove(region, currentRegion));
return removeCells(baseMesh(), syncCouples).getExposedFaces(cellsToRemove);
}
void Foam::fvMeshSubset::setLargeCellSubset
(
const labelList& region,
const label currentRegion,
const labelList& exposedFaces,
const labelList& patchIDs,
const bool syncCouples
)
{
// Collect cells to remove
labelList cellsToRemove(getCellsToRemove(region, currentRegion));
// Mesh changing engine.
polyTopoChange meshMod(baseMesh());
removeCells cellRemover(baseMesh(), syncCouples);
cellRemover.setRefinement
(
cellsToRemove,
exposedFaces,
patchIDs,
meshMod
);
// Create mesh, return map from old to new mesh.
autoPtr<mapPolyMesh> map = meshMod.makeMesh
(
fvMeshSubsetPtr_,
IOobject
(
baseMesh().name(),
baseMesh().time().timeName(),
baseMesh().time(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
baseMesh(),
syncCouples
);
pointMap_ = map().pointMap();
faceMap_ = map().faceMap();
cellMap_ = map().cellMap();
patchMap_ = identity(baseMesh().boundaryMesh().size());
}
bool Foam::fvMeshSubset::hasSubMesh() const
{
return fvMeshSubsetPtr_.valid();
@ -1409,6 +1514,44 @@ const labelList& Foam::fvMeshSubset::faceMap() const
}
const labelList& Foam::fvMeshSubset::faceFlipMap() const
{
if (!faceFlipMapPtr_.valid())
{
const labelList& subToBaseFace = faceMap();
const labelList& subToBaseCell = cellMap();
faceFlipMapPtr_.reset(new labelList(subToBaseFace.size()));
labelList& faceFlipMap = faceFlipMapPtr_();
// Only exposed internal faces might be flipped (since we don't do
// any cell renumbering, just compacting)
label subInt = subMesh().nInternalFaces();
const labelList& subOwn = subMesh().faceOwner();
const labelList& own = baseMesh_.faceOwner();
for (label subFaceI = 0; subFaceI < subInt; subFaceI++)
{
faceFlipMap[subFaceI] = subToBaseFace[subFaceI]+1;
}
for (label subFaceI = subInt; subFaceI < subOwn.size(); subFaceI++)
{
label faceI = subToBaseFace[subFaceI];
if (subToBaseCell[subOwn[subFaceI]] == own[faceI])
{
faceFlipMap[subFaceI] = faceI+1;
}
else
{
faceFlipMap[subFaceI] = -faceI-1;
}
}
}
return faceFlipMapPtr_();
}
const labelList& Foam::fvMeshSubset::cellMap() const
{
checkCellSubset();

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -41,10 +41,12 @@ Description
a face on a coupled patch 'losing' its neighbour it will move the
face into the oldInternalFaces patch.
- if a user supplied patch is used the mapping becomes a problem.
Do the new faces get the value of the internal face they came from?
What if e.g. the user supplied patch is a fixedValue 0? So for now
they get the face of existing patch face 0.
- if a user supplied patch is used it is up to the destination
patchField to handle exposed internal faces (mapping from face -1).
If not provided the default is to assign the internalField. All the
basic patch field types (e.g. fixedValue) will give a warning and
preferably derived patch field types should be used that know how to
handle exposed faces (e.g. use uniformFixedValue instead of fixedValue)
SourceFiles
fvMeshSubset.C
@ -94,6 +96,8 @@ private:
//- Patch mapping array
labelList patchMap_;
mutable autoPtr<labelList> faceFlipMapPtr_;
// Private Member Functions
@ -124,6 +128,13 @@ private:
//- Create zones for submesh
void subsetZones();
//- Helper: extract cells-to-remove from cells-to-keep
labelList getCellsToRemove
(
const labelList& region,
const label currentRegion
) const;
//- Disallow default bitwise copy construct
fvMeshSubset(const fvMeshSubset&);
@ -174,6 +185,32 @@ public:
);
//- Two step subsetting
//- Get labels of exposed faces.
// These are
// - internal faces that become boundary faces
// - coupled faces that become uncoupled (since one of the
// sides gets deleted)
labelList getExposedFaces
(
const labelList& region,
const label currentRegion,
const bool syncCouples = true
) const;
//- For every exposed face (from above getExposedFaces)
// used supplied (existing!) patch
void setLargeCellSubset
(
const labelList& region,
const label currentRegion,
const labelList& exposedFaces,
const labelList& patchIDs,
const bool syncCouples = true
);
// Access
//- Original mesh
@ -196,6 +233,9 @@ public:
//- Return face map
const labelList& faceMap() const;
//- Return face map with sign to encode flipped faces
const labelList& faceFlipMap() const;
//- Return cell map
const labelList& cellMap() const;
@ -224,7 +264,8 @@ public:
const GeometricField<Type, fvPatchField, volMesh>&
) const;
//- Map surface field
//- Map surface field. Optionally negates value if flipping
// a face (from exposing an internal face)
template<class Type>
static tmp<GeometricField<Type, fvsPatchField, surfaceMesh> >
interpolate
@ -232,14 +273,17 @@ public:
const GeometricField<Type, fvsPatchField, surfaceMesh>&,
const fvMesh& sMesh,
const labelList& patchMap,
const labelList& faceMap
const labelList& cellMap,
const labelList& faceMap,
const bool negateIfFlipped = true
);
template<class Type>
tmp<GeometricField<Type, fvsPatchField, surfaceMesh> >
interpolate
(
const GeometricField<Type, fvsPatchField, surfaceMesh>&
const GeometricField<Type, fvsPatchField, surfaceMesh>&,
const bool negateIfFlipped = true
) const;
//- Map point field
@ -259,6 +303,24 @@ public:
(
const GeometricField<Type, pointPatchField, pointMesh>&
) const;
//- Map dimensioned fields
template<class Type>
static tmp<DimensionedField<Type, volMesh> >
interpolate
(
const DimensionedField<Type, volMesh>&,
const fvMesh& sMesh,
const labelList& cellMap
);
template<class Type>
tmp<DimensionedField<Type, volMesh> >
interpolate
(
const DimensionedField<Type, volMesh>&
) const;
};

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -29,6 +29,7 @@ License
#include "emptyFvPatchFields.H"
#include "directFvPatchFieldMapper.H"
#include "directPointPatchFieldMapper.H"
#include "flipOp.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -178,7 +179,9 @@ tmp<GeometricField<Type, fvsPatchField, surfaceMesh> > fvMeshSubset::interpolate
const GeometricField<Type, fvsPatchField, surfaceMesh>& vf,
const fvMesh& sMesh,
const labelList& patchMap,
const labelList& faceMap
const labelList& cellMap,
const labelList& faceMap,
const bool negateIfFlipped
)
{
// 1. Create the complete field with dummy patch fields
@ -297,14 +300,24 @@ tmp<GeometricField<Type, fvsPatchField, surfaceMesh> > fvMeshSubset::interpolate
// Postprocess patch field for exposed faces
fvsPatchField<Type>& pfld = bf[patchI];
const labelUList& fc = bf[patchI].patch().faceCells();
const labelList& own = vf.mesh().faceOwner();
forAll(pfld, i)
{
label baseFaceI = faceMap[subPatch.start()+i];
if (baseFaceI < vf.internalField().size())
{
// Exposed internal face
pfld[i] = vf.internalField()[baseFaceI];
Type val = vf.internalField()[baseFaceI];
if (cellMap[fc[i]] == own[baseFaceI] || !negateIfFlipped)
{
pfld[i] = val;
}
else
{
pfld[i] = flipOp()(val);
}
}
else
{
@ -329,7 +342,8 @@ tmp<GeometricField<Type, fvsPatchField, surfaceMesh> > fvMeshSubset::interpolate
template<class Type>
tmp<GeometricField<Type, fvsPatchField, surfaceMesh> > fvMeshSubset::interpolate
(
const GeometricField<Type, fvsPatchField, surfaceMesh>& sf
const GeometricField<Type, fvsPatchField, surfaceMesh>& sf,
const bool negateIfFlipped
) const
{
return interpolate
@ -337,7 +351,9 @@ tmp<GeometricField<Type, fvsPatchField, surfaceMesh> > fvMeshSubset::interpolate
sf,
subMesh(),
patchMap(),
faceMap()
cellMap(),
faceMap(),
negateIfFlipped
);
}
@ -489,6 +505,47 @@ tmp<GeometricField<Type, pointPatchField, pointMesh> > fvMeshSubset::interpolate
}
template<class Type>
tmp<DimensionedField<Type, volMesh> > fvMeshSubset::interpolate
(
const DimensionedField<Type, volMesh>& df,
const fvMesh& sMesh,
const labelList& cellMap
)
{
// Create the complete field from the pieces
tmp<DimensionedField<Type, volMesh> > tresF
(
new DimensionedField<Type, volMesh>
(
IOobject
(
"subset"+df.name(),
sMesh.time().timeName(),
sMesh,
IOobject::NO_READ,
IOobject::NO_WRITE
),
sMesh,
df.dimensions(),
Field<Type>(df, cellMap)
)
);
return tresF;
}
template<class Type>
tmp<DimensionedField<Type, volMesh> > fvMeshSubset::interpolate
(
const DimensionedField<Type, volMesh>& df
) const
{
return interpolate(df, subMesh(), cellMap());
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2012 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2012-2014 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -23,6 +23,9 @@ License
\*---------------------------------------------------------------------------*/
#include "fvMeshTools.H"
#include "processorCyclicPolyPatch.H"
#include "polyBoundaryMeshEntries.H"
#include "fvMeshTools.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -352,4 +355,264 @@ void Foam::fvMeshTools::reorderPatches
}
Foam::autoPtr<Foam::fvMesh> Foam::fvMeshTools::newMesh
(
const IOobject& io,
const bool masterOnlyReading
)
{
// Region name
// ~~~~~~~~~~~
fileName meshSubDir;
if (io.name() == polyMesh::defaultRegion)
{
meshSubDir = polyMesh::meshSubDir;
}
else
{
meshSubDir = io.name()/polyMesh::meshSubDir;
}
fileName facesInstance;
// Patch types
// ~~~~~~~~~~~
// Read and scatter master patches (without reading master mesh!)
PtrList<entry> patchEntries;
if (Pstream::master())
{
facesInstance = io.time().findInstance
(
meshSubDir,
"faces",
IOobject::MUST_READ
);
patchEntries = polyBoundaryMeshEntries
(
IOobject
(
"boundary",
facesInstance,
meshSubDir,
io.db(),
IOobject::MUST_READ,
IOobject::NO_WRITE,
false
)
);
// Send patches
for
(
int slave=Pstream::firstSlave();
slave<=Pstream::lastSlave();
slave++
)
{
OPstream toSlave(Pstream::scheduled, slave);
toSlave << patchEntries;
}
}
else
{
// Receive patches
IPstream fromMaster(Pstream::scheduled, Pstream::masterNo());
fromMaster >> patchEntries;
}
Pstream::scatter(facesInstance);
// Dummy meshes
// ~~~~~~~~~~~~
// Check who has a mesh
const fileName meshDir = io.time().path()/facesInstance/meshSubDir;
bool haveMesh = isDir(meshDir);
if (masterOnlyReading && !Pstream::master())
{
haveMesh = false;
}
// Set up to read-if-present. Note: does not search for mesh so set
// instance explicitly
IOobject meshIO(io);
meshIO.instance() = facesInstance;
if (masterOnlyReading && !Pstream::master())
{
meshIO.readOpt() = IOobject::NO_READ;
}
else
{
meshIO.readOpt() = IOobject::READ_IF_PRESENT;
}
// Read mesh
// ~~~~~~~~~
// Now all processors read a mesh and use supplied points,faces etc
// if there is none.
// Note: fvSolution, fvSchemes are also using the supplied Ioobject so
// on slave will be NO_READ, on master READ_IF_PRESENT. This will
// conflict with e.g. timeStampMaster reading so switch off.
const regIOobject::fileCheckTypes oldCheckType =
regIOobject::fileModificationChecking;
regIOobject::fileModificationChecking = regIOobject::timeStamp;
autoPtr<fvMesh> meshPtr
(
new fvMesh
(
meshIO,
xferCopy(pointField()),
xferCopy(faceList()),
xferCopy(labelList()),
xferCopy(labelList())
)
);
fvMesh& mesh = meshPtr();
regIOobject::fileModificationChecking = oldCheckType;
// Add patches
// ~~~~~~~~~~~
bool havePatches = mesh.boundary().size();
reduce(havePatches, andOp<bool>());
if (!havePatches)
{
// There are one or more processors without full complement of
// patches
DynamicList<polyPatch*> newPatches;
if (haveMesh) //Pstream::master())
{
forAll(mesh.boundary(), patchI)
{
newPatches.append
(
mesh.boundaryMesh()[patchI].clone(mesh.boundaryMesh()).ptr()
);
}
}
else
{
forAll(patchEntries, patchI)
{
const entry& e = patchEntries[patchI];
const word type(e.dict().lookup("type"));
if
(
type == processorPolyPatch::typeName
|| type == processorCyclicPolyPatch::typeName
)
{}
else
{
dictionary patchDict(e.dict());
patchDict.set("nFaces", 0);
patchDict.set("startFace", 0);
newPatches.append
(
polyPatch::New
(
patchEntries[patchI].keyword(),
patchDict,
newPatches.size(),
mesh.boundaryMesh()
).ptr()
);
}
}
}
mesh.removeFvBoundary();
mesh.addFvPatches(newPatches);
}
//Pout<< "patches:" << endl;
//forAll(mesh.boundary(), patchI)
//{
// Pout<< " type" << mesh.boundary()[patchI].type()
// << " size:" << mesh.boundary()[patchI].size()
// << " start:" << mesh.boundary()[patchI].start() << endl;
//}
//Pout<< endl;
// Determine zones
// ~~~~~~~~~~~~~~~
wordList pointZoneNames(mesh.pointZones().names());
Pstream::scatter(pointZoneNames);
wordList faceZoneNames(mesh.faceZones().names());
Pstream::scatter(faceZoneNames);
wordList cellZoneNames(mesh.cellZones().names());
Pstream::scatter(cellZoneNames);
if (!haveMesh)
{
// Add the zones. Make sure to remove the old dummy ones first
mesh.pointZones().clear();
mesh.faceZones().clear();
mesh.cellZones().clear();
List<pointZone*> pz(pointZoneNames.size());
forAll(pointZoneNames, i)
{
pz[i] = new pointZone
(
pointZoneNames[i],
labelList(0),
i,
mesh.pointZones()
);
}
List<faceZone*> fz(faceZoneNames.size());
forAll(faceZoneNames, i)
{
fz[i] = new faceZone
(
faceZoneNames[i],
labelList(0),
boolList(0),
i,
mesh.faceZones()
);
}
List<cellZone*> cz(cellZoneNames.size());
forAll(cellZoneNames, i)
{
cz[i] = new cellZone
(
cellZoneNames[i],
labelList(0),
i,
mesh.cellZones()
);
}
if (pz.size() && fz.size() && cz.size())
{
mesh.addZones(pz, fz, cz);
}
}
return meshPtr;
}
// ************************************************************************* //

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2012 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2012-2014 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -112,7 +112,7 @@ public:
//- Change patchField to zero on registered fields
static void zeroPatchFields(fvMesh& mesh, const label patchI);
// -Reorder and remove trailing patches. If validBoundary call is parallel
//- Reorder and remove trailing patches. If validBoundary call is parallel
// synced and all add the same patch with same settings
static void reorderPatches
(
@ -122,6 +122,18 @@ public:
const bool validBoundary
);
//- Read mesh or create dummy mesh (0 cells, >0 patches). Works in two
// modes according to masterOnlyReading:
// true : all slaves create dummy mesh
// false: checks locally for mesh directories and only creates dummy mesh
// if not present
static autoPtr<fvMesh> newMesh
(
const IOobject& io,
const bool masterOnlyReading
);
};

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -31,7 +31,7 @@ Description
cell centre and normal in direction of provided direction. Snaps cuts
close to edge endpoints (close = snapTol * minEdgeLen) to vertices.
Currently determines cuts through edges (and edgeendpoints close to plane)
Currently determines cuts through edges (and edge endpoints close to plane)
in random order and then sorts them acc. to angle. Could be converted to
use walk but problem is that face can be cut multiple times (since does
not need to be convex). Another problem is that edges parallel to plane

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -25,17 +25,14 @@ License
#include "multiDirRefinement.H"
#include "polyMesh.H"
#include "polyTopoChanger.H"
#include "Time.H"
#include "undoableMeshCutter.H"
#include "hexCellLooper.H"
#include "geomCellLooper.H"
#include "topoSet.H"
#include "directions.H"
#include "hexRef8.H"
#include "mapPolyMesh.H"
#include "polyTopoChange.H"
#include "ListOps.H"
#include "cellModeller.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -265,7 +262,8 @@ void Foam::multiDirRefinement::refineHex8
false
),
List<refinementHistory::splitCell8>(0),
labelList(0)
labelList(0),
false
) // refinement history
);

View File

@ -2234,7 +2234,8 @@ Foam::hexRef8::hexRef8
IOobject::AUTO_WRITE
),
List<refinementHistory::splitCell8>(0),
labelList(0)
labelList(0),
false
),
faceRemover_(mesh_, GREAT), // merge boundary faces wherever possible
savedPointLevel_(0),

View File

@ -0,0 +1,339 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "IOobject.H"
#include "UList.H"
#include "hexRef8Data.H"
#include "mapPolyMesh.H"
#include "mapDistributePolyMesh.H"
#include "polyMesh.H"
#include "syncTools.H"
#include "refinementHistory.H"
#include "fvMesh.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::hexRef8Data::hexRef8Data(const IOobject& io)
{
{
IOobject rio(io);
rio.rename("cellLevel");
bool haveFile = returnReduce(rio.headerOk(), orOp<bool>());
if (haveFile)
{
Info<< "Reading hexRef8 data : " << rio.name() << endl;
cellLevelPtr_.reset(new labelIOList(rio));
}
}
{
IOobject rio(io);
rio.rename("pointLevel");
bool haveFile = returnReduce(rio.headerOk(), orOp<bool>());
if (haveFile)
{
Info<< "Reading hexRef8 data : " << rio.name() << endl;
pointLevelPtr_.reset(new labelIOList(rio));
}
}
{
IOobject rio(io);
rio.rename("level0Edge");
bool haveFile = returnReduce(rio.headerOk(), orOp<bool>());
if (haveFile)
{
Info<< "Reading hexRef8 data : " << rio.name() << endl;
level0EdgePtr_.reset(new uniformDimensionedScalarField(rio));
}
}
{
IOobject rio(io);
rio.rename("refinementHistory");
bool haveFile = returnReduce(rio.headerOk(), orOp<bool>());
if (haveFile)
{
Info<< "Reading hexRef8 data : " << rio.name() << endl;
refHistoryPtr_.reset(new refinementHistory(rio));
}
}
}
Foam::hexRef8Data::hexRef8Data
(
const IOobject& io,
const hexRef8Data& data,
const labelList& cellMap,
const labelList& pointMap
)
{
if (data.cellLevelPtr_.valid())
{
IOobject rio(io);
rio.rename(data.cellLevelPtr_().name());
cellLevelPtr_.reset
(
new labelIOList
(
rio,
UIndirectList<label>(data.cellLevelPtr_(), cellMap)()
)
);
}
if (data.pointLevelPtr_.valid())
{
IOobject rio(io);
rio.rename(data.pointLevelPtr_().name());
pointLevelPtr_.reset
(
new labelIOList
(
rio,
UIndirectList<label>(data.pointLevelPtr_(), pointMap)()
)
);
}
if (data.level0EdgePtr_.valid())
{
IOobject rio(io);
rio.rename(data.level0EdgePtr_().name());
level0EdgePtr_.reset
(
new uniformDimensionedScalarField(rio, data.level0EdgePtr_())
);
}
if (data.refHistoryPtr_.valid())
{
IOobject rio(io);
rio.rename(data.refHistoryPtr_().name());
refHistoryPtr_ = data.refHistoryPtr_().clone(rio, cellMap);
}
}
Foam::hexRef8Data::hexRef8Data
(
const IOobject& io,
const UPtrList<const labelList>& cellMaps,
const UPtrList<const labelList>& pointMaps,
const UPtrList<const hexRef8Data>& procDatas
)
{
const polyMesh& mesh = dynamic_cast<const polyMesh&>(io.db());
// cellLevel
if (procDatas[0].cellLevelPtr_.valid())
{
IOobject rio(io);
rio.rename(procDatas[0].cellLevelPtr_().name());
cellLevelPtr_.reset(new labelIOList(rio, mesh.nCells()));
labelList& cellLevel = cellLevelPtr_();
forAll(procDatas, procI)
{
const labelList& procCellLevel = procDatas[procI].cellLevelPtr_();
UIndirectList<label>(cellLevel, cellMaps[procI]) = procCellLevel;
}
}
// pointLevel
if (procDatas[0].pointLevelPtr_.valid())
{
IOobject rio(io);
rio.rename(procDatas[0].pointLevelPtr_().name());
pointLevelPtr_.reset(new labelIOList(rio, mesh.nPoints()));
labelList& pointLevel = pointLevelPtr_();
forAll(procDatas, procI)
{
const labelList& procPointLevel = procDatas[procI].pointLevelPtr_();
UIndirectList<label>(pointLevel, pointMaps[procI]) = procPointLevel;
}
}
// level0Edge
if (procDatas[0].level0EdgePtr_.valid())
{
IOobject rio(io);
rio.rename(procDatas[0].level0EdgePtr_().name());
level0EdgePtr_.reset
(
new uniformDimensionedScalarField
(
rio,
procDatas[0].level0EdgePtr_()
)
);
}
// refinementHistory
if (procDatas[0].refHistoryPtr_.valid())
{
IOobject rio(io);
rio.rename(procDatas[0].refHistoryPtr_().name());
UPtrList<const refinementHistory> procRefs(procDatas.size());
forAll(procDatas, i)
{
procRefs.set(i, &procDatas[i].refHistoryPtr_());
}
refHistoryPtr_.reset
(
new refinementHistory
(
rio,
cellMaps,
procRefs
)
);
}
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::hexRef8Data::~hexRef8Data()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::hexRef8Data::sync(const IOobject& io)
{
const polyMesh& mesh = dynamic_cast<const polyMesh&>(io.db());
bool hasCellLevel = returnReduce(cellLevelPtr_.valid(), orOp<bool>());
if (hasCellLevel && !cellLevelPtr_.valid())
{
IOobject rio(io);
rio.rename("cellLevel");
rio.readOpt() = IOobject::NO_READ;
cellLevelPtr_.reset(new labelIOList(rio, labelList(mesh.nCells(), 0)));
}
bool hasPointLevel = returnReduce(pointLevelPtr_.valid(), orOp<bool>());
if (hasPointLevel && !pointLevelPtr_.valid())
{
IOobject rio(io);
rio.rename("pointLevel");
rio.readOpt() = IOobject::NO_READ;
pointLevelPtr_.reset
(
new labelIOList(rio, labelList(mesh.nPoints(), 0))
);
}
bool hasLevel0Edge = returnReduce(level0EdgePtr_.valid(), orOp<bool>());
if (hasLevel0Edge)
{
// Get master length
scalar masterLen = level0EdgePtr_().value();
Pstream::scatter(masterLen);
if (!level0EdgePtr_.valid())
{
IOobject rio(io);
rio.rename("level0Edge");
rio.readOpt() = IOobject::NO_READ;
level0EdgePtr_.reset
(
new uniformDimensionedScalarField
(
rio,
dimensionedScalar("zero", dimLength, masterLen)
)
);
}
}
bool hasHistory = returnReduce(refHistoryPtr_.valid(), orOp<bool>());
if (hasHistory && !refHistoryPtr_.valid())
{
IOobject rio(io);
rio.rename("refinementHistory");
rio.readOpt() = IOobject::NO_READ;
refHistoryPtr_.reset(new refinementHistory(rio, mesh.nCells(), true));
}
}
void Foam::hexRef8Data::distribute(const mapDistributePolyMesh& map)
{
if (cellLevelPtr_.valid())
{
map.cellMap().distribute(cellLevelPtr_());
}
if (pointLevelPtr_.valid())
{
map.pointMap().distribute(pointLevelPtr_());
}
// No need to distribute the level0Edge
if (refHistoryPtr_.valid() && refHistoryPtr_().active())
{
refHistoryPtr_().distribute(map);
}
}
bool Foam::hexRef8Data::write() const
{
bool ok = true;
if (cellLevelPtr_.valid())
{
ok = ok && cellLevelPtr_().write();
}
if (pointLevelPtr_.valid())
{
ok = ok && pointLevelPtr_().write();
}
if (level0EdgePtr_.valid())
{
ok = ok && level0EdgePtr_().write();
}
if (refHistoryPtr_.valid())
{
ok = ok && refHistoryPtr_().write();
}
return ok;
}
// ************************************************************************* //

View File

@ -0,0 +1,136 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::hexRef8Data
Description
Various for reading/decomposing/reconstructing/distributing refinement
data.
SourceFiles
hexRef8Data.C
\*---------------------------------------------------------------------------*/
#ifndef hexRef8Data_H
#define hexRef8Data_H
#include "labelIOList.H"
#include "uniformDimensionedFields.H"
#include "UPtrList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
class mapPolyMesh;
class mapDistributePolyMesh;
class refinementHistory;
class fvMesh;
/*---------------------------------------------------------------------------*\
Class hexRef8Data Declaration
\*---------------------------------------------------------------------------*/
class hexRef8Data
{
private:
// Private data
autoPtr<labelIOList> cellLevelPtr_;
autoPtr<labelIOList> pointLevelPtr_;
autoPtr<uniformDimensionedScalarField> level0EdgePtr_;
autoPtr<refinementHistory> refHistoryPtr_;
// Private Member Functions
//- Disallow default bitwise copy construct
hexRef8Data(const hexRef8Data&);
//- Disallow default bitwise assignment
void operator=(const hexRef8Data&);
public:
// Constructors
//- Construct read. Has special provision for only some processors
// having the files so can be used in redistribution.
hexRef8Data(const IOobject& io);
//- Construct as subset
hexRef8Data
(
const IOobject& io,
const hexRef8Data&,
const labelList& cellMap,
const labelList& pointMap
);
//- Construct from multiple hexRef8Data
hexRef8Data
(
const IOobject& io,
const UPtrList<const labelList>& cellMaps,
const UPtrList<const labelList>& pointMaps,
const UPtrList<const hexRef8Data>&
);
//- Destructor
~hexRef8Data();
// Member Functions
//- Parallel synchronise. This enforces valid objects on all processors
// (even if they don't have a mesh). Used by redistributePar.
void sync(const IOobject& io);
//- In-place distribute
void distribute(const mapDistributePolyMesh&);
//- Write
bool write() const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

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.
@ -23,12 +23,11 @@ License
\*---------------------------------------------------------------------------*/
#include "DynamicList.H"
#include "refinementHistory.H"
#include "ListOps.H"
#include "mapPolyMesh.H"
#include "mapDistributePolyMesh.H"
#include "polyMesh.H"
#include "syncTools.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -39,6 +38,139 @@ defineTypeNameAndDebug(refinementHistory, 0);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
//- Construct null
Foam::refinementHistory::splitCell8::splitCell8()
:
parent_(-1),
addedCellsPtr_(NULL)
{}
//- Construct as child element of parent
Foam::refinementHistory::splitCell8::splitCell8(const label parent)
:
parent_(parent),
addedCellsPtr_(NULL)
{}
//- Construct from Istream
Foam::refinementHistory::splitCell8::splitCell8(Istream& is)
{
is >> *this;
}
//- Construct as (deep) copy.
Foam::refinementHistory::splitCell8::splitCell8(const splitCell8& sc)
:
parent_(sc.parent_),
addedCellsPtr_
(
sc.addedCellsPtr_.valid()
? new FixedList<label, 8>(sc.addedCellsPtr_())
: NULL
)
{}
// * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * * //
//- Copy operator since autoPtr otherwise 'steals' storage.
void Foam::refinementHistory::splitCell8::operator=(const splitCell8& s)
{
// Check for assignment to self
if (this == &s)
{
FatalErrorIn("splitCell8::operator=(const Foam::splitCell8&)")
<< "Attempted assignment to self"
<< abort(FatalError);
}
parent_ = s.parent_;
addedCellsPtr_.reset
(
s.addedCellsPtr_.valid()
? new FixedList<label, 8>(s.addedCellsPtr_())
: NULL
);
}
bool Foam::refinementHistory::splitCell8::operator==(const splitCell8& s) const
{
if (addedCellsPtr_.valid() != s.addedCellsPtr_.valid())
{
return false;
}
else if (parent_ != s.parent_)
{
return false;
}
else if (addedCellsPtr_.valid())
{
return addedCellsPtr_() == s.addedCellsPtr_();
}
else
{
return true;
}
}
bool Foam::refinementHistory::splitCell8::operator!=(const splitCell8& s) const
{
return !operator==(s);
}
// * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * * //
Foam::Istream& Foam::operator>>(Istream& is, refinementHistory::splitCell8& sc)
{
labelList addedCells;
is >> sc.parent_ >> addedCells;
if (addedCells.size())
{
sc.addedCellsPtr_.reset(new FixedList<label, 8>(addedCells));
}
else
{
sc.addedCellsPtr_.reset(NULL);
}
return is;
}
Foam::Ostream& Foam::operator<<
(
Ostream& os,
const refinementHistory::splitCell8& sc
)
{
// Output as labelList so we can have 0 sized lists. Alternative is to
// output as fixedlist with e.g. -1 elements and check for this upon
// reading. However would cause much more data to be transferred.
if (sc.addedCellsPtr_.valid())
{
return os
<< sc.parent_
<< token::SPACE
<< labelList(sc.addedCellsPtr_());
}
else
{
return os << sc.parent_ << token::SPACE << labelList(0);
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@ -106,89 +238,6 @@ void Foam::refinementHistory::writeDebug
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
//- Construct null
Foam::refinementHistory::splitCell8::splitCell8()
:
parent_(-1),
addedCellsPtr_(NULL)
{}
//- Construct as child element of parent
Foam::refinementHistory::splitCell8::splitCell8(const label parent)
:
parent_(parent),
addedCellsPtr_(NULL)
{}
//- Construct from Istream
Foam::refinementHistory::splitCell8::splitCell8(Istream& is)
{
is >> *this;
}
//- Construct as (deep) copy.
Foam::refinementHistory::splitCell8::splitCell8(const splitCell8& sc)
:
parent_(sc.parent_),
addedCellsPtr_
(
sc.addedCellsPtr_.valid()
? new FixedList<label, 8>(sc.addedCellsPtr_())
: NULL
)
{}
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
Foam::Istream& Foam::operator>>(Istream& is, refinementHistory::splitCell8& sc)
{
labelList addedCells;
is >> sc.parent_ >> addedCells;
if (addedCells.size())
{
sc.addedCellsPtr_.reset(new FixedList<label, 8>(addedCells));
}
else
{
sc.addedCellsPtr_.reset(NULL);
}
return is;
}
Foam::Ostream& Foam::operator<<
(
Ostream& os,
const refinementHistory::splitCell8& sc
)
{
// Output as labelList so we can have 0 sized lists. Alternative is to
// output as fixedlist with e.g. -1 elements and check for this upon
// reading. However would cause much more data to be transferred.
if (sc.addedCellsPtr_.valid())
{
return os
<< sc.parent_
<< token::SPACE
<< labelList(sc.addedCellsPtr_());
}
else
{
return os << sc.parent_ << token::SPACE << labelList(0);
}
}
void Foam::refinementHistory::checkIndices() const
{
// Check indices.
@ -325,11 +374,193 @@ void Foam::refinementHistory::markSplit
}
// Mark index and all its descendants
void Foam::refinementHistory::mark
(
const label val,
const label index,
labelList& splitToVal
) const
{
splitToVal[index] = val;
const splitCell8& split = splitCells_[index];
if (split.addedCellsPtr_.valid())
{
const FixedList<label, 8>& splits = split.addedCellsPtr_();
forAll(splits, i)
{
if (splits[i] >= 0)
{
mark(val, splits[i], splitToVal);
}
}
}
}
Foam::label Foam::refinementHistory::markCommonCells
(
labelList& cellToCluster
) const
{
label clusterI = 0;
labelList splitToCluster(splitCells_.size(), -1);
// Pass1: find top of all clusters
forAll(visibleCells_, cellI)
{
label index = visibleCells_[cellI];
if (index >= 0)
{
// Find highest ancestor
while (splitCells_[index].parent_ != -1)
{
index = splitCells_[index].parent_;
}
// Mark tree with clusterI
if (splitToCluster[index] == -1)
{
mark(clusterI, index, splitToCluster);
clusterI++;
}
}
}
// Pass2: mark all cells with cluster
cellToCluster.setSize(visibleCells_.size(), -1);
forAll(visibleCells_, cellI)
{
label index = visibleCells_[cellI];
if (index >= 0)
{
cellToCluster[cellI] = splitToCluster[index];
}
}
return clusterI;
}
void Foam::refinementHistory::add
(
boolList& blockedFace,
PtrList<labelList>& specifiedProcessorFaces,
labelList& specifiedProcessor,
List<labelPair>& explicitConnections
) const
{
const polyMesh& mesh = dynamic_cast<const polyMesh&>(db());
blockedFace.setSize(mesh.nFaces(), true);
// Find common parent for all cells
labelList cellToCluster;
markCommonCells(cellToCluster);
// Unblock all faces inbetween same cluster
label nUnblocked = 0;
forAll(mesh.faceNeighbour(), faceI)
{
label ownCluster = cellToCluster[mesh.faceOwner()[faceI]];
label neiCluster = cellToCluster[mesh.faceNeighbour()[faceI]];
if (ownCluster != -1 && ownCluster == neiCluster)
{
if (blockedFace[faceI])
{
blockedFace[faceI] = false;
nUnblocked++;
}
}
}
if (refinementHistory::debug)
{
reduce(nUnblocked, sumOp<label>());
Info<< type() << " : unblocked " << nUnblocked << " faces" << endl;
}
syncTools::syncFaceList(mesh, blockedFace, andEqOp<bool>());
}
void Foam::refinementHistory::apply
(
const boolList& blockedFace,
const PtrList<labelList>& specifiedProcessorFaces,
const labelList& specifiedProcessor,
const List<labelPair>& explicitConnections,
labelList& decomposition
) const
{
const polyMesh& mesh = dynamic_cast<const polyMesh&>(db());
// Find common parent for all cells
labelList cellToCluster;
label nClusters = markCommonCells(cellToCluster);
// Unblock all faces inbetween same cluster
labelList clusterToProc(nClusters, -1);
label nChanged = 0;
forAll(mesh.faceNeighbour(), faceI)
{
label own = mesh.faceOwner()[faceI];
label nei = mesh.faceNeighbour()[faceI];
label ownCluster = cellToCluster[own];
label neiCluster = cellToCluster[nei];
if (ownCluster != -1 && ownCluster == neiCluster)
{
if (clusterToProc[ownCluster] == -1)
{
clusterToProc[ownCluster] = decomposition[own];
}
if (decomposition[own] != clusterToProc[ownCluster])
{
decomposition[own] = clusterToProc[ownCluster];
nChanged++;
}
if (decomposition[nei] != clusterToProc[ownCluster])
{
decomposition[nei] = clusterToProc[ownCluster];
nChanged++;
}
}
}
if (refinementHistory::debug)
{
reduce(nChanged, sumOp<label>());
Info<< type() << " : changed decomposition on " << nChanged
<< " cells" << endl;
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::refinementHistory::refinementHistory(const IOobject& io)
:
regIOobject(io)
regIOobject(io),
refCount(),
active_(false)
{
// Temporary warning
if (io.readOpt() == IOobject::MUST_READ_IF_MODIFIED)
@ -353,6 +584,11 @@ Foam::refinementHistory::refinementHistory(const IOobject& io)
close();
}
// When running in redistributPar + READ_IF_PRESENT it can happen
// that some processors do have refinementHistory and some don't so
// test for active has to be outside of above condition.
active_ = (returnReduce(visibleCells_.size(), sumOp<label>()) > 0);
if (debug)
{
Pout<< "refinementHistory::refinementHistory :"
@ -369,10 +605,13 @@ Foam::refinementHistory::refinementHistory
(
const IOobject& io,
const List<splitCell8>& splitCells,
const labelList& visibleCells
const labelList& visibleCells,
const bool active
)
:
regIOobject(io),
refCount(),
active_(active),
splitCells_(splitCells),
freeSplitCells_(0),
visibleCells_(visibleCells)
@ -422,6 +661,8 @@ Foam::refinementHistory::refinementHistory
)
:
regIOobject(io),
refCount(),
active_(false),
freeSplitCells_(0)
{
// Temporary warning
@ -429,8 +670,70 @@ Foam::refinementHistory::refinementHistory
{
WarningIn
(
"refinementHistory::refinementHistory"
"(const IOobject&, const label)"
"refinementHistory::refinementHistory(const IOobject&)"
) << "Specified IOobject::MUST_READ_IF_MODIFIED but class"
<< " does not support automatic rereading."
<< endl;
}
if
(
io.readOpt() == IOobject::MUST_READ
|| io.readOpt() == IOobject::MUST_READ_IF_MODIFIED
|| (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
)
{
readStream(typeName) >> *this;
close();
}
else
{
visibleCells_.setSize(nCells);
splitCells_.setCapacity(nCells);
for (label cellI = 0; cellI < nCells; cellI++)
{
visibleCells_[cellI] = cellI;
splitCells_.append(splitCell8());
}
}
active_ = (returnReduce(visibleCells_.size(), sumOp<label>()) > 0);
// Check indices.
checkIndices();
if (debug)
{
Pout<< "refinementHistory::refinementHistory :"
<< " constructed history from IOobject or initial size :"
<< " splitCells:" << splitCells_.size()
<< " visibleCells:" << visibleCells_.size()
<< endl;
}
}
// Construct from initial number of cells (all visible)
Foam::refinementHistory::refinementHistory
(
const IOobject& io,
const label nCells,
const bool active
)
:
regIOobject(io),
refCount(),
active_(active),
freeSplitCells_(0)
{
// Temporary warning
if (io.readOpt() == IOobject::MUST_READ_IF_MODIFIED)
{
WarningIn
(
"refinementHistory::refinementHistory(const IOobject&)"
) << "Specified IOobject::MUST_READ_IF_MODIFIED but class"
<< " does not support automatic rereading."
<< endl;
@ -480,6 +783,8 @@ Foam::refinementHistory::refinementHistory
)
:
regIOobject(io),
refCount(),
active_(rh.active_),
splitCells_(rh.splitCells()),
freeSplitCells_(rh.freeSplitCells()),
visibleCells_(rh.visibleCells())
@ -492,14 +797,138 @@ Foam::refinementHistory::refinementHistory
}
// Construct from multiple
Foam::refinementHistory::refinementHistory
(
const IOobject& io,
const UPtrList<const labelList>& cellMaps,
const UPtrList<const refinementHistory>& refs
)
:
regIOobject(io),
refCount(),
active_(false)
{
if
(
io.readOpt() == IOobject::MUST_READ
|| io.readOpt() == IOobject::MUST_READ_IF_MODIFIED
|| (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
)
{
WarningIn
(
"refinementHistory::refinementHistory(const IOobject&"
", const labelListList&, const PtrList<refinementHistory>&)"
) << "read option IOobject::MUST_READ, READ_IF_PRESENT or "
<< "MUST_READ_IF_MODIFIED"
<< " suggests that a read constructor would be more appropriate."
<< endl;
}
const polyMesh& mesh = dynamic_cast<const polyMesh&>(db());
// Determine offsets into splitCells
labelList offsets(refs.size()+1);
offsets[0] = 0;
forAll(refs, refI)
{
const DynamicList<splitCell8>& subSplits = refs[refI].splitCells();
offsets[refI+1] = offsets[refI]+subSplits.size();
}
// Construct merged splitCells
splitCells_.setSize(offsets.last());
forAll(refs, refI)
{
const DynamicList<splitCell8>& subSplits = refs[refI].splitCells();
forAll(subSplits, i)
{
splitCell8& newSplit = splitCells_[offsets[refI]+i];
// Copy
newSplit = subSplits[i];
// Offset indices
if (newSplit.parent_ >= 0)
{
newSplit.parent_ += offsets[refI];
}
if (newSplit.addedCellsPtr_.valid())
{
FixedList<label, 8>& splits = newSplit.addedCellsPtr_();
forAll(splits, i)
{
if (splits[i] >= 0)
{
splits[i] += offsets[refI];
}
}
}
}
}
// Construct merged visibleCells
visibleCells_.setSize(mesh.nCells(), -1);
forAll(refs, refI)
{
const labelList& cellMap = cellMaps[refI];
const labelList& subVis = refs[refI].visibleCells();
forAll(subVis, i)
{
label& newVis = visibleCells_[cellMap[i]];
newVis = subVis[i];
if (newVis >= 0)
{
newVis += offsets[refI];
}
}
}
// Is active if any of the refinementHistories is active (assumes active
// flag parallel synchronised)
active_ = false;
forAll(refs, refI)
{
if (refs[refI].active())
{
active_ = true;
break;
}
}
// Check indices.
checkIndices();
if (debug)
{
Pout<< "refinementHistory::refinementHistory :"
<< " constructed history from multiple refinementHistories :"
<< " splitCells:" << splitCells_.size()
<< " visibleCells:" << visibleCells_.size()
<< endl;
}
}
// Construct from Istream
Foam::refinementHistory::refinementHistory(const IOobject& io, Istream& is)
:
regIOobject(io),
refCount(),
splitCells_(is),
freeSplitCells_(0),
visibleCells_(is)
{
active_ = (returnReduce(visibleCells_.size(), sumOp<label>()) > 0);
// Check indices.
checkIndices();
@ -516,6 +945,192 @@ Foam::refinementHistory::refinementHistory(const IOobject& io, Istream& is)
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::autoPtr<Foam::refinementHistory> Foam::refinementHistory::clone
(
const IOobject& io,
// Per visible cell the processor it is going to
const labelList& decomposition,
// Per splitCell entry the processor it moves to
const labelList& splitCellProc,
// Per splitCell entry the number of live cells that move to that processor
const labelList& splitCellNum,
const label procI,
// From old to new splitCells
labelList& oldToNewSplit
) const
{
oldToNewSplit.setSize(splitCells_.size());
oldToNewSplit = -1;
// Compacted splitCells
DynamicList<splitCell8> newSplitCells(splitCells_.size());
// Loop over all entries. Note: could recurse like countProc so only
// visit used entries but is probably not worth it.
forAll(splitCells_, index)
{
if (splitCellProc[index] == procI && splitCellNum[index] == 8)
{
// Entry moves in its whole to procI
oldToNewSplit[index] = newSplitCells.size();
newSplitCells.append(splitCells_[index]);
}
}
// Add live cells that are subsetted.
forAll(visibleCells_, cellI)
{
label index = visibleCells_[cellI];
if (index >= 0 && decomposition[cellI] == procI)
{
label parent = splitCells_[index].parent_;
// Create new splitCell with parent
oldToNewSplit[index] = newSplitCells.size();
newSplitCells.append(splitCell8(parent));
}
}
//forAll(oldToNewSplit, index)
//{
// Pout<< "old:" << index << " new:" << oldToNewSplit[index]
// << endl;
//}
newSplitCells.shrink();
// Renumber contents of newSplitCells
forAll(newSplitCells, index)
{
splitCell8& split = newSplitCells[index];
if (split.parent_ >= 0)
{
split.parent_ = oldToNewSplit[split.parent_];
}
if (split.addedCellsPtr_.valid())
{
FixedList<label, 8>& splits = split.addedCellsPtr_();
forAll(splits, i)
{
if (splits[i] >= 0)
{
splits[i] = oldToNewSplit[splits[i]];
}
}
}
}
// Count number of cells
label nSub = 0;
forAll(decomposition, cellI)
{
if (decomposition[cellI] == procI)
{
nSub++;
}
}
labelList newVisibleCells(nSub);
nSub = 0;
forAll(visibleCells_, cellI)
{
if (decomposition[cellI] == procI)
{
label index = visibleCells_[cellI];
if (index >= 0)
{
index = oldToNewSplit[index];
}
newVisibleCells[nSub++] = index;
}
}
return autoPtr<refinementHistory>
(
new refinementHistory
(
io,
newSplitCells,
newVisibleCells,
active_
)
);
}
Foam::autoPtr<Foam::refinementHistory> Foam::refinementHistory::clone
(
const IOobject& io,
const labelList& cellMap
) const
{
if (active_)
{
// Mark selected cells with '1'
labelList decomposition(visibleCells_.size(), 0);
forAll(cellMap, i)
{
decomposition[cellMap[i]] = 1;
}
// Per splitCell entry the processor it moves to
labelList splitCellProc(splitCells_.size(), -1);
// Per splitCell entry the number of live cells that move to that
// processor
labelList splitCellNum(splitCells_.size(), 0);
forAll(visibleCells_, cellI)
{
label index = visibleCells_[cellI];
if (index >= 0)
{
countProc
(
splitCells_[index].parent_,
decomposition[cellI],
splitCellProc,
splitCellNum
);
}
}
labelList oldToNewSplit;
return clone
(
io,
decomposition,
splitCellProc,
splitCellNum,
1, //procI,
oldToNewSplit
);
}
else
{
return autoPtr<refinementHistory>
(
new refinementHistory
(
io,
DynamicList<splitCell8>(0),
labelList(0),
false
)
);
}
}
void Foam::refinementHistory::resize(const label size)
{
label oldSize = visibleCells_.size();
@ -720,9 +1335,6 @@ void Foam::refinementHistory::distribute(const mapDistributePolyMesh& map)
}
}
//Pout<< "refinementHistory::distribute :"
// << " destination:" << destination << endl;
// Per splitCell entry the processor it moves to
labelList splitCellProc(splitCells_.size(), -1);
// Per splitCell entry the number of live cells that move to that processor
@ -768,21 +1380,11 @@ void Foam::refinementHistory::distribute(const mapDistributePolyMesh& map)
forAll(splitCells_, index)
{
// Pout<< "oldCell:" << index
// << " proc:" << splitCellProc[index]
// << " nCells:" << splitCellNum[index]
// << endl;
if (splitCellProc[index] == procI && splitCellNum[index] == 8)
{
// Entry moves in its whole to procI
oldToNew[index] = newSplitCells.size();
newSplitCells.append(splitCells_[index]);
//Pout<< "Added oldCell " << index
// << " info " << newSplitCells.last()
// << " at position " << newSplitCells.size()-1
// << endl;
}
}
@ -795,10 +1397,6 @@ void Foam::refinementHistory::distribute(const mapDistributePolyMesh& map)
{
label parent = splitCells_[index].parent_;
//Pout<< "Adding refined cell " << cellI
// << " since moves to "
// << procI << " old parent:" << parent << endl;
// Create new splitCell with parent
oldToNew[index] = newSplitCells.size();
newSplitCells.append(splitCell8(parent));
@ -871,7 +1469,9 @@ void Foam::refinementHistory::distribute(const mapDistributePolyMesh& map)
// Remove all entries. Leave storage intact.
splitCells_.clear();
visibleCells_.setSize(map.mesh().nCells());
const polyMesh& mesh = dynamic_cast<const polyMesh&>(db());
visibleCells_.setSize(mesh.nCells());
visibleCells_ = -1;
for (label procI = 0; procI < Pstream::nProcs(); procI++)
@ -1160,6 +1760,17 @@ void Foam::refinementHistory::combineCells
}
bool Foam::refinementHistory::read()
{
bool ok = readData(readStream(typeName));
close();
active_ = (returnReduce(visibleCells_.size(), sumOp<label>()) > 0);
return ok;
}
bool Foam::refinementHistory::readData(Istream& is)
{
is >> *this;

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.
@ -28,7 +28,7 @@ Description
All refinement history. Used in unrefinement.
- visibleCells: valid for the current mesh and contains per cell -1
(cell unrefined) or an index into splitCells_.
(cell unrefined) or an index into splitCells_.
- splitCells: for every split contains the parent (also index into
splitCells) and optionally a subsplit as 8 indices into splitCells.
Note that the numbers in splitCells are not cell labels, they are purely
@ -71,12 +71,14 @@ SourceFiles
#ifndef refinementHistory_H
#define refinementHistory_H
#include "UPtrList.H"
#include "DynamicList.H"
#include "labelList.H"
#include "FixedList.H"
#include "SLList.H"
#include "autoPtr.H"
#include "regIOobject.H"
#include "boolList.H"
#include "labelPair.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -93,7 +95,8 @@ class mapDistributePolyMesh;
class refinementHistory
:
public regIOobject
public regIOobject,
public refCount
{
public:
@ -122,50 +125,11 @@ public:
splitCell8(const splitCell8&);
//- Copy operator since autoPtr otherwise 'steals' storage.
void operator=(const splitCell8& s)
{
// Check for assignment to self
if (this == &s)
{
FatalErrorIn("splitCell8::operator=(const Foam::splitCell8&)")
<< "Attempted assignment to self"
<< abort(FatalError);
}
void operator=(const splitCell8& s);
parent_ = s.parent_;
bool operator==(const splitCell8& s) const;
addedCellsPtr_.reset
(
s.addedCellsPtr_.valid()
? new FixedList<label, 8>(s.addedCellsPtr_())
: NULL
);
}
bool operator==(const splitCell8& s) const
{
if (addedCellsPtr_.valid() != s.addedCellsPtr_.valid())
{
return false;
}
else if (parent_ != s.parent_)
{
return false;
}
else if (addedCellsPtr_.valid())
{
return addedCellsPtr_() == s.addedCellsPtr_();
}
else
{
return true;
}
}
bool operator!=(const splitCell8& s) const
{
return !operator==(s);
}
bool operator!=(const splitCell8& s) const;
friend Istream& operator>>(Istream&, splitCell8&);
friend Ostream& operator<<(Ostream&, const splitCell8&);
@ -176,6 +140,9 @@ private:
// Private data
//- Is active?
bool active_;
//- Storage for splitCells
DynamicList<splitCell8> splitCells_;
@ -226,6 +193,15 @@ private:
labelList& splitCellNum
) const;
// For distribution:
//- Mark index and all its descendants
void mark(const label, const label, labelList&) const;
//- Mark cells according to top parent. Return number of clusters
// (set of cells originating from same parent)
label markCommonCells(labelList& cellToCluster) const;
public:
// Declare name of the class and its debug switch
@ -234,25 +210,47 @@ public:
// Constructors
//- Construct (read) given an IOobject
//- Construct (read) given an IOobject. If global number of visible
// cells > 0 becomes active
refinementHistory(const IOobject&);
//- Construct (read) or construct null
//- Construct (read) or construct from components
refinementHistory
(
const IOobject&,
const List<splitCell8>& splitCells,
const labelList& visibleCells
const labelList& visibleCells,
const bool active
);
//- Construct (read) or construct from initial number of cells
// (all visible)
// (all visible). If global number of visible
// cells > 0 becomes active
refinementHistory(const IOobject&, const label nCells);
//- Construct (read) or construct from initial number of cells
// (all visible) and active flag
refinementHistory
(
const IOobject&,
const label nCells,
const bool active
);
//- Construct as copy
refinementHistory(const IOobject&, const refinementHistory&);
//- Construct from Istream
//- Construct from multiple refinement histories. If global number of
// visible cells > 0 becomes active
refinementHistory
(
const IOobject&,
const UPtrList<const labelList>& cellMaps,
const UPtrList<const refinementHistory>&
);
//- Construct from Istream. If global number of
// visible cells > 0 becomes active
refinementHistory(const IOobject&, Istream&);
@ -278,12 +276,16 @@ public:
return freeSplitCells_;
}
//- Is there unrefinement history. Note that this will fall over if
// there are 0 cells in the mesh. But this gives problems with
// lots of other programs anyway.
//- Is there unrefinement history?
bool active() const
{
return visibleCells_.size() > 0;
return active_;
}
//- Is there unrefinement history?
bool& active()
{
return active_;
}
//- Get parent of cell
@ -314,6 +316,23 @@ public:
const labelList& combinedCells
);
//- Low level clone
autoPtr<refinementHistory> clone
(
const IOobject& io,
const labelList& decomposition,
const labelList& splitCellProc,
const labelList& splitCellNum,
const label procI,
labelList& oldToNewSplit
) const;
//- Create clone from subset
autoPtr<refinementHistory> clone
(
const IOobject& io,
const labelList& cellMap
) const;
//- Update numbering for mesh changes
void updateMesh(const mapPolyMesh&);
@ -331,7 +350,6 @@ public:
// handle parts recombined in multiple passes.
void distribute(const mapDistributePolyMesh&);
//- Compact splitCells_. Removes all freeSplitCells_ elements.
void compact();
@ -343,20 +361,44 @@ public:
void writeDebug() const;
//- ReadData function required for regIOobject read operation
//- Read object. If global number of visible cells > 0 becomes active
virtual bool read();
//- ReadData function required for regIOobject read operation. Note:
// does not do a reduction - does not set active_ flag
virtual bool readData(Istream&);
//- WriteData function required for regIOobject write operation
virtual bool writeData(Ostream&) const;
// Helpers for decompositionConstraint
// Friend Functions
//- Add my decomposition constraints
void add
(
boolList& blockedFace,
PtrList<labelList>& specifiedProcessorFaces,
labelList& specifiedProcessor,
List<labelPair>& explicitConnections
) const;
//- Apply any additional post-decomposition constraints
void apply
(
const boolList& blockedFace,
const PtrList<labelList>& specifiedProcessorFaces,
const labelList& specifiedProcessor,
const List<labelPair>& explicitConnections,
labelList& decomposition
) const;
// Friend Operators
// IOstream Operators
//- Istream operator. Note: does not do a reduction - does not set
// active_ flag
friend Istream& operator>>(Istream&, refinementHistory&);
friend Ostream& operator<<(Ostream&, const refinementHistory&);
};

View File

@ -2,7 +2,6 @@ fvMesh/fvMeshGeometry.C
fvMesh/fvMesh.C
fvMesh/singleCellFvMesh/singleCellFvMesh.C
fvMesh/fvMeshSubset/fvMeshSubset.C
fvBoundaryMesh = fvMesh/fvBoundaryMesh
$(fvBoundaryMesh)/fvBoundaryMesh.C

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -60,15 +60,26 @@ Foam::fixedFluxPressureFvPatchScalarField::fixedFluxPressureFvPatchScalarField
gradient().map(ptf.gradient(), mapper);
// Evaluate the value field from the gradient if the internal field is valid
if (notNull(iF) && iF.size())
if (notNull(iF))
{
scalarField::operator=
(
//patchInternalField() + gradient()/patch().deltaCoeffs()
// ***HGW Hack to avoid the construction of mesh.deltaCoeffs
// which fails for AMI patches for some mapping operations
patchInternalField() + gradient()*(patch().nf() & patch().delta())
);
if (iF.size())
{
// Note: cannot ask for nf() if zero faces
scalarField::operator=
(
//patchInternalField() + gradient()/patch().deltaCoeffs()
// ***HGW Hack to avoid the construction of mesh.deltaCoeffs
// which fails for AMI patches for some mapping operations
patchInternalField()
+ gradient()*(patch().nf() & patch().delta())
);
}
}
else
{
// Enforce mapping of values so we have a valid starting value
this->map(ptf, mapper);
}
}

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.
@ -272,7 +272,7 @@ void timeVaryingMappedFixedValueFvPatchField<Type>::checkTable()
IOobject
(
"points",
this->db().time().constant(),
this->db().time().caseConstant(),
"boundaryData"/this->patch().name(),
this->db(),
IOobject::MUST_READ,
@ -304,7 +304,7 @@ void timeVaryingMappedFixedValueFvPatchField<Type>::checkTable()
new pointToPointPlanarInterpolation
(
samplePoints,
this->patch().patch().faceCentres(),
this->patch().patch().faceCentres(),
perturb_,
nearestOnly
)
@ -392,7 +392,7 @@ void timeVaryingMappedFixedValueFvPatchField<Type>::checkTable()
IOobject
(
fieldTableName_,
this->db().time().constant(),
this->db().time().caseConstant(),
"boundaryData"
/this->patch().name()
/sampleTimes_[startSampleTime_].name(),
@ -450,7 +450,7 @@ void timeVaryingMappedFixedValueFvPatchField<Type>::checkTable()
IOobject
(
fieldTableName_,
this->db().time().constant(),
this->db().time().caseConstant(),
"boundaryData"
/this->patch().name()
/sampleTimes_[endSampleTime_].name(),

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -98,7 +98,7 @@ Foam::fvPatchField<Type>::fvPatchField
patchType_(ptf.patchType_)
{
// For unmapped faces set to internal field value (zero-gradient)
if (notNull(iF) && iF.size())
if (notNull(iF) && mapper.hasUnmapped())
{
fvPatchField<Type>::operator=(this->patchInternalField());
}
@ -233,7 +233,7 @@ void Foam::fvPatchField<Type>::autoMap
{
Field<Type>& f = *this;
if (!this->size())
if (!this->size() && !mapper.distributed())
{
f.setSize(mapper.size());
if (f.size())
@ -246,39 +246,41 @@ void Foam::fvPatchField<Type>::autoMap
// Map all faces provided with mapping data
Field<Type>::autoMap(mapper);
// For unmapped faces set to internal field value (zero-gradient)
if
(
mapper.direct()
&& notNull(mapper.directAddressing())
&& mapper.directAddressing().size()
)
if (mapper.hasUnmapped())
{
Field<Type> pif(this->patchInternalField());
const labelList& mapAddressing = mapper.directAddressing();
forAll(mapAddressing, i)
if
(
mapper.direct()
&& notNull(mapper.directAddressing())
&& mapper.directAddressing().size()
)
{
if (mapAddressing[i] < 0)
const labelList& mapAddressing = mapper.directAddressing();
forAll(mapAddressing, i)
{
f[i] = pif[i];
if (mapAddressing[i] < 0)
{
f[i] = pif[i];
}
}
}
}
else if (!mapper.direct() && mapper.addressing().size())
{
Field<Type> pif(this->patchInternalField());
const labelListList& mapAddressing = mapper.addressing();
forAll(mapAddressing, i)
else if (!mapper.direct() && mapper.addressing().size())
{
const labelList& localAddrs = mapAddressing[i];
const labelListList& mapAddressing = mapper.addressing();
if (!localAddrs.size())
forAll(mapAddressing, i)
{
f[i] = pif[i];
const labelList& localAddrs = mapAddressing[i];
if (!localAddrs.size())
{
f[i] = pif[i];
}
}
}
}

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -159,6 +159,66 @@ void volPointInterpolation::interpolateInternalField
}
template<class Type>
void volPointInterpolation::interpolateDimensionedInternalField
(
const DimensionedField<Type, volMesh>& vf,
DimensionedField<Type, pointMesh>& pf
) const
{
if (debug)
{
Pout<< "volPointInterpolation::interpolateDimensionedInternalField("
<< "const DimensionedField<Type, volMesh>&, "
<< "DimensionedField<Type, pointMesh>&) : "
<< "interpolating field from cells to points"
<< endl;
}
const fvMesh& mesh = vf.mesh();
const labelListList& pointCells = mesh.pointCells();
const pointField& points = mesh.points();
const vectorField& cellCentres = mesh.cellCentres();
// Re-do weights and interpolation since normal interpolation
// pointWeights_ are for non-boundary points only. Not efficient but
// then saves on space.
// Multiply volField by weighting factor matrix to create pointField
scalarField sumW(points.size(), 0.0);
forAll(pointCells, pointi)
{
const labelList& ppc = pointCells[pointi];
pf[pointi] = pTraits<Type>::zero;
forAll(ppc, pointCelli)
{
label celli = ppc[pointCelli];
scalar pw = 1.0/mag(points[pointi] - cellCentres[celli]);
pf[pointi] += pw*vf[celli];
sumW[pointi] += pw;
}
}
// Sum collocated contributions
pointConstraints::syncUntransformedData(mesh, sumW, plusEqOp<scalar>());
pointConstraints::syncUntransformedData(mesh, pf, plusEqOp<Type>());
// Normalise
forAll(pf, pointi)
{
scalar s = sumW[pointi];
if (s > ROOTVSMALL)
{
pf[pointi] /= s;
}
}
}
template<class Type>
tmp<Field<Type> > volPointInterpolation::flatBoundaryField
(
@ -424,24 +484,13 @@ volPointInterpolation::interpolate
if (pf.upToDate(vf)) //TBD: , vf.mesh().points()))
{
solution::cachePrintMessage("Reusing", name, vf);
return pf;
}
else
{
solution::cachePrintMessage("Deleting", name, vf);
pf.release();
delete &pf;
solution::cachePrintMessage("Recalculating", name, vf);
tmp<PointFieldType> tpf = interpolate(vf, name, false);
solution::cachePrintMessage("Storing", name, vf);
PointFieldType* pfPtr = tpf.ptr();
regIOobject::store(pfPtr);
// Note: return reference, not pointer
return *pfPtr;
solution::cachePrintMessage("Updating", name, vf);
interpolate(vf, pf);
}
return pf;
}
}
}
@ -473,6 +522,116 @@ volPointInterpolation::interpolate
}
template<class Type>
tmp<DimensionedField<Type, pointMesh> >
volPointInterpolation::interpolate
(
const DimensionedField<Type, volMesh>& vf,
const word& name,
const bool cache
) const
{
typedef DimensionedField<Type, pointMesh> PointFieldType;
const pointMesh& pm = pointMesh::New(vf.mesh());
const objectRegistry& db = pm.thisDb();
if (!cache || vf.mesh().changing())
{
// Delete any old occurences to avoid double registration
if (db.objectRegistry::template foundObject<PointFieldType>(name))
{
PointFieldType& pf = const_cast<PointFieldType&>
(
db.objectRegistry::template lookupObject<PointFieldType>(name)
);
if (pf.ownedByRegistry())
{
solution::cachePrintMessage("Deleting", name, vf);
pf.release();
delete &pf;
}
}
tmp<DimensionedField<Type, pointMesh> > tpf
(
new DimensionedField<Type, pointMesh>
(
IOobject
(
name,
vf.instance(),
pm.thisDb()
),
pm,
vf.dimensions()
)
);
interpolateDimensionedInternalField(vf, tpf());
return tpf;
}
else
{
if (!db.objectRegistry::template foundObject<PointFieldType>(name))
{
solution::cachePrintMessage("Calculating and caching", name, vf);
tmp<PointFieldType> tpf = interpolate(vf, name, false);
PointFieldType* pfPtr = tpf.ptr();
regIOobject::store(pfPtr);
return *pfPtr;
}
else
{
PointFieldType& pf = const_cast<PointFieldType&>
(
db.objectRegistry::template lookupObject<PointFieldType>(name)
);
if (pf.upToDate(vf)) //TBD: , vf.mesh().points()))
{
solution::cachePrintMessage("Reusing", name, vf);
}
else
{
solution::cachePrintMessage("Updating", name, vf);
interpolateDimensionedInternalField(vf, pf);
}
return pf;
}
}
}
template<class Type>
tmp<DimensionedField<Type, pointMesh> >
volPointInterpolation::interpolate
(
const DimensionedField<Type, volMesh>& vf
) const
{
return interpolate(vf, "volPointInterpolate(" + vf.name() + ')', false);
}
template<class Type>
tmp<DimensionedField<Type, pointMesh> >
volPointInterpolation::interpolate
(
const tmp<DimensionedField<Type, volMesh> >& tvf
) const
{
// Construct tmp<pointField>
tmp<DimensionedField<Type, pointMesh> > tpf = interpolate(tvf());
tvf.clear();
return tpf;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -187,6 +187,22 @@ public:
const wordList& patchFieldTypes
) const;
//- Interpolate dimensionedField using inverse distance weighting
// returning pointField
template<class Type>
tmp<DimensionedField<Type, pointMesh> > interpolate
(
const DimensionedField<Type, volMesh>&
) const;
//- Interpolate tmp<dimensionedField> using inverse distance
// weighting returning pointField
template<class Type>
tmp<DimensionedField<Type, pointMesh> > interpolate
(
const tmp<DimensionedField<Type, volMesh> >&
) const;
// Low level
@ -236,6 +252,24 @@ public:
const bool cache
) const;
//- Interpolate dimensioned internal field from cells to points
// using inverse distance weighting
template<class Type>
void interpolateDimensionedInternalField
(
const DimensionedField<Type, volMesh>& vf,
DimensionedField<Type, pointMesh>& pf
) const;
//- Interpolate dimensionedField using inverse distance weighting
// returning pointField with name. Optionally caches
template<class Type>
tmp<DimensionedField<Type, pointMesh> > interpolate
(
const DimensionedField<Type, volMesh>&,
const word& name,
const bool cache
) const;
// Interpolation for displacement (applies 2D correction)

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -105,6 +105,30 @@ public:
{
return autoPtr<particle>(new passiveParticle(*this));
}
//- Factory class to read-construct particles used for
// parallel transfer
class iNew
{
const polyMesh& mesh_;
public:
iNew(const polyMesh& mesh)
:
mesh_(mesh)
{}
autoPtr<passiveParticle> operator()(Istream& is) const
{
return autoPtr<passiveParticle>
(
new passiveParticle(mesh_, is, true)
);
}
};
};

View File

@ -0,0 +1,531 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "AABBTree.H"
#include "meshTools.H"
#include "PackedBoolList.H"
//#include "OFstream.H"
template<class Type>
Foam::scalar Foam::AABBTree<Type>::tolerance_ = 1e-4;
// * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
template<class Type>
void Foam::AABBTree<Type>::writeOBJ
(
const bool writeLinesOnly,
const treeBoundBox& bb,
label& vertI,
Ostream& os
) const
{
const pointField pts(bb.points());
forAll(pts, i)
{
meshTools::writeOBJ(os, pts[i]);
}
if (writeLinesOnly)
{
forAll(bb.edges, i)
{
const edge& e = bb.edges[i];
os << "l " << e[0] + vertI + 1 << ' ' << e[1] + vertI + 1 << nl;
}
}
else
{
forAll(bb.faces, i)
{
const face& f = bb.faces[i];
os << 'f';
forAll(f, fp)
{
os << ' ' << f[fp] + vertI + 1;
}
os << nl;
}
}
vertI += pts.size();
}
template<class Type>
void Foam::AABBTree<Type>::writeOBJ
(
const bool leavesOnly,
const bool writeLinesOnly,
const treeBoundBox& bb,
const label nodeI,
const List<Pair<treeBoundBox> >& bbs,
const List<Pair<label> >& nodes,
label& vertI,
Ostream& os
) const
{
if (!leavesOnly || nodeI < 0)
{
writeOBJ(writeLinesOnly, bb, vertI, os);
}
// recurse to find leaves
if (nodeI >= 0)
{
writeOBJ
(
leavesOnly,
writeLinesOnly,
bbs[nodeI].first(),
nodes[nodeI].first(),
bbs,
nodes,
vertI,
os
);
writeOBJ
(
leavesOnly,
writeLinesOnly,
bbs[nodeI].second(),
nodes[nodeI].second(),
bbs,
nodes,
vertI,
os
);
}
}
template<class Type>
void Foam::AABBTree<Type>::createBoxes
(
const bool equalBinSize,
const label level,
const List<Type>& objects,
const pointField& points,
const DynamicList<label>& objectIDs,
const treeBoundBox& bb,
const label nodeI,
DynamicList<Pair<treeBoundBox> >& bbs,
DynamicList<labelPair>& nodes,
DynamicList<labelList>& addressing
) const
{
const vector span = bb.span();
// Determine which direction to divide the box
direction maxDir = 0;
scalar maxSpan = span[maxDir];
for (label dirI = 1; dirI < 3; dirI++)
{
if (span[dirI] > maxSpan)
{
maxSpan = span[dirI];
maxDir = dirI;
}
}
scalar divide;
if (equalBinSize)
{
// Pick up points used by this set of objects
PackedBoolList isUsedPoint(points.size());
DynamicList<scalar> component(points.size());
forAll(objectIDs, i)
{
const label objI = objectIDs[i];
const Type& obj = objects[objI];
forAll(obj, pI)
{
const label pointI = obj[pI];
if (isUsedPoint.set(pointI))
{
component.append(points[pointI][maxDir]);
}
}
}
// Determine the median
Foam::sort(component);
divide = component[component.size()/2];
}
else
{
// Geometric middle
divide = bb.min()[maxDir] + 0.5*maxSpan;
}
scalar divMin = divide + tolerance_*maxSpan;
scalar divMax = divide - tolerance_*maxSpan;
// Assign the objects to min or max bin
DynamicList<label> minBinObjectIDs(objectIDs.size());
treeBoundBox minBb(point::max, point::min);
DynamicList<label> maxBinObjectIDs(objectIDs.size());
treeBoundBox maxBb(point::max, point::min);
forAll(objectIDs, i)
{
const label objI = objectIDs[i];
const Type& obj = objects[objI];
bool intoMin = false;
bool intoMax = false;
forAll(obj, pI)
{
const label pointI = obj[pI];
const point& pt = points[pointI];
if (pt[maxDir] < divMin)
{
intoMin = true;
}
if (pt[maxDir] > divMax)
{
intoMax = true;
}
}
if (intoMin)
{
minBinObjectIDs.append(objI);
const boundBox objBb(points, obj, false);
minBb.min() = min(minBb.min(), objBb.min());
minBb.max() = max(minBb.max(), objBb.max());
}
if (intoMax)
{
maxBinObjectIDs.append(objI);
const boundBox objBb(points, obj, false);
maxBb.min() = min(maxBb.min(), objBb.min());
maxBb.max() = max(maxBb.max(), objBb.max());
}
}
// inflate box in case geometry reduces to 2-D
if (minBinObjectIDs.size())
{
minBb.inflate(0.01);
}
if (maxBinObjectIDs.size())
{
maxBb.inflate(0.01);
}
minBinObjectIDs.shrink();
maxBinObjectIDs.shrink();
label minI;
if (minBinObjectIDs.size() > minLeafSize_ && level < maxLevel_)
{
// new leaf
minI = nodes.size();
nodes.append(labelPair(-1, -1));
}
else
{
// update existing leaf
minI = -addressing.size() - 1;
addressing.append(minBinObjectIDs);
}
label maxI;
if (maxBinObjectIDs.size() > minLeafSize_ && level < maxLevel_)
{
// new leaf
maxI = nodes.size();
nodes.append(labelPair(-1, -1));
}
else
{
// update existing leaf
maxI = -addressing.size() - 1;
addressing.append(maxBinObjectIDs);
}
nodes(nodeI) = labelPair(minI, maxI);
bbs(nodeI) = Pair<treeBoundBox>(minBb, maxBb);
// recurse
if (minI >= 0)
{
createBoxes
(
equalBinSize,
level + 1,
objects,
points,
minBinObjectIDs,
minBb,
minI,
bbs,
nodes,
addressing
);
}
if (maxI >= 0)
{
createBoxes
(
equalBinSize,
level + 1,
objects,
points,
maxBinObjectIDs,
maxBb,
maxI,
bbs,
nodes,
addressing
);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Type>
Foam::AABBTree<Type>::AABBTree()
:
maxLevel_(0),
minLeafSize_(0),
boundBoxes_(),
addressing_()
{}
template<class Type>
Foam::AABBTree<Type>::AABBTree
(
const UList<Type>& objects,
const pointField& points,
const bool equalBinSize,
const label maxLevel,
const label minLeafSize
)
:
maxLevel_(maxLevel),
minLeafSize_(minLeafSize),
boundBoxes_(),
addressing_()
{
if (objects.empty())
{
return;
}
DynamicList<Pair<treeBoundBox> > bbs(maxLevel);
DynamicList<labelPair> nodes(maxLevel);
DynamicList<labelList> addr(maxLevel);
nodes.append(labelPair(-1, -1));
treeBoundBox topBb(points);
topBb.inflate(0.01);
DynamicList<label> objectIDs(identity(objects.size()));
createBoxes
(
equalBinSize,
0, // starting at top level
objects,
points,
objectIDs,
topBb,
0, // starting node
bbs,
nodes,
addr
);
//{
// OFstream os("tree.obj");
// label vertI = 0;
// writeOBJ
// (
// true, // leavesOnly
// false, // writeLinesOnly
//
// topBb,
// 0,
// bbs,
// nodes,
// vertI,
// os
// );
//}
// transfer flattened tree to persistent storage
DynamicList<treeBoundBox> boundBoxes(2*bbs.size());
DynamicList<labelList> addressing(2*addr.size());
forAll(nodes, nodeI)
{
if (nodes[nodeI].first() < 0)
{
boundBoxes.append(bbs[nodeI].first());
addressing.append(addr[nodeI + 1]);
}
if (nodes[nodeI].second() < 0)
{
boundBoxes.append(bbs[nodeI].second());
addressing.append(addr[nodeI + 1]);
}
}
boundBoxes_.transfer(boundBoxes);
addressing_.transfer(addressing);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
const Foam::List<Foam::treeBoundBox>& Foam::AABBTree<Type>::boundBoxes() const
{
return boundBoxes_;
}
template<class Type>
const Foam::List<Foam::labelList>& Foam::AABBTree<Type>::addressing() const
{
return addressing_;
}
template<class Type>
bool Foam::AABBTree<Type>::pointInside(const point& pt) const
{
forAll(boundBoxes_, i)
{
const treeBoundBox& bb = boundBoxes_[i];
if (bb.contains(pt))
{
return true;
}
}
return false;
}
template<class Type>
bool Foam::AABBTree<Type>::overlaps(const boundBox& bbIn) const
{
forAll(boundBoxes_, i)
{
const treeBoundBox& bb = boundBoxes_[i];
if (bb.overlaps(bbIn))
{
return true;
}
}
return false;
}
// * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * * //
template<class Type>
Foam::Ostream& Foam::operator<<(Ostream& os, const AABBTree<Type>& tree)
{
if (os.format() == IOstream::ASCII)
{
os << tree.maxLevel_ << token::SPACE
<< tree.minLeafSize_ << token::SPACE
<< tree.boundBoxes_ << token::SPACE
<< tree.addressing_ << token::SPACE;
}
else
{
os.write
(
reinterpret_cast<const char*>(&tree.maxLevel_),
sizeof(tree.maxLevel_)
+ sizeof(tree.minLeafSize_)
);
os << tree.boundBoxes_
<< tree.addressing_;
}
os.check("Ostream& operator<<(Ostream&, const AABBTree<Type>&)");
return os;
}
template<class Type>
Foam::Istream& Foam::operator>>(Istream& is, AABBTree<Type>& tree)
{
if (is.format() == IOstream::ASCII)
{
is >> tree.maxLevel_
>> tree.minLeafSize_
>> tree.boundBoxes_
>> tree.addressing_;
}
else
{
is.read
(
reinterpret_cast<char*>(&tree.maxLevel_),
sizeof(tree.maxLevel_)
+ sizeof(tree.minLeafSize_)
);
is >> tree.boundBoxes_
>> tree.addressing_;
}
is.check("Istream& operator>>(Istream&, AABBTree<Type>&)");
return is;
}
// ************************************************************************* //

View File

@ -0,0 +1,197 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::AABBTree
Description
Templated tree of axis-aligned bounding boxes (AABB)
Designed to be templated on either faces or cells, the AABBTree will
decompose the input into a tree of AABB's. The maximum number of tree
levels and minimum number of objects per leaf are provided on construction,
and the contents (addressing) is stored.
SourceFiles
AABBTree.C
\*---------------------------------------------------------------------------*/
#ifndef AABBTree_H
#define AABBTree_H
#include "labelList.H"
#include "labelPair.H"
#include "DynamicList.H"
#include "pointField.H"
#include "treeBoundBox.H"
#include "Ostream.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of friend functions and operators
template<class Type>
class AABBTree;
template<class Type>
Istream& operator>>(Istream&, AABBTree<Type>&);
template<class Type>
Ostream& operator<<(Ostream&, const AABBTree<Type>&);
/*---------------------------------------------------------------------------*\
Class AABBTree Declaration
\*---------------------------------------------------------------------------*/
template<class Type>
class AABBTree
{
protected:
// Protected Data
//- Tolerance
static scalar tolerance_;
//- Maximum tree level
label maxLevel_;
//- Minimum points per leaf
label minLeafSize_;
//- Bounding boxes making up the tree
List<treeBoundBox> boundBoxes_;
//- Leaf adressing
List<labelList> addressing_;
// Protected Member Functions
//- Write OBJ file of bounding box
void writeOBJ
(
const bool writeLinesOnly,
const treeBoundBox& bb,
label& vertI,
Ostream& os
) const;
//- Write OBJ for all bounding boxes
void writeOBJ
(
const bool leavesOnly,
const bool writeLinesOnly,
const treeBoundBox& bb,
const label nodeI,
const List<Pair<treeBoundBox> >& bbs,
const List<Pair<label> >& nodes,
label& vertI,
Ostream& os
) const;
//- Create the bounding boxes by interrogating points
void createBoxes
(
const bool equalBinSize,
const label level,
const List<Type>& objects,
const pointField& points,
const DynamicList<label>& objectIDs,
const treeBoundBox& bb,
const label nodeI,
DynamicList<Pair<treeBoundBox> >& bbs,
DynamicList<labelPair>& nodes,
DynamicList<labelList>& addressing
) const;
public:
// Constructors
//- Null constructor
AABBTree();
//- Construct from components
// equalBinSize: divide into equal number of elements or
// equal span
AABBTree
(
const UList<Type>& objects,
const pointField& points,
const bool equalBinSize = true,
const label maxLevel = 3,
const label minBinSize = 100
);
// Public Member Functions
// Access
//- Return the bounding boxes making up the tree
const List<treeBoundBox>& boundBoxes() const;
//- Return the contents addressing
const List<labelList>& addressing() const;
// Evaluation
//- Determine whether a point is inside the bounding boxes
bool pointInside(const point& pt) const;
//- Determine whether a bounding box overlaps the tree bounding
// boxes
bool overlaps(const boundBox& bbIn) const;
// IOstream operators
friend Istream& operator>> <Type>(Istream&, AABBTree&);
friend Ostream& operator<< <Type>(Ostream&, const AABBTree&);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "AABBTree.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

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.
@ -27,6 +27,7 @@ License
#include "AMIMethod.H"
#include "meshTools.H"
#include "mapDistribute.H"
#include "flipOp.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -604,7 +605,6 @@ void Foam::AMIInterpolation<SourcePatch, TargetPatch>::constructFromSurface
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class SourcePatch, class TargetPatch>
@ -965,7 +965,7 @@ void Foam::AMIInterpolation<SourcePatch, TargetPatch>::update
tgtMagSf_,
triMode_,
reverseTarget_,
requireMatch_
requireMatch_ && (lowWeightCorrection_ < 0)
)
);
@ -1010,27 +1010,33 @@ void Foam::AMIInterpolation<SourcePatch, TargetPatch>::update
// send data back to originating procs. Note that contributions
// from different processors get added (ListAppendEqOp)
mapDistribute::distribute
mapDistributeBase::distribute
(
Pstream::nonBlocking,
List<labelPair>(),
tgtPatch.size(),
map.constructMap(),
false, // has flip
map.subMap(),
false, // has flip
tgtAddress_,
ListAppendEqOp<label>(),
flipOp(), // flip operation
labelList()
);
mapDistribute::distribute
mapDistributeBase::distribute
(
Pstream::nonBlocking,
List<labelPair>(),
tgtPatch.size(),
map.constructMap(),
false,
map.subMap(),
false,
tgtWeights_,
ListAppendEqOp<scalar>(),
flipOp(),
scalarList()
);
@ -1082,7 +1088,7 @@ void Foam::AMIInterpolation<SourcePatch, TargetPatch>::update
tgtMagSf_,
triMode_,
reverseTarget_,
requireMatch_
requireMatch_ && (lowWeightCorrection_ < 0)
)
);

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -26,6 +26,7 @@ License
#include "AMIInterpolation.H"
#include "mergePoints.H"
#include "mapDistribute.H"
#include "AABBTree.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@ -97,11 +98,11 @@ Foam::AMIInterpolation<SourcePatch, TargetPatch>::calcOverlappingProcs
forAll(procBb, procI)
{
const List<treeBoundBox>& bbs = procBb[procI];
const treeBoundBoxList& bbp = procBb[procI];
forAll(bbs, bbI)
forAll(bbp, bbI)
{
if (bbs[bbI].overlaps(bb))
if (bbp[bbI].overlaps(bb))
{
overlaps[procI] = true;
nOverlaps++;
@ -109,6 +110,7 @@ Foam::AMIInterpolation<SourcePatch, TargetPatch>::calcOverlappingProcs
}
}
}
return nOverlaps;
}
@ -338,33 +340,22 @@ Foam::AMIInterpolation<SourcePatch, TargetPatch>::calcProcMap
if (srcPatch.size())
{
procBb[Pstream::myProcNo()] = treeBoundBoxList
(
1, // For now single bounding box per proc
treeBoundBox
procBb[Pstream::myProcNo()] =
AABBTree<face>
(
srcPatch.points(),
srcPatch.meshPoints()
)
);
srcPatch.localFaces(),
srcPatch.localPoints(),
false
).boundBoxes();
}
else
{
procBb[Pstream::myProcNo()] = treeBoundBoxList();
}
// slightly increase size of bounding boxes to allow for cases where
// bounding boxes are perfectly alligned
forAll(procBb[Pstream::myProcNo()], bbI)
{
treeBoundBox& bb = procBb[Pstream::myProcNo()][bbI];
bb.inflate(0.01);
}
Pstream::gatherList(procBb);
Pstream::scatterList(procBb);
if (debug)
{
Info<< "Determining extent of srcPatch per processor:" << nl
@ -375,7 +366,6 @@ Foam::AMIInterpolation<SourcePatch, TargetPatch>::calcProcMap
}
}
// Determine which faces of tgtPatch overlaps srcPatch per proc
const faceList& faces = tgtPatch.localFaces();
const pointField& points = tgtPatch.localPoints();

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2013-2014 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -221,7 +221,7 @@ void Foam::AMIMethod<SourcePatch, TargetPatch>::resetTree()
// Clear the old octree
treePtr_.clear();
treeBoundBox bb(tgtPatch_.points());
treeBoundBox bb(tgtPatch_.points(), tgtPatch_.meshPoints());
bb.inflate(0.01);
if (!treePtr_.valid())

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2013-2014 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -310,16 +310,14 @@ void Foam::directAMI<SourcePatch, TargetPatch>::calculate
forAll(srcAddr, i)
{
scalar magSf = this->srcMagSf_[i];
// srcWeights[i] = scalarList(srcAddr[i].size(), magSf);
srcWeights[i] = scalarList(1, magSf);
srcAddress[i].transfer(srcAddr[i]);
srcWeights[i] = scalarList(1, magSf);
}
forAll(tgtAddr, i)
{
scalar magSf = this->tgtMagSf_[i];
// tgtWeights[i] = scalarList(tgtAddr[i].size(), magSf);
tgtWeights[i] = scalarList(1, magSf);
tgtAddress[i].transfer(tgtAddr[i]);
tgtWeights[i] = scalarList(1, magSf);
}
}

View File

@ -2,8 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -41,6 +41,7 @@ SourceFiles
#include "FixedList.H"
#include "plane.H"
#include "face.H"
#include "triPoints.H"
#include "NamedEnum.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -56,8 +57,6 @@ class faceAreaIntersect
{
public:
typedef FixedList<point, 3> triPoints;
enum triangulationMode
{
tmFan,

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