diff --git a/applications/utilities/mesh/manipulation/splitMeshRegions/splitMeshRegions.C b/applications/utilities/mesh/manipulation/splitMeshRegions/splitMeshRegions.C index 6565776cdf2dce931b7e86184160fbb3a9b1aeda..9120fd6dd9e97a3694ed3f7dc043865f688cb201 100644 --- a/applications/utilities/mesh/manipulation/splitMeshRegions/splitMeshRegions.C +++ b/applications/utilities/mesh/manipulation/splitMeshRegions/splitMeshRegions.C @@ -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 ); diff --git a/applications/utilities/parallelProcessing/decomposePar/Make/options b/applications/utilities/parallelProcessing/decomposePar/Make/options index 5d5d67f98932b2c57203c73786eaf24c3c0ab41b..cd78de0d1ef148557308ac65f002bce66653d1c6 100644 --- a/applications/utilities/parallelProcessing/decomposePar/Make/options +++ b/applications/utilities/parallelProcessing/decomposePar/Make/options @@ -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 diff --git a/applications/utilities/parallelProcessing/decomposePar/decomposePar.C b/applications/utilities/parallelProcessing/decomposePar/decomposePar.C index 60206085415b3a4e35dff35d82c82691a7198dde..63303d9f8c5b1a63ecb7e18acad49adfcce7f0bd 100644 --- a/applications/utilities/parallelProcessing/decomposePar/decomposePar.C +++ b/applications/utilities/parallelProcessing/decomposePar/decomposePar.C @@ -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)) { diff --git a/applications/utilities/parallelProcessing/decomposePar/decomposeParDict b/applications/utilities/parallelProcessing/decomposePar/decomposeParDict index 39483a01e3eddb5f08b4cdd9dcf91438baf93d8f..0beef4f7621cd734d27b43f31e8d44ee12443b42 100644 --- a/applications/utilities/parallelProcessing/decomposePar/decomposeParDict +++ b/applications/utilities/parallelProcessing/decomposePar/decomposeParDict @@ -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. diff --git a/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.C b/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.C index 7d863693983488887ec07ee24c9d5750b65adba1..b27f7628c8fbb1f6099f3cb9de97d88dbf7a9e55 100644 --- a/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.C +++ b/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.C @@ -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 - ( - "cellLevel", - 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 + // Load refinement data (if any) + hexRef8Data baseMeshData + ( + IOobject ( - "level0Edge", + "dummy", 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 - ( - 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 + // Optional hexRef8 data + hexRef8Data + ( + IOobject ( - 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 diff --git a/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.H b/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.H index 21bc8e61690461cd25f81ede6bad0f35faf41645..f5b737699776fab887af6ae7787d92588e604754 100644 --- a/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.H +++ b/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.H @@ -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 diff --git a/applications/utilities/parallelProcessing/decomposePar/domainDecompositionDistribute.C b/applications/utilities/parallelProcessing/decomposePar/domainDecompositionDistribute.C index 944853ad9501df3d424ffff7f40af1a336163a1b..0b1d5fb1434119f19fab99aa090b4c26725665fb 100644 --- a/applications/utilities/parallelProcessing/decomposePar/domainDecompositionDistribute.C +++ b/applications/utilities/parallelProcessing/decomposePar/domainDecompositionDistribute.C @@ -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() diff --git a/applications/utilities/parallelProcessing/decomposePar/readFields.C b/applications/utilities/parallelProcessing/decomposePar/readFields.C index e949e0c2fa7e7071f0604629ca48e2c301d7acbc..546756caa6ddb479f5c988d666394edfa35e3f07 100644 --- a/applications/utilities/parallelProcessing/decomposePar/readFields.C +++ b/applications/utilities/parallelProcessing/decomposePar/readFields.C @@ -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,18 +23,22 @@ License \*---------------------------------------------------------------------------*/ +#include "GeometricField.H" #include "readFields.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -template<class Mesh, class GeoField> +template<class Type, template<class> class PatchField, class GeoMesh> void Foam::readFields ( - const Mesh& mesh, + const typename GeoMesh::Mesh& mesh, const IOobjectList& objects, - PtrList<GeoField>& fields + 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)); @@ -45,17 +49,48 @@ void Foam::readFields 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 +( + const Mesh& mesh, + const IOobjectList& objects, + PtrList<GeoField>& fields +) +{ + // Search list of objects for fields of type GeomField + IOobjectList fieldObjects(objects.lookupClass(GeoField::typeName)); + // 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)); } } diff --git a/applications/utilities/parallelProcessing/decomposePar/readFields.H b/applications/utilities/parallelProcessing/decomposePar/readFields.H index 0ff4c1f92b001ea123c5e827f0eba8e7c3ad46b3..35eae288826de296f778294e69ff1f772416ea86 100644 --- a/applications/utilities/parallelProcessing/decomposePar/readFields.H +++ b/applications/utilities/parallelProcessing/decomposePar/readFields.H @@ -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 diff --git a/applications/utilities/parallelProcessing/reconstructPar/Make/options b/applications/utilities/parallelProcessing/reconstructPar/Make/options index ece7c8b030bee4fab556a964b9da1eec4c51a64d..1ebb8c02d314fb6230eef50e44957be3befdfdda 100644 --- a/applications/utilities/parallelProcessing/reconstructPar/Make/options +++ b/applications/utilities/parallelProcessing/reconstructPar/Make/options @@ -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 diff --git a/applications/utilities/parallelProcessing/reconstructPar/reconstructPar.C b/applications/utilities/parallelProcessing/reconstructPar/reconstructPar.C index db2df9eecc2f0530443107a01eeeb03940da4318..5295f2353068a636c745accfdc233c5c89054702 100644 --- a/applications/utilities/parallelProcessing/reconstructPar/reconstructPar.C +++ b/applications/utilities/parallelProcessing/reconstructPar/reconstructPar.C @@ -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; } diff --git a/applications/utilities/parallelProcessing/reconstructParMesh/reconstructParMesh.C b/applications/utilities/parallelProcessing/reconstructParMesh/reconstructParMesh.C index cfa77f70235b7dc304d0c92653e213234a28d008..866bc24bb8019ed4b29979fbd70f78e9dd0b8cc3 100644 --- a/applications/utilities/parallelProcessing/reconstructParMesh/reconstructParMesh.C +++ b/applications/utilities/parallelProcessing/reconstructParMesh/reconstructParMesh.C @@ -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; } diff --git a/applications/utilities/parallelProcessing/redistributePar/Make/files b/applications/utilities/parallelProcessing/redistributePar/Make/files index 8bf23d0895bd62d08b893465256cf9d4ed8ab2d4..1dfb53f3078d8ccc1cac85efabd4c377b6451fef 100644 --- a/applications/utilities/parallelProcessing/redistributePar/Make/files +++ b/applications/utilities/parallelProcessing/redistributePar/Make/files @@ -1,3 +1,5 @@ +parLagrangianRedistributor.C +parFvFieldReconstructor.C loadOrCreateMesh.C redistributePar.C diff --git a/applications/utilities/parallelProcessing/redistributePar/Make/options b/applications/utilities/parallelProcessing/redistributePar/Make/options index a23979358b7e2662728d21ed54c8ffabeeacfd5c..08d24a07f75ec9cfff77d2bfe14ca89ab0139f5f 100644 --- a/applications/utilities/parallelProcessing/redistributePar/Make/options +++ b/applications/utilities/parallelProcessing/redistributePar/Make/options @@ -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 diff --git a/applications/utilities/parallelProcessing/redistributePar/distributedUnallocatedDirectFieldMapper.H b/applications/utilities/parallelProcessing/redistributePar/distributedUnallocatedDirectFieldMapper.H new file mode 100644 index 0000000000000000000000000000000000000000..c3a21fe5860b57e5b1c5cd5be7afdba97f65be5b --- /dev/null +++ b/applications/utilities/parallelProcessing/redistributePar/distributedUnallocatedDirectFieldMapper.H @@ -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 + +// ************************************************************************* // diff --git a/src/sampling/meshToMesh/weightedFvPatchFieldMapper.H b/applications/utilities/parallelProcessing/redistributePar/distributedUnallocatedDirectFvPatchFieldMapper.H similarity index 60% rename from src/sampling/meshToMesh/weightedFvPatchFieldMapper.H rename to applications/utilities/parallelProcessing/redistributePar/distributedUnallocatedDirectFvPatchFieldMapper.H index c14b5500fd4c48025d68cf5843e86affc567dab8..b9f7102bf16e48b18daccfdfac7179e6010ff706 100644 --- a/src/sampling/meshToMesh/weightedFvPatchFieldMapper.H +++ b/applications/utilities/parallelProcessing/redistributePar/distributedUnallocatedDirectFvPatchFieldMapper.H @@ -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,29 +88,38 @@ 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 hasUnmapped() const + virtual bool distributed() const { - return hasUnmapped_; + return true; } - virtual const labelListList& addressing() const + virtual const mapDistributeBase& distributeMap() const { - return addressing_; + return distMap_; } - virtual const scalarListList& weights() const + virtual bool hasUnmapped() const { - return weights_; + return hasUnmapped_; } + virtual const labelUList& directAddressing() const + { + return directAddressing_; + } }; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/applications/utilities/parallelProcessing/redistributePar/loadOrCreateMesh.C b/applications/utilities/parallelProcessing/redistributePar/loadOrCreateMesh.C index aa7927121084f59f5a295758e0cd4916e779e080..d3f6fb282ab0c0a3107e96d326062981f32fcde1 100644 --- a/applications/utilities/parallelProcessing/redistributePar/loadOrCreateMesh.C +++ b/applications/utilities/parallelProcessing/redistributePar/loadOrCreateMesh.C @@ -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(); diff --git a/applications/utilities/parallelProcessing/redistributePar/parFvFieldReconstructor.C b/applications/utilities/parallelProcessing/redistributePar/parFvFieldReconstructor.C new file mode 100644 index 0000000000000000000000000000000000000000..c9f8926c8266f664bbcb27b8a4eb8024b1717827 --- /dev/null +++ b/applications/utilities/parallelProcessing/redistributePar/parFvFieldReconstructor.C @@ -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(); + } +} + + +// ************************************************************************* // diff --git a/applications/utilities/parallelProcessing/redistributePar/parFvFieldReconstructor.H b/applications/utilities/parallelProcessing/redistributePar/parFvFieldReconstructor.H new file mode 100644 index 0000000000000000000000000000000000000000..a0e7d992233083a1aacdb1a2a29fba0bf0360750 --- /dev/null +++ b/applications/utilities/parallelProcessing/redistributePar/parFvFieldReconstructor.H @@ -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 + +// ************************************************************************* // diff --git a/applications/utilities/parallelProcessing/redistributePar/parFvFieldReconstructorReconstructFields.C b/applications/utilities/parallelProcessing/redistributePar/parFvFieldReconstructorReconstructFields.C new file mode 100644 index 0000000000000000000000000000000000000000..a56c5fdde1392f18097f968e65571561c0b9a1b0 --- /dev/null +++ b/applications/utilities/parallelProcessing/redistributePar/parFvFieldReconstructorReconstructFields.C @@ -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; + } +} + + +// ************************************************************************* // diff --git a/applications/utilities/parallelProcessing/redistributePar/parLagrangianRedistributor.C b/applications/utilities/parallelProcessing/redistributePar/parLagrangianRedistributor.C new file mode 100644 index 0000000000000000000000000000000000000000..2e775f2ef8fde86274a420c7f70ed3855e317d3c --- /dev/null +++ b/applications/utilities/parallelProcessing/redistributePar/parLagrangianRedistributor.C @@ -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); +} + + +// ************************************************************************* // diff --git a/applications/utilities/parallelProcessing/redistributePar/parLagrangianRedistributor.H b/applications/utilities/parallelProcessing/redistributePar/parLagrangianRedistributor.H new file mode 100644 index 0000000000000000000000000000000000000000..29fdb5e7aa2634746aef85d46ca944282b6a26b9 --- /dev/null +++ b/applications/utilities/parallelProcessing/redistributePar/parLagrangianRedistributor.H @@ -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 + +// ************************************************************************* // diff --git a/applications/utilities/parallelProcessing/redistributePar/parLagrangianRedistributorRedistributeFields.C b/applications/utilities/parallelProcessing/redistributePar/parLagrangianRedistributorRedistributeFields.C new file mode 100644 index 0000000000000000000000000000000000000000..bc17570d3cc775ae8ab803caa895f91d543b01b4 --- /dev/null +++ b/applications/utilities/parallelProcessing/redistributePar/parLagrangianRedistributorRedistributeFields.C @@ -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(); + } + } + } +} + + +// ************************************************************************* // diff --git a/applications/utilities/parallelProcessing/redistributePar/redistributePar.C b/applications/utilities/parallelProcessing/redistributePar/redistributePar.C index 7cc21c4adc85290ff1745067aa4320f1de4f5212..7debc6a9f74a74d3d01645949350eca329490d65 100644 --- a/applications/utilities/parallelProcessing/redistributePar/redistributePar.C +++ b/applications/utilities/parallelProcessing/redistributePar/redistributePar.C @@ -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,30 +31,54 @@ Description Must be run on maximum number of source and destination processors. Balances mesh and writes new mesh to new time directory. - Can also work like decomposePar: - \verbatim - # Create empty processor directories (have to exist for argList) - mkdir processor0 - .. - mkdir processorN +Usage - # Copy undecomposed polyMesh - cp -r constant processor0 + - redistributePar [OPTION] + + \param -region regionName \n + Distribute named region. + + \param -decompose \n + Remove any existing \a processor subdirectories and decomposes the + geometry. Equivalent to running without processor subdirectories. + + \param -reconstruct \n + Reconstruct geometry (like reconstructParMesh). Equivalent to setting + numberOfSubdomains 1 in the decomposeParDict. + + \param -newTimes \n + (in combination with -reconstruct) reconstruct only new times. + + \param -cellDist \n + Write the cell distribution as a labelList, for use with 'manual' + decomposition method or as a volScalarField for post-processing. - # Distribute - mpirun -np ddd redistributePar -parallel - \endverbatim \*---------------------------------------------------------------------------*/ +#include "argList.H" +#include "Time.H" #include "fvMesh.H" +#include "fvMeshTools.H" +#include "fvMeshDistribute.H" #include "decompositionMethod.H" +#include "timeSelector.H" #include "PstreamReduceOps.H" -#include "fvCFD.H" -#include "fvMeshDistribute.H" -#include "mapDistributePolyMesh.H" +#include "volFields.H" +#include "surfaceFields.H" +#include "IOmapDistributePolyMesh.H" #include "IOobjectList.H" #include "globalIndex.H" #include "loadOrCreateMesh.H" +#include "processorFvPatchField.H" +#include "zeroGradientFvPatchFields.H" +#include "decompositionModel.H" + +#include "parFvFieldReconstructor.H" +#include "parLagrangianRedistributor.H" +#include "unmappedPassiveParticleCloud.H" +#include "hexRef8Data.H" + +using namespace Foam; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -104,19 +128,6 @@ scalar getMergeDistance } -//void printMeshData(Ostream& os, const polyMesh& mesh) -//{ -// os << "Number of points: " << mesh.points().size() << nl -// << " faces: " << mesh.faces().size() << nl -// << " internal faces: " << mesh.faceNeighbour().size() << nl -// << " cells: " << mesh.cells().size() << nl -// << " boundary patches: " << mesh.boundaryMesh().size() << nl -// << " point zones: " << mesh.pointZones().size() << nl -// << " face zones: " << mesh.faceZones().size() << nl -// << " cell zones: " << mesh.cellZones().size() << nl; -//} - - void printMeshData(const polyMesh& mesh) { // Collect all data on master @@ -173,7 +184,7 @@ void printMeshData(const polyMesh& mesh) Info<< " Number of processor patches = " << nei.size() << nl << " Number of processor faces = " << nProcFaces << nl << " Number of boundary faces = " - << globalBoundaryFaces.localSize(procI) << endl; + << globalBoundaryFaces.localSize(procI)-nProcFaces << endl; maxProcCells = max(maxProcCells, globalCells.localSize(procI)); totProcFaces += nProcFaces; @@ -221,6 +232,23 @@ void writeDecomposition const labelList& decomp ) { + // Write the decomposition as labelList for use with 'manual' + // decomposition method. + labelIOList cellDecomposition + ( + IOobject + ( + "cellDecomposition", + mesh.facesInstance(), // mesh read from facesInstance + mesh, + IOobject::NO_READ, + IOobject::NO_WRITE, + false + ), + decomp + ); + cellDecomposition.write(); + Info<< "Writing wanted cell distribution to volScalarField " << name << " for postprocessing purposes." << nl << endl; @@ -248,8 +276,320 @@ void writeDecomposition } +void determineDecomposition +( + const Time& baseRunTime, + const fileName& decompDictFile, // optional location for decomposeParDict + const bool decompose, // decompose, i.e. read from undecomposed case + const fileName& proc0CaseName, + const fvMesh& mesh, + const bool writeCellDist, + + label& nDestProcs, + labelList& decomp +) +{ + // Read decomposeParDict (on all processors) + const decompositionModel& method = decompositionModel::New + ( + mesh, + decompDictFile + ); + + decompositionMethod& decomposer = method.decomposer(); + + if (!decomposer.parallelAware()) + { + WarningIn("determineDecomposition(..)") + << "You have selected decomposition method " + << decomposer.typeName + << " which does" << endl + << "not synchronise the decomposition across" + << " processor patches." << endl + << " You might want to select a decomposition method" + << " which is aware of this. Continuing." + << endl; + } + + if (Pstream::master() && decompose) + { + Info<< "Setting caseName to " << baseRunTime.caseName() + << " to read decomposeParDict" << endl; + const_cast<Time&>(mesh.time()).TimePaths::caseName() = + baseRunTime.caseName(); + } + + scalarField cellWeights; + if (method.found("weightField")) + { + word weightName = method.lookup("weightField"); + + volScalarField weights + ( + IOobject + ( + weightName, + mesh.time().timeName(), + mesh, + IOobject::MUST_READ, + IOobject::NO_WRITE + ), + mesh + ); + cellWeights = weights.internalField(); + } + + nDestProcs = decomposer.nDomains(); + decomp = decomposer.decompose(mesh, cellWeights); + + if (Pstream::master() && decompose) + { + Info<< "Restoring caseName to " << proc0CaseName << endl; + const_cast<Time&>(mesh.time()).TimePaths::caseName() = + proc0CaseName; + } + + // Dump decomposition to volScalarField + if (writeCellDist) + { + // Note: on master make sure to write to processor0 + if (decompose) + { + if (Pstream::master()) + { + Info<< "Setting caseName to " << baseRunTime.caseName() + << " to write undecomposed cellDist" << endl; + + Time& tm = const_cast<Time&>(mesh.time()); + + tm.TimePaths::caseName() = baseRunTime.caseName(); + writeDecomposition("cellDist", mesh, decomp); + Info<< "Restoring caseName to " << proc0CaseName << endl; + tm.TimePaths::caseName() = proc0CaseName; + } + } + else + { + writeDecomposition("cellDist", mesh, decomp); + } + } +} + + +// Write addressing if decomposing (1 to many) or reconstructing (many to 1) +void writeProcAddressing +( + const bool decompose, + const fileName& meshSubDir, + const fvMesh& mesh, + const mapDistributePolyMesh& map +) +{ + Info<< "Writing procAddressing files to " << mesh.facesInstance() + << endl; + + labelIOList cellMap + ( + IOobject + ( + "cellProcAddressing", + mesh.facesInstance(), + meshSubDir, + mesh, + IOobject::NO_READ + ), + 0 + ); + + labelIOList faceMap + ( + IOobject + ( + "faceProcAddressing", + mesh.facesInstance(), + meshSubDir, + mesh, + IOobject::NO_READ + ), + 0 + ); + + labelIOList pointMap + ( + IOobject + ( + "pointProcAddressing", + mesh.facesInstance(), + meshSubDir, + mesh, + IOobject::NO_READ + ), + 0 + ); + + labelIOList patchMap + ( + IOobject + ( + "boundaryProcAddressing", + mesh.facesInstance(), + meshSubDir, + mesh, + IOobject::NO_READ + ), + 0 + ); + + // Decomposing: see how cells moved from undecomposed case + if (decompose) + { + cellMap = identity(map.nOldCells()); + map.distributeCellData(cellMap); + + faceMap = identity(map.nOldFaces()); + { + const mapDistribute& faceDistMap = map.faceMap(); + + if (faceDistMap.subHasFlip() || faceDistMap.constructHasFlip()) + { + // Offset by 1 + faceMap = faceMap + 1; + } + // Apply face flips + mapDistributeBase::distribute + ( + Pstream::nonBlocking, + List<labelPair>(), + faceDistMap.constructSize(), + faceDistMap.subMap(), + faceDistMap.subHasFlip(), + faceDistMap.constructMap(), + faceDistMap.constructHasFlip(), + faceMap, + flipLabelOp() + ); + } + + pointMap = identity(map.nOldPoints()); + map.distributePointData(pointMap); + + patchMap = identity(map.oldPatchSizes().size()); + const mapDistribute& patchDistMap = map.patchMap(); + // Use explicit distribute since we need to provide a null value + // (for new patches) and this is the only call that allow us to + // provide one ... + mapDistributeBase::distribute + ( + Pstream::nonBlocking, + List<labelPair>(), + patchDistMap.constructSize(), + patchDistMap.subMap(), + patchDistMap.subHasFlip(), + patchDistMap.constructMap(), + patchDistMap.constructHasFlip(), + patchMap, + eqOp<label>(), + flipOp(), + label(-1), + UPstream::msgType() + ); + } + else // if (nDestProcs == 1) + { + cellMap = identity(mesh.nCells()); + map.cellMap().reverseDistribute(map.nOldCells(), cellMap); + + faceMap = identity(mesh.nFaces()); + { + const mapDistribute& faceDistMap = map.faceMap(); + + if (faceDistMap.subHasFlip() || faceDistMap.constructHasFlip()) + { + // Offset by 1 + faceMap = faceMap + 1; + } + + mapDistributeBase::distribute + ( + Pstream::nonBlocking, + List<labelPair>(), + map.nOldFaces(), + faceDistMap.constructMap(), + faceDistMap.constructHasFlip(), + faceDistMap.subMap(), + faceDistMap.subHasFlip(), + faceMap, + flipLabelOp() + ); + } + + pointMap = identity(mesh.nPoints()); + map.pointMap().reverseDistribute(map.nOldPoints(), pointMap); + + const mapDistribute& patchDistMap = map.patchMap(); + patchMap = identity(mesh.boundaryMesh().size()); + patchDistMap.reverseDistribute + ( + map.oldPatchSizes().size(), + label(-1), + patchMap + ); + } + + bool cellOk = cellMap.write(); + bool faceOk = faceMap.write(); + bool pointOk = pointMap.write(); + bool patchOk = patchMap.write(); + + if (!cellOk || !faceOk || !pointOk || !patchOk) + { + WarningIn + ( + "void writeProcAddressing" + "(const bool, const fvMesh&, const mapDistributePolyMesh&)" + ) << "Failed to write " << cellMap.objectPath() + << ", " << faceMap.objectPath() + << ", " << pointMap.objectPath() + << ", " << patchMap.objectPath() + << endl; + } +} + + + +// Generic mesh-based field reading +template<class GeoField> +void readField +( + const IOobject& io, + const fvMesh& mesh, + const label i, + PtrList<GeoField>& fields +) +{ + fields.set(i, new GeoField(io, mesh)); +} + + +// Definition of readField for GeometricFields only +template<class Type, template<class> class PatchField, class GeoMesh> +void readField +( + const IOobject& io, + const fvMesh& mesh, + const label i, + PtrList<GeometricField<Type, PatchField, GeoMesh> >& fields +) +{ + fields.set + ( + i, + new GeometricField<Type, PatchField, GeoMesh>(io, mesh, false) + ); +} + + // Read vol or surface fields -//template<class T, class Mesh> template<class GeoField> void readFields ( @@ -265,7 +605,7 @@ void readFields // Get my objects of type IOobjectList objects(allObjects.lookupClass(GeoField::typeName)); // Check that we all have all objects - wordList objectNames = objects.toc(); + wordList objectNames = objects.sortedNames(); // Get master names wordList masterNames(objectNames); Pstream::scatter(masterNames); @@ -291,9 +631,8 @@ void readFields IOobject& io = *objects[name]; io.writeOpt() = IOobject::AUTO_WRITE; - // Load field - fields.set(i, new GeoField(io, mesh)); - + // Load field (but not oldTime) + readField(io, mesh, i, fields); // Create zero sized field and send if (subsetterPtr.valid()) { @@ -354,461 +693,2207 @@ void readFields IOobject& io = *objects[name]; io.writeOpt() = IOobject::AUTO_WRITE; - // Load field - fields.set(i, new GeoField(io, mesh)); + // Load field (but not oldtime) + readField(io, mesh, i, fields); } } } -// Debugging: compare two fields. -void compareFields -( - const scalar tolDim, - const volVectorField& a, - const volVectorField& b -) +// Variant of GeometricField::correctBoundaryConditions that only +// evaluates selected patch fields +template<class GeoField, class CoupledPatchType> +void correctCoupledBoundaryConditions(fvMesh& mesh) { - forAll(a, cellI) + HashTable<GeoField*> flds + ( + mesh.objectRegistry::lookupClass<GeoField>() + ); + + forAllIter(typename HashTable<GeoField*>, flds, iter) { - if (mag(b[cellI] - a[cellI]) > tolDim) + GeoField& fld = *iter(); + + typename GeoField::GeometricBoundaryField& bfld = + fld.boundaryField(); + if + ( + Pstream::defaultCommsType == Pstream::blocking + || Pstream::defaultCommsType == Pstream::nonBlocking + ) { - FatalErrorIn - ( - "compareFields" - "(const scalar, const volVectorField&, const volVectorField&)" - ) << "Did not map volVectorField correctly:" << nl - << "cell:" << cellI - << " transfer b:" << b[cellI] - << " real cc:" << a[cellI] - << abort(FatalError); - } - } - forAll(a.boundaryField(), patchI) - { - // We have real mesh cellcentre and - // mapped original cell centre. + label nReq = Pstream::nRequests(); - const fvPatchVectorField& aBoundary = - a.boundaryField()[patchI]; + forAll(bfld, patchi) + { + typename GeoField::PatchFieldType& pfld = bfld[patchi]; + + //if (pfld.coupled()) + //if (isA<CoupledPatchType>(pfld)) + if (pfld.patch().coupled()) + { + pfld.initEvaluate(Pstream::defaultCommsType); + } + } + + // Block for any outstanding requests + if + ( + Pstream::parRun() + && Pstream::defaultCommsType == Pstream::nonBlocking + ) + { + Pstream::waitRequests(nReq); + } - const fvPatchVectorField& bBoundary = - b.boundaryField()[patchI]; + forAll(bfld, patchi) + { + typename GeoField::PatchFieldType& pfld = bfld[patchi]; - if (!bBoundary.coupled()) + //if (pfld.coupled()) + //if (isA<CoupledPatchType>(pfld)) + if (pfld.patch().coupled()) + { + pfld.evaluate(Pstream::defaultCommsType); + } + } + } + else if (Pstream::defaultCommsType == Pstream::scheduled) { - forAll(aBoundary, i) + const lduSchedule& patchSchedule = + fld.mesh().globalData().patchSchedule(); + + forAll(patchSchedule, patchEvali) { - if (mag(aBoundary[i] - bBoundary[i]) > tolDim) + label patchi = patchSchedule[patchEvali].patch; + typename GeoField::PatchFieldType& pfld = bfld[patchi]; + + //if (pfld.coupled()) + //if (isA<CoupledPatchType>(pfld)) + if (pfld.patch().coupled()) { - WarningIn - ( - "compareFields" - "(const scalar, const volVectorField&" - ", const volVectorField&)" - ) << "Did not map volVectorField correctly:" - << endl - << "patch:" << patchI << " patchFace:" << i - << " cc:" << endl - << " real :" << aBoundary[i] << endl - << " mapped :" << bBoundary[i] << endl - << "This might be just a precision entry" - << " on writing the mesh." << endl; - //<< abort(FatalError); + if (patchSchedule[patchEvali].init) + { + pfld.initEvaluate(Pstream::scheduled); + } + else + { + pfld.evaluate(Pstream::scheduled); + } } } } + else + { + FatalErrorIn("correctCoupledBoundaryConditions()") + << "Unsuported communications type " + << Pstream::commsTypeNames[Pstream::defaultCommsType] + << exit(FatalError); + } } } - -int main(int argc, char *argv[]) +// Inplace redistribute mesh and any fields +autoPtr<mapDistributePolyMesh> redistributeAndWrite +( + const Time& baseRunTime, + const scalar tolDim, + const boolList& haveMesh, + const fileName& meshSubDir, + const bool doReadFields, + const bool decompose, // decompose, i.e. read from undecomposed case + const bool overwrite, + const fileName& proc0CaseName, + const label nDestProcs, + const labelList& decomp, + const fileName& masterInstDir, + fvMesh& mesh +) { - #include "addRegionOption.H" - #include "addOverwriteOption.H" - argList::addOption - ( - "mergeTol", - "scalar", - "specify the merge distance relative to the bounding box size " - "(default 1e-6)" - ); - // Include explicit constant options, have zero from time range - timeSelector::addOptions(); + Time& runTime = const_cast<Time&>(mesh.time()); - #include "setRootCase.H" - if (env("FOAM_SIGFPE")) - { - WarningIn(args.executable()) - << "Detected floating point exception trapping (FOAM_SIGFPE)." - << " This might give" << nl - << " problems when mapping fields. Switch it off in case" - << " of problems." << endl; - } + //// Print some statistics + //Info<< "Before distribution:" << endl; + //printMeshData(mesh); - // Create processor directory if non-existing - if (!Pstream::master() && !isDir(args.path())) - { - Pout<< "Creating case directory " << args.path() << endl; - mkDir(args.path()); - } - + PtrList<volScalarField> volScalarFields; + PtrList<volVectorField> volVectorFields; + PtrList<volSphericalTensorField> volSphereTensorFields; + PtrList<volSymmTensorField> volSymmTensorFields; + PtrList<volTensorField> volTensorFields; - // Make sure we do not use the master-only reading. - regIOobject::fileModificationChecking = regIOobject::timeStamp; - #include "createTime.H" - // Allow override of time - instantList times = timeSelector::selectIfPresent(runTime, args); - runTime.setTime(times[0], 0); + PtrList<surfaceScalarField> surfScalarFields; + PtrList<surfaceVectorField> surfVectorFields; + PtrList<surfaceSphericalTensorField> surfSphereTensorFields; + PtrList<surfaceSymmTensorField> surfSymmTensorFields; + PtrList<surfaceTensorField> surfTensorFields; - runTime.functionObjects().off(); + PtrList<DimensionedField<scalar, volMesh> > dimScalarFields; + PtrList<DimensionedField<vector, volMesh> > dimVectorFields; + PtrList<DimensionedField<sphericalTensor, volMesh> > dimSphereTensorFields; + PtrList<DimensionedField<symmTensor, volMesh> > dimSymmTensorFields; + PtrList<DimensionedField<tensor, volMesh> > dimTensorFields; - word regionName = polyMesh::defaultRegion; - fileName meshSubDir; - if (args.optionReadIfPresent("region", regionName)) - { - meshSubDir = regionName/polyMesh::meshSubDir; - } - else + if (doReadFields) { - meshSubDir = polyMesh::meshSubDir; - } - Info<< "Using mesh subdirectory " << meshSubDir << nl << endl; + // Create 0 sized mesh to do all the generation of zero sized + // fields on processors that have zero sized meshes. Note that this is + // only nessecary on master but since polyMesh construction with + // Pstream::parRun does parallel comms we have to do it on all + // processors + autoPtr<fvMeshSubset> subsetterPtr; + + const bool allHaveMesh = (findIndex(haveMesh, false) == -1); + if (!allHaveMesh) + { + // Find last non-processor patch. + const polyBoundaryMesh& patches = mesh.boundaryMesh(); - const bool overwrite = args.optionFound("overwrite"); + label nonProcI = -1; + forAll(patches, patchI) + { + if (isA<processorPolyPatch>(patches[patchI])) + { + break; + } + nonProcI++; + } - // Get time instance directory. Since not all processors have meshes - // just use the master one everywhere. + if (nonProcI == -1) + { + FatalErrorIn("redistributeAndWrite(..)") + << "Cannot find non-processor patch on processor " + << Pstream::myProcNo() << endl + << " Current patches:" << patches.names() + << abort(FatalError); + } - fileName masterInstDir; - if (Pstream::master()) - { - masterInstDir = runTime.findInstance(meshSubDir, "points"); - } - Pstream::scatter(masterInstDir); + // Subset 0 cells, no parallel comms. This is used to create + // zero-sized fields. + subsetterPtr.reset(new fvMeshSubset(mesh)); + subsetterPtr().setLargeCellSubset(labelHashSet(0), nonProcI, false); + } - // Check who has a mesh - const fileName meshPath = runTime.path()/masterInstDir/meshSubDir; - Info<< "Found points in " << meshPath << nl << endl; + // Get original objects (before incrementing time!) + if (Pstream::master() && decompose) + { + runTime.TimePaths::caseName() = baseRunTime.caseName(); + } + IOobjectList objects(mesh, runTime.timeName()); + if (Pstream::master() && decompose) + { + runTime.TimePaths::caseName() = proc0CaseName; + } + Info<< "From time " << runTime.timeName() + << " have objects:" << objects.names() << endl; - boolList haveMesh(Pstream::nProcs(), false); - haveMesh[Pstream::myProcNo()] = isDir(meshPath); - Pstream::gatherList(haveMesh); - Pstream::scatterList(haveMesh); - Info<< "Per processor mesh availability : " << haveMesh << endl; - const bool allHaveMesh = (findIndex(haveMesh, false) == -1); + // We don't want to map the decomposition (mapping already tested when + // mapping the cell centre field) + IOobjectList::iterator iter = objects.find("cellDist"); + if (iter != objects.end()) + { + objects.erase(iter); + } - autoPtr<fvMesh> meshPtr = loadOrCreateMesh - ( - IOobject + + // volFields + + if (Pstream::master() && decompose) + { + runTime.TimePaths::caseName() = baseRunTime.caseName(); + } + readFields ( - regionName, - masterInstDir, - runTime, - Foam::IOobject::MUST_READ - ) - ); + haveMesh, + mesh, + subsetterPtr, + objects, + volScalarFields + ); + + readFields + ( + haveMesh, + mesh, + subsetterPtr, + objects, + volVectorFields + ); + + readFields + ( + haveMesh, + mesh, + subsetterPtr, + objects, + volSphereTensorFields + ); + + readFields + ( + haveMesh, + mesh, + subsetterPtr, + objects, + volSymmTensorFields + ); + + readFields + ( + haveMesh, + mesh, + subsetterPtr, + objects, + volTensorFields + ); + + + // surfaceFields + + readFields + ( + haveMesh, + mesh, + subsetterPtr, + objects, + surfScalarFields + ); + + readFields + ( + haveMesh, + mesh, + subsetterPtr, + objects, + surfVectorFields + ); + + readFields + ( + haveMesh, + mesh, + subsetterPtr, + objects, + surfSphereTensorFields + ); + + readFields + ( + haveMesh, + mesh, + subsetterPtr, + objects, + surfSymmTensorFields + ); + + readFields + ( + haveMesh, + mesh, + subsetterPtr, + objects, + surfTensorFields + ); + + + // Dimensioned internal fields + readFields + ( + haveMesh, + mesh, + subsetterPtr, + objects, + dimScalarFields + ); + + readFields + ( + haveMesh, + mesh, + subsetterPtr, + objects, + dimVectorFields + ); + + readFields + ( + haveMesh, + mesh, + subsetterPtr, + objects, + dimSphereTensorFields + ); + + readFields + ( + haveMesh, + mesh, + subsetterPtr, + objects, + dimSymmTensorFields + ); + + readFields + ( + haveMesh, + mesh, + subsetterPtr, + objects, + dimTensorFields + ); + + + + if (Pstream::master() && decompose) + { + runTime.TimePaths::caseName() = proc0CaseName; + } + } + - fvMesh& mesh = meshPtr(); + // Mesh distribution engine + fvMeshDistribute distributor(mesh, tolDim); + + // Do all the distribution of mesh and fields + autoPtr<mapDistributePolyMesh> rawMap = distributor.distribute(decomp); // Print some statistics - Info<< "Before distribution:" << endl; + Info<< "After distribution:" << endl; printMeshData(mesh); + // Get other side of processor boundaries + correctCoupledBoundaryConditions + < + volScalarField, + processorFvPatchField<scalar> + >(mesh); + correctCoupledBoundaryConditions + < + volVectorField, + processorFvPatchField<vector> + >(mesh); + correctCoupledBoundaryConditions + < + volSphericalTensorField, + processorFvPatchField<sphericalTensor> + >(mesh); + correctCoupledBoundaryConditions + < + volSymmTensorField, + processorFvPatchField<symmTensor> + >(mesh); + correctCoupledBoundaryConditions + < + volTensorField, + processorFvPatchField<tensor> + >(mesh); + // No update surface fields + + + // Set the minimum write precision + IOstream::defaultPrecision(max(10u, IOstream::defaultPrecision())); + + + if (!overwrite) + { + runTime++; + mesh.setInstance(runTime.timeName()); + } + else + { + mesh.setInstance(masterInstDir); + } - IOdictionary decompositionDict + IOmapDistributePolyMesh map ( IOobject ( - "decomposeParDict", - runTime.system(), + "procAddressing", + mesh.facesInstance(), + meshSubDir, mesh, - IOobject::MUST_READ_IF_MODIFIED, - IOobject::NO_WRITE + IOobject::NO_READ, + IOobject::AUTO_WRITE ) ); + map.transfer(rawMap()); - labelList finalDecomp; - // Create decompositionMethod and new decomposition + if (nDestProcs == 1) { - autoPtr<decompositionMethod> decomposer - ( - decompositionMethod::New - ( - decompositionDict - ) - ); - - if (!decomposer().parallelAware()) + if (Pstream::master()) { - WarningIn(args.executable()) - << "You have selected decomposition method " - << decomposer().typeName - << " which does" << endl - << "not synchronise the decomposition across" - << " processor patches." << endl - << " You might want to select a decomposition method which" - << " is aware of this. Continuing." - << endl; - } + Info<< "Setting caseName to " << baseRunTime.caseName() + << " to write reconstructed mesh and fields." << endl; + runTime.TimePaths::caseName() = baseRunTime.caseName(); - finalDecomp = decomposer().decompose(mesh, mesh.cellCentres()); - } + mesh.write(); - // Dump decomposition to volScalarField - if (!overwrite) + // Now we've written all. Reset caseName on master + Info<< "Restoring caseName to " << proc0CaseName << endl; + runTime.TimePaths::caseName() = proc0CaseName; + } + } + else { - writeDecomposition("decomposition", mesh, finalDecomp); + mesh.write(); } + Info<< "Written redistributed mesh to " << mesh.facesInstance() << nl + << endl; - // Create 0 sized mesh to do all the generation of zero sized - // fields on processors that have zero sized meshes. Note that this is - // only nessecary on master but since polyMesh construction with - // Pstream::parRun does parallel comms we have to do it on all - // processors - autoPtr<fvMeshSubset> subsetterPtr; - - if (!allHaveMesh) + if (decompose || nDestProcs == 1) { - // Find last non-processor patch. - const polyBoundaryMesh& patches = mesh.boundaryMesh(); + writeProcAddressing(decompose, meshSubDir, mesh, map); + } + - label nonProcI = -1; + // Refinement data + { - forAll(patches, patchI) + // Read refinement data + if (Pstream::master() && decompose) { - if (isA<processorPolyPatch>(patches[patchI])) - { - break; - } - nonProcI++; + runTime.TimePaths::caseName() = baseRunTime.caseName(); } + IOobject io + ( + "dummy", + mesh.facesInstance(), + polyMesh::meshSubDir, + mesh, + IOobject::READ_IF_PRESENT, + IOobject::NO_WRITE, + false + ); - if (nonProcI == -1) + hexRef8Data refData(io); + if (Pstream::master() && decompose) { - FatalErrorIn(args.executable()) - << "Cannot find non-processor patch on processor " - << Pstream::myProcNo() << endl - << " Current patches:" << patches.names() << abort(FatalError); + runTime.TimePaths::caseName() = proc0CaseName; } - - // Subset 0 cells, no parallel comms. This is used to create zero-sized - // fields. - subsetterPtr.reset(new fvMeshSubset(mesh)); - subsetterPtr().setLargeCellSubset(labelHashSet(0), nonProcI, false); - } + // Make sure all processors have valid data (since only some will + // read) + refData.sync(io); - // Get original objects (before incrementing time!) - IOobjectList objects(mesh, runTime.timeName()); - // We don't want to map the decomposition (mapping already tested when - // mapping the cell centre field) - IOobjectList::iterator iter = objects.find("decomposition"); - if (iter != objects.end()) - { - objects.erase(iter); - } + // Distribute + refData.distribute(map); + if (nDestProcs == 1) + { + if (Pstream::master()) + { + Info<< "Setting caseName to " << baseRunTime.caseName() + << " to write reconstructed refinement data." << endl; + runTime.TimePaths::caseName() = baseRunTime.caseName(); - // volFields + refData.write(); - PtrList<volScalarField> volScalarFields; - readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - volScalarFields - ); + // Now we've written all. Reset caseName on master + Info<< "Restoring caseName to " << proc0CaseName << endl; + runTime.TimePaths::caseName() = proc0CaseName; + } + } + else + { + refData.write(); + } + } - PtrList<volVectorField> volVectorFields; - readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - volVectorFields - ); - PtrList<volSphericalTensorField> volSphereTensorFields; - readFields + return autoPtr<mapDistributePolyMesh> ( - haveMesh, - mesh, - subsetterPtr, - objects, - volSphereTensorFields + new mapDistributePolyMesh(map.xfer()) ); +} - PtrList<volSymmTensorField> volSymmTensorFields; - readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - volSymmTensorFields - ); - PtrList<volTensorField> volTensorFields; - readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - volTensorFields - ); +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Field Mapping +// +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +autoPtr<mapDistributePolyMesh> createReconstructMap +( + const autoPtr<fvMesh>& baseMeshPtr, + const fvMesh& mesh, + const labelList& cellProcAddressing, + const labelList& faceProcAddressing, + const labelList& pointProcAddressing, + const labelList& boundaryProcAddressing +) +{ + // Send addressing to master + labelListList cellAddressing(Pstream::nProcs()); + cellAddressing[Pstream::myProcNo()] = cellProcAddressing; + Pstream::gatherList(cellAddressing); - // surfaceFields + labelListList faceAddressing(Pstream::nProcs()); + faceAddressing[Pstream::myProcNo()] = faceProcAddressing; + Pstream::gatherList(faceAddressing); - PtrList<surfaceScalarField> surfScalarFields; - readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - surfScalarFields - ); + labelListList pointAddressing(Pstream::nProcs()); + pointAddressing[Pstream::myProcNo()] = pointProcAddressing; + Pstream::gatherList(pointAddressing); - PtrList<surfaceVectorField> surfVectorFields; - readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - surfVectorFields - ); + labelListList boundaryAddressing(Pstream::nProcs()); + { + // Remove -1 entries + DynamicList<label> patchProcAddressing(boundaryProcAddressing.size()); + forAll(boundaryProcAddressing, i) + { + if (boundaryProcAddressing[i] != -1) + { + patchProcAddressing.append(boundaryProcAddressing[i]); + } + } + boundaryAddressing[Pstream::myProcNo()] = patchProcAddressing; + Pstream::gatherList(boundaryAddressing); + } - PtrList<surfaceSphericalTensorField> surfSphereTensorFields; - readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - surfSphereTensorFields - ); - PtrList<surfaceSymmTensorField> surfSymmTensorFields; - readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - surfSymmTensorFields - ); + autoPtr<mapDistributePolyMesh> mapPtr; - PtrList<surfaceTensorField> surfTensorFields; - readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - surfTensorFields - ); + if (baseMeshPtr.valid() && baseMeshPtr().nCells()) //baseMeshPtr.valid()) + { + const fvMesh& baseMesh = baseMeshPtr(); + labelListList cellSubMap(Pstream::nProcs()); + cellSubMap[Pstream::masterNo()] = identity(mesh.nCells()); - // Debugging: Create additional volField that will be mapped. - // Used to test correctness of mapping - //volVectorField mapCc("mapCc", 1*mesh.C()); + mapDistribute cellMap + ( + baseMesh.nCells(), + cellSubMap.xfer(), + cellAddressing.xfer() + ); - // Global matching tolerance - const scalar tolDim = getMergeDistance - ( - args, - runTime, - mesh.bounds() - ); + labelListList faceSubMap(Pstream::nProcs()); + faceSubMap[Pstream::masterNo()] = identity(mesh.nFaces()); - // Mesh distribution engine - fvMeshDistribute distributor(mesh, tolDim); + mapDistribute faceMap + ( + baseMesh.nFaces(), + faceSubMap.xfer(), + faceAddressing.xfer(), + false, //subHasFlip + true //constructHasFlip + ); - //Pout<< "Wanted distribution:" - // << distributor.countCells(finalDecomp) << nl << endl; + labelListList pointSubMap(Pstream::nProcs()); + pointSubMap[Pstream::masterNo()] = identity(mesh.nPoints()); - // Do actual sending/receiving of mesh - autoPtr<mapDistributePolyMesh> map = distributor.distribute(finalDecomp); + mapDistribute pointMap + ( + baseMesh.nPoints(), + pointSubMap.xfer(), + pointAddressing.xfer() + ); - //// Distribute any non-registered data accordingly - //map().distributeFaceData(faceCc); + labelListList patchSubMap(Pstream::nProcs()); + // Send (filtered) patches to master + patchSubMap[Pstream::masterNo()] = + boundaryAddressing[Pstream::myProcNo()]; + mapDistribute patchMap + ( + baseMesh.boundaryMesh().size(), + patchSubMap.xfer(), + boundaryAddressing.xfer() + ); - // Print some statistics - Info<< "After distribution:" << endl; - printMeshData(mesh); + const label nOldPoints = mesh.nPoints(); + const label nOldFaces = mesh.nFaces(); + const label nOldCells = mesh.nCells(); + const polyBoundaryMesh& pbm = mesh.boundaryMesh(); + labelList oldPatchStarts(pbm.size()); + labelList oldPatchNMeshPoints(pbm.size()); + forAll(pbm, patchI) + { + oldPatchStarts[patchI] = pbm[patchI].start(); + oldPatchNMeshPoints[patchI] = pbm[patchI].nPoints(); + } - if (!overwrite) - { - runTime++; + mapPtr.reset + ( + new mapDistributePolyMesh + ( + nOldPoints, + nOldFaces, + nOldCells, + oldPatchStarts.xfer(), + oldPatchNMeshPoints.xfer(), + pointMap.xfer(), + faceMap.xfer(), + cellMap.xfer(), + patchMap.xfer() + ) + ); } else { - mesh.setInstance(masterInstDir); - } - Info<< "Writing redistributed mesh to " << runTime.timeName() << nl << endl; - mesh.write(); + labelListList cellSubMap(Pstream::nProcs()); + cellSubMap[Pstream::masterNo()] = identity(mesh.nCells()); + labelListList cellConstructMap(Pstream::nProcs()); + + mapDistribute cellMap + ( + 0, + cellSubMap.xfer(), + cellConstructMap.xfer() + ); + labelListList faceSubMap(Pstream::nProcs()); + faceSubMap[Pstream::masterNo()] = identity(mesh.nFaces()); + labelListList faceConstructMap(Pstream::nProcs()); - // Debugging: test mapped cellcentre field. - //compareFields(tolDim, mesh.C(), mapCc); + mapDistribute faceMap + ( + 0, + faceSubMap.xfer(), + faceConstructMap.xfer(), + false, //subHasFlip + true //constructHasFlip + ); - // Print nice message - // ~~~~~~~~~~~~~~~~~~ + labelListList pointSubMap(Pstream::nProcs()); + pointSubMap[Pstream::masterNo()] = identity(mesh.nPoints()); + labelListList pointConstructMap(Pstream::nProcs()); - // Determine which processors remain so we can print nice final message. - labelList nFaces(Pstream::nProcs()); - nFaces[Pstream::myProcNo()] = mesh.nFaces(); - Pstream::gatherList(nFaces); - Pstream::scatterList(nFaces); + mapDistribute pointMap + ( + 0, + pointSubMap.xfer(), + pointConstructMap.xfer() + ); - Info<< nl - << "You can pick up the redecomposed mesh from the polyMesh directory" - << " in " << runTime.timeName() << "." << nl - << "If you redecomposed the mesh to less processors you can delete" - << nl - << "the processor directories with 0 sized meshes in them." << nl - << "Below is a sample set of commands to do this." - << " Take care when issuing these" << nl - << "commands." << nl << endl; + labelListList patchSubMap(Pstream::nProcs()); + // Send (filtered) patches to master + patchSubMap[Pstream::masterNo()] = + boundaryAddressing[Pstream::myProcNo()]; + labelListList patchConstructMap(Pstream::nProcs()); - forAll(nFaces, procI) - { - fileName procDir = "processor" + name(procI); + mapDistribute patchMap + ( + 0, + patchSubMap.xfer(), + patchConstructMap.xfer() + ); - if (nFaces[procI] == 0) + const label nOldPoints = mesh.nPoints(); + const label nOldFaces = mesh.nFaces(); + const label nOldCells = mesh.nCells(); + + const polyBoundaryMesh& pbm = mesh.boundaryMesh(); + labelList oldPatchStarts(pbm.size()); + labelList oldPatchNMeshPoints(pbm.size()); + forAll(pbm, patchI) { - Info<< " rm -r " << procDir.c_str() << nl; + oldPatchStarts[patchI] = pbm[patchI].start(); + oldPatchNMeshPoints[patchI] = pbm[patchI].nPoints(); } - else - { - fileName timeDir = procDir/runTime.timeName()/meshSubDir; - fileName constDir = procDir/runTime.constant()/meshSubDir; - Info<< " rm -r " << constDir.c_str() << nl - << " mv " << timeDir.c_str() - << ' ' << constDir.c_str() << nl; + mapPtr.reset + ( + new mapDistributePolyMesh + ( + nOldPoints, + nOldFaces, + nOldCells, + oldPatchStarts.xfer(), + oldPatchNMeshPoints.xfer(), + pointMap.xfer(), + faceMap.xfer(), + cellMap.xfer(), + patchMap.xfer() + ) + ); + } + + return mapPtr; +} + + +void readProcAddressing +( + const fvMesh& mesh, + const autoPtr<fvMesh>& baseMeshPtr, + autoPtr<mapDistributePolyMesh>& distMap +) +{ + //IOobject io + //( + // "procAddressing", + // mesh.facesInstance(), + // polyMesh::meshSubDir, + // mesh, + // IOobject::MUST_READ + //); + //if (io.headerOk()) + //{ + // Pout<< "Reading addressing from " << io.name() << " at " + // << mesh.facesInstance() << nl << endl; + // distMap.clear(); + // distMap.reset(new IOmapDistributePolyMesh(io)); + //} + //else + { + Info<< "Reading addressing from procXXXAddressing at " + << mesh.facesInstance() << nl << endl; + labelIOList cellProcAddressing + ( + IOobject + ( + "cellProcAddressing", + mesh.facesInstance(), + polyMesh::meshSubDir, + mesh, + IOobject::READ_IF_PRESENT + ), + labelList(0) + ); + labelIOList faceProcAddressing + ( + IOobject + ( + "faceProcAddressing", + mesh.facesInstance(), + polyMesh::meshSubDir, + mesh, + IOobject::READ_IF_PRESENT + ), + labelList(0) + ); + labelIOList pointProcAddressing + ( + IOobject + ( + "pointProcAddressing", + mesh.facesInstance(), + polyMesh::meshSubDir, + mesh, + IOobject::READ_IF_PRESENT + ), + labelList(0) + ); + labelIOList boundaryProcAddressing + ( + IOobject + ( + "boundaryProcAddressing", + mesh.facesInstance(), + polyMesh::meshSubDir, + mesh, + IOobject::READ_IF_PRESENT + ), + labelList(0) + ); + + + if + ( + mesh.nCells() != cellProcAddressing.size() + || mesh.nPoints() != pointProcAddressing.size() + || mesh.nFaces() != faceProcAddressing.size() + || mesh.boundaryMesh().size() != boundaryProcAddressing.size() + ) + { + FatalErrorIn + ( + "readProcAddressing(const fvMesh&, const autoPtr<fvMesh>&," + "autoPtr<mapDistributePolyMesh>&" + ) << "Read addressing inconsistent with mesh sizes" << nl + << "cells:" << mesh.nCells() + << " addressing:" << cellProcAddressing.objectPath() + << " size:" << cellProcAddressing.size() << nl + << "faces:" << mesh.nFaces() + << " addressing:" << faceProcAddressing.objectPath() + << " size:" << faceProcAddressing.size() << nl + << "points:" << mesh.nPoints() + << " addressing:" << pointProcAddressing.objectPath() + << " size:" << pointProcAddressing.size() + << "patches:" << mesh.boundaryMesh().size() + << " addressing:" << boundaryProcAddressing.objectPath() + << " size:" << boundaryProcAddressing.size() + << exit(FatalError); + } + + distMap.clear(); + distMap = createReconstructMap + ( + baseMeshPtr, + mesh, + cellProcAddressing, + faceProcAddressing, + pointProcAddressing, + boundaryProcAddressing + ); + } +} + + +void reconstructMeshFields +( + const parFvFieldReconstructor& fvReconstructor, + const IOobjectList& objects, + const HashSet<word>& selectedFields +) +{ + // Dimensioned fields + + fvReconstructor.reconstructFvVolumeInternalFields<scalar> + ( + objects, + selectedFields + ); + fvReconstructor.reconstructFvVolumeInternalFields<vector> + ( + objects, + selectedFields + ); + fvReconstructor.reconstructFvVolumeInternalFields<sphericalTensor> + ( + objects, + selectedFields + ); + fvReconstructor.reconstructFvVolumeInternalFields<symmTensor> + ( + objects, + selectedFields + ); + fvReconstructor.reconstructFvVolumeInternalFields<tensor> + ( + objects, + selectedFields + ); + + + // volFields + + fvReconstructor.reconstructFvVolumeFields<scalar> + ( + objects, + selectedFields + ); + fvReconstructor.reconstructFvVolumeFields<vector> + ( + objects, + selectedFields + ); + fvReconstructor.reconstructFvVolumeFields<sphericalTensor> + ( + objects, + selectedFields + ); + fvReconstructor.reconstructFvVolumeFields<symmTensor> + ( + objects, + selectedFields + ); + fvReconstructor.reconstructFvVolumeFields<tensor> + ( + objects, + selectedFields + ); + + + // surfaceFields + + fvReconstructor.reconstructFvSurfaceFields<scalar> + ( + objects, + selectedFields + ); + fvReconstructor.reconstructFvSurfaceFields<vector> + ( + objects, + selectedFields + ); + fvReconstructor.reconstructFvSurfaceFields<sphericalTensor> + ( + objects, + selectedFields + ); + fvReconstructor.reconstructFvSurfaceFields<symmTensor> + ( + objects, + selectedFields + ); + fvReconstructor.reconstructFvSurfaceFields<tensor> + ( + objects, + selectedFields + ); +} + + +void reconstructLagrangian +( + autoPtr<parLagrangianRedistributor>& lagrangianReconstructorPtr, + const fvMesh& baseMesh, + const fvMesh& mesh, + const mapDistributePolyMesh& distMap, + const HashSet<word>& selectedLagrangianFields +) +{ + // Clouds (note: might not be present on all processors) + + wordList cloudNames; + List<wordList> fieldNames; + // Find all cloudNames on all processors + parLagrangianRedistributor::findClouds(mesh, cloudNames, fieldNames); + + if (cloudNames.size()) + { + if (!lagrangianReconstructorPtr.valid()) + { + lagrangianReconstructorPtr.reset + ( + new parLagrangianRedistributor + ( + mesh, + baseMesh, + mesh.nCells(), // range of cell indices in clouds + distMap + ) + ); + } + const parLagrangianRedistributor& lagrangianReconstructor = + lagrangianReconstructorPtr(); + + forAll(cloudNames, i) + { + Info<< "Reconstructing lagrangian fields for cloud " + << cloudNames[i] << nl << endl; + + autoPtr<mapDistributeBase> lagrangianMap = + lagrangianReconstructor.redistributeLagrangianPositions + ( + cloudNames[i] + ); + IOobjectList sprayObjs + ( + mesh, + mesh.time().timeName(), + cloud::prefix/cloudNames[i] + ); + + lagrangianReconstructor.redistributeLagrangianFields<label> + ( + lagrangianMap, + cloudNames[i], + sprayObjs, + selectedLagrangianFields + ); + lagrangianReconstructor.redistributeLagrangianFieldFields<label> + ( + lagrangianMap, + cloudNames[i], + sprayObjs, + selectedLagrangianFields + ); + lagrangianReconstructor.redistributeLagrangianFields<scalar> + ( + lagrangianMap, + cloudNames[i], + sprayObjs, + selectedLagrangianFields + ); + lagrangianReconstructor.redistributeLagrangianFieldFields<scalar> + ( + lagrangianMap, + cloudNames[i], + sprayObjs, + selectedLagrangianFields + ); + lagrangianReconstructor.redistributeLagrangianFields<vector> + ( + lagrangianMap, + cloudNames[i], + sprayObjs, + selectedLagrangianFields + ); + lagrangianReconstructor.redistributeLagrangianFieldFields<vector> + ( + lagrangianMap, + cloudNames[i], + sprayObjs, + selectedLagrangianFields + ); + lagrangianReconstructor.redistributeLagrangianFields + <sphericalTensor> + ( + lagrangianMap, + cloudNames[i], + sprayObjs, + selectedLagrangianFields + ); + lagrangianReconstructor.redistributeLagrangianFieldFields + <sphericalTensor> + ( + lagrangianMap, + cloudNames[i], + sprayObjs, + selectedLagrangianFields + ); + lagrangianReconstructor.redistributeLagrangianFields<symmTensor> + ( + lagrangianMap, + cloudNames[i], + sprayObjs, + selectedLagrangianFields + ); + lagrangianReconstructor.redistributeLagrangianFieldFields + <symmTensor> + ( + lagrangianMap, + cloudNames[i], + sprayObjs, + selectedLagrangianFields + ); + lagrangianReconstructor.redistributeLagrangianFields<tensor> + ( + lagrangianMap, + cloudNames[i], + sprayObjs, + selectedLagrangianFields + ); + lagrangianReconstructor.redistributeLagrangianFieldFields<tensor> + ( + lagrangianMap, + cloudNames[i], + sprayObjs, + selectedLagrangianFields + ); + } + } +} + +// Read clouds (note: might not be present on all processors) +void readLagrangian +( + const fvMesh& mesh, + const wordList& cloudNames, + const HashSet<word>& selectedLagrangianFields, + PtrList<unmappedPassiveParticleCloud>& clouds +) +{ + (void)mesh.tetBasePtIs(); + + forAll(cloudNames, i) + { + { + // Note: disable master-only reading of uniform/cloudProperties + regIOobject::fileCheckTypes oldCheckType = + regIOobject::fileModificationChecking; + + if (oldCheckType == regIOobject::timeStampMaster) + { + regIOobject::fileModificationChecking = regIOobject::timeStamp; + } + else if (oldCheckType == regIOobject::inotifyMaster) + { + regIOobject::fileModificationChecking = regIOobject::inotify; + } + + clouds.set + ( + i, + new unmappedPassiveParticleCloud(mesh, cloudNames[i], false) + ); + + regIOobject::fileModificationChecking = oldCheckType; + } + + + //forAllConstIter + //( + // unmappedPassiveParticleCloud, + // clouds[i], + // iter + //) + //{ + // Pout<< "Particle position:" << iter().position() + // << " cell:" << iter().cell() + // << " with cc:" << mesh.cellCentres()[iter().cell()] + // << endl; + //} + + + IOobjectList sprayObjs(clouds[i], clouds[i].time().timeName()); + + //Pout<< "Found clould objects:" << sprayObjs.names() << endl; + + parLagrangianRedistributor::readLagrangianFields + <IOField<label> > + ( + clouds[i], + sprayObjs, + selectedLagrangianFields + ); + parLagrangianRedistributor::readLagrangianFields + <IOField<Field<label> > > + ( + clouds[i], + sprayObjs, + selectedLagrangianFields + ); + parLagrangianRedistributor::readLagrangianFields + <CompactIOField<Field<label>, label> > + ( + clouds[i], + sprayObjs, + selectedLagrangianFields + ); + + + parLagrangianRedistributor::readLagrangianFields + <IOField<scalar> > + ( + clouds[i], + sprayObjs, + selectedLagrangianFields + ); + parLagrangianRedistributor::readLagrangianFields + <IOField<Field<scalar> > > + ( + clouds[i], + sprayObjs, + selectedLagrangianFields + ); + parLagrangianRedistributor::readLagrangianFields + <CompactIOField<Field<scalar>, scalar> > + ( + clouds[i], + sprayObjs, + selectedLagrangianFields + ); + + + parLagrangianRedistributor::readLagrangianFields + <IOField<vector> > + ( + clouds[i], + sprayObjs, + selectedLagrangianFields + ); + parLagrangianRedistributor::readLagrangianFields + <IOField<Field<vector> > > + ( + clouds[i], + sprayObjs, + selectedLagrangianFields + ); + parLagrangianRedistributor::readLagrangianFields + <CompactIOField<Field<vector>, vector> > + ( + clouds[i], + sprayObjs, + selectedLagrangianFields + ); + + + parLagrangianRedistributor::readLagrangianFields + <IOField<sphericalTensor> > + ( + clouds[i], + sprayObjs, + selectedLagrangianFields + ); + parLagrangianRedistributor::readLagrangianFields + <IOField<Field<sphericalTensor> > > + ( + clouds[i], + sprayObjs, + selectedLagrangianFields + ); + parLagrangianRedistributor::readLagrangianFields + <CompactIOField<Field<sphericalTensor>, sphericalTensor> > + ( + clouds[i], + sprayObjs, + selectedLagrangianFields + ); + + + parLagrangianRedistributor::readLagrangianFields + <IOField<symmTensor> > + ( + clouds[i], + sprayObjs, + selectedLagrangianFields + ); + parLagrangianRedistributor::readLagrangianFields + <IOField<Field<symmTensor> > > + ( + clouds[i], + sprayObjs, + selectedLagrangianFields + ); + parLagrangianRedistributor::readLagrangianFields + <CompactIOField<Field<symmTensor>, symmTensor> > + ( + clouds[i], + sprayObjs, + selectedLagrangianFields + ); + + + parLagrangianRedistributor::readLagrangianFields + <IOField<tensor> > + ( + clouds[i], + sprayObjs, + selectedLagrangianFields + ); + parLagrangianRedistributor::readLagrangianFields + <IOField<Field<tensor> > > + ( + clouds[i], + sprayObjs, + selectedLagrangianFields + ); + parLagrangianRedistributor::readLagrangianFields + <CompactIOField<Field<tensor>, tensor> > + ( + clouds[i], + sprayObjs, + selectedLagrangianFields + ); + } +} + + +void redistributeLagrangian +( + autoPtr<parLagrangianRedistributor>& lagrangianReconstructorPtr, + const fvMesh& mesh, + const label nOldCells, + const mapDistributePolyMesh& distMap, + PtrList<unmappedPassiveParticleCloud>& clouds +) +{ + if (clouds.size()) + { + if (!lagrangianReconstructorPtr.valid()) + { + lagrangianReconstructorPtr.reset + ( + new parLagrangianRedistributor + ( + mesh, + mesh, + nOldCells, // range of cell indices in clouds + distMap + ) + ); + } + const parLagrangianRedistributor& distributor = + lagrangianReconstructorPtr(); + + forAll(clouds, i) + { + autoPtr<mapDistributeBase> lagrangianMap = + distributor.redistributeLagrangianPositions(clouds[i]); + + distributor.redistributeStoredLagrangianFields + <IOField<label> > + ( + lagrangianMap, + clouds[i] + ); + distributor.redistributeStoredLagrangianFields + <IOField<Field<label> > > + ( + lagrangianMap, + clouds[i] + ); + distributor.redistributeStoredLagrangianFields + <CompactIOField<Field<label>, label> > + ( + lagrangianMap, + clouds[i] + ); + + + distributor.redistributeStoredLagrangianFields + <IOField<scalar> > + ( + lagrangianMap, + clouds[i] + ); + distributor.redistributeStoredLagrangianFields + <IOField<Field<scalar> > > + ( + lagrangianMap, + clouds[i] + ); + distributor.redistributeStoredLagrangianFields + <CompactIOField<Field<scalar>, scalar> > + ( + lagrangianMap, + clouds[i] + ); + + + distributor.redistributeStoredLagrangianFields + <IOField<vector> > + ( + lagrangianMap, + clouds[i] + ); + distributor.redistributeStoredLagrangianFields + <IOField<Field<vector> > > + ( + lagrangianMap, + clouds[i] + ); + distributor.redistributeStoredLagrangianFields + <CompactIOField<Field<vector>, vector> > + ( + lagrangianMap, + clouds[i] + ); + + + distributor.redistributeStoredLagrangianFields + <IOField<sphericalTensor> > + ( + lagrangianMap, + clouds[i] + ); + distributor.redistributeStoredLagrangianFields + <IOField<Field<sphericalTensor> > > + ( + lagrangianMap, + clouds[i] + ); + distributor.redistributeStoredLagrangianFields + <CompactIOField<Field<sphericalTensor>, sphericalTensor> > + ( + lagrangianMap, + clouds[i] + ); + + + distributor.redistributeStoredLagrangianFields + <IOField<symmTensor> > + ( + lagrangianMap, + clouds[i] + ); + distributor.redistributeStoredLagrangianFields + <IOField<Field<symmTensor> > > + ( + lagrangianMap, + clouds[i] + ); + distributor.redistributeStoredLagrangianFields + <CompactIOField<Field<symmTensor>, symmTensor> > + ( + lagrangianMap, + clouds[i] + ); + + + distributor.redistributeStoredLagrangianFields + <IOField<tensor> > + ( + lagrangianMap, + clouds[i] + ); + distributor.redistributeStoredLagrangianFields + <IOField<Field<tensor> > > + ( + lagrangianMap, + clouds[i] + ); + distributor.redistributeStoredLagrangianFields + <CompactIOField<Field<tensor>, tensor> > + ( + lagrangianMap, + clouds[i] + ); + } + } +} + + +int main(int argc, char *argv[]) +{ + // enable -constant ... if someone really wants it + // enable -zeroTime to prevent accidentally trashing the initial fields + timeSelector::addOptions(true, true); + #include "addRegionOption.H" + #include "addOverwriteOption.H" + argList::addBoolOption("decompose", "decompose case"); + argList::addBoolOption("reconstruct", "reconstruct case"); + argList::addOption + ( + "mergeTol", + "scalar", + "specify the merge distance relative to the bounding box size " + "(default 1e-6)" + ); + argList::addBoolOption + ( + "cellDist", + "write cell distribution as a labelList - for use with 'manual' " + "decomposition method or as a volScalarField for post-processing." + ); + argList::addBoolOption + ( + "newTimes", + "only reconstruct new times (i.e. that do not exist already)" + ); + + + // Handle arguments + // ~~~~~~~~~~~~~~~~ + // (replacement for setRootCase that does not abort) + + Foam::argList args(argc, argv); + bool decompose = args.optionFound("decompose"); + const bool reconstruct = args.optionFound("reconstruct"); + bool overwrite = args.optionFound("overwrite"); + bool writeCellDist = args.optionFound("cellDist"); + bool newTimes = args.optionFound("newTimes"); + + + + if (env("FOAM_SIGFPE")) + { + WarningIn(args.executable()) + << "Detected floating point exception trapping (FOAM_SIGFPE)." + << " This might give" << nl + << " problems when mapping fields. Switch it off in case" + << " of problems." << endl; + } + + + + const HashSet<word> selectedFields(0); + const HashSet<word> selectedLagrangianFields(0); + + + if (decompose) + { + Info<< "Decomposing case (like decomposePar)" << nl << endl; + if (reconstruct) + { + FatalErrorIn(args.executable()) + << "Cannot specify both -decompose and -reconstruct" + << exit(FatalError); + } + } + else if (reconstruct) + { + Info<< "Reconstructing case (like reconstructParMesh)" << nl << endl; + } + + + if (decompose || reconstruct) + { + if (!overwrite) + { + WarningIn(args.executable()) + << "Working in decompose or reconstruction mode automatically" + << " implies -overwrite" << nl << endl; + overwrite = true; + } + } + + + if (!Pstream::parRun()) + { + FatalErrorIn(args.executable()) + << ": This utility can only be run parallel" + << exit(FatalError); + } + + + if (!isDir(args.rootPath())) + { + FatalErrorIn(args.executable()) + << ": cannot open root directory " << args.rootPath() + << exit(FatalError); + } + + // Detect if running data-distributed (multiple roots) + bool nfs = true; + { + List<fileName> roots(1, args.rootPath()); + combineReduce(roots, ListUniqueEqOp<fileName>()); + nfs = (roots.size() == 1); + } + + if (!nfs) + { + Info<< "Detected multiple roots i.e. non-nfs running" + << nl << endl; + } + + if (isDir(args.path())) + { + if (decompose) + { + Info<< "Removing existing processor directories" << endl; + rmDir(args.path()); + } + } + else + { + // Directory does not exist. If this happens on master -> decompose mode + decompose = true; + Info<< "No processor directories; switching on decompose mode" + << nl << endl; + } + // If master changed to decompose mode make sure all nodes know about + // it + Pstream::scatter(decompose); + + + + + // If running distributed we have problem of new processors not finding + // a system/controlDict. However if we switch on the master-only reading + // the problem becomes that the time directories are differing sizes and + // e.g. latestTime will pick up a different time (which causes createTime.H + // to abort). So for now make sure to have master times on all + // processors + { + Info<< "Creating time directories on all processors" << nl << endl; + instantList timeDirs; + if (Pstream::master()) + { + timeDirs = Time::findTimes(args.path(), "constant"); + } + Pstream::scatter(timeDirs); + forAll(timeDirs, i) + { + mkDir(args.path()/timeDirs[i].name()); + } + } + + + // Construct time + // ~~~~~~~~~~~~~~ + + #include "createTime.H" + runTime.functionObjects().off(); + + + // Save local processor0 casename + const fileName proc0CaseName = runTime.caseName(); + + + // Construct undecomposed Time + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // This will read the same controlDict but might have a different + // set of times so enforce same times + + if (!nfs) + { + Info<< "Creating time directories for undecomposed Time" + << " on all processors" << nl << endl; + instantList timeDirs; + + const fileName basePath(args.rootPath()/args.globalCaseName()); + + if (Pstream::master()) + { + timeDirs = Time::findTimes(basePath, "constant"); + } + Pstream::scatter(timeDirs); + forAll(timeDirs, i) + { + mkDir(basePath/timeDirs[i].name()); + } + } + + + Info<< "Create undecomposed database"<< nl << endl; + Time baseRunTime + ( + runTime.controlDict(), + runTime.rootPath(), + runTime.globalCaseName(), + runTime.system(), + runTime.constant(), + false // enableFunctionObjects + ); + + + HashSet<word> masterTimeDirSet; + if (newTimes) + { + instantList baseTimeDirs(baseRunTime.times()); + forAll(baseTimeDirs, i) + { + masterTimeDirSet.insert(baseTimeDirs[i].name()); + } + } + + + // Determine any region + word regionName = polyMesh::defaultRegion; + fileName meshSubDir; + + if (args.optionReadIfPresent("region", regionName)) + { + meshSubDir = regionName/polyMesh::meshSubDir; + } + else + { + meshSubDir = polyMesh::meshSubDir; + } + Info<< "Using mesh subdirectory " << meshSubDir << nl << endl; + + + + // Demand driven lagrangian mapper + autoPtr<parLagrangianRedistributor> lagrangianReconstructorPtr; + + + + if (reconstruct) + { + // use the times list from the master processor + // and select a subset based on the command-line options + instantList timeDirs = timeSelector::select(runTime.times(), args); + Pstream::scatter(timeDirs); + + if (timeDirs.empty()) + { + FatalErrorIn(args.executable()) + << "No times selected" + << exit(FatalError); + } + + + // Pass1 : reconstruct mesh and addressing + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + Info<< nl + << "Pass1 : reconstructing mesh and addressing" << nl << endl; + + // Loop over all times + forAll(timeDirs, timeI) + { + // Set time for global database + runTime.setTime(timeDirs[timeI], timeI); + baseRunTime.setTime(timeDirs[timeI], timeI); + + Info<< "Time = " << runTime.timeName() << endl << endl; + + + // See where the mesh is + fileName facesInstance = runTime.findInstance + ( + meshSubDir, + "faces", + IOobject::READ_IF_PRESENT + ); + //Pout<< "facesInstance:" << facesInstance << endl; + + Pstream::scatter(facesInstance); + + // Check who has a mesh + const fileName meshPath = + runTime.path()/facesInstance/meshSubDir/"faces"; + + Info<< "Checking for mesh in " << meshPath << nl << endl; + + boolList haveMesh(Pstream::nProcs(), false); + haveMesh[Pstream::myProcNo()] = isFile(meshPath); + Pstream::gatherList(haveMesh); + Pstream::scatterList(haveMesh); + Info<< "Per processor mesh availability : " << haveMesh << endl; + + + // Addressing back to reconstructed mesh as xxxProcAddressing. + // - all processors have consistent faceProcAddressing + // - processors with no mesh don't need faceProcAddressing + + + // Note: filePath searches up on processors that don't have + // processor if instance = constant so explicitly check found + // filename. + bool haveAddressing = false; + if (haveMesh[Pstream::myProcNo()]) + { + haveAddressing = IOobject + ( + "faceProcAddressing", + facesInstance, + meshSubDir, + runTime, + IOobject::READ_IF_PRESENT + ).headerOk(); + } + else + { + // Have no mesh. Don't need addressing + haveAddressing = true; + } + + if (!returnReduce(haveAddressing, andOp<bool>())) + { + Info<< "loading mesh from " << facesInstance << endl; + autoPtr<fvMesh> meshPtr = loadOrCreateMesh + ( + IOobject + ( + regionName, + facesInstance, + runTime, + Foam::IOobject::MUST_READ + ) + ); + fvMesh& mesh = meshPtr(); + + // Global matching tolerance + const scalar tolDim = getMergeDistance + ( + args, + runTime, + mesh.bounds() + ); + + + // Determine decomposition + // ~~~~~~~~~~~~~~~~~~~~~~~ + + Info<< "Reconstructing mesh for time " << facesInstance << endl; + + label nDestProcs = 1; + labelList finalDecomp = labelList(mesh.nCells(), 0); + + redistributeAndWrite + ( + baseRunTime, + tolDim, + haveMesh, + meshSubDir, + false, // do not read fields + false, // do not read undecomposed case on processor0 + overwrite, + proc0CaseName, + nDestProcs, + finalDecomp, + facesInstance, + mesh + ); + } + } + + + // Pass2 : read mesh and addressing and reconstruct fields + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Info<< nl + << "Pass2 : reconstructing fields" << nl << endl; + + runTime.setTime(timeDirs[0], 0); + baseRunTime.setTime(timeDirs[0], 0); + Info<< "Time = " << runTime.timeName() << endl << endl; + + + Info<< "Reading undecomposed mesh (on master)" << endl; + autoPtr<fvMesh> baseMeshPtr = fvMeshTools::newMesh + ( + IOobject + ( + regionName, + baseRunTime.timeName(), + baseRunTime, + IOobject::MUST_READ + ), + true // read on master only + ); + + Info<< "Reading local, decomposed mesh" << endl; + autoPtr<fvMesh> meshPtr = loadOrCreateMesh + ( + IOobject + ( + regionName, + baseMeshPtr().facesInstance(), + runTime, + Foam::IOobject::MUST_READ + ) + ); + fvMesh& mesh = meshPtr(); + + + // Read addressing back to base mesh + autoPtr<mapDistributePolyMesh> distMap; + readProcAddressing(mesh, baseMeshPtr, distMap); + + // Construct field mapper + autoPtr<parFvFieldReconstructor> fvReconstructorPtr + ( + new parFvFieldReconstructor + ( + baseMeshPtr(), + mesh, + distMap, + Pstream::master() // do I need to write? + ) + ); + + + + // Since we start from Times[0] and not runTime.timeName() we + // might overlook point motion in the first timestep + // (since mesh.readUpdate() below will not be triggered). Instead + // detect points by hand + if (mesh.pointsInstance() != mesh.facesInstance()) + { + Info<< " Dected initial mesh motion; reconstructing points" << nl + << endl; + fvReconstructorPtr().reconstructPoints(); + } + + + // Loop over all times + forAll(timeDirs, timeI) + { + if (newTimes && masterTimeDirSet.found(timeDirs[timeI].name())) + { + Info<< "Skipping time " << timeDirs[timeI].name() + << endl << endl; + continue; + } + + // Set time for global database + runTime.setTime(timeDirs[timeI], timeI); + baseRunTime.setTime(timeDirs[timeI], timeI); + + Info<< "Time = " << runTime.timeName() << endl << endl; + + + // Check if any new meshes need to be read. + fvMesh::readUpdateState procStat = mesh.readUpdate(); + + if (procStat == fvMesh::POINTS_MOVED) + { + Info<< " Dected mesh motion; reconstructing points" << nl + << endl; + fvReconstructorPtr().reconstructPoints(); + } + else if + ( + procStat == fvMesh::TOPO_CHANGE + || procStat == fvMesh::TOPO_PATCH_CHANGE + ) + { + Info<< " Detected topology change; reconstructing addressing" + << nl << endl; + + if (baseMeshPtr.valid()) + { + // Cannot do a baseMesh::readUpdate() since not all + // processors will have mesh files. So instead just + // recreate baseMesh + baseMeshPtr.clear(); + baseMeshPtr = fvMeshTools::newMesh + ( + IOobject + ( + regionName, + baseRunTime.timeName(), + baseRunTime, + IOobject::MUST_READ + ), + true // read on master only + ); + } + + // Re-read procXXXaddressing + readProcAddressing(mesh, baseMeshPtr, distMap); + + // Reset field mapper + fvReconstructorPtr.reset + ( + new parFvFieldReconstructor + ( + baseMeshPtr(), + mesh, + distMap, + Pstream::master() + ) + ); + lagrangianReconstructorPtr.clear(); + } + + + // Get list of objects + IOobjectList objects(mesh, runTime.timeName()); + + + // Mesh fields (vol, surface, volInternal) + reconstructMeshFields + ( + fvReconstructorPtr(), + objects, + selectedFields + ); + + // Clouds (note: might not be present on all processors) + reconstructLagrangian + ( + lagrangianReconstructorPtr, + baseMeshPtr(), + mesh, + distMap, + selectedLagrangianFields + ); + + // If there are any "uniform" directories copy them from + // the master processor + if (Pstream::master()) + { + fileName uniformDir0 = runTime.timePath()/"uniform"; + if (isDir(uniformDir0)) + { + Info<< "Detected additional non-decomposed files in " + << uniformDir0 << endl; + cp(uniformDir0, baseRunTime.timePath()); + } + } + } + } + else + { + // Time coming from processor0 (or undecomposed if no processor0) + scalar masterTime; + if (decompose) + { + // Use base time. This is to handle e.g. startTime = latestTime + // which will not do anything if there are no processor directories + masterTime = timeSelector::selectIfPresent + ( + baseRunTime, + args + )[0].value(); + } + else + { + masterTime = timeSelector::selectIfPresent + ( + runTime, + args + )[0].value(); + } + Pstream::scatter(masterTime); + Info<< "Setting time to that of master or undecomposed case : " + << masterTime << endl; + runTime.setTime(masterTime, 0); + + + // Get time instance directory + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // At this point we should be able to read at least a mesh on + // processor0. Note the changing of the processor0 casename to + // enforce it to read/write from the undecomposed case + + fileName masterInstDir; + if (Pstream::master()) + { + if (decompose) + { + Info<< "Setting caseName to " << baseRunTime.caseName() + << " to find undecomposed mesh" << endl; + runTime.TimePaths::caseName() = baseRunTime.caseName(); + } + + masterInstDir = runTime.findInstance + ( + meshSubDir, + "faces", + IOobject::READ_IF_PRESENT + ); + + if (decompose) + { + Info<< "Restoring caseName to " << proc0CaseName << endl; + runTime.TimePaths::caseName() = proc0CaseName; + } + } + Pstream::scatter(masterInstDir); + + // Check who has a mesh + const fileName meshPath = + runTime.path()/masterInstDir/meshSubDir/"faces"; + + Info<< "Checking for mesh in " << meshPath << nl << endl; + + + boolList haveMesh(Pstream::nProcs(), false); + haveMesh[Pstream::myProcNo()] = isFile(meshPath); + Pstream::gatherList(haveMesh); + Pstream::scatterList(haveMesh); + Info<< "Per processor mesh availability : " << haveMesh << endl; + + // Load mesh (or create dummy one) + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + if (Pstream::master() && decompose) + { + Info<< "Setting caseName to " << baseRunTime.caseName() + << " to read undecomposed mesh" << endl; + runTime.TimePaths::caseName() = baseRunTime.caseName(); + } + + autoPtr<fvMesh> meshPtr = loadOrCreateMesh + ( + IOobject + ( + regionName, + masterInstDir, + runTime, + Foam::IOobject::MUST_READ + ) + ); + + if (Pstream::master() && decompose) + { + Info<< "Restoring caseName to " << proc0CaseName << endl; + runTime.TimePaths::caseName() = proc0CaseName; + } + + fvMesh& mesh = meshPtr(); + + + label nOldCells = mesh.nCells(); + //Pout<< "Loaded mesh : nCells:" << nOldCells + // << " nPatches:" << mesh.boundaryMesh().size() << endl; + + + // Global matching tolerance + const scalar tolDim = getMergeDistance + ( + args, + runTime, + mesh.bounds() + ); + + // Allow override of decomposeParDict location + fileName decompDictFile; + if (args.optionReadIfPresent("decomposeParDict", decompDictFile)) + { + if (isDir(decompDictFile)) + { + decompDictFile = decompDictFile / "decomposeParDict"; + } + } + + + // Determine decomposition + // ~~~~~~~~~~~~~~~~~~~~~~~ + + label nDestProcs; + labelList finalDecomp; + determineDecomposition + ( + baseRunTime, + decompDictFile, + decompose, + proc0CaseName, + mesh, + writeCellDist, + + nDestProcs, + finalDecomp + ); + + + wordList cloudNames; + List<wordList> fieldNames; + + // Detect lagrangian fields + if (Pstream::master() && decompose) + { + runTime.TimePaths::caseName() = baseRunTime.caseName(); + } + parLagrangianRedistributor::findClouds + ( + mesh, + cloudNames, + fieldNames + ); + + // Read lagrangian fields and store on cloud (objectRegistry) + PtrList<unmappedPassiveParticleCloud> clouds(cloudNames.size()); + readLagrangian + ( + mesh, + cloudNames, + selectedLagrangianFields, + clouds + ); + if (Pstream::master() && decompose) + { + runTime.TimePaths::caseName() = proc0CaseName; + } + + + // Load fields, do all distribution (mesh and fields - but not + // lagrangian fields; these are done later) + autoPtr<mapDistributePolyMesh> distMap = redistributeAndWrite + ( + baseRunTime, + tolDim, + haveMesh, + meshSubDir, + true, // read fields + decompose, // decompose, i.e. read from undecomposed case + overwrite, + proc0CaseName, + nDestProcs, + finalDecomp, + masterInstDir, + mesh + ); + + + // Redistribute any clouds + redistributeLagrangian + ( + lagrangianReconstructorPtr, + mesh, + nOldCells, + distMap, + clouds + ); + + + // Copy any uniform data + const fileName uniformDir("uniform"); + if (isDir(baseRunTime.timePath()/uniformDir)) + { + Info<< "Detected additional non-decomposed files in " + << baseRunTime.timePath()/uniformDir << endl; + cp + ( + baseRunTime.timePath()/uniformDir, + runTime.timePath()/uniformDir + ); } } - Info<< endl; Info<< "End\n" << endl; diff --git a/applications/utilities/parallelProcessing/redistributePar/unmappedPassiveParticleCloud.H b/applications/utilities/parallelProcessing/redistributePar/unmappedPassiveParticleCloud.H new file mode 100644 index 0000000000000000000000000000000000000000..37049552d5b655b0c9ffe55af94d627021218adb --- /dev/null +++ b/applications/utilities/parallelProcessing/redistributePar/unmappedPassiveParticleCloud.H @@ -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 + +// ************************************************************************* // diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/options b/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/options index 7799242880217734105bd4f630e73042539721b0..f53b4b31ce588f8beead223cf99b01f392a097d9 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/options +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/options @@ -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 \ diff --git a/applications/utilities/postProcessing/dataConversion/foamToTecplot360/Make/options b/applications/utilities/postProcessing/dataConversion/foamToTecplot360/Make/options index 97a2251f7bb9bf8d90bb23bd4ddbccf3c74a04a9..e087302bf9f2d27c019d17cad93f71e21b224e0a 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToTecplot360/Make/options +++ b/applications/utilities/postProcessing/dataConversion/foamToTecplot360/Make/options @@ -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 diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/Make/options b/applications/utilities/postProcessing/dataConversion/foamToVTK/Make/options index 2b32e21ed08c9f90f72f311484face64c6685cd1..7cd106bdd0d99f452e963424fe7831a5ff48a88b 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/Make/options +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/Make/options @@ -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 diff --git a/applications/utilities/postProcessing/graphics/PV4Readers/PV4FoamReader/vtkPV4Foam/Make/options b/applications/utilities/postProcessing/graphics/PV4Readers/PV4FoamReader/vtkPV4Foam/Make/options index 1ed6a9e569fd731725492c1c08241866a3f40367..2ca47f135daa889e329dbc054ae3ea861fd62c71 100644 --- a/applications/utilities/postProcessing/graphics/PV4Readers/PV4FoamReader/vtkPV4Foam/Make/options +++ b/applications/utilities/postProcessing/graphics/PV4Readers/PV4FoamReader/vtkPV4Foam/Make/options @@ -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 \ diff --git a/applications/utilities/preProcessing/mapFieldsPar/mapFieldsPar.C b/applications/utilities/preProcessing/mapFieldsPar/mapFieldsPar.C index 1ef16c7d221b3b7b2de1d513525e51a6dc68c69b..9f16746adbb24684de64cf4765e851f0e3c20cac 100644 --- a/applications/utilities/preProcessing/mapFieldsPar/mapFieldsPar.C +++ b/applications/utilities/preProcessing/mapFieldsPar/mapFieldsPar.C @@ -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 diff --git a/bin/tools/CleanFunctions b/bin/tools/CleanFunctions index b5edc1979677e22a07efa3ad04a305c74a8a2480..3e67077db90e1c3ade03c564230855bfb1b60c10 100644 --- a/bin/tools/CleanFunctions +++ b/bin/tools/CleanFunctions @@ -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 diff --git a/bin/tools/RunFunctions b/bin/tools/RunFunctions index 5a254ea43b873dde82eb56b8ab4aa4cee90f2789..e635c521d78ff3591170e288f35fb39d778cdf2c 100644 --- a/bin/tools/RunFunctions +++ b/bin/tools/RunFunctions @@ -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 } diff --git a/bin/tools/foamLog.db b/bin/tools/foamLog.db index d2719eb203394d43d578dad46dc8212e54307ce1..08077630c89fbcc62a080e0d5779a30200c292b4 100644 --- a/bin/tools/foamLog.db +++ b/bin/tools/foamLog.db @@ -15,12 +15,18 @@ # #------------------------------------------------------------------------------ +#- Lines to ignore +Ignore/Solving for .* region / + #- String to recognize new iteration by (usually same as 'Time') Separator/^[ \t]*Time = /Time = #- Time value: Time/^[ \t]*Time = /Time = +#- DeltaT value: +deltaT/^[ \t]*deltaT = /deltaT = + #- Continuity errors: contLocal/time step continuity errors :/sum local = contGlobal/time step continuity errors :/ global = @@ -33,6 +39,10 @@ minFt/min\(ft\) = /min(ft) = #- Execution time: executionTime/ExecutionTime = /ExecutionTime = +#- Interface Courant no: +IntCourantMax/Interface Courant Number /max: +IntCourantMean/Interface Courant Number /mean: + #- Courant no: CourantMax/Courant Number /max: CourantMean/Courant Number /mean: @@ -48,8 +58,8 @@ epsMax/bounding epsilon,/max: epsAvg/bounding epsilon,/average: #- gamma bounding -alpha1Min/Min\(alpha1\) =/Min(alpha1) = -alpha1Max/Max\(alpha1\) =/Max(alpha1) = +alpha1Min/Min\(alpha1\) =/Min(alpha1) = +alpha1Max/Max\(alpha1\) =/Max(alpha1) = # AMI AMIMin/AMI: Patch source sum/average = diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files index 47c8dee78897a440b9f0bd9b9de5386199bd1da8..f6d3379ecfdf306ec8a5c38238279a79bdb5e1d1 100644 --- a/src/OpenFOAM/Make/files +++ b/src/OpenFOAM/Make/files @@ -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 diff --git a/src/OpenFOAM/containers/Lists/ListOps/ListOps.H b/src/OpenFOAM/containers/Lists/ListOps/ListOps.H index c322c7856faae1accc1c36db8790131b1eb3e5c5..cbaf373a44fa22bb47da862c4460d8a0424f3533 100644 --- a/src/OpenFOAM/containers/Lists/ListOps/ListOps.H +++ b/src/OpenFOAM/containers/Lists/ListOps/ListOps.H @@ -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. @@ -226,7 +226,7 @@ label findLower ( const ListType&, typename ListType::const_reference, - const label stary, + const label start, const BinaryOp& bop ); @@ -263,6 +263,15 @@ public: }; +//- Helper class for list to append unique elelements of y onto the end of x +template<class T> +class ListUniqueEqOp +{ +public: + void operator()(List<T>& x, const List<T>& y) const; +}; + + //- Reverse a list. First element becomes last element etc. template<class ListType> ListType reverseList(const ListType& list); diff --git a/src/OpenFOAM/containers/Lists/ListOps/ListOpsTemplates.C b/src/OpenFOAM/containers/Lists/ListOps/ListOpsTemplates.C index 29ea65055121aedf96dc1ac262601134c97e6953..7aabfd796454dba1801db3fe96988e1f87c15957 100644 --- a/src/OpenFOAM/containers/Lists/ListOps/ListOpsTemplates.C +++ b/src/OpenFOAM/containers/Lists/ListOps/ListOpsTemplates.C @@ -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. @@ -742,6 +742,29 @@ void Foam::ListAppendEqOp<T>::operator()(List<T>& x, const List<T>& y) const } +template<class T> +void Foam::ListUniqueEqOp<T>::operator()(List<T>& x, const List<T>& y) const +{ + if (y.size()) + { + if (x.size()) + { + forAll(y, i) + { + if (findIndex(x, y[i]) == -1) + { + x.append(y[i]); + } + } + } + else + { + x = y; + } + } +} + + template<class ListType> ListType Foam::reverseList(const ListType& list) { diff --git a/src/OpenFOAM/containers/Lists/UList/UListI.H b/src/OpenFOAM/containers/Lists/UList/UListI.H index 815c9aafcdb6cafd6a7dabc287a95fdb0d54784a..ba72bc8871301d03ff8c96984621874651fa6526 100644 --- a/src/OpenFOAM/containers/Lists/UList/UListI.H +++ b/src/OpenFOAM/containers/Lists/UList/UListI.H @@ -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. @@ -101,7 +101,7 @@ inline void Foam::UList<T>::checkIndex(const label i) const if (!size_) { FatalErrorIn("UList<T>::checkIndex(const label)") - << "attempt to access element from zero sized list" + << "attempt to access element " << i << " from zero sized list" << abort(FatalError); } else if (i<0 || i>=size_) diff --git a/src/OpenFOAM/containers/Lists/UPtrList/UPtrList.C b/src/OpenFOAM/containers/Lists/UPtrList/UPtrList.C index cc54117f8b9e3e3614a126bb64cf47afd7dc9cc9..0d1a2fe63f02b9a18781ef8f2392695c5becff5a 100644 --- a/src/OpenFOAM/containers/Lists/UPtrList/UPtrList.C +++ b/src/OpenFOAM/containers/Lists/UPtrList/UPtrList.C @@ -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. @@ -43,6 +43,30 @@ Foam::UPtrList<T>::UPtrList(const label s) {} +template<class T> +Foam::UPtrList<T>::UPtrList(UList<T>& lst) +: + ptrs_(lst.size()) +{ + forAll(lst, i) + { + ptrs_[i] = &lst[i]; + } +} + + +template<class T> +Foam::UPtrList<T>::UPtrList(PtrList<T>& lst) +: + ptrs_(lst.size()) +{ + forAll(lst, i) + { + ptrs_[i] = &lst[i]; + } +} + + template<class T> Foam::UPtrList<T>::UPtrList(const Xfer<UPtrList<T> >& lst) { diff --git a/src/OpenFOAM/containers/Lists/UPtrList/UPtrList.H b/src/OpenFOAM/containers/Lists/UPtrList/UPtrList.H index cdf32f630ae7b78210a4fa54398801843f8e49b2..4df5a8262732785fa0461eb733c55f29e3f03898 100644 --- a/src/OpenFOAM/containers/Lists/UPtrList/UPtrList.H +++ b/src/OpenFOAM/containers/Lists/UPtrList/UPtrList.H @@ -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. @@ -42,6 +42,7 @@ SourceFiles #define UPtrList_H #include "List.H" +#include "PtrList.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -109,6 +110,12 @@ public: //- Construct with size specified. explicit UPtrList(const label); + //- Construct from UList + explicit UPtrList(UList<T>&); + + //- Construct from PtrList + explicit UPtrList(PtrList<T>&); + //- Construct by transferring the parameter contents UPtrList(const Xfer<UPtrList<T> >&); diff --git a/src/OpenFOAM/db/IOobjects/CompactIOList/CompactIOList.C b/src/OpenFOAM/db/IOobjects/CompactIOList/CompactIOList.C index a7ada172d4f46ca4c3b4da382113428da0641aad..e723e6ad5e1f2aaba5f60a09658f7375dd7c1665 100644 --- a/src/OpenFOAM/db/IOobjects/CompactIOList/CompactIOList.C +++ b/src/OpenFOAM/db/IOobjects/CompactIOList/CompactIOList.C @@ -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. @@ -58,6 +58,23 @@ void Foam::CompactIOList<T, BaseType>::readFromStream() } +template<class T, class BaseType> +bool Foam::CompactIOList<T, BaseType>::overflows() const +{ + label size = 0; + forAll(*this, i) + { + label oldSize = size; + size += this->operator[](i).size(); + if (size < oldSize) + { + return true; + } + } + return false; +} + + // * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * // template<class T, class BaseType> @@ -178,6 +195,29 @@ bool Foam::CompactIOList<T, BaseType>::writeObject return good; } + else if (overflows()) + { + WarningIn + ( + "CompactIOList<T, BaseType>::writeObject" + "(IOstream::streamFormat, IOstream::versionNumber" + ", IOstream::compressionType) const" + ) << "Overall number of elements of CompactIOList of size " + << this->size() << " overflows the representation of a label" + << endl << " Switching to ascii writing" << endl; + + // Change type to be non-compact format type + const word oldTypeName = typeName; + + const_cast<word&>(typeName) = IOList<T>::typeName; + + bool good = regIOobject::writeObject(IOstream::ASCII, ver, cmp); + + // Change type back + const_cast<word&>(typeName) = oldTypeName; + + return good; + } else { return regIOobject::writeObject(fmt, ver, cmp); @@ -264,7 +304,22 @@ Foam::Ostream& Foam::operator<< start[0] = 0; for (label i = 1; i < start.size(); i++) { - start[i] = start[i-1]+L[i-1].size(); + label prev = start[i-1]; + start[i] = prev+L[i-1].size(); + + if (start[i] < prev) + { + FatalIOErrorIn + ( + "operator<<" + "(Ostream& os, const CompactIOList<T, BaseType>&)", + os + ) << "Overall number of elements " << start[i] + << " of CompactIOList of size " + << L.size() << " overflows the representation of a label" + << endl << "Please recompile with a larger representation" + << " for label" << exit(FatalIOError); + } } List<BaseType> elems(start[start.size()-1]); diff --git a/src/OpenFOAM/db/IOobjects/CompactIOList/CompactIOList.H b/src/OpenFOAM/db/IOobjects/CompactIOList/CompactIOList.H index dc06092c59758ed0a941f9cf8c6ee19a69d8eda7..fafcdef52f934554cd53a8650caf26092384fbe7 100644 --- a/src/OpenFOAM/db/IOobjects/CompactIOList/CompactIOList.H +++ b/src/OpenFOAM/db/IOobjects/CompactIOList/CompactIOList.H @@ -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. @@ -79,6 +79,9 @@ class CompactIOList //- Read according to header type void readFromStream(); + //- Has too many elements in it? + bool overflows() const; + public: //- Runtime type information diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.C b/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.C index a721eb2a05588544fbf5ff806783140751151dc2..e73b0bd4dc7511bc06fc3f16076061fbac676d4b 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.C +++ b/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.C @@ -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() = ""; + Perr.prefix() = ""; } + else + { + parRun_ = true; - Pout.prefix() = '[' + name(myProcNo(Pstream::worldComm)) + "] "; - Perr.prefix() = '[' + name(myProcNo(Pstream::worldComm)) + "] "; + // 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)) + "] "; + } } diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.H b/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.H index 09706b704d20bec76c0c722c0915c097cefa3943..a2a564839363f1f7ae20416f7c94618930887ab5 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.H +++ b/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.H @@ -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) { diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/combineGatherScatter.C b/src/OpenFOAM/db/IOstreams/Pstreams/combineGatherScatter.C index 48036e7c522a64084c08533fc81284125660be17..ca5a254cd38b8e1caaa5943cdf5ec54945d2886e 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/combineGatherScatter.C +++ b/src/OpenFOAM/db/IOstreams/Pstreams/combineGatherScatter.C @@ -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)]; diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/exchange.C b/src/OpenFOAM/db/IOstreams/Pstreams/exchange.C index ddc39244f6fc1a898c646b934e1dd67c7497dd0d..76430e91313a4dd5e461c35f6fe1ec786b8475f1 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/exchange.C +++ b/src/OpenFOAM/db/IOstreams/Pstreams/exchange.C @@ -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)]; diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/gatherScatter.C b/src/OpenFOAM/db/IOstreams/Pstreams/gatherScatter.C index 477dbe35f540b57b6bef16449b7cf0d9c3ba2ae4..25193551df567302b8082cb05520ec605382f1cc 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/gatherScatter.C +++ b/src/OpenFOAM/db/IOstreams/Pstreams/gatherScatter.C @@ -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)]; diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/gatherScatterList.C b/src/OpenFOAM/db/IOstreams/Pstreams/gatherScatterList.C index 3b3133b49516ccc00671046b42d8cbf236d16185..ce9aa77a1105ac303f0fa636b760af77c49f80a9 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/gatherScatterList.C +++ b/src/OpenFOAM/db/IOstreams/Pstreams/gatherScatterList.C @@ -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)) { diff --git a/src/OpenFOAM/db/IOstreams/Sstreams/ISstreamI.H b/src/OpenFOAM/db/IOstreams/Sstreams/ISstreamI.H index 6135f51f4693edb88d087db5ca1e0071136480de..2488bb04e340f003f19a4308bf9ccaac149a246b 100644 --- a/src/OpenFOAM/db/IOstreams/Sstreams/ISstreamI.H +++ b/src/OpenFOAM/db/IOstreams/Sstreams/ISstreamI.H @@ -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. @@ -59,7 +59,7 @@ inline Foam::ISstream& Foam::ISstream::get(char& c) is_.get(c); setState(is_.rdstate()); - if (c == '\n') + if (good() && c == '\n') { lineNumber_++; } diff --git a/src/OpenFOAM/db/Time/TimePaths.H b/src/OpenFOAM/db/Time/TimePaths.H index 0f5e1b11fd4384d07c4bc9865803e973bf0f11eb..708ab6b1668df20b299f46575700e2af247cfcdf 100644 --- a/src/OpenFOAM/db/Time/TimePaths.H +++ b/src/OpenFOAM/db/Time/TimePaths.H @@ -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 { diff --git a/src/OpenFOAM/db/dictionary/dictionary.C b/src/OpenFOAM/db/dictionary/dictionary.C index d8d791a21d649ae018e41bb6d3bd055a608de923..3ca3d5e21a6ddc728d729ef64df94ca4dc6c5f35 100644 --- a/src/OpenFOAM/db/dictionary/dictionary.C +++ b/src/OpenFOAM/db/dictionary/dictionary.C @@ -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. @@ -221,9 +221,7 @@ Foam::autoPtr<Foam::dictionary> Foam::dictionary::clone() const // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // Foam::dictionary::~dictionary() -{ - // cerr<< "~dictionary() " << name() << " " << long(this) << std::endl; -} +{} // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // @@ -238,7 +236,7 @@ const Foam::dictionary& Foam::dictionary::topDict() const } else { - return p; + return *this; } } diff --git a/src/OpenFOAM/db/dictionary/dictionary.H b/src/OpenFOAM/db/dictionary/dictionary.H index bbba527971e059c3456a4e491b09cfdb8e6ed226..b01f9dfb61f6a09bfdbe98ef586f2e64a263b89c 100644 --- a/src/OpenFOAM/db/dictionary/dictionary.H +++ b/src/OpenFOAM/db/dictionary/dictionary.H @@ -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 diff --git a/src/OpenFOAM/db/objectRegistry/objectRegistry.C b/src/OpenFOAM/db/objectRegistry/objectRegistry.C index 4903ca4e285148524d81c69fd9e8fe637a7ccc51..f2420e13d1efc3db1e8dbab9ad3f57249453a918 100644 --- a/src/OpenFOAM/db/objectRegistry/objectRegistry.C +++ b/src/OpenFOAM/db/objectRegistry/objectRegistry.C @@ -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. @@ -222,6 +222,7 @@ bool Foam::objectRegistry::checkIn(regIOobject& io) const { Pout<< "objectRegistry::checkIn(regIOobject&) : " << name() << " : checking in " << io.name() + << " of type " << io.type() << endl; } @@ -354,6 +355,7 @@ bool Foam::objectRegistry::writeObject Pout<< "objectRegistry::write() : " << name() << " : Considering writing object " << iter.key() + << " of type " << iter()->type() << " with writeOpt " << iter()->writeOpt() << " to file " << iter()->objectPath() << endl; diff --git a/src/OpenFOAM/db/regIOobject/regIOobjectRead.C b/src/OpenFOAM/db/regIOobject/regIOobjectRead.C index bc950e518f2f61f552c2c2d98e53cf4b85db3faf..6dde1b36ede0ae4c153bbe785d8709585cf0b78b 100644 --- a/src/OpenFOAM/db/regIOobject/regIOobjectRead.C +++ b/src/OpenFOAM/db/regIOobject/regIOobjectRead.C @@ -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(); diff --git a/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedField.C b/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedField.C index a33942e9b9d63b468cc1692ddcb1892d28190bd9..4692f030b6e683e888649a60a34bb6e09d6a2f3c 100644 --- a/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedField.C +++ b/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedField.C @@ -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); \ } diff --git a/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedField.H b/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedField.H index b3beb9577c09d6f6ef5868dbf197b99150eab3e7..6b86f17c4617a03e8db887093ca816f9449603f8 100644 --- a/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedField.H +++ b/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedField.H @@ -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 ( diff --git a/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedFieldIO.C b/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedFieldIO.C index be049a4be8a05656d97b6ba99cbe738f17b8734d..6ff8dd2c7f6c29df291d69c6462da5612087597f 100644 --- a/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedFieldIO.C +++ b/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedFieldIO.C @@ -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> diff --git a/src/OpenFOAM/fields/Fields/Field/Field.C b/src/OpenFOAM/fields/Fields/Field/Field.C index 48fcaacac07d101c4d4c4d4873a79c8b4f29d78a..7136eb0a75563fb2ddb7d23e53d96750ca0d27c1 100644 --- a/src/OpenFOAM/fields/Fields/Field/Field.C +++ b/src/OpenFOAM/fields/Fields/Field/Field.C @@ -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()); + } } } diff --git a/src/OpenFOAM/fields/Fields/Field/Field.H b/src/OpenFOAM/fields/Fields/Field/Field.H index f9c340f9bc6a2ce5d9f6e538574ba0c22027969c..8ea48c3f7d86573bb35ea452fdb7b49d262fbe82 100644 --- a/src/OpenFOAM/fields/Fields/Field/Field.H +++ b/src/OpenFOAM/fields/Fields/Field/Field.H @@ -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 diff --git a/src/OpenFOAM/fields/Fields/Field/FieldMapper.H b/src/OpenFOAM/fields/Fields/Field/FieldMapper.H index f463f97c5765188731a4c028d7a2e40a4ab6773f..31ecb13f092351f15f00e979c389045510928535 100644 --- a/src/OpenFOAM/fields/Fields/Field/FieldMapper.H +++ b/src/OpenFOAM/fields/Fields/Field/FieldMapper.H @@ -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; diff --git a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.C b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.C index d18f24e19fb6442c2ebaf5b9e666d77afac892d4..70ec726379f032c680351dce23d85e303e4faa93 100644 --- a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.C +++ b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.C @@ -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; } diff --git a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.H b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.H index 334bdc26701f0670ff0b03224523b7ba0672e283..18c5c37b2d1cb4164470379bc01bafed0021a402 100644 --- a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.H +++ b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.H @@ -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 diff --git a/src/OpenFOAM/fields/ReadFields/ReadFields.C b/src/OpenFOAM/fields/ReadFields/ReadFields.C index a679082b417626c95f1928af2cc1c84ee8dd3b78..40166046b633bc70ad767318e371f1b184f84321 100644 --- a/src/OpenFOAM/fields/ReadFields/ReadFields.C +++ b/src/OpenFOAM/fields/ReadFields/ReadFields.C @@ -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) - ) - ); -} - - // ************************************************************************* // diff --git a/src/OpenFOAM/fields/ReadFields/ReadFields.H b/src/OpenFOAM/fields/ReadFields/ReadFields.H index ac4bdb37c740e385ee3ad4b1a14ceadb0459ceca..c698988c079e86133ab05d5791aa4d285ee8e123 100644 --- a/src/OpenFOAM/fields/ReadFields/ReadFields.H +++ b/src/OpenFOAM/fields/ReadFields/ReadFields.H @@ -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 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/OpenFOAM/fields/ReadFields/ReadFieldsTemplates.C b/src/OpenFOAM/fields/ReadFields/ReadFieldsTemplates.C new file mode 100644 index 0000000000000000000000000000000000000000..e01ed92fb8896e41036c06942a4772cde64fe919 --- /dev/null +++ b/src/OpenFOAM/fields/ReadFields/ReadFieldsTemplates.C @@ -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) + ) + ); +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/fields/UniformDimensionedFields/UniformDimensionedField.C b/src/OpenFOAM/fields/UniformDimensionedFields/UniformDimensionedField.C index 1fd8eac973e94ae22b4f934edaea327f25dbfd47..98934aec31e08735a36cf10f57b459c6fd487dbc 100644 --- a/src/OpenFOAM/fields/UniformDimensionedFields/UniformDimensionedField.C +++ b/src/OpenFOAM/fields/UniformDimensionedFields/UniformDimensionedField.C @@ -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(); } diff --git a/src/OpenFOAM/fields/pointPatchFields/derived/uniformFixedValue/uniformFixedValuePointPatchField.H b/src/OpenFOAM/fields/pointPatchFields/derived/uniformFixedValue/uniformFixedValuePointPatchField.H index 120f1ffe169d9c12c4b2f030fd6e304e1dd7b384..a9f93d1d38d7d8fa8581cbdfb858bea2d469ecb7 100644 --- a/src/OpenFOAM/fields/pointPatchFields/derived/uniformFixedValue/uniformFixedValuePointPatchField.H +++ b/src/OpenFOAM/fields/pointPatchFields/derived/uniformFixedValue/uniformFixedValuePointPatchField.H @@ -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. @@ -149,7 +149,7 @@ public: // Access - //- Return the fluctuation scale + //- Return the uniform value const DataEntry<Type>& uniformValue() const { return uniformValue_; diff --git a/src/OpenFOAM/global/argList/argList.C b/src/OpenFOAM/global/argList/argList.C index 973bc87648ee9801ba3f8fa64f88cbafb2341bff..ea72b7083e07d41be943a8877b7125e994517e7f 100644 --- a/src/OpenFOAM/global/argList/argList.C +++ b/src/OpenFOAM/global/argList/argList.C @@ -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(); } } diff --git a/src/OpenFOAM/meshes/meshTools/matchPoints.C b/src/OpenFOAM/meshes/meshTools/matchPoints.C index d309e8e501f8c4bed7696984bcebb42997e82a02..0afa4e3ae6982ec4fa1e8b796834679df53b6b6e 100644 --- a/src/OpenFOAM/meshes/meshTools/matchPoints.C +++ b/src/OpenFOAM/meshes/meshTools/matchPoints.C @@ -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. @@ -187,9 +187,11 @@ bool Foam::matchPoints // Go through range of equal mag and find nearest vector. scalar minDistSqr = VGREAT; - scalar minDistNorm = 0; label minFaceI = -1; + // Valid candidate points should have opposite normal + const scalar minDistNorm = 0; + for ( label j = startI; @@ -220,7 +222,6 @@ bool Foam::matchPoints // Check that the normals point in equal and opposite directions if (distNorm < minDistNorm) { - minDistNorm = distNorm; minDistSqr = distSqr; minFaceI = faceI; } diff --git a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/IOmapDistribute.C b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/IOmapDistribute.C index bb057b63f41104208856574a7783f86b6832f8ca..a7f6841484df54d95b15477ba5a9f7e8199ffb3f 100644 --- a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/IOmapDistribute.C +++ b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/IOmapDistribute.C @@ -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&)") diff --git a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistribute.C b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistribute.C index 8feeefcffe22a7d81d3d50d0233cf1a9fb5feb63..a87a798c03c541b7bfba87680cef1288d622323c 100644 --- a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistribute.C +++ b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistribute.C @@ -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. @@ -24,12 +24,8 @@ License \*---------------------------------------------------------------------------*/ #include "mapDistribute.H" -#include "commSchedule.H" -#include "HashSet.H" -#include "globalIndex.H" #include "globalIndexAndTransform.H" #include "transformField.H" -#include "ListOps.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -134,229 +130,10 @@ void Foam::mapDistribute::transform::operator() {} -Foam::List<Foam::labelPair> Foam::mapDistribute::schedule -( - const labelListList& subMap, - const labelListList& constructMap, - const int tag -) -{ - // Communications: send and receive processor - List<labelPair> allComms; - - { - HashSet<labelPair, labelPair::Hash<> > commsSet(Pstream::nProcs()); - - // Find what communication is required - forAll(subMap, procI) - { - if (procI != Pstream::myProcNo()) - { - if (subMap[procI].size()) - { - // I need to send to procI - commsSet.insert(labelPair(Pstream::myProcNo(), procI)); - } - if (constructMap[procI].size()) - { - // I need to receive from procI - commsSet.insert(labelPair(procI, Pstream::myProcNo())); - } - } - } - allComms = commsSet.toc(); - } - - - // Reduce - if (Pstream::master()) - { - // Receive and merge - for - ( - int slave=Pstream::firstSlave(); - slave<=Pstream::lastSlave(); - slave++ - ) - { - IPstream fromSlave(Pstream::scheduled, slave, 0, tag); - List<labelPair> nbrData(fromSlave); - - forAll(nbrData, i) - { - if (findIndex(allComms, nbrData[i]) == -1) - { - label sz = allComms.size(); - allComms.setSize(sz+1); - allComms[sz] = nbrData[i]; - } - } - } - // Send back - for - ( - int slave=Pstream::firstSlave(); - slave<=Pstream::lastSlave(); - slave++ - ) - { - OPstream toSlave(Pstream::scheduled, slave, 0, tag); - toSlave << allComms; - } - } - else - { - { - OPstream toMaster(Pstream::scheduled, Pstream::masterNo(), 0, tag); - toMaster << allComms; - } - { - IPstream fromMaster - ( - Pstream::scheduled, - Pstream::masterNo(), - 0, - tag - ); - fromMaster >> allComms; - } - } - - - // Determine my schedule. - labelList mySchedule - ( - commSchedule - ( - Pstream::nProcs(), - allComms - ).procSchedule()[Pstream::myProcNo()] - ); - - // Processors involved in my schedule - return List<labelPair>(UIndirectList<labelPair>(allComms, mySchedule)); - - - //if (debug) - //{ - // Pout<< "I need to:" << endl; - // const List<labelPair>& comms = schedule(); - // forAll(comms, i) - // { - // const labelPair& twoProcs = comms[i]; - // label sendProc = twoProcs[0]; - // label recvProc = twoProcs[1]; - // - // if (recvProc == Pstream::myProcNo()) - // { - // Pout<< " receive from " << sendProc << endl; - // } - // else - // { - // Pout<< " send to " << recvProc << endl; - // } - // } - //} -} - - -const Foam::List<Foam::labelPair>& Foam::mapDistribute::schedule() const -{ - if (schedulePtr_.empty()) - { - schedulePtr_.reset - ( - new List<labelPair> - ( - schedule(subMap_, constructMap_, Pstream::msgType()) - ) - ); - } - return schedulePtr_(); -} - - -void Foam::mapDistribute::checkReceivedSize -( - const label procI, - const label expectedSize, - const label receivedSize -) -{ - if (receivedSize != expectedSize) - { - FatalErrorIn - ( - "template<class T>\n" - "void mapDistribute::distribute\n" - "(\n" - " const Pstream::commsTypes commsType,\n" - " const List<labelPair>& schedule,\n" - " const label constructSize,\n" - " const labelListList& subMap,\n" - " const labelListList& constructMap,\n" - " List<T>& field\n" - ")\n" - ) << "Expected from processor " << procI - << " " << expectedSize << " but received " - << receivedSize << " elements." - << abort(FatalError); - } -} - - void Foam::mapDistribute::printLayout(Ostream& os) const { - // Determine offsets of remote data. - labelList minIndex(Pstream::nProcs(), labelMax); - labelList maxIndex(Pstream::nProcs(), labelMin); - forAll(constructMap_, procI) - { - const labelList& construct = constructMap_[procI]; - minIndex[procI] = min(minIndex[procI], min(construct)); - maxIndex[procI] = max(maxIndex[procI], max(construct)); - } - - label localSize; - if (maxIndex[Pstream::myProcNo()] == labelMin) - { - localSize = 0; - } - else - { - localSize = maxIndex[Pstream::myProcNo()]+1; - } + mapDistributeBase::printLayout(os); - os << "Layout: (constructSize:" << constructSize_ << ")" << endl - << "local (processor " << Pstream::myProcNo() << "):" << endl - << " start : 0" << endl - << " size : " << localSize << endl; - - label offset = localSize; - forAll(minIndex, procI) - { - if (procI != Pstream::myProcNo()) - { - if (constructMap_[procI].size() > 0) - { - if (minIndex[procI] != offset) - { - FatalErrorIn("mapDistribute::printLayout(..)") - << "offset:" << offset - << " procI:" << procI - << " minIndex:" << minIndex[procI] - << abort(FatalError); - } - - label size = maxIndex[procI]-minIndex[procI]+1; - os << "processor " << procI << ':' << endl - << " start : " << offset << endl - << " size : " << size << endl; - - offset += size; - } - } - } forAll(transformElements_, trafoI) { if (transformElements_[trafoI].size() > 0) @@ -369,289 +146,12 @@ void Foam::mapDistribute::printLayout(Ostream& os) const } -// Construct per processor compact addressing of the global elements -// needed. The ones from the local processor are not included since -// these are always all needed. -void Foam::mapDistribute::calcCompactAddressing -( - const globalIndex& globalNumbering, - const labelList& elements, - List<Map<label> >& compactMap -) const -{ - compactMap.setSize(Pstream::nProcs()); - - // Count all (non-local) elements needed. Just for presizing map. - labelList nNonLocal(Pstream::nProcs(), 0); - - forAll(elements, i) - { - label globalIndex = elements[i]; - - if (globalIndex != -1 && !globalNumbering.isLocal(globalIndex)) - { - label procI = globalNumbering.whichProcID(globalIndex); - nNonLocal[procI]++; - } - } - - forAll(compactMap, procI) - { - compactMap[procI].clear(); - if (procI != Pstream::myProcNo()) - { - compactMap[procI].resize(2*nNonLocal[procI]); - } - } - - - // Collect all (non-local) elements needed. - forAll(elements, i) - { - label globalIndex = elements[i]; - - if (globalIndex != -1 && !globalNumbering.isLocal(globalIndex)) - { - label procI = globalNumbering.whichProcID(globalIndex); - label index = globalNumbering.toLocal(procI, globalIndex); - label nCompact = compactMap[procI].size(); - compactMap[procI].insert(index, nCompact); - } - } -} - - -void Foam::mapDistribute::calcCompactAddressing -( - const globalIndex& globalNumbering, - const labelListList& cellCells, - List<Map<label> >& compactMap -) const -{ - compactMap.setSize(Pstream::nProcs()); - - // Count all (non-local) elements needed. Just for presizing map. - labelList nNonLocal(Pstream::nProcs(), 0); - - forAll(cellCells, cellI) - { - const labelList& cCells = cellCells[cellI]; - - forAll(cCells, i) - { - label globalIndex = cCells[i]; - - if (globalIndex != -1 && !globalNumbering.isLocal(globalIndex)) - { - label procI = globalNumbering.whichProcID(globalIndex); - nNonLocal[procI]++; - } - } - } - - forAll(compactMap, procI) - { - compactMap[procI].clear(); - if (procI != Pstream::myProcNo()) - { - compactMap[procI].resize(2*nNonLocal[procI]); - } - } - - - // Collect all (non-local) elements needed. - forAll(cellCells, cellI) - { - const labelList& cCells = cellCells[cellI]; - - forAll(cCells, i) - { - label globalIndex = cCells[i]; - - if (globalIndex != -1 && !globalNumbering.isLocal(globalIndex)) - { - label procI = globalNumbering.whichProcID(globalIndex); - label index = globalNumbering.toLocal(procI, globalIndex); - label nCompact = compactMap[procI].size(); - compactMap[procI].insert(index, nCompact); - } - } - } -} - - -void Foam::mapDistribute::exchangeAddressing -( - const int tag, - const globalIndex& globalNumbering, - labelList& elements, - List<Map<label> >& compactMap, - labelList& compactStart -) -{ - // The overall compact addressing is - // - myProcNo data first (uncompacted) - // - all other processors consecutively - - compactStart.setSize(Pstream::nProcs()); - compactStart[Pstream::myProcNo()] = 0; - constructSize_ = globalNumbering.localSize(); - forAll(compactStart, procI) - { - if (procI != Pstream::myProcNo()) - { - compactStart[procI] = constructSize_; - constructSize_ += compactMap[procI].size(); - } - } - - - - // Find out what to receive/send in compact addressing. - - // What I want to receive is what others have to send - labelListList wantedRemoteElements(Pstream::nProcs()); - // Compact addressing for received data - constructMap_.setSize(Pstream::nProcs()); - forAll(compactMap, procI) - { - if (procI == Pstream::myProcNo()) - { - // All my own elements are used - label nLocal = globalNumbering.localSize(); - wantedRemoteElements[procI] = identity(nLocal); - constructMap_[procI] = identity(nLocal); - } - else - { - // Remote elements wanted from processor procI - labelList& remoteElem = wantedRemoteElements[procI]; - labelList& localElem = constructMap_[procI]; - remoteElem.setSize(compactMap[procI].size()); - localElem.setSize(compactMap[procI].size()); - label i = 0; - forAllIter(Map<label>, compactMap[procI], iter) - { - const label compactI = compactStart[procI] + iter(); - remoteElem[i] = iter.key(); - localElem[i] = compactI; - iter() = compactI; - i++; - } - } - } - - subMap_.setSize(Pstream::nProcs()); - labelListList sendSizes; - Pstream::exchange<labelList, label> - ( - wantedRemoteElements, - subMap_, - sendSizes, - tag, - Pstream::worldComm //TBD - ); - - // Renumber elements - forAll(elements, i) - { - elements[i] = renumber(globalNumbering, compactMap, elements[i]); - } -} - - -void Foam::mapDistribute::exchangeAddressing -( - const int tag, - const globalIndex& globalNumbering, - labelListList& cellCells, - List<Map<label> >& compactMap, - labelList& compactStart -) -{ - // The overall compact addressing is - // - myProcNo data first (uncompacted) - // - all other processors consecutively - - compactStart.setSize(Pstream::nProcs()); - compactStart[Pstream::myProcNo()] = 0; - constructSize_ = globalNumbering.localSize(); - forAll(compactStart, procI) - { - if (procI != Pstream::myProcNo()) - { - compactStart[procI] = constructSize_; - constructSize_ += compactMap[procI].size(); - } - } - - - - // Find out what to receive/send in compact addressing. - - // What I want to receive is what others have to send - labelListList wantedRemoteElements(Pstream::nProcs()); - // Compact addressing for received data - constructMap_.setSize(Pstream::nProcs()); - forAll(compactMap, procI) - { - if (procI == Pstream::myProcNo()) - { - // All my own elements are used - label nLocal = globalNumbering.localSize(); - wantedRemoteElements[procI] = identity(nLocal); - constructMap_[procI] = identity(nLocal); - } - else - { - // Remote elements wanted from processor procI - labelList& remoteElem = wantedRemoteElements[procI]; - labelList& localElem = constructMap_[procI]; - remoteElem.setSize(compactMap[procI].size()); - localElem.setSize(compactMap[procI].size()); - label i = 0; - forAllIter(Map<label>, compactMap[procI], iter) - { - const label compactI = compactStart[procI] + iter(); - remoteElem[i] = iter.key(); - localElem[i] = compactI; - iter() = compactI; - i++; - } - } - } - - subMap_.setSize(Pstream::nProcs()); - labelListList sendSizes; - Pstream::exchange<labelList, label> - ( - wantedRemoteElements, - subMap_, - sendSizes, - tag, - Pstream::worldComm //TBD - ); - - // Renumber elements - forAll(cellCells, cellI) - { - labelList& cCells = cellCells[cellI]; - - forAll(cCells, i) - { - cCells[i] = renumber(globalNumbering, compactMap, cCells[i]); - } - } -} - - // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // //- Construct null Foam::mapDistribute::mapDistribute() : - constructSize_(0), - schedulePtr_() + mapDistributeBase() {} @@ -660,13 +160,19 @@ Foam::mapDistribute::mapDistribute ( const label constructSize, const Xfer<labelListList>& subMap, - const Xfer<labelListList>& constructMap + const Xfer<labelListList>& constructMap, + const bool subHasFlip, + const bool constructHasFlip ) : - constructSize_(constructSize), - subMap_(subMap), - constructMap_(constructMap), - schedulePtr_() + mapDistributeBase + ( + constructSize, + subMap, + constructMap, + subHasFlip, + constructHasFlip + ) {} @@ -677,15 +183,21 @@ Foam::mapDistribute::mapDistribute const Xfer<labelListList>& subMap, const Xfer<labelListList>& constructMap, const Xfer<labelListList>& transformElements, - const Xfer<labelList>& transformStart + const Xfer<labelList>& transformStart, + const bool subHasFlip, + const bool constructHasFlip ) : - constructSize_(constructSize), - subMap_(subMap), - constructMap_(constructMap), + mapDistributeBase + ( + constructSize, + subMap, + constructMap, + subHasFlip, + constructHasFlip + ), transformElements_(transformElements), - transformStart_(transformStart), - schedulePtr_() + transformStart_(transformStart) {} @@ -695,72 +207,8 @@ Foam::mapDistribute::mapDistribute const labelList& recvProcs ) : - constructSize_(0), - schedulePtr_() -{ - if (sendProcs.size() != recvProcs.size()) - { - FatalErrorIn - ( - "mapDistribute::mapDistribute(const labelList&, const labelList&)" - ) << "The send and receive data is not the same length. sendProcs:" - << sendProcs.size() << " recvProcs:" << recvProcs.size() - << abort(FatalError); - } - - // Per processor the number of samples we have to send/receive. - labelList nSend(Pstream::nProcs(), 0); - labelList nRecv(Pstream::nProcs(), 0); - - forAll(sendProcs, sampleI) - { - label sendProc = sendProcs[sampleI]; - label recvProc = recvProcs[sampleI]; - - // Note that also need to include local communication (both - // RecvProc and sendProc on local processor) - - if (Pstream::myProcNo() == sendProc) - { - // I am the sender. Count destination processor. - nSend[recvProc]++; - } - if (Pstream::myProcNo() == recvProc) - { - // I am the receiver. - nRecv[sendProc]++; - } - } - - subMap_.setSize(Pstream::nProcs()); - constructMap_.setSize(Pstream::nProcs()); - forAll(nSend, procI) - { - subMap_[procI].setSize(nSend[procI]); - constructMap_[procI].setSize(nRecv[procI]); - } - nSend = 0; - nRecv = 0; - - forAll(sendProcs, sampleI) - { - label sendProc = sendProcs[sampleI]; - label recvProc = recvProcs[sampleI]; - - if (Pstream::myProcNo() == sendProc) - { - // I am the sender. Store index I need to send. - subMap_[recvProc][nSend[recvProc]++] = sampleI; - } - if (Pstream::myProcNo() == recvProc) - { - // I am the receiver. - constructMap_[sendProc][nRecv[sendProc]++] = sampleI; - // Largest entry inside constructMap - constructSize_ = sampleI+1; - } - } -} + mapDistributeBase(sendProcs, recvProcs) +{} Foam::mapDistribute::mapDistribute @@ -771,54 +219,14 @@ Foam::mapDistribute::mapDistribute const int tag ) : - constructSize_(0), - schedulePtr_() -{ - // Construct per processor compact addressing of the global elements - // needed. The ones from the local processor are not included since - // these are always all needed. - calcCompactAddressing - ( - globalNumbering, - elements, - compactMap - ); - - //// Sort remote elements needed (not really necessary) - //forAll(compactMap, procI) - //{ - // if (procI != Pstream::myProcNo()) - // { - // Map<label>& globalMap = compactMap[procI]; - // - // SortableList<label> sorted(globalMap.toc().xfer()); - // - // forAll(sorted, i) - // { - // Map<label>::iterator iter = globalMap.find(sorted[i]); - // iter() = i; - // } - // } - //} - - - // Exchange what I need with processor that supplies it. Renumber elements - // into compact numbering - labelList compactStart; - exchangeAddressing + mapDistributeBase ( - tag, globalNumbering, elements, compactMap, - compactStart - ); - - if (debug) - { - printLayout(Pout); - } -} + tag + ) +{} Foam::mapDistribute::mapDistribute @@ -829,54 +237,14 @@ Foam::mapDistribute::mapDistribute const int tag ) : - constructSize_(0), - schedulePtr_() -{ - // Construct per processor compact addressing of the global elements - // needed. The ones from the local processor are not included since - // these are always all needed. - calcCompactAddressing - ( - globalNumbering, - cellCells, - compactMap - ); - - //// Sort remote elements needed (not really necessary) - //forAll(compactMap, procI) - //{ - // if (procI != Pstream::myProcNo()) - // { - // Map<label>& globalMap = compactMap[procI]; - // - // SortableList<label> sorted(globalMap.toc().xfer()); - // - // forAll(sorted, i) - // { - // Map<label>::iterator iter = globalMap.find(sorted[i]); - // iter() = i; - // } - // } - //} - - - // Exchange what I need with processor that supplies it. Renumber elements - // into compact numbering - labelList compactStart; - exchangeAddressing + mapDistributeBase ( - tag, globalNumbering, cellCells, compactMap, - compactStart - ); - - if (debug) - { - printLayout(Pout); - } -} + tag + ) +{} Foam::mapDistribute::mapDistribute @@ -890,8 +258,7 @@ Foam::mapDistribute::mapDistribute const int tag ) : - constructSize_(0), - schedulePtr_() + mapDistributeBase() { // Construct per processor compact addressing of the global elements // needed. The ones from the local processor are not included since @@ -996,8 +363,7 @@ Foam::mapDistribute::mapDistribute const int tag ) : - constructSize_(0), - schedulePtr_() + mapDistributeBase() { // Construct per processor compact addressing of the global elements // needed. The ones from the local processor are not included since @@ -1104,218 +470,67 @@ Foam::mapDistribute::mapDistribute } -Foam::mapDistribute::mapDistribute(const mapDistribute& map) +Foam::mapDistribute::mapDistribute +( + const mapDistribute& map +) : - constructSize_(map.constructSize_), - subMap_(map.subMap_), - constructMap_(map.constructMap_), + mapDistributeBase(map), transformElements_(map.transformElements_), - transformStart_(map.transformStart_), - schedulePtr_() + transformStart_(map.transformStart_) {} -Foam::mapDistribute::mapDistribute(const Xfer<mapDistribute>& map) +Foam::mapDistribute::mapDistribute +( + const Xfer<mapDistribute>& map +) : - constructSize_(map().constructSize_), - subMap_(map().subMap_.xfer()), - constructMap_(map().constructMap_.xfer()), + mapDistributeBase + ( + map().constructSize_, + map().subMap_.xfer(), + map().constructMap_.xfer(), + map().subHasFlip(), + map().constructHasFlip() + ), transformElements_(map().transformElements_.xfer()), - transformStart_(map().transformStart_.xfer()), - schedulePtr_() + transformStart_(map().transformStart_.xfer()) {} -// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // - -Foam::label Foam::mapDistribute::whichTransform(const label index) const +Foam::mapDistribute::mapDistribute(Istream& is) { - return findLower(transformStart_, index+1); + is >> *this; } -void Foam::mapDistribute::transfer(mapDistribute& rhs) +Foam::autoPtr<Foam::mapDistribute> Foam::mapDistribute::clone() const { - constructSize_ = rhs.constructSize_; - subMap_.transfer(rhs.subMap_); - constructMap_.transfer(rhs.constructMap_); - transformElements_.transfer(rhs.transformElements_); - transformStart_.transfer(rhs.transformStart_); - schedulePtr_.clear(); + return autoPtr<mapDistribute>(new mapDistribute(*this)); } -Foam::Xfer<Foam::mapDistribute> Foam::mapDistribute::xfer() +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +Foam::label Foam::mapDistribute::whichTransform(const label index) +const { - return xferMove(*this); + return findLower(transformStart_, index+1); } -Foam::label Foam::mapDistribute::renumber -( - const globalIndex& globalNumbering, - const List<Map<label> >& compactMap, - const label globalI -) +void Foam::mapDistribute::transfer(mapDistribute& rhs) { - if (globalI == -1) - { - return globalI; - } - if (globalNumbering.isLocal(globalI)) - { - return globalNumbering.toLocal(globalI); - } - else - { - label procI = globalNumbering.whichProcID(globalI); - label index = globalNumbering.toLocal(procI, globalI); - return compactMap[procI][index]; - } + mapDistributeBase::transfer(rhs); + transformElements_.transfer(rhs.transformElements_); + transformStart_.transfer(rhs.transformStart_); } -void Foam::mapDistribute::compact(const boolList& elemIsUsed, const int tag) +Foam::Xfer<Foam::mapDistribute> Foam::mapDistribute::xfer() { - // 1. send back to sender. Have sender delete the corresponding element - // from the submap and do the same to the constructMap locally - // (and in same order). - - // Send elemIsUsed field to neighbour. Use nonblocking code from - // mapDistribute but in reverse order. - if (Pstream::parRun()) - { - label startOfRequests = Pstream::nRequests(); - - // Set up receives from neighbours - - List<boolList> recvFields(Pstream::nProcs()); - - for (label domain = 0; domain < Pstream::nProcs(); domain++) - { - const labelList& map = subMap_[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].size()*sizeof(bool), - tag - ); - } - } - - - List<boolList> sendFields(Pstream::nProcs()); - - for (label domain = 0; domain < Pstream::nProcs(); domain++) - { - const labelList& map = constructMap_[domain]; - - if (domain != Pstream::myProcNo() && map.size()) - { - boolList& subField = sendFields[domain]; - subField.setSize(map.size()); - forAll(map, i) - { - subField[i] = elemIsUsed[map[i]]; - } - - OPstream::write - ( - Pstream::nonBlocking, - domain, - reinterpret_cast<const char*>(subField.begin()), - subField.size()*sizeof(bool), - tag - ); - } - } - - - - // Set up 'send' to myself - write directly into recvFields - - { - const labelList& map = constructMap_[Pstream::myProcNo()]; - - recvFields[Pstream::myProcNo()].setSize(map.size()); - forAll(map, i) - { - recvFields[Pstream::myProcNo()][i] = elemIsUsed[map[i]]; - } - } - - - // Wait for all to finish - - Pstream::waitRequests(startOfRequests); - - - // Compact out all submap entries that are referring to unused elements - for (label domain = 0; domain < Pstream::nProcs(); domain++) - { - const labelList& map = subMap_[domain]; - - labelList newMap(map.size()); - label newI = 0; - - forAll(map, i) - { - if (recvFields[domain][i]) - { - // So element is used on destination side - newMap[newI++] = map[i]; - } - } - if (newI < map.size()) - { - newMap.setSize(newI); - subMap_[domain].transfer(newMap); - } - } - } - - - // 2. remove from construct map - since end-result (element in elemIsUsed) - // not used. - - label maxConstructIndex = -1; - - for (label domain = 0; domain < Pstream::nProcs(); domain++) - { - const labelList& map = constructMap_[domain]; - - labelList newMap(map.size()); - label newI = 0; - - forAll(map, i) - { - label destinationI = map[i]; - - // Is element is used on destination side - if (elemIsUsed[destinationI]) - { - maxConstructIndex = max(maxConstructIndex, destinationI); - - newMap[newI++] = destinationI; - } - } - if (newI < map.size()) - { - newMap.setSize(newI); - constructMap_[domain].transfer(newMap); - } - } - - constructSize_ = maxConstructIndex+1; - - // Clear the schedule (note:not necessary if nothing changed) - schedulePtr_.clear(); + return xferMove(*this); } @@ -1328,16 +543,14 @@ void Foam::mapDistribute::operator=(const mapDistribute& rhs) { FatalErrorIn ( - "Foam::mapDistribute::operator=(const Foam::mapDistribute&)" + "Foam::mapDistribute::operator=" + "(const Foam::mapDistribute&)" ) << "Attempted assignment to self" << abort(FatalError); } - constructSize_ = rhs.constructSize_; - subMap_ = rhs.subMap_; - constructMap_ = rhs.constructMap_; + mapDistributeBase::operator=(rhs); transformElements_ = rhs.transformElements_; transformStart_ = rhs.transformStart_; - schedulePtr_.clear(); } @@ -1347,7 +560,7 @@ Foam::Istream& Foam::operator>>(Istream& is, mapDistribute& map) { is.fatalCheck("operator>>(Istream&, mapDistribute&)"); - is >> map.constructSize_ >> map.subMap_ >> map.constructMap_ + is >> static_cast<mapDistributeBase&>(map) >> map.transformElements_ >> map.transformStart_; return is; @@ -1358,11 +571,9 @@ Foam::Istream& Foam::operator>>(Istream& is, mapDistribute& map) Foam::Ostream& Foam::operator<<(Ostream& os, const mapDistribute& map) { - os << map.constructSize_ << token::NL - << map.subMap_ << token::NL - << map.constructMap_ << token::NL + os << static_cast<const mapDistributeBase&>(map) << token::NL << map.transformElements_ << token::NL - << map.transformStart_ << token::NL; + << map.transformStart_; return os; } diff --git a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistribute.H b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistribute.H index 94953027260fcf1a7c9f9d5523c63682bf9737ed..139a36a11f9fad4c6d57d9bea7de88b14c82d661 100644 --- a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistribute.H +++ b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistribute.H @@ -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_; - - //- 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_; - + //- For every globalIndexAndTransform::transformPermutations + // gives the elements that need to be transformed + labelListList transformElements_; - //- 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,46 +403,21 @@ public: //- Construct copy mapDistribute(const mapDistribute&); + //- Construct from Istream + mapDistribute(Istream&); - // Member Functions + //- Clone + autoPtr<mapDistribute> clone() const; - // 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_; - } + //- Destructor + virtual ~mapDistribute() + {} - //- From subsetted data back to original data - labelListList& subMap() - { - return subMap_; - } - //- From subsetted data to new reconstructed data - const labelListList& constructMap() const - { - return constructMap_; - } + // Member Functions - //- From subsetted data to new reconstructed data - labelListList& constructMap() - { - return constructMap_; - } + // Access //- For every globalIndexAndTransform::transformPermutations // gives the elements that need to be transformed @@ -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,59 +444,22 @@ 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 - ( - const Pstream::commsTypes commsType, - const List<labelPair>& schedule, - const label constructSize, - const labelListList& subMap, - const labelListList& constructMap, - List<T>&, - const int tag = UPstream::msgType() - ); - - //- Distribute data. If multiple processors writing to same - // position adds contributions using cop. - template<class T, class CombineOp> - static void distribute + 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 bool dummyTransform = true, const int tag = UPstream::msgType() - ); + ) const; //- Distribute data using default commsType. - template<class T> + template<class T, class negateOp> void distribute ( - DynamicList<T>& fld, + List<T>& fld, + const negateOp& negOp, const bool dummyTransform = true, const int tag = UPstream::msgType() ) const; @@ -591,56 +468,56 @@ public: template<class T> void distribute ( - List<T>& fld, + DynamicList<T>& fld, const bool dummyTransform = true, const int tag = UPstream::msgType() ) const; - //- Same but with transforms - template<class T, class TransformOp> - void distribute + //- Reverse distribute data using default commsType. + template<class T> + void reverseDistribute ( - const globalIndexAndTransform&, - List<T>& fld, - const TransformOp& top, + const label constructSize, + List<T>&, + const bool dummyTransform = true, 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, - List<T>&, + const T& nullValue, + List<T>& fld, const bool dummyTransform = true, const int tag = UPstream::msgType() ) const; - //- Same but with transforms + //- Distribute with transforms template<class T, class TransformOp> - void reverseDistribute + void distribute ( 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 - template<class T> + //- Reverse distribute with transforms + template<class T, class TransformOp> void reverseDistribute ( + const globalIndexAndTransform&, const label constructSize, - const T& nullValue, List<T>& fld, - const bool dummyTransform = true, + const TransformOp& top, const int tag = UPstream::msgType() ) const; - //- Same but with transforms + //- 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() ( diff --git a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBase.C b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBase.C new file mode 100644 index 0000000000000000000000000000000000000000..6ac881c880c21f380841192106dd07f082fa8645 --- /dev/null +++ b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBase.C @@ -0,0 +1,1293 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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 "mapDistributeBase.H" +#include "commSchedule.H" +#include "HashSet.H" +#include "globalIndex.H" +#include "ListOps.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +defineTypeNameAndDebug(mapDistributeBase, 0); +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +Foam::List<Foam::labelPair> Foam::mapDistributeBase::schedule +( + const labelListList& subMap, + const labelListList& constructMap, + const int tag +) +{ + // Communications: send and receive processor + List<labelPair> allComms; + + { + HashSet<labelPair, labelPair::Hash<> > commsSet(Pstream::nProcs()); + + // Find what communication is required + forAll(subMap, procI) + { + if (procI != Pstream::myProcNo()) + { + if (subMap[procI].size()) + { + // I need to send to procI + commsSet.insert(labelPair(Pstream::myProcNo(), procI)); + } + if (constructMap[procI].size()) + { + // I need to receive from procI + commsSet.insert(labelPair(procI, Pstream::myProcNo())); + } + } + } + allComms = commsSet.toc(); + } + + + // Reduce + if (Pstream::master()) + { + // Receive and merge + for + ( + int slave=Pstream::firstSlave(); + slave<=Pstream::lastSlave(); + slave++ + ) + { + IPstream fromSlave(Pstream::scheduled, slave, 0, tag); + List<labelPair> nbrData(fromSlave); + + forAll(nbrData, i) + { + if (findIndex(allComms, nbrData[i]) == -1) + { + label sz = allComms.size(); + allComms.setSize(sz+1); + allComms[sz] = nbrData[i]; + } + } + } + // Send back + for + ( + int slave=Pstream::firstSlave(); + slave<=Pstream::lastSlave(); + slave++ + ) + { + OPstream toSlave(Pstream::scheduled, slave, 0, tag); + toSlave << allComms; + } + } + else + { + { + OPstream toMaster(Pstream::scheduled, Pstream::masterNo(), 0, tag); + toMaster << allComms; + } + { + IPstream fromMaster + ( + Pstream::scheduled, + Pstream::masterNo(), + 0, + tag + ); + fromMaster >> allComms; + } + } + + + // Determine my schedule. + labelList mySchedule + ( + commSchedule + ( + Pstream::nProcs(), + allComms + ).procSchedule()[Pstream::myProcNo()] + ); + + // Processors involved in my schedule + return List<labelPair>(UIndirectList<labelPair>(allComms, mySchedule)); + + + //if (debug) + //{ + // Pout<< "I need to:" << endl; + // const List<labelPair>& comms = schedule(); + // forAll(comms, i) + // { + // const labelPair& twoProcs = comms[i]; + // label sendProc = twoProcs[0]; + // label recvProc = twoProcs[1]; + // + // if (recvProc == Pstream::myProcNo()) + // { + // Pout<< " receive from " << sendProc << endl; + // } + // else + // { + // Pout<< " send to " << recvProc << endl; + // } + // } + //} +} + + +const Foam::List<Foam::labelPair>& Foam::mapDistributeBase::schedule() const +{ + if (schedulePtr_.empty()) + { + schedulePtr_.reset + ( + new List<labelPair> + ( + schedule(subMap_, constructMap_, Pstream::msgType()) + ) + ); + } + return schedulePtr_(); +} + + +void Foam::mapDistributeBase::checkReceivedSize +( + const label procI, + const label expectedSize, + const label receivedSize +) +{ + if (receivedSize != expectedSize) + { + FatalErrorIn + ( + "template<class T>\n" + "void mapDistributeBase::distribute\n" + "(\n" + " const Pstream::commsTypes commsType,\n" + " const List<labelPair>& schedule,\n" + " const label constructSize,\n" + " const labelListList& subMap,\n" + " const labelListList& constructMap,\n" + " List<T>& field\n" + ")\n" + ) << "Expected from processor " << procI + << " " << expectedSize << " but received " + << receivedSize << " elements." + << abort(FatalError); + } +} + + +void Foam::mapDistributeBase::printLayout(Ostream& os) const +{ + // Determine offsets of remote data. + labelList minIndex(Pstream::nProcs(), labelMax); + labelList maxIndex(Pstream::nProcs(), labelMin); + forAll(constructMap_, procI) + { + const labelList& construct = constructMap_[procI]; + if (constructHasFlip_) + { + forAll(construct, i) + { + label index = mag(construct[i])-1; + minIndex[procI] = min(minIndex[procI], index); + maxIndex[procI] = max(maxIndex[procI], index); + } + } + else + { + forAll(construct, i) + { + label index = construct[i]; + minIndex[procI] = min(minIndex[procI], index); + maxIndex[procI] = max(maxIndex[procI], index); + } + } + } + + label localSize; + if (maxIndex[Pstream::myProcNo()] == labelMin) + { + localSize = 0; + } + else + { + localSize = maxIndex[Pstream::myProcNo()]+1; + } + + os << "Layout: (constructSize:" << constructSize_ + << " subHasFlip:" << subHasFlip_ + << " constructHasFlip:" << constructHasFlip_ + << ")" << endl + << "local (processor " << Pstream::myProcNo() << "):" << endl + << " start : 0" << endl + << " size : " << localSize << endl; + + label offset = localSize; + forAll(minIndex, procI) + { + if (procI != Pstream::myProcNo()) + { + if (constructMap_[procI].size() > 0) + { + if (minIndex[procI] != offset) + { + FatalErrorIn("mapDistributeBase::printLayout(..)") + << "offset:" << offset + << " procI:" << procI + << " minIndex:" << minIndex[procI] + << abort(FatalError); + } + + label size = maxIndex[procI]-minIndex[procI]+1; + os << "processor " << procI << ':' << endl + << " start : " << offset << endl + << " size : " << size << endl; + + offset += size; + } + } + } +} + + +// Construct per processor compact addressing of the global elements +// needed. The ones from the local processor are not included since +// these are always all needed. +void Foam::mapDistributeBase::calcCompactAddressing +( + const globalIndex& globalNumbering, + const labelList& elements, + List<Map<label> >& compactMap +) const +{ + compactMap.setSize(Pstream::nProcs()); + + // Count all (non-local) elements needed. Just for presizing map. + labelList nNonLocal(Pstream::nProcs(), 0); + + forAll(elements, i) + { + label globalIndex = elements[i]; + + if (globalIndex != -1 && !globalNumbering.isLocal(globalIndex)) + { + label procI = globalNumbering.whichProcID(globalIndex); + nNonLocal[procI]++; + } + } + + forAll(compactMap, procI) + { + compactMap[procI].clear(); + if (procI != Pstream::myProcNo()) + { + compactMap[procI].resize(2*nNonLocal[procI]); + } + } + + + // Collect all (non-local) elements needed. + forAll(elements, i) + { + label globalIndex = elements[i]; + + if (globalIndex != -1 && !globalNumbering.isLocal(globalIndex)) + { + label procI = globalNumbering.whichProcID(globalIndex); + label index = globalNumbering.toLocal(procI, globalIndex); + label nCompact = compactMap[procI].size(); + compactMap[procI].insert(index, nCompact); + } + } +} + + +void Foam::mapDistributeBase::calcCompactAddressing +( + const globalIndex& globalNumbering, + const labelListList& cellCells, + List<Map<label> >& compactMap +) const +{ + compactMap.setSize(Pstream::nProcs()); + + // Count all (non-local) elements needed. Just for presizing map. + labelList nNonLocal(Pstream::nProcs(), 0); + + forAll(cellCells, cellI) + { + const labelList& cCells = cellCells[cellI]; + + forAll(cCells, i) + { + label globalIndex = cCells[i]; + + if (globalIndex != -1 && !globalNumbering.isLocal(globalIndex)) + { + label procI = globalNumbering.whichProcID(globalIndex); + nNonLocal[procI]++; + } + } + } + + forAll(compactMap, procI) + { + compactMap[procI].clear(); + if (procI != Pstream::myProcNo()) + { + compactMap[procI].resize(2*nNonLocal[procI]); + } + } + + + // Collect all (non-local) elements needed. + forAll(cellCells, cellI) + { + const labelList& cCells = cellCells[cellI]; + + forAll(cCells, i) + { + label globalIndex = cCells[i]; + + if (globalIndex != -1 && !globalNumbering.isLocal(globalIndex)) + { + label procI = globalNumbering.whichProcID(globalIndex); + label index = globalNumbering.toLocal(procI, globalIndex); + label nCompact = compactMap[procI].size(); + compactMap[procI].insert(index, nCompact); + } + } + } +} + + +void Foam::mapDistributeBase::exchangeAddressing +( + const int tag, + const globalIndex& globalNumbering, + labelList& elements, + List<Map<label> >& compactMap, + labelList& compactStart +) +{ + // The overall compact addressing is + // - myProcNo data first (uncompacted) + // - all other processors consecutively + + compactStart.setSize(Pstream::nProcs()); + compactStart[Pstream::myProcNo()] = 0; + constructSize_ = globalNumbering.localSize(); + forAll(compactStart, procI) + { + if (procI != Pstream::myProcNo()) + { + compactStart[procI] = constructSize_; + constructSize_ += compactMap[procI].size(); + } + } + + + + // Find out what to receive/send in compact addressing. + + // What I want to receive is what others have to send + labelListList wantedRemoteElements(Pstream::nProcs()); + // Compact addressing for received data + constructMap_.setSize(Pstream::nProcs()); + forAll(compactMap, procI) + { + if (procI == Pstream::myProcNo()) + { + // All my own elements are used + label nLocal = globalNumbering.localSize(); + wantedRemoteElements[procI] = identity(nLocal); + constructMap_[procI] = identity(nLocal); + } + else + { + // Remote elements wanted from processor procI + labelList& remoteElem = wantedRemoteElements[procI]; + labelList& localElem = constructMap_[procI]; + remoteElem.setSize(compactMap[procI].size()); + localElem.setSize(compactMap[procI].size()); + label i = 0; + forAllIter(Map<label>, compactMap[procI], iter) + { + const label compactI = compactStart[procI] + iter(); + remoteElem[i] = iter.key(); + localElem[i] = compactI; + iter() = compactI; + i++; + } + } + } + + subMap_.setSize(Pstream::nProcs()); + labelListList sendSizes; + Pstream::exchange<labelList, label> + ( + wantedRemoteElements, + subMap_, + sendSizes, + tag, + Pstream::worldComm //TBD + ); + + // Renumber elements + forAll(elements, i) + { + elements[i] = renumber(globalNumbering, compactMap, elements[i]); + } +} + + +void Foam::mapDistributeBase::exchangeAddressing +( + const int tag, + const globalIndex& globalNumbering, + labelListList& cellCells, + List<Map<label> >& compactMap, + labelList& compactStart +) +{ + // The overall compact addressing is + // - myProcNo data first (uncompacted) + // - all other processors consecutively + + compactStart.setSize(Pstream::nProcs()); + compactStart[Pstream::myProcNo()] = 0; + constructSize_ = globalNumbering.localSize(); + forAll(compactStart, procI) + { + if (procI != Pstream::myProcNo()) + { + compactStart[procI] = constructSize_; + constructSize_ += compactMap[procI].size(); + } + } + + + + // Find out what to receive/send in compact addressing. + + // What I want to receive is what others have to send + labelListList wantedRemoteElements(Pstream::nProcs()); + // Compact addressing for received data + constructMap_.setSize(Pstream::nProcs()); + forAll(compactMap, procI) + { + if (procI == Pstream::myProcNo()) + { + // All my own elements are used + label nLocal = globalNumbering.localSize(); + wantedRemoteElements[procI] = identity(nLocal); + constructMap_[procI] = identity(nLocal); + } + else + { + // Remote elements wanted from processor procI + labelList& remoteElem = wantedRemoteElements[procI]; + labelList& localElem = constructMap_[procI]; + remoteElem.setSize(compactMap[procI].size()); + localElem.setSize(compactMap[procI].size()); + label i = 0; + forAllIter(Map<label>, compactMap[procI], iter) + { + const label compactI = compactStart[procI] + iter(); + remoteElem[i] = iter.key(); + localElem[i] = compactI; + iter() = compactI; + i++; + } + } + } + + subMap_.setSize(Pstream::nProcs()); + labelListList sendSizes; + Pstream::exchange<labelList, label> + ( + wantedRemoteElements, + subMap_, + sendSizes, + tag, + Pstream::worldComm //TBD + ); + + // Renumber elements + forAll(cellCells, cellI) + { + labelList& cCells = cellCells[cellI]; + + forAll(cCells, i) + { + cCells[i] = renumber(globalNumbering, compactMap, cCells[i]); + } + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +//- Construct null +Foam::mapDistributeBase::mapDistributeBase() +: + constructSize_(0), + subHasFlip_(false), + constructHasFlip_(false), + schedulePtr_() +{} + + +//- Construct from components +Foam::mapDistributeBase::mapDistributeBase +( + const label constructSize, + const Xfer<labelListList>& subMap, + const Xfer<labelListList>& constructMap, + const bool subHasFlip, + const bool constructHasFlip +) +: + constructSize_(constructSize), + subMap_(subMap), + constructMap_(constructMap), + subHasFlip_(subHasFlip), + constructHasFlip_(constructHasFlip), + schedulePtr_() +{} + + +Foam::mapDistributeBase::mapDistributeBase +( + const labelList& sendProcs, + const labelList& recvProcs +) +: + constructSize_(0), + subHasFlip_(false), + constructHasFlip_(false), + schedulePtr_() +{ + if (sendProcs.size() != recvProcs.size()) + { + FatalErrorIn + ( + "mapDistributeBase::mapDistributeBase" + "(const labelList&, const labelList&)" + ) << "The send and receive data is not the same length. sendProcs:" + << sendProcs.size() << " recvProcs:" << recvProcs.size() + << abort(FatalError); + } + + // Per processor the number of samples we have to send/receive. + labelList nSend(Pstream::nProcs(), 0); + labelList nRecv(Pstream::nProcs(), 0); + + forAll(sendProcs, sampleI) + { + label sendProc = sendProcs[sampleI]; + label recvProc = recvProcs[sampleI]; + + // Note that also need to include local communication (both + // RecvProc and sendProc on local processor) + + if (Pstream::myProcNo() == sendProc) + { + // I am the sender. Count destination processor. + nSend[recvProc]++; + } + if (Pstream::myProcNo() == recvProc) + { + // I am the receiver. + nRecv[sendProc]++; + } + } + + subMap_.setSize(Pstream::nProcs()); + constructMap_.setSize(Pstream::nProcs()); + forAll(nSend, procI) + { + subMap_[procI].setSize(nSend[procI]); + constructMap_[procI].setSize(nRecv[procI]); + } + nSend = 0; + nRecv = 0; + + forAll(sendProcs, sampleI) + { + label sendProc = sendProcs[sampleI]; + label recvProc = recvProcs[sampleI]; + + if (Pstream::myProcNo() == sendProc) + { + // I am the sender. Store index I need to send. + subMap_[recvProc][nSend[recvProc]++] = sampleI; + } + if (Pstream::myProcNo() == recvProc) + { + // I am the receiver. + constructMap_[sendProc][nRecv[sendProc]++] = sampleI; + // Largest entry inside constructMap + constructSize_ = sampleI+1; + } + } +} + + +Foam::mapDistributeBase::mapDistributeBase +( + const globalIndex& globalNumbering, + labelList& elements, + List<Map<label> >& compactMap, + const int tag +) +: + constructSize_(0), + subHasFlip_(false), + constructHasFlip_(false), + schedulePtr_() +{ + // Construct per processor compact addressing of the global elements + // needed. The ones from the local processor are not included since + // these are always all needed. + calcCompactAddressing + ( + globalNumbering, + elements, + compactMap + ); + + //// Sort remote elements needed (not really necessary) + //forAll(compactMap, procI) + //{ + // if (procI != Pstream::myProcNo()) + // { + // Map<label>& globalMap = compactMap[procI]; + // + // SortableList<label> sorted(globalMap.toc().xfer()); + // + // forAll(sorted, i) + // { + // Map<label>::iterator iter = globalMap.find(sorted[i]); + // iter() = i; + // } + // } + //} + + + // Exchange what I need with processor that supplies it. Renumber elements + // into compact numbering + labelList compactStart; + exchangeAddressing + ( + tag, + globalNumbering, + elements, + compactMap, + compactStart + ); + + if (debug) + { + printLayout(Pout); + } +} + + +Foam::mapDistributeBase::mapDistributeBase +( + const globalIndex& globalNumbering, + labelListList& cellCells, + List<Map<label> >& compactMap, + const int tag +) +: + constructSize_(0), + subHasFlip_(false), + constructHasFlip_(false), + schedulePtr_() +{ + // Construct per processor compact addressing of the global elements + // needed. The ones from the local processor are not included since + // these are always all needed. + calcCompactAddressing + ( + globalNumbering, + cellCells, + compactMap + ); + + //// Sort remote elements needed (not really necessary) + //forAll(compactMap, procI) + //{ + // if (procI != Pstream::myProcNo()) + // { + // Map<label>& globalMap = compactMap[procI]; + // + // SortableList<label> sorted(globalMap.toc().xfer()); + // + // forAll(sorted, i) + // { + // Map<label>::iterator iter = globalMap.find(sorted[i]); + // iter() = i; + // } + // } + //} + + + // Exchange what I need with processor that supplies it. Renumber elements + // into compact numbering + labelList compactStart; + exchangeAddressing + ( + tag, + globalNumbering, + cellCells, + compactMap, + compactStart + ); + + if (debug) + { + printLayout(Pout); + } +} + + +Foam::mapDistributeBase::mapDistributeBase(const mapDistributeBase& map) +: + constructSize_(map.constructSize_), + subMap_(map.subMap_), + constructMap_(map.constructMap_), + subHasFlip_(map.subHasFlip_), + constructHasFlip_(map.constructHasFlip_), + schedulePtr_() +{} + + +Foam::mapDistributeBase::mapDistributeBase(const Xfer<mapDistributeBase>& map) +: + constructSize_(map().constructSize_), + subMap_(map().subMap_.xfer()), + constructMap_(map().constructMap_.xfer()), + subHasFlip_(map().subHasFlip_), + constructHasFlip_(map().constructHasFlip_), + schedulePtr_() +{} + + +Foam::mapDistributeBase::mapDistributeBase(Istream& is) +{ + is >> *this; +} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +void Foam::mapDistributeBase::transfer(mapDistributeBase& rhs) +{ + constructSize_ = rhs.constructSize_; + subMap_.transfer(rhs.subMap_); + constructMap_.transfer(rhs.constructMap_); + subHasFlip_ = rhs.subHasFlip_; + constructHasFlip_ = rhs.constructHasFlip_; + schedulePtr_.clear(); +} + + +Foam::Xfer<Foam::mapDistributeBase> Foam::mapDistributeBase::xfer() +{ + return xferMove(*this); +} + + +Foam::label Foam::mapDistributeBase::renumber +( + const globalIndex& globalNumbering, + const List<Map<label> >& compactMap, + const label globalI +) +{ + if (globalI == -1) + { + return globalI; + } + if (globalNumbering.isLocal(globalI)) + { + return globalNumbering.toLocal(globalI); + } + else + { + label procI = globalNumbering.whichProcID(globalI); + label index = globalNumbering.toLocal(procI, globalI); + return compactMap[procI][index]; + } +} + + +void Foam::mapDistributeBase::compact(const boolList& elemIsUsed, const int tag) +{ + // 1. send back to sender. Have sender delete the corresponding element + // from the submap and do the same to the constructMap locally + // (and in same order). + + // Send elemIsUsed field to neighbour. Use nonblocking code from + // mapDistributeBase but in reverse order. + if (Pstream::parRun()) + { + label startOfRequests = Pstream::nRequests(); + + // Set up receives from neighbours + + List<boolList> recvFields(Pstream::nProcs()); + + for (label domain = 0; domain < Pstream::nProcs(); domain++) + { + const labelList& map = subMap_[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].size()*sizeof(bool), + tag + ); + } + } + + + List<boolList> sendFields(Pstream::nProcs()); + + for (label domain = 0; domain < Pstream::nProcs(); domain++) + { + const labelList& map = constructMap_[domain]; + + if (domain != Pstream::myProcNo() && map.size()) + { + boolList& subField = sendFields[domain]; + subField.setSize(map.size()); + forAll(map, i) + { + subField[i] = accessAndFlip + ( + elemIsUsed, + map[i], + constructHasFlip_, + noOp() // do not flip elemIsUsed value + ); + } + + OPstream::write + ( + Pstream::nonBlocking, + domain, + reinterpret_cast<const char*>(subField.begin()), + subField.size()*sizeof(bool), + tag + ); + } + } + + + + // Set up 'send' to myself - write directly into recvFields + + { + const labelList& map = constructMap_[Pstream::myProcNo()]; + + recvFields[Pstream::myProcNo()].setSize(map.size()); + forAll(map, i) + { + recvFields[Pstream::myProcNo()][i] = accessAndFlip + ( + elemIsUsed, + map[i], + constructHasFlip_, + noOp() // do not flip elemIsUsed value + ); + } + } + + + // Wait for all to finish + + Pstream::waitRequests(startOfRequests); + + + // Compact out all submap entries that are referring to unused elements + for (label domain = 0; domain < Pstream::nProcs(); domain++) + { + const labelList& map = subMap_[domain]; + + labelList newMap(map.size()); + label newI = 0; + + forAll(map, i) + { + if (recvFields[domain][i]) + { + // So element is used on destination side + newMap[newI++] = map[i]; + } + } + if (newI < map.size()) + { + newMap.setSize(newI); + subMap_[domain].transfer(newMap); + } + } + } + + + // 2. remove from construct map - since end-result (element in elemIsUsed) + // not used. + + label maxConstructIndex = -1; + + for (label domain = 0; domain < Pstream::nProcs(); domain++) + { + const labelList& map = constructMap_[domain]; + + labelList newMap(map.size()); + label newI = 0; + + forAll(map, i) + { + label destinationI = map[i]; + if (constructHasFlip_) + { + destinationI = mag(destinationI)-1; + } + + // Is element is used on destination side + if (elemIsUsed[destinationI]) + { + maxConstructIndex = max(maxConstructIndex, destinationI); + + newMap[newI++] = map[i]; + } + } + if (newI < map.size()) + { + newMap.setSize(newI); + constructMap_[domain].transfer(newMap); + } + } + + constructSize_ = maxConstructIndex+1; + + // Clear the schedule (note:not necessary if nothing changed) + schedulePtr_.clear(); +} + + +void Foam::mapDistributeBase::compact +( + const boolList& elemIsUsed, + const label localSize, // max index for subMap + labelList& oldToNewSub, + labelList& oldToNewConstruct, + const int tag +) +{ + // 1. send back to sender. Have sender delete the corresponding element + // from the submap and do the same to the constructMap locally + // (and in same order). + + // Send elemIsUsed field to neighbour. Use nonblocking code from + // mapDistributeBase but in reverse order. + if (Pstream::parRun()) + { + label startOfRequests = Pstream::nRequests(); + + // Set up receives from neighbours + + List<boolList> recvFields(Pstream::nProcs()); + + for (label domain = 0; domain < Pstream::nProcs(); domain++) + { + const labelList& map = subMap_[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].size()*sizeof(bool), + tag + ); + } + } + + + List<boolList> sendFields(Pstream::nProcs()); + + for (label domain = 0; domain < Pstream::nProcs(); domain++) + { + const labelList& map = constructMap_[domain]; + + if (domain != Pstream::myProcNo() && map.size()) + { + boolList& subField = sendFields[domain]; + subField.setSize(map.size()); + forAll(map, i) + { + label index = map[i]; + if (constructHasFlip_) + { + index = mag(index)-1; + } + subField[i] = elemIsUsed[index]; + } + + OPstream::write + ( + Pstream::nonBlocking, + domain, + reinterpret_cast<const char*>(subField.begin()), + subField.size()*sizeof(bool), + tag + ); + } + } + + + + // Set up 'send' to myself - write directly into recvFields + + { + const labelList& map = constructMap_[Pstream::myProcNo()]; + + recvFields[Pstream::myProcNo()].setSize(map.size()); + forAll(map, i) + { + label index = map[i]; + if (constructHasFlip_) + { + index = mag(index)-1; + } + recvFields[Pstream::myProcNo()][i] = elemIsUsed[index]; + } + } + + + // Wait for all to finish + + Pstream::waitRequests(startOfRequests); + + + + + // Work out which elements on the sending side are needed + { + oldToNewSub.setSize(localSize, -1); + + boolList sendElemIsUsed(localSize, false); + + for (label domain = 0; domain < Pstream::nProcs(); domain++) + { + const labelList& map = subMap_[domain]; + forAll(map, i) + { + if (recvFields[domain][i]) + { + label index = map[i]; + if (subHasFlip_) + { + index = mag(index)-1; + } + sendElemIsUsed[index] = true; + } + } + } + + label newI = 0; + forAll(sendElemIsUsed, i) + { + if (sendElemIsUsed[i]) + { + oldToNewSub[i] = newI++; + } + } + } + + + // Compact out all submap entries that are referring to unused elements + for (label domain = 0; domain < Pstream::nProcs(); domain++) + { + const labelList& map = subMap_[domain]; + + labelList newMap(map.size()); + label newI = 0; + + forAll(map, i) + { + if (recvFields[domain][i]) + { + // So element is used on destination side + label index = map[i]; + label sign = 1; + if (subHasFlip_) + { + if (index < 0) + { + sign = -1; + } + index = mag(index)-1; + } + label newIndex = oldToNewSub[index]; + if (subHasFlip_) + { + newIndex = sign*(newIndex+1); + } + newMap[newI++] = newIndex; + } + } + newMap.setSize(newI); + subMap_[domain].transfer(newMap); + } + } + + + // 2. remove from construct map - since end-result (element in elemIsUsed) + // not used. + + + oldToNewConstruct.setSize(elemIsUsed.size(), -1); + constructSize_ = 0; + forAll(elemIsUsed, i) + { + if (elemIsUsed[i]) + { + oldToNewConstruct[i] = constructSize_++; + } + } + + for (label domain = 0; domain < Pstream::nProcs(); domain++) + { + const labelList& map = constructMap_[domain]; + + labelList newMap(map.size()); + label newI = 0; + + forAll(map, i) + { + label destinationI = map[i]; + label sign = 1; + if (constructHasFlip_) + { + if (destinationI < 0) + { + sign = -1; + } + destinationI = mag(destinationI)-1; + } + + // Is element is used on destination side + if (elemIsUsed[destinationI]) + { + label newIndex = oldToNewConstruct[destinationI]; + if (constructHasFlip_) + { + newIndex = sign*(newIndex+1); + } + newMap[newI++] = newIndex; + } + } + newMap.setSize(newI); + constructMap_[domain].transfer(newMap); + } +} + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + +void Foam::mapDistributeBase::operator=(const mapDistributeBase& rhs) +{ + // Check for assignment to self + if (this == &rhs) + { + FatalErrorIn + ( + "Foam::mapDistributeBase::operator=(const Foam::mapDistributeBase&)" + ) << "Attempted assignment to self" + << abort(FatalError); + } + constructSize_ = rhs.constructSize_; + subMap_ = rhs.subMap_; + constructMap_ = rhs.constructMap_; + subHasFlip_ = rhs.subHasFlip_; + constructHasFlip_ = rhs.constructHasFlip_; + schedulePtr_.clear(); +} + + +// * * * * * * * * * * * * * * Istream Operator * * * * * * * * * * * * * * // + +Foam::Istream& Foam::operator>>(Istream& is, mapDistributeBase& map) +{ + is.fatalCheck("operator>>(Istream&, mapDistributeBase&)"); + + is >> map.constructSize_ >> map.subMap_ >> map.constructMap_ + >> map.subHasFlip_ >> map.constructHasFlip_; + + return is; +} + + +// * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * * // + +Foam::Ostream& Foam::operator<<(Ostream& os, const mapDistributeBase& map) +{ + os << map.constructSize_ << token::NL + << map.subMap_ << token::NL + << map.constructMap_ << token::NL + << map.subHasFlip_ << token::SPACE << map.constructHasFlip_ + << token::NL; + + return os; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBase.H b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBase.H new file mode 100644 index 0000000000000000000000000000000000000000..9f88e0553492f335d6a91eb23cd911d222723904 --- /dev/null +++ b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBase.H @@ -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 + +// ************************************************************************* // diff --git a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBaseTemplates.C b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBaseTemplates.C new file mode 100644 index 0000000000000000000000000000000000000000..f205072d0ac3169bba002c61c2b8a9d7d962a844 --- /dev/null +++ b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeBaseTemplates.C @@ -0,0 +1,1375 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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 "Pstream.H" +#include "PstreamBuffers.H" +#include "PstreamCombineReduceOps.H" +#include "flipOp.H" + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +template<class T, class CombineOp, class negateOp> +void Foam::mapDistributeBase::flipAndCombine +( + const UList<label>& map, + const bool hasFlip, + const UList<T>& rhs, + const CombineOp& cop, + const negateOp& negOp, + List<T>& lhs +) +{ + if (hasFlip) + { + forAll(map, i) + { + if (map[i] > 0) + { + label index = map[i]-1; + cop(lhs[index], rhs[i]); + } + else if (map[i] < 0) + { + label index = -map[i]-1; + cop(lhs[index], negOp(rhs[i])); + } + else + { + FatalErrorIn("mapDistributeBase::combine(..)") + << "At index " << i << " out of " << map.size() + << " have illegal index " << map[i] + << " for field " << rhs.size() << " with flipMap" + << exit(FatalError); + } + } + } + else + { + forAll(map, i) + { + cop(lhs[map[i]], rhs[i]); + } + } +} + + +template<class T, class negateOp> +T Foam::mapDistributeBase::accessAndFlip +( + const UList<T>& fld, + const label index, + const bool hasFlip, + const negateOp& negOp +) +{ + T t; + if (hasFlip) + { + if (index > 0) + { + t = fld[index-1]; + } + else if (index < 0) + { + t = negOp(fld[-index-1]); + } + else + { + FatalErrorIn("mapDistributeBase::accessAndFlip(..)") + << "Illegal index " << index + << " into field of size " << fld.size() + << " with face-flipping" + << exit(FatalError); + t = fld[index]; + } + } + else + { + t = fld[index]; + } + return t; +} + + +// Distribute list. +template<class T, class negateOp> +void Foam::mapDistributeBase::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>& field, + const negateOp& negOp, + 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] = accessAndFlip(field, mySubMap[i], subHasFlip, negOp); + } + + // Receive sub field from myself (subField) + const labelList& map = constructMap[Pstream::myProcNo()]; + + field.setSize(constructSize); + + flipAndCombine + ( + map, + constructHasFlip, + subField, + eqOp<T>(), + negOp, + field + ); + + 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); + + List<T> subField(map.size()); + forAll(subField, i) + { + subField[i] = accessAndFlip + ( + field, + map[i], + subHasFlip, + negOp + ); + } + toNbr << subField; + } + } + + // Subset myself + const labelList& mySubMap = subMap[Pstream::myProcNo()]; + + List<T> subField(mySubMap.size()); + forAll(mySubMap, i) + { + subField[i] = accessAndFlip(field, mySubMap[i], subHasFlip, negOp); + } + + // Receive sub field from myself (subField) + const labelList& map = constructMap[Pstream::myProcNo()]; + + field.setSize(constructSize); + + flipAndCombine + ( + map, + constructHasFlip, + subField, + eqOp<T>(), + negOp, + field + ); + + // 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()); + + flipAndCombine + ( + map, + constructHasFlip, + subField, + eqOp<T>(), + negOp, + field + ); + } + } + } + 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); + + // Receive sub field from myself + { + const labelList& mySubMap = subMap[Pstream::myProcNo()]; + + List<T> subField(mySubMap.size()); + forAll(subField, i) + { + subField[i] = accessAndFlip + ( + field, + mySubMap[i], + subHasFlip, + negOp + ); + } + + // Receive sub field from myself (subField) + flipAndCombine + ( + constructMap[Pstream::myProcNo()], + constructHasFlip, + subField, + eqOp<T>(), + negOp, + newField + ); + } + + // 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); + + const labelList& map = subMap[recvProc]; + List<T> subField(map.size()); + forAll(subField, i) + { + subField[i] = accessAndFlip + ( + field, + map[i], + subHasFlip, + negOp + ); + } + toNbr << subField; + } + { + IPstream fromNbr(Pstream::scheduled, recvProc, 0, tag); + List<T> subField(fromNbr); + + const labelList& map = constructMap[recvProc]; + + checkReceivedSize(recvProc, map.size(), subField.size()); + + flipAndCombine + ( + map, + constructHasFlip, + subField, + eqOp<T>(), + negOp, + newField + ); + } + } + 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()); + + flipAndCombine + ( + map, + constructHasFlip, + subField, + eqOp<T>(), + negOp, + newField + ); + } + { + OPstream toNbr(Pstream::scheduled, sendProc, 0, tag); + + const labelList& map = subMap[sendProc]; + List<T> subField(map.size()); + forAll(subField, i) + { + subField[i] = accessAndFlip + ( + field, + map[i], + subHasFlip, + negOp + ); + } + toNbr << subField; + } + } + } + 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); + + List<T> subField(map.size()); + forAll(subField, i) + { + subField[i] = accessAndFlip + ( + field, + map[i], + subHasFlip, + negOp + ); + } + toDomain << subField; + } + } + + // Start receiving. Do not block. + pBufs.finishedSends(false); + + { + // Set up 'send' to myself + const labelList& mySub = subMap[Pstream::myProcNo()]; + List<T> mySubField(mySub.size()); + forAll(mySub, i) + { + mySubField[i] = accessAndFlip + ( + field, + mySub[i], + subHasFlip, + negOp + ); + } + // Combine bits. Note that can reuse field storage + field.setSize(constructSize); + // Receive sub field from myself + { + const labelList& map = constructMap[Pstream::myProcNo()]; + + flipAndCombine + ( + map, + constructHasFlip, + mySubField, + eqOp<T>(), + negOp, + field + ); + } + } + + // 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()); + + flipAndCombine + ( + map, + constructHasFlip, + recvField, + eqOp<T>(), + negOp, + field + ); + } + } + } + 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] = accessAndFlip + ( + field, + map[i], + subHasFlip, + negOp + ); + } + + 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] = accessAndFlip + ( + field, + map[i], + subHasFlip, + negOp + ); + } + } + + + // 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()]; + + flipAndCombine + ( + map, + constructHasFlip, + subField, + eqOp<T>(), + negOp, + field + ); + } + + + // 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()); + + flipAndCombine + ( + map, + constructHasFlip, + subField, + eqOp<T>(), + negOp, + field + ); + } + } + } + } + else + { + FatalErrorIn("mapDistributeBase::distribute(..)") + << "Unknown communication schedule " << commsType + << abort(FatalError); + } +} + + +// Distribute list. +template<class T, class CombineOp, class negateOp> +void Foam::mapDistributeBase::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>& field, + const CombineOp& cop, + const negateOp& negOp, + 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] = accessAndFlip(field, mySubMap[i], subHasFlip, negOp); + } + + // Receive sub field from myself (subField) + const labelList& map = constructMap[Pstream::myProcNo()]; + + field.setSize(constructSize); + field = nullValue; + + flipAndCombine(map, constructHasFlip, subField, cop, negOp, field); + + 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); + List<T> subField(map.size()); + forAll(subField, i) + { + subField[i] = accessAndFlip + ( + field, + map[i], + subHasFlip, + negOp + ); + } + toNbr << subField; + } + } + + // Subset myself + const labelList& mySubMap = subMap[Pstream::myProcNo()]; + + List<T> subField(mySubMap.size()); + forAll(mySubMap, i) + { + subField[i] = accessAndFlip(field, mySubMap[i], subHasFlip, negOp); + } + + // Receive sub field from myself (subField) + const labelList& map = constructMap[Pstream::myProcNo()]; + + field.setSize(constructSize); + field = nullValue; + + flipAndCombine(map, constructHasFlip, subField, cop, negOp, field); + + // 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()); + + flipAndCombine + ( + map, + constructHasFlip, + subField, + cop, + negOp, + field + ); + } + } + } + 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); + + { + const labelList& mySubMap = subMap[Pstream::myProcNo()]; + + // Subset myself + List<T> subField(mySubMap.size()); + forAll(subField, i) + { + subField[i] = accessAndFlip + ( + field, + mySubMap[i], + subHasFlip, + negOp + ); + } + + // Receive sub field from myself (subField) + const labelList& map = constructMap[Pstream::myProcNo()]; + + flipAndCombine + ( + map, + constructHasFlip, + subField, + cop, + negOp, + newField + ); + } + + + // 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); + + const labelList& map = subMap[recvProc]; + + List<T> subField(map.size()); + forAll(subField, i) + { + subField[i] = accessAndFlip + ( + field, + map[i], + subHasFlip, + negOp + ); + } + toNbr << subField; + } + { + IPstream fromNbr(Pstream::scheduled, recvProc, 0, tag); + List<T> subField(fromNbr); + const labelList& map = constructMap[recvProc]; + + checkReceivedSize(recvProc, map.size(), subField.size()); + + flipAndCombine + ( + map, + constructHasFlip, + subField, + cop, + negOp, + newField + ); + } + } + 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()); + + flipAndCombine + ( + map, + constructHasFlip, + subField, + cop, + negOp, + newField + ); + } + { + OPstream toNbr(Pstream::scheduled, sendProc, 0, tag); + + const labelList& map = subMap[sendProc]; + + List<T> subField(map.size()); + forAll(subField, i) + { + subField[i] = accessAndFlip + ( + field, + map[i], + subHasFlip, + negOp + ); + } + toNbr << subField; + } + } + } + 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); + + List<T> subField(map.size()); + forAll(subField, i) + { + subField[i] = accessAndFlip + ( + field, + map[i], + subHasFlip, + negOp + ); + } + toDomain << subField; + } + } + + // Start receiving. Do not block. + pBufs.finishedSends(false); + + { + // Set up 'send' to myself + const labelList& myMap = subMap[Pstream::myProcNo()]; + + List<T> mySubField(myMap.size()); + forAll(myMap, i) + { + mySubField[i] = accessAndFlip + ( + field, + myMap[i], + subHasFlip, + negOp + ); + } + + // Combine bits. Note that can reuse field storage + field.setSize(constructSize); + field = nullValue; + // Receive sub field from myself + { + const labelList& map = constructMap[Pstream::myProcNo()]; + + flipAndCombine + ( + map, + constructHasFlip, + mySubField, + cop, + negOp, + field + ); + } + } + + // 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()); + + flipAndCombine + ( + map, + constructHasFlip, + recvField, + cop, + negOp, + field + ); + } + } + } + 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] = accessAndFlip + ( + field, + map[i], + subHasFlip, + negOp + ); + } + + 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] = accessAndFlip + ( + field, + map[i], + subHasFlip, + negOp + ); + } + } + + + // 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()]; + + flipAndCombine + ( + map, + constructHasFlip, + subField, + cop, + negOp, + field + ); + } + + + // 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()); + + flipAndCombine + ( + map, + constructHasFlip, + subField, + cop, + negOp, + field + ); + } + } + } + } + else + { + FatalErrorIn("mapDistributeBase::distribute(..)") + << "Unknown communication schedule " << commsType + << abort(FatalError); + } +} + + +template<class T> +void Foam::mapDistributeBase::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); + + List<T> subField(map.size()); + forAll(subField, i) + { + subField[i] = accessAndFlip + ( + field, + map[i], + subHasFlip_, + flipOp() + ); + } + toDomain << subField; + } + } + + // Start sending and receiving but do not block. + pBufs.finishedSends(false); +} + + +template<class T> +void Foam::mapDistributeBase::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 mapDistributeBase::receive\n" + "(\n" + " PstreamBuffers&,\n" + " List<T>&\n" + ")\n" + ) << "Expected from processor " << domain + << " " << map.size() << " but received " + << recvField.size() << " elements." + << abort(FatalError); + } + + flipAndCombine + ( + map, + constructHasFlip_, + recvField, + eqOp<T>(), + flipOp(), + field + ); + } + } +} + + +//- Distribute data using default commsType. +template<class T, class negateOp> +void Foam::mapDistributeBase::distribute +( + List<T>& fld, + const negateOp& negOp, + const int tag +) const +{ + if (Pstream::defaultCommsType == Pstream::nonBlocking) + { + distribute + ( + Pstream::nonBlocking, + List<labelPair>(), + constructSize_, + subMap_, + subHasFlip_, + constructMap_, + constructHasFlip_, + fld, + negOp, + tag + ); + } + else if (Pstream::defaultCommsType == Pstream::scheduled) + { + distribute + ( + Pstream::scheduled, + schedule(), + constructSize_, + subMap_, + subHasFlip_, + constructMap_, + constructHasFlip_, + fld, + negOp, + tag + ); + } + else + { + distribute + ( + Pstream::blocking, + List<labelPair>(), + constructSize_, + subMap_, + subHasFlip_, + constructMap_, + constructHasFlip_, + fld, + negOp, + tag + ); + } +} + + +//- Distribute data using default commsType. +template<class T> +void Foam::mapDistributeBase::distribute +( + List<T>& fld, + const int tag +) const +{ + distribute(fld, flipOp(), tag); +} + + +//- Distribute data using default commsType. +template<class T> +void Foam::mapDistributeBase::distribute +( + DynamicList<T>& fld, + const int tag +) const +{ + fld.shrink(); + + List<T>& fldList = static_cast<List<T>& >(fld); + + distribute(fldList, tag); + + fld.setCapacity(fldList.size()); +} + + +//- Reverse distribute data using default commsType. +template<class T> +void Foam::mapDistributeBase::reverseDistribute +( + const label constructSize, + List<T>& fld, + const int tag +) const +{ + if (Pstream::defaultCommsType == Pstream::nonBlocking) + { + distribute + ( + Pstream::nonBlocking, + List<labelPair>(), + constructSize, + constructMap_, + constructHasFlip_, + subMap_, + subHasFlip_, + fld, + flipOp(), + tag + ); + } + else if (Pstream::defaultCommsType == Pstream::scheduled) + { + distribute + ( + Pstream::scheduled, + schedule(), + constructSize, + constructMap_, + constructHasFlip_, + subMap_, + subHasFlip_, + fld, + flipOp(), + tag + ); + } + else + { + distribute + ( + Pstream::blocking, + List<labelPair>(), + constructSize, + constructMap_, + constructHasFlip_, + subMap_, + subHasFlip_, + fld, + flipOp(), + tag + ); + } +} + + +//- Reverse distribute data using default commsType. +// Since constructSize might be larger than supplied size supply +// a nullValue +template<class T> +void Foam::mapDistributeBase::reverseDistribute +( + const label constructSize, + const T& nullValue, + List<T>& fld, + const int tag +) const +{ + if (Pstream::defaultCommsType == Pstream::nonBlocking) + { + distribute + ( + Pstream::nonBlocking, + List<labelPair>(), + constructSize, + constructMap_, + constructHasFlip_, + subMap_, + subHasFlip_, + fld, + eqOp<T>(), + flipOp(), + nullValue, + tag + ); + } + else if (Pstream::defaultCommsType == Pstream::scheduled) + { + distribute + ( + Pstream::scheduled, + schedule(), + constructSize, + constructMap_, + constructHasFlip_, + subMap_, + subHasFlip_, + fld, + eqOp<T>(), + flipOp(), + nullValue, + tag + ); + } + else + { + distribute + ( + Pstream::blocking, + List<labelPair>(), + constructSize, + constructMap_, + constructHasFlip_, + subMap_, + subHasFlip_, + fld, + eqOp<T>(), + flipOp(), + nullValue, + tag + ); + } +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributePolyMesh.C b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributePolyMesh.C index 0dc63bdb577a8bf4385ecf7d416c97f090d2bd1d..a3be3258f09547e546f2ecb7e531bad26dba68c0 100644 --- a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributePolyMesh.C +++ b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributePolyMesh.C @@ -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++) - { - oldPatchSizes_[patchI] = - oldPatchStarts_[patchI + 1] - oldPatchStarts_[patchI]; - } - - // Set the last one by hand - const label lastPatchID = oldPatchStarts_.size() - 1; - - oldPatchSizes_[lastPatchID] = nOldFaces_ - oldPatchStarts_[lastPatchID]; - - if (min(oldPatchSizes_) < 0) + if (oldPatchStarts_.size()) { - FatalErrorIn("mapDistributePolyMesh::calcPatchSizes()") - << "Calculated negative old patch size:" << oldPatchSizes_ << nl - << "Error in mapping data" << abort(FatalError); + // 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; + + 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); + } } } // * * * * * * * * * * * * * * * * 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_; +} + +// * * * * * * * * * * * * * * Istream Operator * * * * * * * * * * * * * * // -// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // +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; +} // ************************************************************************* // diff --git a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributePolyMesh.H b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributePolyMesh.H index 5429e75730f9534e3a10f580044acc8483e0ce94..cf96988d9ffe03c5ac93681aeb933e01c61d8f90 100644 --- a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributePolyMesh.H +++ b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributePolyMesh.H @@ -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&); }; diff --git a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeTemplates.C b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeTemplates.C index 577af21ed12b9d78b41f0a857225411505ffbd20..758ad9b08ddc5edd71de142359950cb9b53c6098 100644 --- a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeTemplates.C +++ b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeTemplates.C @@ -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 @@ -888,21 +130,35 @@ void Foam::mapDistribute::applyInverseTransforms //- Distribute data using default commsType. -template<class T> +template<class T, class negateOp> void Foam::mapDistribute::distribute ( - DynamicList<T>& fld, + List<T>& fld, + const negateOp& negOp, const bool dummyTransform, const int tag ) const { - fld.shrink(); + mapDistributeBase::distribute(fld, negOp, tag); - List<T>& fldList = static_cast<List<T>& >(fld); + //- Fill in transformed slots with copies + if (dummyTransform) + { + applyDummyTransforms(fld); + } +} - distribute(fldList, dummyTransform, tag); - fld.setCapacity(fldList.size()); +//- 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); } @@ -910,56 +166,18 @@ void Foam::mapDistribute::distribute template<class T> void Foam::mapDistribute::distribute ( - List<T>& fld, + DynamicList<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 - ); - } + fld.shrink(); - //- Fill in transformed slots with copies - if (dummyTransform) - { - applyDummyTransforms(fld); - } + List<T>& fldList = static_cast<List<T>& >(fld); + + distribute(fldList, dummyTransform, tag); + + fld.setCapacity(fldList.size()); } @@ -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); } diff --git a/src/OpenFOAM/meshes/polyMesh/polyMeshIO.C b/src/OpenFOAM/meshes/polyMesh/polyMeshIO.C index 6015f1167ddfed9f450c2d0ef5f6911123294165..7b36d92c5875f37db8a065afc56043339e8fd0f2 100644 --- a/src/OpenFOAM/meshes/polyMesh/polyMeshIO.C +++ b/src/OpenFOAM/meshes/polyMesh/polyMeshIO.C @@ -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. @@ -227,7 +227,8 @@ Foam::polyMesh::readUpdateState Foam::polyMesh::readUpdate() newBoundary[patchI].start(), patchI, boundary_, - newBoundary[patchI].type() + newBoundary[patchI].physicalType(), + newBoundary[patchI].inGroups() ); } } diff --git a/src/OpenFOAM/meshes/polyMesh/polyMeshUpdate.C b/src/OpenFOAM/meshes/polyMesh/polyMeshUpdate.C index 4a8b5dd7d73802016d71614d439423c05d35a3ec..f26f77cad30b27fcd26c4311bb23a25f1412cccb 100644 --- a/src/OpenFOAM/meshes/polyMesh/polyMeshUpdate.C +++ b/src/OpenFOAM/meshes/polyMesh/polyMeshUpdate.C @@ -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. @@ -78,15 +78,43 @@ void Foam::polyMesh::updateMesh(const mapPolyMesh& mpm) newMotionPoints.setSize(points_.size()); // Map the list - newMotionPoints.map(oldMotionPoints, mpm.pointMap()); + if (mpm.hasMotionPoints()) + { + newMotionPoints.map(oldMotionPoints, mpm.pointMap()); - // Any points created out-of-nothing get set to the current coordinate - // for lack of anything better. - forAll(mpm.pointMap(), newPointI) + // Any points created out-of-nothing get set to the current + // coordinate for lack of anything better. + forAll(mpm.pointMap(), newPointI) + { + if (mpm.pointMap()[newPointI] == -1) + { + newMotionPoints[newPointI] = points_[newPointI]; + } + } + } + else { - if (mpm.pointMap()[newPointI] == -1) + const labelList& pointMap = mpm.pointMap(); + const labelList& revPointMap = mpm.reversePointMap(); + + forAll(pointMap, newPointI) { - newMotionPoints[newPointI] = points_[newPointI]; + label oldPointI = pointMap[newPointI]; + if (oldPointI >= 0) + { + if (revPointMap[oldPointI] == newPointI) // master point + { + newMotionPoints[newPointI] = oldMotionPoints[oldPointI]; + } + else + { + newMotionPoints[newPointI] = points_[newPointI]; + } + } + else + { + newMotionPoints[newPointI] = points_[newPointI]; + } } } } diff --git a/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/cyclic/cyclicPolyPatch.C b/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/cyclic/cyclicPolyPatch.C index 05720e178f18951c9e60b976801df101a9a8161a..c4fcaf52c0f4b7e9f9a3c4a518003687fd7fb536 100644 --- a/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/cyclic/cyclicPolyPatch.C +++ b/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/cyclic/cyclicPolyPatch.C @@ -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. @@ -29,11 +29,9 @@ License #include "polyMesh.H" #include "demandDrivenData.H" #include "OFstream.H" -#include "patchZones.H" #include "matchPoints.H" #include "EdgeMap.H" #include "Time.H" -#include "diagTensor.H" #include "transformField.H" #include "SubField.H" #include "unitConversion.H" diff --git a/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/nonuniformTransformCyclic/nonuniformTransformCyclicPolyPatch.H b/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/nonuniformTransformCyclic/nonuniformTransformCyclicPolyPatch.H index 75431fdaa8250d9dc83ef6aace600e2c346161e9..e04604c4ed528de7b3dd42ee62147bccbba3ab46 100644 --- a/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/nonuniformTransformCyclic/nonuniformTransformCyclicPolyPatch.H +++ b/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/nonuniformTransformCyclic/nonuniformTransformCyclicPolyPatch.H @@ -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. @@ -44,7 +44,7 @@ namespace Foam { /*---------------------------------------------------------------------------*\ - Class nonuniformTransformCyclicPolyPatch Declaration + Class nonuniformTransformCyclicPolyPatch Declaration \*---------------------------------------------------------------------------*/ class nonuniformTransformCyclicPolyPatch diff --git a/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/processor/processorPolyPatch.C b/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/processor/processorPolyPatch.C index 5b2a4332fdca2af5f616d95fcb91d509d4ffb2cd..0ca20652c9c910d07d6df92743d17bf3e8987b89 100644 --- a/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/processor/processorPolyPatch.C +++ b/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/processor/processorPolyPatch.C @@ -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. @@ -913,7 +913,7 @@ bool Foam::processorPolyPatch::order faceMap ); - // Try using face point average for matching + // Fallback: try using face point average for matching if (!matchedAll) { const pointField& ppPoints = pp.points(); @@ -933,16 +933,20 @@ bool Foam::processorPolyPatch::order scalarField tols2 ( - calcFaceTol(pp, pp.points(), facePointAverages) + matchTolerance() + *calcFaceTol(pp, pp.points(), facePointAverages) ); + // Note that we do not use the faceNormals anymore for + // comparison. Since we're + // having problems with the face centres (e.g. due to extreme + // aspect ratios) we will probably also have problems with + // reliable normals calculation labelList faceMap2(faceMap.size(), -1); matchedAll = matchPoints ( facePointAverages, masterFacePointAverages, - pp.faceNormals(), - masterNormals, tols2, true, faceMap2 diff --git a/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/processor/processorPolyPatch.H b/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/processor/processorPolyPatch.H index 63c2a7dd8ad3d3f6b2914cff5530139f3831c703..188bc45e6260aea8d8ec23314e1fb4dfc79b8677 100644 --- a/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/processor/processorPolyPatch.H +++ b/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/processor/processorPolyPatch.H @@ -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. @@ -62,13 +62,13 @@ class processorPolyPatch int myProcNo_; int neighbProcNo_; - //- Processor-neighbbour patch face centres + //- Processor-neighbour patch face centres vectorField neighbFaceCentres_; - //- Processor-neighbbour patch face areas + //- Processor-neighbour patch face areas vectorField neighbFaceAreas_; - //- Processor-neighbbour patch neighbour cell centres + //- Processor-neighbour patch neighbour cell centres vectorField neighbFaceCellCentres_; //- Corresponding neighbouring local point label for every local point @@ -270,19 +270,19 @@ public: return !owner(); } - //- Return processor-neighbbour patch face centres + //- Return processor-neighbour patch face centres const vectorField& neighbFaceCentres() const { return neighbFaceCentres_; } - //- Return processor-neighbbour patch face areas + //- Return processor-neighbour patch face areas const vectorField& neighbFaceAreas() const { return neighbFaceAreas_; } - //- Return processor-neighbbour patch neighbour cell centres + //- Return processor-neighbour patch neighbour cell centres const vectorField& neighbFaceCellCentres() const { return neighbFaceCellCentres_; diff --git a/src/OpenFOAM/meshes/polyMesh/polyPatches/polyPatch/polyPatch.C b/src/OpenFOAM/meshes/polyMesh/polyPatches/polyPatch/polyPatch.C index d7508c3d94a5b214f6ef45991488380d2b0cde29..dd1583577ffac12499a8f453ff8be82335d5b648 100644 --- a/src/OpenFOAM/meshes/polyMesh/polyPatches/polyPatch/polyPatch.C +++ b/src/OpenFOAM/meshes/polyMesh/polyPatches/polyPatch/polyPatch.C @@ -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. @@ -107,6 +107,30 @@ Foam::polyPatch::polyPatch } +Foam::polyPatch::polyPatch +( + const word& name, + const label size, + const label start, + const label index, + const polyBoundaryMesh& bm, + const word& physicalType, + const wordList& inGroups +) +: + patchIdentifier(name, index, physicalType, inGroups), + primitivePatch + ( + faceSubList(bm.mesh().faces(), size, start), + bm.mesh().points() + ), + start_(start), + boundaryMesh_(bm), + faceCellsPtr_(NULL), + mePtr_(NULL) +{} + + Foam::polyPatch::polyPatch ( const word& name, diff --git a/src/OpenFOAM/meshes/polyMesh/polyPatches/polyPatch/polyPatch.H b/src/OpenFOAM/meshes/polyMesh/polyPatches/polyPatch/polyPatch.H index b13faf0968f96576e3f96cf29cb17488215e71c3..2e12697a1843124b1be69017053c5c7208d48c76 100644 --- a/src/OpenFOAM/meshes/polyMesh/polyPatches/polyPatch/polyPatch.H +++ b/src/OpenFOAM/meshes/polyMesh/polyPatches/polyPatch/polyPatch.H @@ -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. @@ -179,6 +179,18 @@ public: const word& patchType ); + //- Construct from components + polyPatch + ( + const word& name, + const label size, + const label start, + const label index, + const polyBoundaryMesh& bm, + const word& physicalType, + const wordList& inGroups + ); + //- Construct from dictionary polyPatch ( diff --git a/src/OpenFOAM/meshes/primitiveShapes/triangle/triPoints.H b/src/OpenFOAM/meshes/primitiveShapes/triangle/triPoints.H new file mode 100644 index 0000000000000000000000000000000000000000..e152599dc61742877e6edf533fe4a00f59b1a90d --- /dev/null +++ b/src/OpenFOAM/meshes/primitiveShapes/triangle/triPoints.H @@ -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 + +// ************************************************************************* // diff --git a/src/OpenFOAM/primitives/ops/flipOp.C b/src/OpenFOAM/primitives/ops/flipOp.C new file mode 100644 index 0000000000000000000000000000000000000000..5555f686b3d0fb026212f842242c3454ec1b4eaa --- /dev/null +++ b/src/OpenFOAM/primitives/ops/flipOp.C @@ -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; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/primitives/ops/flipOp.H b/src/OpenFOAM/primitives/ops/flipOp.H new file mode 100644 index 0000000000000000000000000000000000000000..58d671ab38bb3ebc632a75b4972587c38508bfe2 --- /dev/null +++ b/src/OpenFOAM/primitives/ops/flipOp.H @@ -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 + +// ************************************************************************* // diff --git a/src/dynamicMesh/Make/files b/src/dynamicMesh/Make/files index c9c748ec4aa995c5adf81e9a06e7f5375dc2e611..96b80d6e3202f710261150d4dfb32352110018d0 100644 --- a/src/dynamicMesh/Make/files +++ b/src/dynamicMesh/Make/files @@ -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 diff --git a/src/dynamicMesh/fvMeshDistribute/IOmapDistributePolyMesh.C b/src/dynamicMesh/fvMeshDistribute/IOmapDistributePolyMesh.C new file mode 100644 index 0000000000000000000000000000000000000000..c476a1ed2cb94179aade83f25ed180ab969e4d9d --- /dev/null +++ b/src/dynamicMesh/fvMeshDistribute/IOmapDistributePolyMesh.C @@ -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(); +} + + +// ************************************************************************* // diff --git a/src/dynamicMesh/fvMeshDistribute/IOmapDistributePolyMesh.H b/src/dynamicMesh/fvMeshDistribute/IOmapDistributePolyMesh.H new file mode 100644 index 0000000000000000000000000000000000000000..4aede4a7ecc6bda9bed408cdff58ca9c7c9ddfb7 --- /dev/null +++ b/src/dynamicMesh/fvMeshDistribute/IOmapDistributePolyMesh.H @@ -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 + +// ************************************************************************* // diff --git a/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.C b/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.C index 31619469d10ebaf18ccae66c26978a96fa3ade19..4859b7efaf7e9dd32f76f0b67412505ba54b7767 100644 --- a/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.C +++ b/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.C @@ -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 ) ); } diff --git a/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.H b/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.H index a469d99d13e5fbb9080d9b327264996ab372b291..b3d3a476563b6e1e4ed790907f80267ca3abc4dc 100644 --- a/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.H +++ b/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.H @@ -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&); }; diff --git a/src/dynamicMesh/fvMeshDistribute/fvMeshDistributeTemplates.C b/src/dynamicMesh/fvMeshDistribute/fvMeshDistributeTemplates.C index c97df63b4ab92d1070c1a4850559995fb9005f3a..ee943c08f3d550d754ba8f4c82c630df8645da76 100644 --- a/src/dynamicMesh/fvMeshDistribute/fvMeshDistributeTemplates.C +++ b/src/dynamicMesh/fvMeshDistribute/fvMeshDistributeTemplates.C @@ -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 diff --git a/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubset.C b/src/dynamicMesh/fvMeshSubset/fvMeshSubset.C similarity index 91% rename from src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubset.C rename to src/dynamicMesh/fvMeshSubset/fvMeshSubset.C index 3a377e2ffa94c96ec2133238ffda2c8508889a10..6b86923a6e11ff1a1ecd699baa6302814d5832a6 100644 --- a/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubset.C +++ b/src/dynamicMesh/fvMeshSubset/fvMeshSubset.C @@ -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(); diff --git a/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubset.H b/src/dynamicMesh/fvMeshSubset/fvMeshSubset.H similarity index 74% rename from src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubset.H rename to src/dynamicMesh/fvMeshSubset/fvMeshSubset.H index 5f2a281d06596dc735a98af6eeb6453ebbaa765c..792825ce6c077efca3f3d1f74ed2b1211987ab88 100644 --- a/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubset.H +++ b/src/dynamicMesh/fvMeshSubset/fvMeshSubset.H @@ -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; + }; diff --git a/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubsetInterpolate.C b/src/dynamicMesh/fvMeshSubset/fvMeshSubsetInterpolate.C similarity index 89% rename from src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubsetInterpolate.C rename to src/dynamicMesh/fvMeshSubset/fvMeshSubsetInterpolate.C index 78811948187039baf4636ed948981f6c620d85e5..e987136f36a8658951107ff376ce983b1ffaf14a 100644 --- a/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubsetInterpolate.C +++ b/src/dynamicMesh/fvMeshSubset/fvMeshSubsetInterpolate.C @@ -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 diff --git a/src/dynamicMesh/fvMeshTools/fvMeshTools.C b/src/dynamicMesh/fvMeshTools/fvMeshTools.C index 682a96422e731eeb70ed7d4c1b8f6e9a3041c5ec..91ad543a0e313eb6da75badafe11079968d4e871 100644 --- a/src/dynamicMesh/fvMeshTools/fvMeshTools.C +++ b/src/dynamicMesh/fvMeshTools/fvMeshTools.C @@ -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; +} + + // ************************************************************************* // diff --git a/src/dynamicMesh/fvMeshTools/fvMeshTools.H b/src/dynamicMesh/fvMeshTools/fvMeshTools.H index 0e7e132d9c182df1ab76a0c67b663ad1babb3b63..e458425d0b2870db96ece3e047c1b27a1e4a871f 100644 --- a/src/dynamicMesh/fvMeshTools/fvMeshTools.H +++ b/src/dynamicMesh/fvMeshTools/fvMeshTools.H @@ -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 + ); + }; diff --git a/src/dynamicMesh/meshCut/cellLooper/geomCellLooper.H b/src/dynamicMesh/meshCut/cellLooper/geomCellLooper.H index bf5b7f1d651d831973d2fd9b41a82f33d8724311..5a2d42e4a0fa4896e8a4ddf64de439630769f5ca 100644 --- a/src/dynamicMesh/meshCut/cellLooper/geomCellLooper.H +++ b/src/dynamicMesh/meshCut/cellLooper/geomCellLooper.H @@ -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 diff --git a/src/dynamicMesh/meshCut/meshModifiers/multiDirRefinement/multiDirRefinement.C b/src/dynamicMesh/meshCut/meshModifiers/multiDirRefinement/multiDirRefinement.C index 3668134cc492cb27c3c8ff47917baedd6fadcf20..1bcfd8c4242770ab139814293f77191129eaaa3c 100644 --- a/src/dynamicMesh/meshCut/meshModifiers/multiDirRefinement/multiDirRefinement.C +++ b/src/dynamicMesh/meshCut/meshModifiers/multiDirRefinement/multiDirRefinement.C @@ -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 ); diff --git a/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8.C b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.C similarity index 99% rename from src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8.C rename to src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.C index 38dd6908e4086c675d91997864f1b7167332be0c..a0a98a1756f402285f52db45df34abd5e5d60291 100644 --- a/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8.C +++ b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.C @@ -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), diff --git a/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8.H b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.H similarity index 100% rename from src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8.H rename to src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.H diff --git a/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8Data.C b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8Data.C new file mode 100644 index 0000000000000000000000000000000000000000..ac5357cafaf321e4e6316deda46e5ac3202dea13 --- /dev/null +++ b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8Data.C @@ -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; +} + + +// ************************************************************************* // diff --git a/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8Data.H b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8Data.H new file mode 100644 index 0000000000000000000000000000000000000000..3e7fc3cec00dfb9df2d70681e407fc6dcc5cd862 --- /dev/null +++ b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8Data.H @@ -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 + +// ************************************************************************* // diff --git a/src/dynamicMesh/polyTopoChange/polyTopoChange/refinementHistory.C b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/refinementHistory.C similarity index 65% rename from src/dynamicMesh/polyTopoChange/polyTopoChange/refinementHistory.C rename to src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/refinementHistory.C index 8e9e844cb5b6d7d834dab0d9882e4969dbf7ae21..95c007145450f4b10e6d881a801346482a891362 100644 --- a/src/dynamicMesh/polyTopoChange/polyTopoChange/refinementHistory.C +++ b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/refinementHistory.C @@ -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,73 +38,6 @@ defineTypeNameAndDebug(refinementHistory, 0); } - -// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // - -void Foam::refinementHistory::writeEntry -( - const List<splitCell8>& splitCells, - const splitCell8& split -) -{ - // Write me: - if (split.addedCellsPtr_.valid()) - { - Pout<< "parent:" << split.parent_ - << " subCells:" << split.addedCellsPtr_() - << endl; - } - else - { - Pout<< "parent:" << split.parent_ - << " no subcells" - << endl; - } - - if (split.parent_ >= 0) - { - Pout<< "parent data:" << endl; - // Write my parent - string oldPrefix = Pout.prefix(); - Pout.prefix() = " " + oldPrefix; - writeEntry(splitCells, splitCells[split.parent_]); - Pout.prefix() = oldPrefix; - } -} - - -void Foam::refinementHistory::writeDebug -( - const labelList& visibleCells, - const List<splitCell8>& splitCells -) -{ - string oldPrefix = Pout.prefix(); - Pout.prefix() = ""; - - forAll(visibleCells, cellI) - { - label index = visibleCells[cellI]; - - if (index >= 0) - { - Pout<< "Cell from refinement:" << cellI << " index:" << index - << endl; - - string oldPrefix = Pout.prefix(); - Pout.prefix() = " " + oldPrefix; - writeEntry(splitCells, splitCells[index]); - Pout.prefix() = oldPrefix; - } - else - { - Pout<< "Unrefined cell:" << cellI << " index:" << index << endl; - } - } - Pout.prefix() = oldPrefix; -} - - // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // //- Construct null @@ -144,7 +76,58 @@ Foam::refinementHistory::splitCell8::splitCell8(const splitCell8& sc) {} -// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // +// * * * * * * * * * * * * * * 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) { @@ -189,6 +172,72 @@ Foam::Ostream& Foam::operator<< } +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::refinementHistory::writeEntry +( + const List<splitCell8>& splitCells, + const splitCell8& split +) +{ + // Write me: + if (split.addedCellsPtr_.valid()) + { + Pout<< "parent:" << split.parent_ + << " subCells:" << split.addedCellsPtr_() + << endl; + } + else + { + Pout<< "parent:" << split.parent_ + << " no subcells" + << endl; + } + + if (split.parent_ >= 0) + { + Pout<< "parent data:" << endl; + // Write my parent + string oldPrefix = Pout.prefix(); + Pout.prefix() = " " + oldPrefix; + writeEntry(splitCells, splitCells[split.parent_]); + Pout.prefix() = oldPrefix; + } +} + + +void Foam::refinementHistory::writeDebug +( + const labelList& visibleCells, + const List<splitCell8>& splitCells +) +{ + string oldPrefix = Pout.prefix(); + Pout.prefix() = ""; + + forAll(visibleCells, cellI) + { + label index = visibleCells[cellI]; + + if (index >= 0) + { + Pout<< "Cell from refinement:" << cellI << " index:" << index + << endl; + + string oldPrefix = Pout.prefix(); + Pout.prefix() = " " + oldPrefix; + writeEntry(splitCells, splitCells[index]); + Pout.prefix() = oldPrefix; + } + else + { + Pout<< "Unrefined cell:" << cellI << " index:" << index << endl; + } + } + Pout.prefix() = oldPrefix; +} + + 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; diff --git a/src/dynamicMesh/polyTopoChange/polyTopoChange/refinementHistory.H b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/refinementHistory.H similarity index 70% rename from src/dynamicMesh/polyTopoChange/polyTopoChange/refinementHistory.H rename to src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/refinementHistory.H index 4d5d854b457ec939319ea705c3bcb47c639c6bb0..40a11a0b6e1595815414eafa0041976f07222e13 100644 --- a/src/dynamicMesh/polyTopoChange/polyTopoChange/refinementHistory.H +++ b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/refinementHistory.H @@ -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&); }; diff --git a/src/finiteVolume/Make/files b/src/finiteVolume/Make/files index 1b9c242765d4fa990d84b093cef7d78a213e8824..3dec7db1683466ad4add2cba78691d5b022d0475 100644 --- a/src/finiteVolume/Make/files +++ b/src/finiteVolume/Make/files @@ -2,7 +2,6 @@ fvMesh/fvMeshGeometry.C fvMesh/fvMesh.C fvMesh/singleCellFvMesh/singleCellFvMesh.C -fvMesh/fvMeshSubset/fvMeshSubset.C fvBoundaryMesh = fvMesh/fvBoundaryMesh $(fvBoundaryMesh)/fvBoundaryMesh.C diff --git a/src/finiteVolume/fields/fvPatchFields/derived/fixedFluxPressure/fixedFluxPressureFvPatchScalarField.C b/src/finiteVolume/fields/fvPatchFields/derived/fixedFluxPressure/fixedFluxPressureFvPatchScalarField.C index 0a5a4b4809391dbf3a85d24e924cb9d4b41fec8b..8ff20e427245e805983b1ba4b119fae3fc218172 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/fixedFluxPressure/fixedFluxPressureFvPatchScalarField.C +++ b/src/finiteVolume/fields/fvPatchFields/derived/fixedFluxPressure/fixedFluxPressureFvPatchScalarField.C @@ -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); } } diff --git a/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingMappedFixedValue/timeVaryingMappedFixedValueFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingMappedFixedValue/timeVaryingMappedFixedValueFvPatchField.C index 48c3af199e25e93612b15f475c69c25bc7733f65..7d12f9e0ca41bd9718436121ae829f5ce283cd0b 100644 --- a/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingMappedFixedValue/timeVaryingMappedFixedValueFvPatchField.C +++ b/src/finiteVolume/fields/fvPatchFields/derived/timeVaryingMappedFixedValue/timeVaryingMappedFixedValueFvPatchField.C @@ -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(), diff --git a/src/finiteVolume/fields/fvPatchFields/fvPatchField/fvPatchField.C b/src/finiteVolume/fields/fvPatchFields/fvPatchField/fvPatchField.C index 21aad2c1ce1a9222226deb910463f514d838e1e9..f6d3b02d2badf2e3414c30168c178f0d3fc40c20 100644 --- a/src/finiteVolume/fields/fvPatchFields/fvPatchField/fvPatchField.C +++ b/src/finiteVolume/fields/fvPatchFields/fvPatchField/fvPatchField.C @@ -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]; + } } } } diff --git a/src/finiteVolume/interpolation/volPointInterpolation/volPointInterpolate.C b/src/finiteVolume/interpolation/volPointInterpolation/volPointInterpolate.C index 2c9bf7d5e4b1d601cce470a11069aa6026a382de..a39468535c9ca6bc06713a01cc16e23cc63d388d 100644 --- a/src/finiteVolume/interpolation/volPointInterpolation/volPointInterpolate.C +++ b/src/finiteVolume/interpolation/volPointInterpolation/volPointInterpolate.C @@ -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 diff --git a/src/finiteVolume/interpolation/volPointInterpolation/volPointInterpolation.H b/src/finiteVolume/interpolation/volPointInterpolation/volPointInterpolation.H index 6e82d741e4c0ef52ebad3fa59148da32bf1989e1..fac26df10c0cb8f1b8bef25cdc14ab5dd9d94903 100644 --- a/src/finiteVolume/interpolation/volPointInterpolation/volPointInterpolation.H +++ b/src/finiteVolume/interpolation/volPointInterpolation/volPointInterpolation.H @@ -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) diff --git a/src/lagrangian/basic/passiveParticle/passiveParticle.H b/src/lagrangian/basic/passiveParticle/passiveParticle.H index 5309722ebfd30f44eed7d6cd4cca96999506bfe5..4b23d84190f3ebca86c3e1641274b5156e56f6a8 100644 --- a/src/lagrangian/basic/passiveParticle/passiveParticle.H +++ b/src/lagrangian/basic/passiveParticle/passiveParticle.H @@ -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) + ); + } + }; + }; diff --git a/src/meshTools/AABBTree/AABBTree.C b/src/meshTools/AABBTree/AABBTree.C new file mode 100644 index 0000000000000000000000000000000000000000..2a2f4eb43e04a5608022ad32f73daf4e6f48cf50 --- /dev/null +++ b/src/meshTools/AABBTree/AABBTree.C @@ -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; +} + + +// ************************************************************************* // diff --git a/src/meshTools/AABBTree/AABBTree.H b/src/meshTools/AABBTree/AABBTree.H new file mode 100644 index 0000000000000000000000000000000000000000..b06c63af7fb7af743e64f26a426ad56d5367e172 --- /dev/null +++ b/src/meshTools/AABBTree/AABBTree.H @@ -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 + +// ************************************************************************* // diff --git a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C index 70372fc724493753794353d62e16bfe7f4901bb5..0e7a76242304b84b8b1d193672038c6f6fee555b 100644 --- a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C +++ b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C @@ -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) ) ); diff --git a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolationParallelOps.C b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolationParallelOps.C index 5abe0778eb4019cfcca028fc71ef30eac493d67f..b5db99c36ff8b35b739c3c38c0f018953b5643f0 100644 --- a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolationParallelOps.C +++ b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolationParallelOps.C @@ -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(); diff --git a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIMethod/AMIMethod/AMIMethod.C b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIMethod/AMIMethod/AMIMethod.C index 292d8167328ab3f36f0271a2af3f6fcc6f54afd1..8937e66ad1185ec366588578b710d15142ecae2a 100644 --- a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIMethod/AMIMethod/AMIMethod.C +++ b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIMethod/AMIMethod/AMIMethod.C @@ -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()) diff --git a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIMethod/directAMI/directAMI.C b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIMethod/directAMI/directAMI.C index b63e0f7ae02f5b01d8efec9b7e7f52d7c6d8cfba..9bf160f181076b285dd23b25181ae1a63f241a24 100644 --- a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIMethod/directAMI/directAMI.C +++ b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIMethod/directAMI/directAMI.C @@ -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); } } diff --git a/src/meshTools/AMIInterpolation/faceAreaIntersect/faceAreaIntersect.H b/src/meshTools/AMIInterpolation/faceAreaIntersect/faceAreaIntersect.H index a8dd739151f9a2a1756b6a3978b2952ae07ec370..91e6b759a3a605d8add57794fddde266398e10d2 100644 --- a/src/meshTools/AMIInterpolation/faceAreaIntersect/faceAreaIntersect.H +++ b/src/meshTools/AMIInterpolation/faceAreaIntersect/faceAreaIntersect.H @@ -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, diff --git a/src/meshTools/AMIInterpolation/faceAreaIntersect/faceAreaIntersectI.H b/src/meshTools/AMIInterpolation/faceAreaIntersect/faceAreaIntersectI.H index 87fab781e075adea10d95d8e0d6f458ce063a5fc..76bf413833ef34c3e744507323ffbe293cc21e10 100644 --- a/src/meshTools/AMIInterpolation/faceAreaIntersect/faceAreaIntersectI.H +++ b/src/meshTools/AMIInterpolation/faceAreaIntersect/faceAreaIntersectI.H @@ -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. @@ -41,7 +41,7 @@ inline void Foam::faceAreaIntersect::setTriPoints } -inline Foam::faceAreaIntersect::triPoints Foam::faceAreaIntersect::getTriPoints +inline Foam::triPoints Foam::faceAreaIntersect::getTriPoints ( const pointField& points, const face& f, diff --git a/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBase.C b/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBase.C index aa8fda17bd100834878109e9946c5c67b61b4ce1..24ab5870d1c8fe3fdb660171268661f1cfb4d1b3 100644 --- a/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBase.C +++ b/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBase.C @@ -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. @@ -837,25 +837,27 @@ void Foam::mappedPatchBase::calcAMI() const AMIPtr_.clear(); - if (debug) - { - const polyPatch& nbr = samplePolyPatch(); - pointField nbrPoints(nbr.localPoints()); + const polyPatch& nbr = samplePolyPatch(); - OFstream os(patch_.name() + "_neighbourPatch-org.obj"); - meshTools::writeOBJ(os, samplePolyPatch().localFaces(), nbrPoints); + // Transform neighbour patch to local system + pointField nbrPoints(samplePoints(nbr.localPoints())); - // transform neighbour patch to local system - primitivePatch nbrPatch0 + primitivePatch nbrPatch0 + ( + SubList<face> ( - SubList<face> - ( - nbr.localFaces(), - nbr.size() - ), - nbrPoints - ); + nbr.localFaces(), + nbr.size() + ), + nbrPoints + ); + + + if (debug) + { + OFstream os(patch_.name() + "_neighbourPatch-org.obj"); + meshTools::writeOBJ(os, samplePolyPatch().localFaces(), nbrPoints); OFstream osN(patch_.name() + "_neighbourPatch-trans.obj"); meshTools::writeOBJ(osN, nbrPatch0, nbrPoints); @@ -870,7 +872,7 @@ void Foam::mappedPatchBase::calcAMI() const new AMIPatchToPatchInterpolation ( patch_, - samplePolyPatch(), // nbrPatch0, + nbrPatch0, surfPtr(), faceAreaIntersect::tmMesh, true, diff --git a/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBaseTemplates.C b/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBaseTemplates.C index 8b5a50e394dac7a59abeb9408bccf1e67fd8a834..8960699bbc2a913eaaecc78cb33948fabd96318c 100644 --- a/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBaseTemplates.C +++ b/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBaseTemplates.C @@ -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. @@ -61,15 +61,18 @@ void Foam::mappedPatchBase::distribute } default: { - map().distribute + mapDistributeBase::distribute ( Pstream::defaultCommsType, map().schedule(), map().constructSize(), map().subMap(), + false, map().constructMap(), + false, lst, cop, + flipOp(), pTraits<Type>::zero ); } @@ -117,15 +120,18 @@ void Foam::mappedPatchBase::reverseDistribute default: { label cSize = sampleSize(); - map().distribute + mapDistributeBase::distribute ( Pstream::defaultCommsType, map().schedule(), cSize, map().constructMap(), + false, map().subMap(), + false, lst, cop, + flipOp(), pTraits<Type>::zero ); break; diff --git a/src/meshTools/momentOfInertia/momentOfInertia.C b/src/meshTools/momentOfInertia/momentOfInertia.C index bb17f5833cc6a8b28a20ef2b1b56ba54e5d4a6c1..93d6b82b3c2503bfeb6dbb747bf65ca55afb8942 100644 --- a/src/meshTools/momentOfInertia/momentOfInertia.C +++ b/src/meshTools/momentOfInertia/momentOfInertia.C @@ -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. @@ -192,7 +192,8 @@ void Foam::momentOfInertia::massPropertiesShell scalar density, scalar& mass, vector& cM, - tensor& J + tensor& J, + bool doReduce ) { // Reset properties for accumulation @@ -221,6 +222,12 @@ void Foam::momentOfInertia::massPropertiesShell mass += triMag; } + if (doReduce) + { + reduce(cM, sumOp<vector>()); + reduce(mass, sumOp<scalar>()); + } + cM /= mass; mass *= density; @@ -238,6 +245,11 @@ void Foam::momentOfInertia::massPropertiesShell pts[tri[2]] ).inertia(cM, density); } + + if (doReduce) + { + reduce(J, sumOp<tensor>()); + } } @@ -267,7 +279,8 @@ void Foam::momentOfInertia::massPropertiesShell scalar density, scalar& mass, vector& cM, - tensor& J + tensor& J, + bool doReduce ) { triFaceList faces(surf.size()); @@ -277,7 +290,41 @@ void Foam::momentOfInertia::massPropertiesShell faces[i] = triFace(surf[i]); } - massPropertiesShell(surf.points(), faces, density, mass, cM, J); + massPropertiesShell(surf.points(), faces, density, mass, cM, J, doReduce); +} + + +void Foam::momentOfInertia::massPropertiesPatch +( + const polyPatch& pp, + scalar density, + scalar& mass, + vector& cM, + tensor& J, + bool doReduce +) +{ + DynamicList<triFace> faces(3*pp.size()); + + // decompose patch faces using triangle fan + forAll(pp, faceI) + { + const face& f = pp[faceI]; + + if (f.size() > 2) + { + const label v0 = 0; + + for (label i = 1; i < f.size() - 1; i++) + { + faces.append(triFace(f[v0], f[i],f[i + 1])); + } + } + } + + triFaceList triFaces; + triFaces.transfer(faces); + massPropertiesShell(pp.points(), triFaces, density, mass, cM, J, doReduce); } diff --git a/src/meshTools/momentOfInertia/momentOfInertia.H b/src/meshTools/momentOfInertia/momentOfInertia.H index 0f56e8b00b7b6b8c9398f2ac9effa28ba11050c5..eef751385c47f5597c2cbe3ea57eaddbaf52b6fa 100644 --- a/src/meshTools/momentOfInertia/momentOfInertia.H +++ b/src/meshTools/momentOfInertia/momentOfInertia.H @@ -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. @@ -72,7 +72,8 @@ public: scalar density, scalar& mass, vector& cM, - tensor& J + tensor& J, + bool doReduce = false ); static void massPropertiesSolid @@ -90,7 +91,18 @@ public: scalar density, scalar& mass, vector& cM, - tensor& J + tensor& J, + bool doReduce = false + ); + + static void massPropertiesPatch + ( + const polyPatch& pp, + scalar density, + scalar& mass, + vector& cM, + tensor& J, + bool doReduce = false ); static tensor applyParallelAxisTheorem diff --git a/src/parallel/decompose/decompositionMethods/decompositionMethod/minData.H b/src/meshTools/regionSplit/minData.H similarity index 98% rename from src/parallel/decompose/decompositionMethods/decompositionMethod/minData.H rename to src/meshTools/regionSplit/minData.H index ad3fb947e1af7b3567f5ae517fc612187768ae25..b4af3a9111fd5deaf6f2601e09ab9c2c140a99be 100644 --- a/src/parallel/decompose/decompositionMethods/decompositionMethod/minData.H +++ b/src/meshTools/regionSplit/minData.H @@ -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. diff --git a/src/parallel/decompose/decompositionMethods/decompositionMethod/minDataI.H b/src/meshTools/regionSplit/minDataI.H similarity index 98% rename from src/parallel/decompose/decompositionMethods/decompositionMethod/minDataI.H rename to src/meshTools/regionSplit/minDataI.H index a079524cb89b960a5658388ceb44ac090666e4a7..88b2a9a2b834383bcd702cffeaa59462f18fec3a 100644 --- a/src/parallel/decompose/decompositionMethods/decompositionMethod/minDataI.H +++ b/src/meshTools/regionSplit/minDataI.H @@ -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. diff --git a/src/meshTools/tetOverlapVolume/tetOverlapVolume.C b/src/meshTools/tetOverlapVolume/tetOverlapVolume.C index db51ee66a6546fbdd0513ba3994d79848fc6d243..1d2bdcc81446d3721e21359665b10bce977d193d 100644 --- a/src/meshTools/tetOverlapVolume/tetOverlapVolume.C +++ b/src/meshTools/tetOverlapVolume/tetOverlapVolume.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2012-2015 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -39,6 +39,12 @@ namespace Foam defineTypeNameAndDebug(tetOverlapVolume, 0); } +// When to consider a tet to be zero volume. We want to avoid doing clipping +// against negative volume tets. Tet volume can be calculated incorrectly +// due to truncation errors. The value below works for single and double +// precision but could probably be tighter for double precision. +Foam::scalar Foam::tetOverlapVolume::minTetVolume_ = SMALL*SMALL; + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // @@ -48,79 +54,12 @@ Foam::tetOverlapVolume::tetOverlapVolume() // * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * * // -Foam::scalar Foam::tetOverlapVolume::tetTetOverlapVol -( - const tetPoints& tetA, - const tetPoints& tetB -) const -{ - static tetPointRef::tetIntersectionList insideTets; - label nInside = 0; - static tetPointRef::tetIntersectionList cutInsideTets; - label nCutInside = 0; - - tetPointRef::storeOp inside(insideTets, nInside); - tetPointRef::storeOp cutInside(cutInsideTets, nCutInside); - tetPointRef::sumVolOp volInside; - tetPointRef::dummyOp outside; - - if ((tetA.tet().mag() < SMALL*SMALL) || (tetB.tet().mag() < SMALL*SMALL)) - { - return 0.0; - } - - // face0 - plane pl0(tetB[1], tetB[3], tetB[2]); - tetA.tet().sliceWithPlane(pl0, cutInside, outside); - if (nCutInside == 0) - { - return 0.0; - } - - // face1 - plane pl1(tetB[0], tetB[2], tetB[3]); - nInside = 0; - for (label i = 0; i < nCutInside; i++) - { - const tetPointRef t = cutInsideTets[i].tet(); - t.sliceWithPlane(pl1, inside, outside); - } - if (nInside == 0) - { - return 0.0; - } - - // face2 - plane pl2(tetB[0], tetB[3], tetB[1]); - nCutInside = 0; - for (label i = 0; i < nInside; i++) - { - const tetPointRef t = insideTets[i].tet(); - t.sliceWithPlane(pl2, cutInside, outside); - } - if (nCutInside == 0) - { - return 0.0; - } - - // face3 - plane pl3(tetB[0], tetB[1], tetB[2]); - for (label i = 0; i < nCutInside; i++) - { - const tetPointRef t = cutInsideTets[i].tet(); - t.sliceWithPlane(pl3, volInside, outside); - } - - return volInside.vol_; -} - - Foam::treeBoundBox Foam::tetOverlapVolume::pyrBb ( const pointField& points, const face& f, const point& fc -) const +) { treeBoundBox bb(fc, fc); forAll(f, fp) @@ -145,122 +84,18 @@ bool Foam::tetOverlapVolume::cellCellOverlapMinDecomp const scalar threshold ) const { - const cell& cFacesA = meshA.cells()[cellAI]; - const point& ccA = meshA.cellCentres()[cellAI]; - - const cell& cFacesB = meshB.cells()[cellBI]; - const point& ccB = meshB.cellCentres()[cellBI]; - - scalar vol = 0.0; - - forAll(cFacesA, cFA) - { - label faceAI = cFacesA[cFA]; - - const face& fA = meshA.faces()[faceAI]; - const treeBoundBox pyrA = pyrBb(meshA.points(), fA, ccA); - if (!pyrA.overlaps(cellBbB)) - { - continue; - } - - bool ownA = (meshA.faceOwner()[faceAI] == cellAI); - - label tetBasePtAI = 0; - - const point& tetBasePtA = meshA.points()[fA[tetBasePtAI]]; - - for (label tetPtI = 1; tetPtI < fA.size() - 1; tetPtI++) - { - label facePtAI = (tetPtI + tetBasePtAI) % fA.size(); - label otherFacePtAI = fA.fcIndex(facePtAI); - - label pt0I = -1; - label pt1I = -1; - - if (ownA) - { - pt0I = fA[facePtAI]; - pt1I = fA[otherFacePtAI]; - } - else - { - pt0I = fA[otherFacePtAI]; - pt1I = fA[facePtAI]; - } - - const tetPoints tetA - ( - ccA, - tetBasePtA, - meshA.points()[pt0I], - meshA.points()[pt1I] - ); - const treeBoundBox tetABb(tetA.bounds()); - - - // Loop over tets of cellB - forAll(cFacesB, cFB) - { - label faceBI = cFacesB[cFB]; - - const face& fB = meshB.faces()[faceBI]; - const treeBoundBox pyrB = pyrBb(meshB.points(), fB, ccB); - if (!pyrB.overlaps(pyrA)) - { - continue; - } - - bool ownB = (meshB.faceOwner()[faceBI] == cellBI); - - label tetBasePtBI = 0; - - const point& tetBasePtB = meshB.points()[fB[tetBasePtBI]]; - - for (label tetPtI = 1; tetPtI < fB.size() - 1; tetPtI++) - { - label facePtBI = (tetPtI + tetBasePtBI) % fB.size(); - label otherFacePtBI = fB.fcIndex(facePtBI); - - label pt0I = -1; - label pt1I = -1; - - if (ownB) - { - pt0I = fB[facePtBI]; - pt1I = fB[otherFacePtBI]; - } - else - { - pt0I = fB[otherFacePtBI]; - pt1I = fB[facePtBI]; - } - - const tetPoints tetB - ( - ccB, - tetBasePtB, - meshB.points()[pt0I], - meshB.points()[pt1I] - ); - - if (!tetB.bounds().overlaps(tetABb)) - { - continue; - } - - vol += tetTetOverlapVol(tetA, tetB); - - if (vol > threshold) - { - return true; - } - } - } - } - } - - return false; + hasOverlapOp overlapCheckOp(threshold); + cellCellOverlapMinDecomp<hasOverlapOp> + ( + meshA, + cellAI, + meshB, + cellBI, + cellBbB, + overlapCheckOp + ); + + return overlapCheckOp.ok_; } @@ -268,121 +103,50 @@ Foam::scalar Foam::tetOverlapVolume::cellCellOverlapVolumeMinDecomp ( const primitiveMesh& meshA, const label cellAI, + const primitiveMesh& meshB, const label cellBI, const treeBoundBox& cellBbB ) const { - const cell& cFacesA = meshA.cells()[cellAI]; - const point& ccA = meshA.cellCentres()[cellAI]; - - const cell& cFacesB = meshB.cells()[cellBI]; - const point& ccB = meshB.cellCentres()[cellBI]; + sumOverlapOp overlapSumOp; + cellCellOverlapMinDecomp<sumOverlapOp> + ( + meshA, + cellAI, + meshB, + cellBI, + cellBbB, + overlapSumOp + ); + + return overlapSumOp.iop_.vol_; +} - scalar vol = 0.0; - forAll(cFacesA, cFA) - { - label faceAI = cFacesA[cFA]; - - const face& fA = meshA.faces()[faceAI]; - const treeBoundBox pyrA = pyrBb(meshA.points(), fA, ccA); - if (!pyrA.overlaps(cellBbB)) - { - continue; - } - - bool ownA = (meshA.faceOwner()[faceAI] == cellAI); - - label tetBasePtAI = 0; - - const point& tetBasePtA = meshA.points()[fA[tetBasePtAI]]; - - for (label tetPtI = 1; tetPtI < fA.size() - 1; tetPtI++) - { - label facePtAI = (tetPtI + tetBasePtAI) % fA.size(); - label otherFacePtAI = fA.fcIndex(facePtAI); - - label pt0I = -1; - label pt1I = -1; - - if (ownA) - { - pt0I = fA[facePtAI]; - pt1I = fA[otherFacePtAI]; - } - else - { - pt0I = fA[otherFacePtAI]; - pt1I = fA[facePtAI]; - } - - const tetPoints tetA - ( - ccA, - tetBasePtA, - meshA.points()[pt0I], - meshA.points()[pt1I] - ); - const treeBoundBox tetABb(tetA.bounds()); - - - // Loop over tets of cellB - forAll(cFacesB, cFB) - { - label faceBI = cFacesB[cFB]; - - const face& fB = meshB.faces()[faceBI]; - const treeBoundBox pyrB = pyrBb(meshB.points(), fB, ccB); - if (!pyrB.overlaps(pyrA)) - { - continue; - } - - bool ownB = (meshB.faceOwner()[faceBI] == cellBI); - - label tetBasePtBI = 0; - - const point& tetBasePtB = meshB.points()[fB[tetBasePtBI]]; - - for (label tetPtI = 1; tetPtI < fB.size() - 1; tetPtI++) - { - label facePtBI = (tetPtI + tetBasePtBI) % fB.size(); - label otherFacePtBI = fB.fcIndex(facePtBI); - - label pt0I = -1; - label pt1I = -1; - - if (ownB) - { - pt0I = fB[facePtBI]; - pt1I = fB[otherFacePtBI]; - } - else - { - pt0I = fB[otherFacePtBI]; - pt1I = fB[facePtBI]; - } - - const tetPoints tetB - ( - ccB, - tetBasePtB, - meshB.points()[pt0I], - meshB.points()[pt1I] - ); - if (!tetB.bounds().overlaps(tetABb)) - { - continue; - } - - vol += tetTetOverlapVol(tetA, tetB); - } - } - } - } +Foam::Tuple2<Foam::scalar, Foam::point> +Foam::tetOverlapVolume::cellCellOverlapMomentMinDecomp +( + const primitiveMesh& meshA, + const label cellAI, - return vol; + const primitiveMesh& meshB, + const label cellBI, + const treeBoundBox& cellBbB +) const +{ + sumOverlapMomentOp overlapSumOp; + cellCellOverlapMinDecomp<sumOverlapMomentOp> + ( + meshA, + cellAI, + meshB, + cellBI, + cellBbB, + overlapSumOp + ); + + return overlapSumOp.iop_.vol_; } diff --git a/src/meshTools/tetOverlapVolume/tetOverlapVolume.H b/src/meshTools/tetOverlapVolume/tetOverlapVolume.H index 87c65dcd89cf96be6cb59ec19e2b0d8b78036f0c..0a47519f58d95e087b6ad474bbde011fbcffd9c6 100644 --- a/src/meshTools/tetOverlapVolume/tetOverlapVolume.H +++ b/src/meshTools/tetOverlapVolume/tetOverlapVolume.H @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2012-2013 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. @@ -29,6 +29,7 @@ Description SourceFiles tetOverlapVolume.C + tetOverlapVolumeTemplates.C \*---------------------------------------------------------------------------*/ @@ -38,13 +39,14 @@ SourceFiles #include "FixedList.H" #include "labelList.H" #include "treeBoundBox.H" +#include "Tuple2.H" +#include "tetrahedron.H" namespace Foam { class primitiveMesh; class polyMesh; -class tetPoints; /*---------------------------------------------------------------------------*\ Class tetOverlapVolume Declaration @@ -52,22 +54,130 @@ class tetPoints; class tetOverlapVolume { + // Private data + + //- Minimum tet volume to skip test + static scalar minTetVolume_; + + + // Private classes + + //- tetPoints handling : sum resulting volumes + class sumMomentOp + { + public: + Tuple2<scalar, point> vol_; + + inline sumMomentOp() + : + vol_(0.0, vector::zero) + {} + + inline void operator()(const tetPoints& tet) + { + const tetPointRef t(tet.tet()); + scalar tetVol = t.mag(); + vol_.first() += tetVol; + vol_.second() += (tetVol*t.centre()); + } + }; + + //- tetPoints combining : check for overlap + class hasOverlapOp + { + public: + + const scalar threshold_; + tetPointRef::sumVolOp iop_; + bool ok_; + + inline hasOverlapOp(const scalar threshold) + : + threshold_(threshold), + iop_(), + ok_(false) + {} + + //- Overlap two tets + inline bool operator()(const tetPoints& A, const tetPoints& B) + { + tetTetOverlap<tetPointRef::sumVolOp>(A, B, iop_); + ok_ = (iop_.vol_ > threshold_); + return ok_; + } + }; + + //- tetPoints combining : sum overlap volume + class sumOverlapOp + { + public: + + tetPointRef::sumVolOp iop_; + + inline sumOverlapOp() + : + iop_() + {} + + //- Overlap two tets + inline bool operator()(const tetPoints& A, const tetPoints& B) + { + tetTetOverlap<tetPointRef::sumVolOp>(A, B, iop_); + return false; + } + }; + + //- tetPoints combining : sum overlap volume + class sumOverlapMomentOp + { + public: + + sumMomentOp iop_; + + inline sumOverlapMomentOp() + : + iop_() + {} + + //- Overlap two tets + inline bool operator()(const tetPoints& A, const tetPoints& B) + { + tetTetOverlap<sumMomentOp>(A, B, iop_); + return false; + } + }; + + // Private member functions - //- Tet overlap volume - scalar tetTetOverlapVol + //- Tet overlap calculation + template<class tetPointsOp> + static void tetTetOverlap ( const tetPoints& tetA, - const tetPoints& tetB - ) const; + const tetPoints& tetB, + tetPointsOp& insideOp + ); + + //- Cell overlap calculation + template<class tetsOp> + static void cellCellOverlapMinDecomp + ( + const primitiveMesh& meshA, + const label cellAI, + const primitiveMesh& meshB, + const label cellBI, + const treeBoundBox& cellBbB, + tetsOp& combineTetsOp + ); //- Return a const treeBoundBox - treeBoundBox pyrBb + static treeBoundBox pyrBb ( const pointField& points, const face& f, const point& fc - ) const; + ); public: @@ -114,6 +224,17 @@ public: const label cellBI, const treeBoundBox& cellBbB ) const; + + //- Calculates the overlap volume and moment + Tuple2<scalar, point> cellCellOverlapMomentMinDecomp + ( + const primitiveMesh& meshA, + const label cellAI, + + const primitiveMesh& meshB, + const label cellBI, + const treeBoundBox& cellBbB + ) const; }; @@ -123,6 +244,12 @@ public: // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +#ifdef NoRepository +# include "tetOverlapVolumeTemplates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + #endif // ************************************************************************* // diff --git a/src/meshTools/tetOverlapVolume/tetOverlapVolumeTemplates.C b/src/meshTools/tetOverlapVolume/tetOverlapVolumeTemplates.C new file mode 100644 index 0000000000000000000000000000000000000000..4a58931cc95efe74434176f8e928146ac2d6ada5 --- /dev/null +++ b/src/meshTools/tetOverlapVolume/tetOverlapVolumeTemplates.C @@ -0,0 +1,220 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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 "tetOverlapVolume.H" +#include "primitiveMesh.H" + +// * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * * // + +template<class tetPointsOp> +void Foam::tetOverlapVolume::tetTetOverlap +( + const tetPoints& tetA, + const tetPoints& tetB, + tetPointsOp& insideOp +) +{ + static tetPointRef::tetIntersectionList insideTets; + label nInside = 0; + static tetPointRef::tetIntersectionList cutInsideTets; + label nCutInside = 0; + + tetPointRef::storeOp inside(insideTets, nInside); + tetPointRef::storeOp cutInside(cutInsideTets, nCutInside); + tetPointRef::dummyOp outside; + + if (tetA.tet().mag() < minTetVolume_ || tetB.tet().mag() < minTetVolume_) + { + return; + } + + // face0 + plane pl0(tetB[1], tetB[3], tetB[2]); + tetA.tet().sliceWithPlane(pl0, cutInside, outside); + if (nCutInside == 0) + { + return; + } + + // face1 + plane pl1(tetB[0], tetB[2], tetB[3]); + nInside = 0; + for (label i = 0; i < nCutInside; i++) + { + const tetPointRef t = cutInsideTets[i].tet(); + t.sliceWithPlane(pl1, inside, outside); + } + if (nInside == 0) + { + return; + } + + // face2 + plane pl2(tetB[0], tetB[3], tetB[1]); + nCutInside = 0; + for (label i = 0; i < nInside; i++) + { + const tetPointRef t = insideTets[i].tet(); + t.sliceWithPlane(pl2, cutInside, outside); + } + if (nCutInside == 0) + { + return; + } + + // face3 + plane pl3(tetB[0], tetB[1], tetB[2]); + for (label i = 0; i < nCutInside; i++) + { + const tetPointRef t = cutInsideTets[i].tet(); + t.sliceWithPlane(pl3, insideOp, outside); + } +} + + +template<class tetsOp> +void Foam::tetOverlapVolume::cellCellOverlapMinDecomp +( + const primitiveMesh& meshA, + const label cellAI, + + const primitiveMesh& meshB, + const label cellBI, + const treeBoundBox& cellBbB, + tetsOp& combineTetsOp +) +{ + const cell& cFacesA = meshA.cells()[cellAI]; + const point& ccA = meshA.cellCentres()[cellAI]; + + const cell& cFacesB = meshB.cells()[cellBI]; + const point& ccB = meshB.cellCentres()[cellBI]; + + forAll(cFacesA, cFA) + { + label faceAI = cFacesA[cFA]; + + const face& fA = meshA.faces()[faceAI]; + const treeBoundBox pyrA = pyrBb(meshA.points(), fA, ccA); + if (!pyrA.overlaps(cellBbB)) + { + continue; + } + + bool ownA = (meshA.faceOwner()[faceAI] == cellAI); + + label tetBasePtAI = 0; + + const point& tetBasePtA = meshA.points()[fA[tetBasePtAI]]; + + for (label tetPtI = 1; tetPtI < fA.size() - 1; tetPtI++) + { + label facePtAI = (tetPtI + tetBasePtAI) % fA.size(); + label otherFacePtAI = fA.fcIndex(facePtAI); + + label pt0I = -1; + label pt1I = -1; + + if (ownA) + { + pt0I = fA[facePtAI]; + pt1I = fA[otherFacePtAI]; + } + else + { + pt0I = fA[otherFacePtAI]; + pt1I = fA[facePtAI]; + } + + const tetPoints tetA + ( + ccA, + tetBasePtA, + meshA.points()[pt0I], + meshA.points()[pt1I] + ); + const treeBoundBox tetABb(tetA.bounds()); + + // Loop over tets of cellB + forAll(cFacesB, cFB) + { + label faceBI = cFacesB[cFB]; + + const face& fB = meshB.faces()[faceBI]; + const treeBoundBox pyrB = pyrBb(meshB.points(), fB, ccB); + if (!pyrB.overlaps(pyrA)) + { + continue; + } + + bool ownB = (meshB.faceOwner()[faceBI] == cellBI); + + label tetBasePtBI = 0; + + const point& tetBasePtB = meshB.points()[fB[tetBasePtBI]]; + + for (label tetPtI = 1; tetPtI < fB.size() - 1; tetPtI++) + { + label facePtBI = (tetPtI + tetBasePtBI) % fB.size(); + label otherFacePtBI = fB.fcIndex(facePtBI); + + label pt0I = -1; + label pt1I = -1; + + if (ownB) + { + pt0I = fB[facePtBI]; + pt1I = fB[otherFacePtBI]; + } + else + { + pt0I = fB[otherFacePtBI]; + pt1I = fB[facePtBI]; + } + + const tetPoints tetB + ( + ccB, + tetBasePtB, + meshB.points()[pt0I], + meshB.points()[pt1I] + ); + if (!tetB.bounds().overlaps(tetABb)) + { + continue; + } + + if (combineTetsOp(tetA, tetB)) + { + return; + } + } + } + } + } +} + + +// ************************************************************************* // diff --git a/src/parallel/decompose/Allwmake b/src/parallel/decompose/Allwmake index 603ee5277b812626c31753f74e6cd488c7f0a4f0..bee297a6e957789e084b82decd3ef49745130ea6 100755 --- a/src/parallel/decompose/Allwmake +++ b/src/parallel/decompose/Allwmake @@ -29,11 +29,13 @@ wmakeMpiLib() do ( WM_OPTIONS="$WM_OPTIONS$WM_MPLIB" - whichmpi="$WM_PROJECT_DIR/platforms/$WM_OPTIONS/src/parallel/decompose/$libName/using:$FOAM_MPI" - whichscotch="$WM_PROJECT_DIR/platforms/$WM_OPTIONS/src/parallel/decompose/$libName/using:$SCOTCH_VERSION" + libDir="$WM_PROJECT_DIR/platforms/$WM_OPTIONS/src/parallel/decompose/$libName" + whichmpi="$libDir/using:$FOAM_MPI" + whichscotch="$libDir/using:$SCOTCH_VERSION" [ -e "$whichmpi" -a -e "$whichscotch" ] || wclean $libName echo "wmake $targetType $libName" wmake $targetType $libName + mkdir -p "$libDir" touch "$whichmpi" "$whichscotch" ) done @@ -50,6 +52,15 @@ then if [ -d "$FOAM_LIBBIN/$FOAM_MPI" ] then + #- Bit of a hack: ptscotch 6 requires scotch linked as well as. Can be + # removed once ptscotch declares dependency on scotch itself. + case "$SCOTCH_VERSION" in + scotch_6.*) + export LINK_FLAGS="-lscotch" + ;; + esac + + wmakeMpiLib ptscotchDecomp fi else diff --git a/src/parallel/decompose/decompose/Make/files b/src/parallel/decompose/decompose/Make/files index 2d0f959eaed2fa913a61f4cdbaf873f4d465ece5..5fabd38ccef57caf31d6d495eb45184fa8bb9fa9 100644 --- a/src/parallel/decompose/decompose/Make/files +++ b/src/parallel/decompose/decompose/Make/files @@ -1,3 +1,4 @@ +decompositionModel.C fvFieldDecomposer.C LIB = $(FOAM_LIBBIN)/libdecompose diff --git a/src/parallel/decompose/decompose/Make/options b/src/parallel/decompose/decompose/Make/options index 7a728f9dd7cf75800c9b44943a2964c781376576..6d9b2cd6e31fe03114f177247b6b183c061eb6cf 100644 --- a/src/parallel/decompose/decompose/Make/options +++ b/src/parallel/decompose/decompose/Make/options @@ -1,6 +1,7 @@ EXE_INC = \ -I$(LIB_SRC)/finiteVolume/lnInclude \ -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(LIB_SRC)/parallel/decompose/decompositionMethods/lnInclude \ -I$(LIB_SRC)/lagrangian/basic/lnInclude LIB_LIBS = \ diff --git a/src/parallel/decompose/decompose/decompositionModel.C b/src/parallel/decompose/decompose/decompositionModel.C new file mode 100644 index 0000000000000000000000000000000000000000..c4ff6724857523c3398383f29fc1eb060b85f063 --- /dev/null +++ b/src/parallel/decompose/decompose/decompositionModel.C @@ -0,0 +1,164 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 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 "decompositionModel.H" +#include "polyMesh.H" +#include "Time.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + defineTypeNameAndDebug(decompositionModel, 0); +} + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::decompositionModel::decompositionModel +( + const polyMesh& mesh, + const fileName& decompDictFile +) +: + MeshObject + < + polyMesh, + Foam::UpdateableMeshObject, + decompositionModel + >(mesh), + IOdictionary + ( + selectIO + ( + IOobject + ( + "decomposeParDict", + mesh.time().system(), + mesh.local(), + mesh.db(), + IOobject::MUST_READ, + IOobject::NO_WRITE, + false //io.registerObject(), + ), + decompDictFile + ) + ) +{} + + +Foam::decompositionModel::decompositionModel +( + const polyMesh& mesh, + const dictionary& dict, + const fileName& decompDictFile +) +: + MeshObject + < + polyMesh, + Foam::UpdateableMeshObject, + decompositionModel + >(mesh), + IOdictionary + ( + selectIO + ( + IOobject + ( + "decomposeParDict", + mesh.time().system(), + mesh.local(), + mesh.db(), + (dict.size() ? IOobject::NO_READ : IOobject::MUST_READ), + IOobject::NO_WRITE, + false //io.registerObject(), + ), + decompDictFile + ), + dict + ) +{} + + +// * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * // + +const Foam::decompositionModel& Foam::decompositionModel::New +( + const polyMesh& mesh, + const fileName& decompDictFile +) +{ + return + MeshObject + < + polyMesh, + Foam::UpdateableMeshObject, + decompositionModel + >::New(mesh, decompDictFile); +} + + +const Foam::decompositionModel& Foam::decompositionModel::New +( + const polyMesh& mesh, + const dictionary& dict, + const fileName& decompDictFile +) +{ + return + MeshObject + < + polyMesh, + Foam::UpdateableMeshObject, + decompositionModel + >::New(mesh, dict, decompDictFile); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +Foam::IOobject Foam::decompositionModel::selectIO +( + const IOobject& io, + const fileName& f +) +{ + return + ( + f.size() + ? IOobject // construct from filePath instead + ( + f, + io.db(), + io.readOpt(), + io.writeOpt(), + io.registerObject() + ) + : io + ); +} + + +// ************************************************************************* // diff --git a/src/parallel/decompose/decompose/decompositionModel.H b/src/parallel/decompose/decompose/decompositionModel.H new file mode 100644 index 0000000000000000000000000000000000000000..30a4b295140685c3f574d976c71e355f2e1eb9cc --- /dev/null +++ b/src/parallel/decompose/decompose/decompositionModel.H @@ -0,0 +1,145 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 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/>. + +Class + Foam::decompositionModel + +Description + MeshObject wrapper of decompositionMethod + +SourceFiles + +\*---------------------------------------------------------------------------*/ + +#ifndef decompositionModel_H +#define decompositionModel_H + +#include "IOdictionary.H" +#include "MeshObject.H" +#include "decompositionMethod.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward declaration of classes +class mapPolyMesh; +class polyMesh; + +/*---------------------------------------------------------------------------*\ + Class decompositionModel Declaration +\*---------------------------------------------------------------------------*/ + +class decompositionModel +: + public MeshObject + < + polyMesh, + UpdateableMeshObject, + decompositionModel + >, + public IOdictionary +{ + + // Private data + + mutable autoPtr<decompositionMethod> decomposerPtr_; + + +public: + + // Declare name of the class and its debug switch + ClassName("decompositionModel"); + + + // Selectors + + //- Read (optionallly from absolute path) & register on mesh + static const decompositionModel& New + ( + const polyMesh& mesh, + const fileName& decompDictFile = "" + ); + + //- Read (optionallly from supplied dictionary) & register on mesh + static const decompositionModel& New + ( + const polyMesh& mesh, + const dictionary& dict, + const fileName& decompDictFile = "" + ); + + + // Constructors + + //- Construct from typeName or optional path to controlDictionary + decompositionModel(const polyMesh&, const fileName& = ""); + + + //- Construct from typeName or optional path to controlDictionary + decompositionModel + ( + const polyMesh&, + const dictionary& dict, + const fileName& = "" + ); + + + // Member functions + + decompositionMethod& decomposer() const + { + if (!decomposerPtr_.valid()) + { + decomposerPtr_ = decompositionMethod::New(*this); + } + return decomposerPtr_(); + } + + //- Helper: return IOobject with optionally absolute path provided + static IOobject selectIO(const IOobject&, const fileName&); + + + // UpdateableMeshObject + + virtual bool movePoints() + { + return false; + } + + virtual void updateMesh(const mapPolyMesh&) + {} + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/parallel/decompose/decompositionMethods/Make/files b/src/parallel/decompose/decompositionMethods/Make/files index c2837d2eb320880626cf8fa1cca120dfa718e39a..2aef948ff7a22d15cb43a6f84f1437e200f2edd3 100644 --- a/src/parallel/decompose/decompositionMethods/Make/files +++ b/src/parallel/decompose/decompositionMethods/Make/files @@ -7,4 +7,15 @@ multiLevelDecomp/multiLevelDecomp.C structuredDecomp/structuredDecomp.C noDecomp/noDecomp.C + +decompositionConstraints = decompositionConstraints + +$(decompositionConstraints)/decompositionConstraint/decompositionConstraint.C +$(decompositionConstraints)/preserveBaffles/preserveBafflesConstraint.C +$(decompositionConstraints)/preserveFaceZones/preserveFaceZonesConstraint.C +$(decompositionConstraints)/preservePatches/preservePatchesConstraint.C +$(decompositionConstraints)/singleProcessorFaceSets/singleProcessorFaceSetsConstraint.C +$(decompositionConstraints)/refinementHistory/refinementHistoryConstraint.C + + LIB = $(FOAM_LIBBIN)/libdecompositionMethods diff --git a/src/parallel/decompose/decompositionMethods/Make/options b/src/parallel/decompose/decompositionMethods/Make/options index f3070a731e46532261f92d0a3e815cf03a1ff2bc..45133caabbc96216595fb48cf8889878c1a620c4 100644 --- a/src/parallel/decompose/decompositionMethods/Make/options +++ b/src/parallel/decompose/decompositionMethods/Make/options @@ -1,7 +1,9 @@ EXE_INC = \ -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(LIB_SRC)/dynamicMesh/lnInclude \ -I$(LIB_SRC)/finiteVolume/lnInclude LIB_LIBS = \ -lmeshTools \ + -ldynamicMesh \ -lfiniteVolume diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/decompositionConstraint/decompositionConstraint.C b/src/parallel/decompose/decompositionMethods/decompositionConstraints/decompositionConstraint/decompositionConstraint.C new file mode 100644 index 0000000000000000000000000000000000000000..397433ff68ded84ca769b6fbcbbd4fd03f672885 --- /dev/null +++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/decompositionConstraint/decompositionConstraint.C @@ -0,0 +1,93 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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 "decompositionConstraint.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +defineTypeNameAndDebug(decompositionConstraint, 1); +defineRunTimeSelectionTable(decompositionConstraint, dictionary); +} + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::decompositionConstraint::decompositionConstraint +( + const dictionary& constraintsDict, + const word& type +) +: + //coeffDict_(constraintsDict.subOrEmptyDict(type + "Coeffs")) + coeffDict_(constraintsDict) +{} + + +// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * // + +Foam::autoPtr<Foam::decompositionConstraint> +Foam::decompositionConstraint::New +( + const dictionary& dict, + const word& modelType +) +{ + Info<< "Selecting decompositionConstraint " << modelType << endl; + + dictionaryConstructorTable::iterator cstrIter = + dictionaryConstructorTablePtr_->find(modelType); + + if (cstrIter == dictionaryConstructorTablePtr_->end()) + { + FatalIOErrorIn + ( + "decompositionConstraint::New" + "(" + "const dictionary&, " + "const word&" + ")", + dict + ) << "Unknown decompositionConstraint type " + << modelType << nl << nl + << "Valid decompositionConstraint types:" << endl + << dictionaryConstructorTablePtr_->sortedToc() + << exit(FatalIOError); + } + + return autoPtr<decompositionConstraint> + ( + cstrIter()(dict, modelType) + ); +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::decompositionConstraint::~decompositionConstraint() +{} + + +// ************************************************************************* // diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/decompositionConstraint/decompositionConstraint.H b/src/parallel/decompose/decompositionMethods/decompositionConstraints/decompositionConstraint/decompositionConstraint.H new file mode 100644 index 0000000000000000000000000000000000000000..e06f7a07dab52be290eeb7f695a80aa98e93f8cf --- /dev/null +++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/decompositionConstraint/decompositionConstraint.H @@ -0,0 +1,155 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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::decompositionConstraint + +Description + +SourceFiles + decompositionConstraint.C + +\*---------------------------------------------------------------------------*/ + +#ifndef decompositionConstraint_H +#define decompositionConstraint_H + +#include "dictionary.H" +#include "runTimeSelectionTables.H" +#include "boolList.H" +#include "labelList.H" +#include "labelPair.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward declaration of classes +class polyMesh; + +/*---------------------------------------------------------------------------*\ + Class decompositionConstraint Declaration +\*---------------------------------------------------------------------------*/ + +class decompositionConstraint +{ +protected: + + // Protected data + + //- Model coefficients dictionary + dictionary coeffDict_; + +private: + + // Private Member Functions + + //- Disallow default bitwise copy construct + decompositionConstraint(const decompositionConstraint&); + + //- Disallow default bitwise assignment + void operator=(const decompositionConstraint&); + + +public: + + //- Runtime type information + TypeName("decompositionConstraint"); + + + // Declare run-time constructor selection table + + declareRunTimeSelectionTable + ( + autoPtr, + decompositionConstraint, + dictionary, + ( + const dictionary& constraintsDict, + const word& type + ), + (constraintsDict, type) + ); + + + // Constructors + + //- Construct with generic dictionary with optional entry for type + decompositionConstraint + ( + const dictionary& constraintsDict, + const word& type + ); + + // Selectors + + //- Return a reference to the selected decompositionConstraint + static autoPtr<decompositionConstraint> New + ( + const dictionary& constraintsDict, + const word& type + ); + + + //- Destructor + virtual ~decompositionConstraint(); + + + // Member Functions + + //- Add my constraints to list of constraints + virtual void add + ( + const polyMesh& mesh, + boolList& blockedFace, + PtrList<labelList>& specifiedProcessorFaces, + labelList& specifiedProcessor, + List<labelPair>& explicitConnections + ) const = 0; + + //- Apply any additional post-decomposition constraints. Usually no + // need to do anything since decomposition method should have already + // obeyed the constraints + virtual void apply + ( + const polyMesh& mesh, + const boolList& blockedFace, + const PtrList<labelList>& specifiedProcessorFaces, + const labelList& specifiedProcessor, + const List<labelPair>& explicitConnections, + labelList& decomposition + ) const + {} +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveBaffles/preserveBafflesConstraint.C b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveBaffles/preserveBafflesConstraint.C new file mode 100644 index 0000000000000000000000000000000000000000..a22f683c04adffd468c90f33f21d278954828d99 --- /dev/null +++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveBaffles/preserveBafflesConstraint.C @@ -0,0 +1,245 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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 "preserveBafflesConstraint.H" +#include "addToRunTimeSelectionTable.H" +#include "syncTools.H" +#include "localPointRegion.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace decompositionConstraints +{ +defineTypeName(preserveBafflesConstraint); +addToRunTimeSelectionTable +( + decompositionConstraint, + preserveBafflesConstraint, + dictionary +); +} +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::decompositionConstraints::preserveBafflesConstraint:: +preserveBafflesConstraint +( + const dictionary& constraintsDict, + const word& modelType +) +: + decompositionConstraint(constraintsDict, typeName) +{ + if (decompositionConstraint::debug) + { + Info<< type() << " : setting constraints to preserve baffles" + //<< returnReduce(bafflePairs.size(), sumOp<label>()) + << endl; + } +} + + +Foam::decompositionConstraints::preserveBafflesConstraint:: +preserveBafflesConstraint() +: + decompositionConstraint(dictionary(), typeName) +{ + if (decompositionConstraint::debug) + { + Info<< type() << " : setting constraints to preserve baffles" + //<< returnReduce(bafflePairs.size(), sumOp<label>()) + << endl; + } +} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +void Foam::decompositionConstraints::preserveBafflesConstraint::add +( + const polyMesh& mesh, + boolList& blockedFace, + PtrList<labelList>& specifiedProcessorFaces, + labelList& specifiedProcessor, + List<labelPair>& explicitConnections +) const +{ + const labelPairList bafflePairs + ( + localPointRegion::findDuplicateFacePairs(mesh) + ); + + if (decompositionConstraint::debug & 2) + { + Info<< type() << " : setting constraints to preserve " + << returnReduce(bafflePairs.size(), sumOp<label>()) + << " baffles" << endl; + } + + + // Merge into explicitConnections + { + // Convert into face-to-face addressing + labelList faceToFace(mesh.nFaces(), -1); + forAll(explicitConnections, i) + { + const labelPair& p = explicitConnections[i]; + faceToFace[p[0]] = p[1]; + faceToFace[p[1]] = p[0]; + } + + // Merge in bafflePairs + forAll(bafflePairs, i) + { + const labelPair& p = bafflePairs[i]; + + if (faceToFace[p[0]] == -1 && faceToFace[p[1]] == -1) + { + faceToFace[p[0]] = p[1]; + faceToFace[p[1]] = p[0]; + } + else if (labelPair::compare(p, labelPair(p[0], faceToFace[p[0]]))) + { + // Connection already present + } + else + { + label p0Slave = faceToFace[p[0]]; + label p1Slave = faceToFace[p[1]]; + IOWarningIn + ( + "preserveBafflesConstraint::add(..)", + coeffDict_ + ) << "When adding baffle between faces " + << p[0] << " at " << mesh.faceCentres()[p[0]] + << " and " + << p[1] << " at " << mesh.faceCentres()[p[1]] + << " : face " << p[0] << " already is connected to face " + << p0Slave << " at " << mesh.faceCentres()[p0Slave] + << " and face " << p[1] << " already is connected to face " + << p1Slave << " at " << mesh.faceCentres()[p1Slave] + << endl; + } + } + + // Convert back into labelPairList + label n = 0; + forAll(faceToFace, faceI) + { + label otherFaceI = faceToFace[faceI]; + if (otherFaceI != -1 && faceI < otherFaceI) + { + // I am master of slave + n++; + } + } + explicitConnections.setSize(n); + n = 0; + forAll(faceToFace, faceI) + { + label otherFaceI = faceToFace[faceI]; + if (otherFaceI != -1 && faceI < otherFaceI) + { + explicitConnections[n++] = labelPair(faceI, otherFaceI); + } + } + } + + // Make sure blockedFace is uptodate + blockedFace.setSize(mesh.nFaces(), true); + forAll(explicitConnections, i) + { + blockedFace[explicitConnections[i].first()] = false; + blockedFace[explicitConnections[i].second()] = false; + } + syncTools::syncFaceList(mesh, blockedFace, andEqOp<bool>()); +} + + +void Foam::decompositionConstraints::preserveBafflesConstraint::apply +( + const polyMesh& mesh, + const boolList& blockedFace, + const PtrList<labelList>& specifiedProcessorFaces, + const labelList& specifiedProcessor, + const List<labelPair>& explicitConnections, + labelList& decomposition +) const +{ + const labelPairList bafflePairs + ( + localPointRegion::findDuplicateFacePairs(mesh) + ); + + label nChanged = 0; + + forAll(bafflePairs, i) + { + const labelPair& baffle = bafflePairs[i]; + label f0 = baffle.first(); + label f1 = baffle.second(); + + const label procI = decomposition[mesh.faceOwner()[f0]]; + + if (mesh.isInternalFace(f0)) + { + label nei0 = mesh.faceNeighbour()[f0]; + if (decomposition[nei0] != procI) + { + decomposition[nei0] = procI; + nChanged++; + } + } + + label own1 = mesh.faceOwner()[f1]; + if (decomposition[own1] != procI) + { + decomposition[own1] = procI; + nChanged++; + } + if (mesh.isInternalFace(f1)) + { + label nei1 = mesh.faceNeighbour()[f1]; + if (decomposition[nei1] != procI) + { + decomposition[nei1] = procI; + } + } + } + + if (decompositionConstraint::debug & 2) + { + reduce(nChanged, sumOp<label>()); + Info<< type() << " : changed decomposition on " << nChanged + << " cells" << endl; + } +} + + +// ************************************************************************* // diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveBaffles/preserveBafflesConstraint.H b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveBaffles/preserveBafflesConstraint.H new file mode 100644 index 0000000000000000000000000000000000000000..ea6fcbfb3821bfabc1a5ad4d7133255574d54e6e --- /dev/null +++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveBaffles/preserveBafflesConstraint.H @@ -0,0 +1,116 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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::preserveBafflesConstraint + +Description + Detects baffles and keeps owner and neighbour on same processor. + +SourceFiles + preserveBafflesConstraint.C + +\*---------------------------------------------------------------------------*/ + +#ifndef preserveBafflesConstraint_H +#define preserveBafflesConstraint_H + +#include "decompositionConstraint.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +namespace decompositionConstraints +{ + +/*---------------------------------------------------------------------------*\ + Class preserveBafflesConstraint Declaration +\*---------------------------------------------------------------------------*/ + +class preserveBafflesConstraint +: + public decompositionConstraint +{ + // Private data + +public: + + //- Runtime type information + TypeName("preserveBaffles"); + + + // Constructors + + //- Construct with generic dictionary with optional entry for type + preserveBafflesConstraint + ( + const dictionary& constraintsDict, + const word& type + ); + + //- Construct from components + preserveBafflesConstraint(); + + + //- Destructor + virtual ~preserveBafflesConstraint() + {} + + + // Member Functions + + //- Add my constraints to list of constraints + virtual void add + ( + const polyMesh& mesh, + boolList& blockedFace, + PtrList<labelList>& specifiedProcessorFaces, + labelList& specifiedProcessor, + List<labelPair>& explicitConnections + ) const; + + //- Apply any additional post-decomposition constraints + virtual void apply + ( + const polyMesh& mesh, + const boolList& blockedFace, + const PtrList<labelList>& specifiedProcessorFaces, + const labelList& specifiedProcessor, + const List<labelPair>& explicitConnections, + labelList& decomposition + ) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace decompositionConstraints +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveFaceZones/preserveFaceZonesConstraint.C b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveFaceZones/preserveFaceZonesConstraint.C new file mode 100644 index 0000000000000000000000000000000000000000..fbc22df250fab4132d3346e6f2f70bb0c69410f5 --- /dev/null +++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveFaceZones/preserveFaceZonesConstraint.C @@ -0,0 +1,215 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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 "preserveFaceZonesConstraint.H" +#include "addToRunTimeSelectionTable.H" +#include "syncTools.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace decompositionConstraints +{ +defineTypeName(preserveFaceZonesConstraint); +addToRunTimeSelectionTable +( + decompositionConstraint, + preserveFaceZonesConstraint, + dictionary +); +} +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::decompositionConstraints::preserveFaceZonesConstraint:: +preserveFaceZonesConstraint +( + const dictionary& constraintsDict, + const word& modelType +) +: + decompositionConstraint(constraintsDict, typeName), + zones_(coeffDict_.lookup("zones")) +{ + if (decompositionConstraint::debug) + { + Info<< type() << " : adding constraints to keep owner and neighbour" + << " of faces in zones " << zones_ + << " on same processor" << endl; + } +} + + +Foam::decompositionConstraints::preserveFaceZonesConstraint:: +preserveFaceZonesConstraint +( + const wordReList& zones +) +: + decompositionConstraint(dictionary(), typeName), + zones_(zones) +{ + if (decompositionConstraint::debug) + { + Info<< type() << " : adding constraints to keep owner and neighbour" + << " of faces in zones " << zones_ + << " on same processor" << endl; + } +} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +void Foam::decompositionConstraints::preserveFaceZonesConstraint::add +( + const polyMesh& mesh, + boolList& blockedFace, + PtrList<labelList>& specifiedProcessorFaces, + labelList& specifiedProcessor, + List<labelPair>& explicitConnections +) const +{ + blockedFace.setSize(mesh.nFaces(), true); + + const faceZoneMesh& fZones = mesh.faceZones(); + + const labelList zoneIDs = findStrings(zones_, fZones.names()); + + label nUnblocked = 0; + + forAll(zoneIDs, i) + { + const faceZone& fz = fZones[zoneIDs[i]]; + + forAll(fz, i) + { + if (blockedFace[fz[i]]) + { + blockedFace[fz[i]] = false; + nUnblocked++; + } + } + } + + if (decompositionConstraint::debug & 2) + { + reduce(nUnblocked, sumOp<label>()); + Info<< type() << " : unblocked " << nUnblocked << " faces" << endl; + } + + syncTools::syncFaceList(mesh, blockedFace, andEqOp<bool>()); +} + + +void Foam::decompositionConstraints::preserveFaceZonesConstraint::apply +( + const polyMesh& mesh, + const boolList& blockedFace, + const PtrList<labelList>& specifiedProcessorFaces, + const labelList& specifiedProcessor, + const List<labelPair>& explicitConnections, + labelList& decomposition +) const +{ + // If the decomposition has not enforced the constraint do it over + // here. + + + // Synchronise decomposition on boundary + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + const polyBoundaryMesh& pbm = mesh.boundaryMesh(); + + labelList destProc(mesh.nFaces()-mesh.nInternalFaces(), labelMax); + + forAll(pbm, patchI) + { + const polyPatch& pp = pbm[patchI]; + + const labelUList& faceCells = pp.faceCells(); + + forAll(faceCells, i) + { + label bFaceI = pp.start()+i-mesh.nInternalFaces(); + destProc[bFaceI] = decomposition[faceCells[i]]; + } + } + + syncTools::syncBoundaryFaceList(mesh, destProc, minEqOp<label>()); + + + // Override if differing + // ~~~~~~~~~~~~~~~~~~~~~ + + const faceZoneMesh& fZones = mesh.faceZones(); + + const labelList zoneIDs = findStrings(zones_, fZones.names()); + + label nChanged = 0; + + forAll(zoneIDs, i) + { + const faceZone& fz = fZones[zoneIDs[i]]; + + forAll(fz, i) + { + label faceI = fz[i]; + + label own = mesh.faceOwner()[faceI]; + + if (mesh.isInternalFace(faceI)) + { + label nei = mesh.faceNeighbour()[faceI]; + if (decomposition[own] != decomposition[nei]) + { + decomposition[nei] = decomposition[own]; + nChanged++; + } + } + else + { + label bFaceI = faceI-mesh.nInternalFaces(); + if (decomposition[own] != destProc[bFaceI]) + { + decomposition[own] = destProc[bFaceI]; + nChanged++; + } + } + } + } + + if (decompositionConstraint::debug & 2) + { + reduce(nChanged, sumOp<label>()); + Info<< type() << " : changed decomposition on " << nChanged + << " cells" << endl; + } +} + + +// ************************************************************************* // diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveFaceZones/preserveFaceZonesConstraint.H b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveFaceZones/preserveFaceZonesConstraint.H new file mode 100644 index 0000000000000000000000000000000000000000..0f98d9a634ce259d1a7dbc0e650122d0543ab2bb --- /dev/null +++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preserveFaceZones/preserveFaceZonesConstraint.H @@ -0,0 +1,122 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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::preserveFaceZonesConstraint + +Description + Constraint to keep/move owner and neighbour of faceZone onto same + processor. + +SourceFiles + preserveFaceZonesConstraint.C + +\*---------------------------------------------------------------------------*/ + +#ifndef preserveFaceZonesConstraint_H +#define preserveFaceZonesConstraint_H + +#include "decompositionConstraint.H" +#include "wordReList.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +namespace decompositionConstraints +{ + +/*---------------------------------------------------------------------------*\ + Class preserveFaceZonesConstraint Declaration +\*---------------------------------------------------------------------------*/ + +class preserveFaceZonesConstraint +: + public decompositionConstraint +{ + // Private data + + //- List of zones to keep together + wordReList zones_; + + +public: + + //- Runtime type information + TypeName("preserveFaceZones"); + + + // Constructors + + //- Construct with generic dictionary with optional entry for type + preserveFaceZonesConstraint + ( + const dictionary& constraintsDict, + const word& type + ); + + //- Construct from components + preserveFaceZonesConstraint(const wordReList& zones); + + + //- Destructor + virtual ~preserveFaceZonesConstraint() + {} + + + // Member Functions + + //- Add my constraints to list of constraints + virtual void add + ( + const polyMesh& mesh, + boolList& blockedFace, + PtrList<labelList>& specifiedProcessorFaces, + labelList& specifiedProcessor, + List<labelPair>& explicitConnections + ) const; + + //- Apply any additional post-decomposition constraints + virtual void apply + ( + const polyMesh& mesh, + const boolList& blockedFace, + const PtrList<labelList>& specifiedProcessorFaces, + const labelList& specifiedProcessor, + const List<labelPair>& explicitConnections, + labelList& decomposition + ) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace decompositionConstraints +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/preservePatches/preservePatchesConstraint.C b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preservePatches/preservePatchesConstraint.C new file mode 100644 index 0000000000000000000000000000000000000000..d7918b0ea8d2b071f9fc9119039aeb59371029b1 --- /dev/null +++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preservePatches/preservePatchesConstraint.C @@ -0,0 +1,199 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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 "preservePatchesConstraint.H" +#include "addToRunTimeSelectionTable.H" +#include "syncTools.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace decompositionConstraints +{ +defineTypeName(preservePatchesConstraint); +addToRunTimeSelectionTable +( + decompositionConstraint, + preservePatchesConstraint, + dictionary +); +} +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::decompositionConstraints::preservePatchesConstraint:: +preservePatchesConstraint +( + const dictionary& constraintsDict, + const word& modelType +) +: + decompositionConstraint(constraintsDict, typeName), + patches_(coeffDict_.lookup("patches")) +{ + if (decompositionConstraint::debug) + { + Info<< type() << " : adding constraints to keep owner of faces" + << " in patches " << patches_ + << " on same processor. This only makes sense for cyclics." << endl; + } +} + + +Foam::decompositionConstraints::preservePatchesConstraint:: +preservePatchesConstraint +( + const wordReList& patches +) +: + decompositionConstraint(dictionary(), typeName), + patches_(patches) +{ + if (decompositionConstraint::debug) + { + Info<< type() << " : adding constraints to keep owner of faces" + << " in patches " << patches_ + << " on same processor. This only makes sense for cyclics." << endl; + } +} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +void Foam::decompositionConstraints::preservePatchesConstraint::add +( + const polyMesh& mesh, + boolList& blockedFace, + PtrList<labelList>& specifiedProcessorFaces, + labelList& specifiedProcessor, + List<labelPair>& explicitConnections +) const +{ + const polyBoundaryMesh& pbm = mesh.boundaryMesh(); + + blockedFace.setSize(mesh.nFaces(), true); + + const labelList patchIDs(pbm.patchSet(patches_).sortedToc()); + + label nUnblocked = 0; + + forAll(patchIDs, i) + { + const polyPatch& pp = pbm[patchIDs[i]]; + + forAll(pp, i) + { + if (blockedFace[pp.start() + i]) + { + blockedFace[pp.start() + i] = false; + nUnblocked++; + } + } + } + + if (decompositionConstraint::debug & 2) + { + reduce(nUnblocked, sumOp<label>()); + Info<< type() << " : unblocked " << nUnblocked << " faces" << endl; + } + + syncTools::syncFaceList(mesh, blockedFace, andEqOp<bool>()); +} + + +void Foam::decompositionConstraints::preservePatchesConstraint::apply +( + const polyMesh& mesh, + const boolList& blockedFace, + const PtrList<labelList>& specifiedProcessorFaces, + const labelList& specifiedProcessor, + const List<labelPair>& explicitConnections, + labelList& decomposition +) const +{ + // If the decomposition has not enforced the constraint do it over + // here. + + // Synchronise decomposition on patchIDs + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + const polyBoundaryMesh& pbm = mesh.boundaryMesh(); + + labelList destProc(mesh.nFaces()-mesh.nInternalFaces(), labelMax); + + forAll(pbm, patchI) + { + const polyPatch& pp = pbm[patchI]; + + const labelUList& faceCells = pp.faceCells(); + + forAll(faceCells, i) + { + label bFaceI = pp.start()+i-mesh.nInternalFaces(); + destProc[bFaceI] = decomposition[faceCells[i]]; + } + } + + syncTools::syncBoundaryFaceList(mesh, destProc, minEqOp<label>()); + + + // Override if differing + // ~~~~~~~~~~~~~~~~~~~~~ + + const labelList patchIDs(pbm.patchSet(patches_).sortedToc()); + + label nChanged = 0; + + forAll(patchIDs, i) + { + const polyPatch& pp = pbm[patchIDs[i]]; + + const labelUList& faceCells = pp.faceCells(); + + forAll(faceCells, i) + { + label bFaceI = pp.start()+i-mesh.nInternalFaces(); + + if (decomposition[faceCells[i]] != destProc[bFaceI]) + { + decomposition[faceCells[i]] = destProc[bFaceI]; + nChanged++; + } + } + } + + if (decompositionConstraint::debug & 2) + { + reduce(nChanged, sumOp<label>()); + Info<< type() << " : changed decomposition on " << nChanged + << " cells" << endl; + } +} + + +// ************************************************************************* // diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/preservePatches/preservePatchesConstraint.H b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preservePatches/preservePatchesConstraint.H new file mode 100644 index 0000000000000000000000000000000000000000..6b69a19ceda8e48f804cc1e7335c08892ce0dc6a --- /dev/null +++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/preservePatches/preservePatchesConstraint.H @@ -0,0 +1,123 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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::preservePatchesConstraint + +Description + Constraint to keep owner and neighbour of (cyclic) patch on same + processor. + +SourceFiles + preservePatchesConstraint.C + +\*---------------------------------------------------------------------------*/ + +#ifndef preservePatchesConstraint_H +#define preservePatchesConstraint_H + +#include "decompositionConstraint.H" +#include "wordReList.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +namespace decompositionConstraints +{ + +/*---------------------------------------------------------------------------*\ + Class preservePatchesConstraint Declaration +\*---------------------------------------------------------------------------*/ + +class preservePatchesConstraint +: + public decompositionConstraint +{ + // Private data + + //- List of patches to keep together + wordReList patches_; + + +public: + + //- Runtime type information + TypeName("preservePatches"); + + + // Constructors + + //- Construct with generic dictionary with optional entry for type + preservePatchesConstraint + ( + const dictionary& constraintsDict, + const word& type + ); + + //- Construct from components + preservePatchesConstraint(const wordReList& patches); + + + + //- Destructor + virtual ~preservePatchesConstraint() + {} + + + // Member Functions + + //- Add my constraints to list of constraints + virtual void add + ( + const polyMesh& mesh, + boolList& blockedFace, + PtrList<labelList>& specifiedProcessorFaces, + labelList& specifiedProcessor, + List<labelPair>& explicitConnections + ) const; + + //- Apply any additional post-decomposition constraints + virtual void apply + ( + const polyMesh& mesh, + const boolList& blockedFace, + const PtrList<labelList>& specifiedProcessorFaces, + const labelList& specifiedProcessor, + const List<labelPair>& explicitConnections, + labelList& decomposition + ) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace decompositionConstraints +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/refinementHistory/refinementHistoryConstraint.C b/src/parallel/decompose/decompositionMethods/decompositionConstraints/refinementHistory/refinementHistoryConstraint.C new file mode 100644 index 0000000000000000000000000000000000000000..25339a852b7345bd0cbd94932737d92ea0434146 --- /dev/null +++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/refinementHistory/refinementHistoryConstraint.C @@ -0,0 +1,211 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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 "refinementHistoryConstraint.H" +#include "addToRunTimeSelectionTable.H" +#include "syncTools.H" +#include "refinementHistory.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +defineTypeName(refinementHistoryConstraint); +addToRunTimeSelectionTable +( + decompositionConstraint, + refinementHistoryConstraint, + dictionary +); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::refinementHistoryConstraint::refinementHistoryConstraint +( + const dictionary& constraintsDict, + const word& modelType +) +: + decompositionConstraint(constraintsDict, typeName) +{ + if (decompositionConstraint::debug) + { + Info<< type() << " : setting constraints to preserve refinement history" + << endl; + } +} + + +Foam::refinementHistoryConstraint::refinementHistoryConstraint() +: + decompositionConstraint(dictionary(), typeName) +{ + if (decompositionConstraint::debug) + { + Info<< type() << " : setting constraints to refinement history" + << endl; + } +} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +void Foam::refinementHistoryConstraint::add +( + const polyMesh& mesh, + boolList& blockedFace, + PtrList<labelList>& specifiedProcessorFaces, + labelList& specifiedProcessor, + List<labelPair>& explicitConnections +) const +{ + autoPtr<const refinementHistory> storagePtr; + refinementHistory const* refPtr = NULL; + + if (mesh.foundObject<refinementHistory>("refinementHistory")) + { + if (decompositionConstraint::debug) + { + Info<< type() << " : found refinementHistory" << endl; + } + refPtr = &mesh.lookupObject<refinementHistory>("refinementHistory"); + } + else + { + if (decompositionConstraint::debug) + { + Info<< type() << " : reading refinementHistory from time " + << mesh.facesInstance() << endl; + } + storagePtr.reset + ( + new refinementHistory + ( + IOobject + ( + "refinementHistory", + mesh.facesInstance(), + polyMesh::meshSubDir, + mesh, + IOobject::READ_IF_PRESENT, + IOobject::NO_WRITE + ), + mesh.nCells() + ) + ); + } + + const refinementHistory& history = + ( + storagePtr.valid() + ? storagePtr() + : *refPtr + ); + + if (history.active()) + { + // refinementHistory itself implements decompositionConstraint + history.add + ( + blockedFace, + specifiedProcessorFaces, + specifiedProcessor, + explicitConnections + ); + } +} + + +void Foam::refinementHistoryConstraint::apply +( + const polyMesh& mesh, + const boolList& blockedFace, + const PtrList<labelList>& specifiedProcessorFaces, + const labelList& specifiedProcessor, + const List<labelPair>& explicitConnections, + labelList& decomposition +) const +{ + autoPtr<const refinementHistory> storagePtr; + refinementHistory const* refPtr = NULL; + + if (mesh.foundObject<refinementHistory>("refinementHistory")) + { + //if (decompositionConstraint::debug) + //{ + // Info<< type() << " : found refinementHistory" << endl; + //} + refPtr = &mesh.lookupObject<refinementHistory>("refinementHistory"); + } + else + { + //if (decompositionConstraint::debug) + //{ + // Info<< type() << " : reading refinementHistory from time " + // << mesh.facesInstance() << endl; + //} + storagePtr.reset + ( + new refinementHistory + ( + IOobject + ( + "refinementHistory", + mesh.facesInstance(), + polyMesh::meshSubDir, + mesh, + IOobject::READ_IF_PRESENT, + IOobject::NO_WRITE + ), + mesh.nCells() + ) + ); + } + + const refinementHistory& history = + ( + storagePtr.valid() + ? storagePtr() + : *refPtr + ); + + if (history.active()) + { + // refinementHistory itself implements decompositionConstraint + history.apply + ( + blockedFace, + specifiedProcessorFaces, + specifiedProcessor, + explicitConnections, + decomposition + ); + } +} + + +// ************************************************************************* // diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/refinementHistory/refinementHistoryConstraint.H b/src/parallel/decompose/decompositionMethods/decompositionConstraints/refinementHistory/refinementHistoryConstraint.H new file mode 100644 index 0000000000000000000000000000000000000000..92ff3aa8b36d66d2fcb86808d2b01f88e0ed3fdf --- /dev/null +++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/refinementHistory/refinementHistoryConstraint.H @@ -0,0 +1,114 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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::refinementHistoryConstraint + +Description + Constraint to keep all cells originating from refining the same cell + onto the same processor. Reads polyMesh/refinementHistory. + +SourceFiles + refinementHistoryConstraint.C + +\*---------------------------------------------------------------------------*/ + +#ifndef refinementHistoryConstraint_H +#define refinementHistoryConstraint_H + +#include "decompositionConstraint.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + + +/*---------------------------------------------------------------------------*\ + Class refinementHistoryConstraint Declaration +\*---------------------------------------------------------------------------*/ + +class refinementHistoryConstraint +: + public decompositionConstraint +{ + // Private data + +public: + + //- Runtime type information + TypeName("refinementHistory"); + + + // Constructors + + //- Construct with generic dictionary with optional entry for type + refinementHistoryConstraint + ( + const dictionary& constraintsDict, + const word& type + ); + + //- Construct from components + refinementHistoryConstraint(); + + + //- Destructor + virtual ~refinementHistoryConstraint() + {} + + + // Member Functions + + //- Add my constraints to list of constraints + virtual void add + ( + const polyMesh& mesh, + boolList& blockedFace, + PtrList<labelList>& specifiedProcessorFaces, + labelList& specifiedProcessor, + List<labelPair>& explicitConnections + ) const; + + //- Apply any additional post-decomposition constraints + virtual void apply + ( + const polyMesh& mesh, + const boolList& blockedFace, + const PtrList<labelList>& specifiedProcessorFaces, + const labelList& specifiedProcessor, + const List<labelPair>& explicitConnections, + labelList& decomposition + ) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/singleProcessorFaceSets/singleProcessorFaceSetsConstraint.C b/src/parallel/decompose/decompositionMethods/decompositionConstraints/singleProcessorFaceSets/singleProcessorFaceSetsConstraint.C new file mode 100644 index 0000000000000000000000000000000000000000..d0e6e2cab7741d90002345e8f05d710b819a605e --- /dev/null +++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/singleProcessorFaceSets/singleProcessorFaceSetsConstraint.C @@ -0,0 +1,318 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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 "singleProcessorFaceSetsConstraint.H" +#include "addToRunTimeSelectionTable.H" +#include "syncTools.H" +#include "faceSet.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace decompositionConstraints +{ +defineTypeName(singleProcessorFaceSetsConstraint); +addToRunTimeSelectionTable +( + decompositionConstraint, + singleProcessorFaceSetsConstraint, + dictionary +); +} +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::decompositionConstraints::singleProcessorFaceSetsConstraint:: +singleProcessorFaceSetsConstraint +( + const dictionary& constraintsDict, + const word& modelType +) +: + decompositionConstraint(constraintsDict, typeName), + setNameAndProcs_(coeffDict_.lookup("singleProcessorFaceSets")) +{ + if (decompositionConstraint::debug) + { + Info<< type() + << " : adding constraints to keep" << endl; + + forAll(setNameAndProcs_, setI) + { + Info<< " all cells connected to faceSet " + << setNameAndProcs_[setI].first() + << " on processor " << setNameAndProcs_[setI].second() << endl; + } + } +} + + +Foam::decompositionConstraints::singleProcessorFaceSetsConstraint:: +singleProcessorFaceSetsConstraint +( + const List<Tuple2<word, label> >& setNameAndProcs +) +: + decompositionConstraint(dictionary(), typeName), + setNameAndProcs_(setNameAndProcs) +{ + if (decompositionConstraint::debug) + { + Info<< type() + << " : adding constraints to keep" << endl; + + forAll(setNameAndProcs_, setI) + { + Info<< " all cells connected to faceSet " + << setNameAndProcs_[setI].first() + << " on processor " << setNameAndProcs_[setI].second() << endl; + } + } +} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +void Foam::decompositionConstraints::singleProcessorFaceSetsConstraint::add +( + const polyMesh& mesh, + boolList& blockedFace, + PtrList<labelList>& specifiedProcessorFaces, + labelList& specifiedProcessor, + List<labelPair>& explicitConnections +) const +{ + blockedFace.setSize(mesh.nFaces(), true); + + // Mark faces already in set + labelList faceToSet(mesh.nFaces(), -1); + forAll(specifiedProcessorFaces, setI) + { + const labelList& faceLabels = specifiedProcessorFaces[setI]; + forAll(faceLabels, i) + { + faceToSet[faceLabels[i]] = setI; + } + } + + + forAll(setNameAndProcs_, setI) + { + //Info<< "Keeping all cells connected to faceSet " + // << setNameAndProcs_[setI].first() + // << " on processor " << setNameAndProcs_[setI].second() << endl; + + const label destProcI = setNameAndProcs_[setI].second(); + + // Read faceSet + const faceSet fz(mesh, setNameAndProcs_[setI].first()); + + // Check that it does not overlap with existing specifiedProcessorFaces + labelList nMatch(specifiedProcessorFaces.size(), 0); + forAllConstIter(faceSet, fz, iter) + { + label setI = faceToSet[iter.key()]; + if (setI != -1) + { + nMatch[setI]++; + } + } + + + // Only store if all faces are not yet in specifiedProcessorFaces + // (on all processors) + bool store = true; + + forAll(nMatch, setI) + { + if (nMatch[setI] == fz.size()) + { + // full match + store = false; + break; + } + else if (nMatch[setI] > 0) + { + // partial match + store = false; + break; + } + } + + reduce(store, andOp<bool>()); + + + if (store) + { + specifiedProcessorFaces.append(new labelList(fz.sortedToc())); + specifiedProcessor.append(destProcI); + } + } + + + // Unblock all point connected faces + // 1. Mark all points on specifiedProcessorFaces + boolList procFacePoint(mesh.nPoints(), false); + forAll(specifiedProcessorFaces, setI) + { + const labelList& set = specifiedProcessorFaces[setI]; + forAll(set, fI) + { + const face& f = mesh.faces()[set[fI]]; + forAll(f, fp) + { + procFacePoint[f[fp]] = true; + } + } + } + syncTools::syncPointList(mesh, procFacePoint, orEqOp<bool>(), false); + + // 2. Unblock all faces on procFacePoint + + label nUnblocked = 0; + + forAll(procFacePoint, pointI) + { + if (procFacePoint[pointI]) + { + const labelList& pFaces = mesh.pointFaces()[pointI]; + forAll(pFaces, i) + { + if (blockedFace[pFaces[i]]) + { + blockedFace[pFaces[i]] = false; + nUnblocked++; + } + } + } + } + + if (decompositionConstraint::debug & 2) + { + reduce(nUnblocked, sumOp<label>()); + Info<< type() << " : unblocked " << nUnblocked << " faces" << endl; + } + + syncTools::syncFaceList(mesh, blockedFace, andEqOp<bool>()); +} + + +void Foam::decompositionConstraints::singleProcessorFaceSetsConstraint::apply +( + const polyMesh& mesh, + const boolList& blockedFace, + const PtrList<labelList>& specifiedProcessorFaces, + const labelList& specifiedProcessor, + const List<labelPair>& explicitConnections, + labelList& decomposition +) const +{ + // For specifiedProcessorFaces rework the cellToProc to enforce + // all on one processor since we can't guarantee that the input + // to regionSplit was a single region. + // E.g. faceSet 'a' with the cells split into two regions + // by a notch formed by two walls + // + // \ / + // \ / + // ---a----+-----a----- + // + // + // Note that reworking the cellToProc might make the decomposition + // unbalanced. + label nChanged = 0; + + forAll(specifiedProcessorFaces, setI) + { + const labelList& set = specifiedProcessorFaces[setI]; + + // Get the processor to use for the set + label procI = specifiedProcessor[setI]; + if (procI == -1) + { + // If no processor specified use the one from the + // 0th element + if (set.size()) + { + procI = decomposition[mesh.faceOwner()[set[0]]]; + } + reduce(procI, maxOp<label>()); + } + + // Get all points on the sets + boolList procFacePoint(mesh.nPoints(), false); + forAll(set, fI) + { + const face& f = mesh.faces()[set[fI]]; + forAll(f, fp) + { + procFacePoint[f[fp]] = true; + } + } + syncTools::syncPointList(mesh, procFacePoint, orEqOp<bool>(), false); + + // 2. Unblock all faces on procFacePoint + forAll(procFacePoint, pointI) + { + if (procFacePoint[pointI]) + { + const labelList& pFaces = mesh.pointFaces()[pointI]; + forAll(pFaces, i) + { + label faceI = pFaces[i]; + + label own = mesh.faceOwner()[faceI]; + if (decomposition[own] != procI) + { + decomposition[own] = procI; + nChanged++; + } + if (mesh.isInternalFace(faceI)) + { + label nei = mesh.faceNeighbour()[faceI]; + if (decomposition[nei] != procI) + { + decomposition[nei] = procI; + nChanged++; + } + } + } + } + } + } + + if (decompositionConstraint::debug & 2) + { + reduce(nChanged, sumOp<label>()); + Info<< type() << " : changed decomposition on " << nChanged + << " cells" << endl; + } +} + + +// ************************************************************************* // diff --git a/src/parallel/decompose/decompositionMethods/decompositionConstraints/singleProcessorFaceSets/singleProcessorFaceSetsConstraint.H b/src/parallel/decompose/decompositionMethods/decompositionConstraints/singleProcessorFaceSets/singleProcessorFaceSetsConstraint.H new file mode 100644 index 0000000000000000000000000000000000000000..646e842459951a57840395314f3a89c36f2de291 --- /dev/null +++ b/src/parallel/decompose/decompositionMethods/decompositionConstraints/singleProcessorFaceSets/singleProcessorFaceSetsConstraint.H @@ -0,0 +1,124 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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::singleProcessorFaceSetsConstraint + +Description + Constraint to keep all cells connected to face or point of faceSet on + a single processor. + +SourceFiles + singleProcessorFaceSetsConstraint.C + +\*---------------------------------------------------------------------------*/ + +#ifndef singleProcessorFaceSetsConstraint_H +#define singleProcessorFaceSetsConstraint_H + +#include "decompositionConstraint.H" +#include "Tuple2.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +namespace decompositionConstraints +{ + +/*---------------------------------------------------------------------------*\ + Class singleProcessorFaceSetsConstraint Declaration +\*---------------------------------------------------------------------------*/ + +class singleProcessorFaceSetsConstraint +: + public decompositionConstraint +{ + // Private data + + //- List of faceSet+processor + List<Tuple2<word, label> > setNameAndProcs_; + +public: + + //- Runtime type information + TypeName("singleProcessorFaceSets"); + + + // Constructors + + //- Construct with generic dictionary with optional entry for type + singleProcessorFaceSetsConstraint + ( + const dictionary& constraintsDict, + const word& type + ); + + //- Construct from components + singleProcessorFaceSetsConstraint + ( + const List<Tuple2<word, label> >& setNameAndProcs + ); + + + //- Destructor + virtual ~singleProcessorFaceSetsConstraint() + {} + + + // Member Functions + + //- Add my constraints to list of constraints + virtual void add + ( + const polyMesh& mesh, + boolList& blockedFace, + PtrList<labelList>& specifiedProcessorFaces, + labelList& specifiedProcessor, + List<labelPair>& explicitConnections + ) const; + + //- Apply any additional post-decomposition constraints + virtual void apply + ( + const polyMesh& mesh, + const boolList& blockedFace, + const PtrList<labelList>& specifiedProcessorFaces, + const labelList& specifiedProcessor, + const List<labelPair>& explicitConnections, + labelList& decomposition + ) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace decompositionConstraints +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.C b/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.C index ff2f3d680021580ef9b6b402ca0c9521cc960e80..142067da60d5625847e9682a527ff1e21efc22e2 100644 --- a/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.C +++ b/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.C @@ -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. @@ -36,6 +36,11 @@ InClass #include "minData.H" #include "FaceCellWave.H" +#include "preserveBafflesConstraint.H" +#include "preservePatchesConstraint.H" +#include "preserveFaceZonesConstraint.H" +#include "singleProcessorFaceSetsConstraint.H" + // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // namespace Foam @@ -44,21 +49,139 @@ namespace Foam defineRunTimeSelectionTable(decompositionMethod, dictionary); } -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // -Foam::autoPtr<Foam::decompositionMethod> Foam::decompositionMethod::New +Foam::decompositionMethod::decompositionMethod ( const dictionary& decompositionDict ) +: + decompositionDict_(decompositionDict), + nProcessors_ + ( + readLabel(decompositionDict.lookup("numberOfSubdomains")) + ) { - word methodType(decompositionDict.lookup("method")); + // Read any constraints + wordList constraintTypes_; + if (decompositionDict_.found("constraints")) + { + //PtrList<dictionary> constraintsList + //( + // decompositionDict_.lookup("constraints") + //); + //forAll(constraintsList, i) + //{ + // const dictionary& dict = constraintsList[i]; + const dictionary& constraintsList = decompositionDict_.subDict + ( + "constraints" + ); + forAllConstIter(dictionary, constraintsList, iter) + { + const dictionary& dict = iter().dict(); + + constraintTypes_.append(dict.lookup("type")); + + constraints_.append + ( + decompositionConstraint::New + ( + dict, + constraintTypes_.last() + ) + ); + } + } + + // Backwards compatibility + if + ( + decompositionDict_.found("preserveBaffles") + && findIndex + ( + constraintTypes_, + decompositionConstraints::preserveBafflesConstraint::typeName + ) == -1 + ) + { + constraints_.append + ( + new decompositionConstraints::preserveBafflesConstraint() + ); + } + + if + ( + decompositionDict_.found("preservePatches") + && findIndex + ( + constraintTypes_, + decompositionConstraints::preservePatchesConstraint::typeName + ) == -1 + ) + { + const wordReList pNames(decompositionDict_.lookup("preservePatches")); + + constraints_.append + ( + new decompositionConstraints::preservePatchesConstraint(pNames) + ); + } + + if + ( + decompositionDict_.found("preserveFaceZones") + && findIndex + ( + constraintTypes_, + decompositionConstraints::preserveFaceZonesConstraint::typeName + ) == -1 + ) + { + const wordReList zNames(decompositionDict_.lookup("preserveFaceZones")); + + constraints_.append + ( + new decompositionConstraints::preserveFaceZonesConstraint(zNames) + ); + } - if (methodType == "scotch" && Pstream::parRun()) + if + ( + decompositionDict_.found("singleProcessorFaceSets") + && findIndex + ( + constraintTypes_, + decompositionConstraints::preserveFaceZonesConstraint::typeName + ) == -1 + ) { - methodType = "ptscotch"; + const List<Tuple2<word, label> > zNameAndProcs + ( + decompositionDict_.lookup("singleProcessorFaceSets") + ); + + constraints_.append + ( + new decompositionConstraints::singleProcessorFaceSetsConstraint + ( + zNameAndProcs + ) + ); } +} +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +Foam::autoPtr<Foam::decompositionMethod> Foam::decompositionMethod::New +( + const dictionary& decompositionDict +) +{ + word methodType(decompositionDict.lookup("method")); + Info<< "Selecting decompositionMethod " << methodType << endl; dictionaryConstructorTable::iterator cstrIter = @@ -370,6 +493,210 @@ void Foam::decompositionMethod::calcCellCells } +void Foam::decompositionMethod::calcCellCells +( + const polyMesh& mesh, + const labelList& agglom, + const label nLocalCoarse, + const bool parallel, + CompactListList<label>& cellCells, + CompactListList<scalar>& cellCellWeights +) +{ + const labelList& faceOwner = mesh.faceOwner(); + const labelList& faceNeighbour = mesh.faceNeighbour(); + const polyBoundaryMesh& patches = mesh.boundaryMesh(); + + + // Create global cell numbers + // ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + globalIndex globalAgglom + ( + nLocalCoarse, + Pstream::msgType(), + Pstream::worldComm, + parallel + ); + + + // Get agglomerate owner on other side of coupled faces + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + labelList globalNeighbour(mesh.nFaces()-mesh.nInternalFaces()); + + forAll(patches, patchI) + { + const polyPatch& pp = patches[patchI]; + + if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp))) + { + label faceI = pp.start(); + label bFaceI = pp.start() - mesh.nInternalFaces(); + + forAll(pp, i) + { + globalNeighbour[bFaceI] = globalAgglom.toGlobal + ( + agglom[faceOwner[faceI]] + ); + + bFaceI++; + faceI++; + } + } + } + + // Get the cell on the other side of coupled patches + syncTools::swapBoundaryFaceList(mesh, globalNeighbour); + + + // Count number of faces (internal + coupled) + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // Number of faces per coarse cell + labelList nFacesPerCell(nLocalCoarse, 0); + + for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++) + { + label own = agglom[faceOwner[faceI]]; + label nei = agglom[faceNeighbour[faceI]]; + + nFacesPerCell[own]++; + nFacesPerCell[nei]++; + } + + forAll(patches, patchI) + { + const polyPatch& pp = patches[patchI]; + + if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp))) + { + label faceI = pp.start(); + label bFaceI = pp.start()-mesh.nInternalFaces(); + + forAll(pp, i) + { + label own = agglom[faceOwner[faceI]]; + + label globalNei = globalNeighbour[bFaceI]; + if + ( + !globalAgglom.isLocal(globalNei) + || globalAgglom.toLocal(globalNei) != own + ) + { + nFacesPerCell[own]++; + } + + faceI++; + bFaceI++; + } + } + } + + + // Fill in offset and data + // ~~~~~~~~~~~~~~~~~~~~~~~ + + cellCells.setSize(nFacesPerCell); + cellCellWeights.setSize(nFacesPerCell); + + nFacesPerCell = 0; + + labelList& m = cellCells.m(); + scalarList& w = cellCellWeights.m(); + const labelList& offsets = cellCells.offsets(); + + // For internal faces is just offsetted owner and neighbour + for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++) + { + label own = agglom[faceOwner[faceI]]; + label nei = agglom[faceNeighbour[faceI]]; + + label ownIndex = offsets[own] + nFacesPerCell[own]++; + label neiIndex = offsets[nei] + nFacesPerCell[nei]++; + + m[ownIndex] = globalAgglom.toGlobal(nei); + w[ownIndex] = mag(mesh.faceAreas()[faceI]); + m[neiIndex] = globalAgglom.toGlobal(own); + w[ownIndex] = mag(mesh.faceAreas()[faceI]); + } + + // For boundary faces is offsetted coupled neighbour + forAll(patches, patchI) + { + const polyPatch& pp = patches[patchI]; + + if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp))) + { + label faceI = pp.start(); + label bFaceI = pp.start()-mesh.nInternalFaces(); + + forAll(pp, i) + { + label own = agglom[faceOwner[faceI]]; + + label globalNei = globalNeighbour[bFaceI]; + + if + ( + !globalAgglom.isLocal(globalNei) + || globalAgglom.toLocal(globalNei) != own + ) + { + label ownIndex = offsets[own] + nFacesPerCell[own]++; + m[ownIndex] = globalNei; + w[ownIndex] = mag(mesh.faceAreas()[faceI]); + } + + faceI++; + bFaceI++; + } + } + } + + + // Check for duplicates connections between cells + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Done as postprocessing step since we now have cellCells. + label newIndex = 0; + labelHashSet nbrCells; + + + if (cellCells.size() == 0) + { + return; + } + + label startIndex = cellCells.offsets()[0]; + + forAll(cellCells, cellI) + { + nbrCells.clear(); + nbrCells.insert(globalAgglom.toGlobal(cellI)); + + label endIndex = cellCells.offsets()[cellI+1]; + + for (label i = startIndex; i < endIndex; i++) + { + if (nbrCells.insert(cellCells.m()[i])) + { + cellCells.m()[newIndex] = cellCells.m()[i]; + cellCellWeights.m()[newIndex] = cellCellWeights.m()[i]; + newIndex++; + } + } + startIndex = endIndex; + cellCells.offsets()[cellI+1] = newIndex; + cellCellWeights.offsets()[cellI+1] = newIndex; + } + + cellCells.m().setSize(newIndex); + cellCellWeights.m().setSize(newIndex); +} + + //void Foam::decompositionMethod::calcCellCells //( // const polyMesh& mesh, @@ -1123,172 +1450,45 @@ void Foam::decompositionMethod::setConstraints { blockedFace.setSize(mesh.nFaces()); blockedFace = true; - //label nUnblocked = 0; specifiedProcessorFaces.clear(); explicitConnections.clear(); - - if (decompositionDict_.found("preservePatches")) - { - wordList pNames(decompositionDict_.lookup("preservePatches")); - - Info<< nl - << "Keeping owner of faces in patches " << pNames - << " on same processor. This only makes sense for cyclics." << endl; - - const polyBoundaryMesh& patches = mesh.boundaryMesh(); - - forAll(pNames, i) - { - const label patchI = patches.findPatchID(pNames[i]); - - if (patchI == -1) - { - FatalErrorIn("decompositionMethod::decompose(const polyMesh&)") - << "Unknown preservePatch " << pNames[i] - << endl << "Valid patches are " << patches.names() - << exit(FatalError); - } - - const polyPatch& pp = patches[patchI]; - - forAll(pp, i) - { - if (blockedFace[pp.start() + i]) - { - blockedFace[pp.start() + i] = false; - //nUnblocked++; - } - } - } - } - if (decompositionDict_.found("preserveFaceZones")) - { - wordList zNames(decompositionDict_.lookup("preserveFaceZones")); - - Info<< nl - << "Keeping owner and neighbour of faces in zones " << zNames - << " on same processor" << endl; - - const faceZoneMesh& fZones = mesh.faceZones(); - - forAll(zNames, i) - { - label zoneI = fZones.findZoneID(zNames[i]); - - if (zoneI == -1) - { - FatalErrorIn("decompositionMethod::decompose(const polyMesh&)") - << "Unknown preserveFaceZone " << zNames[i] - << endl << "Valid faceZones are " << fZones.names() - << exit(FatalError); - } - - const faceZone& fz = fZones[zoneI]; - - forAll(fz, i) - { - if (blockedFace[fz[i]]) - { - blockedFace[fz[i]] = false; - //nUnblocked++; - } - } - } - } - - bool preserveBaffles = decompositionDict_.lookupOrDefault - ( - "preserveBaffles", - false - ); - if (preserveBaffles) - { - Info<< nl - << "Keeping owner of faces in baffles " - << " on same processor." << endl; - - explicitConnections = localPointRegion::findDuplicateFacePairs(mesh); - forAll(explicitConnections, i) - { - blockedFace[explicitConnections[i].first()] = false; - blockedFace[explicitConnections[i].second()] = false; - } - } - - if - ( - decompositionDict_.found("preservePatches") - || decompositionDict_.found("preserveFaceZones") - || preserveBaffles - ) + forAll(constraints_, constraintI) { - syncTools::syncFaceList(mesh, blockedFace, andEqOp<bool>()); - //reduce(nUnblocked, sumOp<label>()); + constraints_[constraintI].add + ( + mesh, + blockedFace, + specifiedProcessorFaces, + specifiedProcessor, + explicitConnections + ); } +} - - // Specified processor for group of cells connected to faces - - label nProcSets = 0; - if (decompositionDict_.found("singleProcessorFaceSets")) +void Foam::decompositionMethod::applyConstraints +( + const polyMesh& mesh, + const boolList& blockedFace, + const PtrList<labelList>& specifiedProcessorFaces, + const labelList& specifiedProcessor, + const List<labelPair>& explicitConnections, + labelList& decomposition +) +{ + forAll(constraints_, constraintI) { - List<Tuple2<word, label> > zNameAndProcs + constraints_[constraintI].apply ( - decompositionDict_.lookup("singleProcessorFaceSets") + mesh, + blockedFace, + specifiedProcessorFaces, + specifiedProcessor, + explicitConnections, + decomposition ); - - specifiedProcessorFaces.setSize(zNameAndProcs.size()); - specifiedProcessor.setSize(zNameAndProcs.size()); - - forAll(zNameAndProcs, setI) - { - Info<< "Keeping all cells connected to faceSet " - << zNameAndProcs[setI].first() - << " on processor " << zNameAndProcs[setI].second() << endl; - - // Read faceSet - faceSet fz(mesh, zNameAndProcs[setI].first()); - - specifiedProcessorFaces.set(setI, new labelList(fz.sortedToc())); - specifiedProcessor[setI] = zNameAndProcs[setI].second(); - nProcSets += fz.size(); - } - reduce(nProcSets, sumOp<label>()); - - - // Unblock all point connected faces - // 1. Mark all points on specifiedProcessorFaces - boolList procFacePoint(mesh.nPoints(), false); - forAll(specifiedProcessorFaces, setI) - { - const labelList& set = specifiedProcessorFaces[setI]; - forAll(set, fI) - { - const face& f = mesh.faces()[set[fI]]; - forAll(f, fp) - { - procFacePoint[f[fp]] = true; - } - } - } - syncTools::syncPointList(mesh, procFacePoint, orEqOp<bool>(), false); - - // 2. Unblock all faces on procFacePoint - forAll(procFacePoint, pointI) - { - if (procFacePoint[pointI]) - { - const labelList& pFaces = mesh.pointFaces()[pointI]; - forAll(pFaces, i) - { - blockedFace[pFaces[i]] = false; - } - } - } - syncTools::syncFaceList(mesh, blockedFace, andEqOp<bool>()); } } @@ -1299,6 +1499,8 @@ Foam::labelList Foam::decompositionMethod::decompose const scalarField& cellWeights ) { + // Collect all constraints + boolList blockedFace; PtrList<labelList> specifiedProcessorFaces; labelList specifiedProcessor; @@ -1326,6 +1528,19 @@ Foam::labelList Foam::decompositionMethod::decompose explicitConnections // baffles ); + + // Give any constraint the option of modifying the decomposition + + applyConstraints + ( + mesh, + blockedFace, + specifiedProcessorFaces, + specifiedProcessor, + explicitConnections, + finalDecomp + ); + return finalDecomp; } diff --git a/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.H b/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.H index 2d02936d2b1b9b3409cc4b606544e807bd07f338..30b3e8b32d4e251a474d5c3ad55a3c83d4605f3e 100644 --- a/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.H +++ b/src/parallel/decompose/decompositionMethods/decompositionMethod/decompositionMethod.H @@ -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. @@ -36,8 +36,8 @@ SourceFiles #define decompositionMethod_H #include "polyMesh.H" -#include "pointField.H" #include "CompactListList.H" +#include "decompositionConstraint.H" namespace Foam { @@ -56,6 +56,8 @@ protected: const dictionary& decompositionDict_; label nProcessors_; + //- Optional constraints + PtrList<decompositionConstraint> constraints_; private: @@ -98,14 +100,7 @@ public: // Constructors //- Construct given the decomposition dictionary - decompositionMethod(const dictionary& decompositionDict) - : - decompositionDict_(decompositionDict), - nProcessors_ - ( - readLabel(decompositionDict.lookup("numberOfSubdomains")) - ) - {} + decompositionMethod(const dictionary& decompositionDict); //- Destructor @@ -233,6 +228,19 @@ public: CompactListList<label>& cellCells ); + //- Helper: determine (local or global) cellCells and face weights + // from mesh agglomeration. + // Uses mag of faceArea as weights + static void calcCellCells + ( + const polyMesh& mesh, + const labelList& agglom, + const label nLocalCoarse, + const bool parallel, + CompactListList<label>& cellCells, + CompactListList<scalar>& cellCellWeights + ); + //- Helper: extract constraints: // blockedface: existing faces where owner and neighbour on same // proc @@ -248,6 +256,19 @@ public: List<labelPair>& explicitConnections ); + //- Helper: apply constraints to a decomposition. This gives + // constraints opportunity to modify decomposition in case + // the native decomposition method has not obeyed all constraints + void applyConstraints + ( + const polyMesh& mesh, + const boolList& blockedFace, + const PtrList<labelList>& specifiedProcessorFaces, + const labelList& specifiedProcessor, + const List<labelPair>& explicitConnections, + labelList& finalDecomp + ); + // Decompose a mesh with constraints: // - blockedFace : whether owner and neighbour should be on same // processor diff --git a/src/parallel/decompose/ptscotchDecomp/ptscotchDecomp.C b/src/parallel/decompose/ptscotchDecomp/ptscotchDecomp.C index 29f1f6b09a6c06a44816c29109257abf7ea7380f..df58fb447cc5871b4d1a354b488a7d55682ae1d2 100644 --- a/src/parallel/decompose/ptscotchDecomp/ptscotchDecomp.C +++ b/src/parallel/decompose/ptscotchDecomp/ptscotchDecomp.C @@ -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. @@ -63,46 +63,134 @@ License "b{sep=m{vert=100,low=h,asc=f}x}" The current default mapping strategy in Scotch can be seen by using the - "-vs" option of program gmap. It is, to date: + "-vs" option of program dgpart. It is, to date: - b + r { - job=t, - map=t, - poli=S, - sep= - ( - m + sep=m + { + asc=b { - asc=b - { - bnd=d{pass=40,dif=1,rem=1}f{move=80,pass=-1,bal=0.005}, - org=f{move=80,pass=-1,bal=0.005}, - width=3 - }, - low=h{pass=10}f{move=80,pass=-1,bal=0.0005}, - type=h, - vert=80, - rat=0.8 - } - | m + width=3, + bnd=(d{pass=40,dif=1,rem=0,type=b}|) + q{strat=f{move=80,pass=-1,bal=0.01,type=b}} + x{sbbt=5,bal=0.05}, + org=q{strat=f{move=80,pass=-1,bal=0.01,type=b}} + x{sbbt=5,bal=0.05} + }, + low=q { - asc=b + strat= + ( + m + { + asc=b + { + bnd=(d{pass=40,type=b}|) + f{move=80,pass=-1,bal=0.05,type=b}, + org=f{move=80,pass=-1,bal=0.05,type=b}, + width=3 + }, + low=h{pass=10} + f{move=80,pass=-1,bal=0.05,type=b}, + vert=80, + rat=0.8 + } + |m + { + asc=b + { + bnd=(d{pass=40,type=b}|) + f{move=80,pass=-1,bal=0.05,type=b}, + org=f{move=80,pass=-1,bal=0.05,type=b}, + width=3 + }, + low=h{pass=10} + f{move=80,pass=-1,bal=0.05,type=b}, + vert=80, + rat=0.8 + } + ) + }, + seq=q + { + strat= + ( + m + { + asc=b + { + bnd=(d{pass=40,type=b}|) + f{move=80,pass=-1,bal=0.05,type=b}, + org=f{move=80,pass=-1,bal=0.05,type=b}, + width=3 + }, + low=h{pass=10} + f{move=80,pass=-1,bal=0.05,type=b}, + vert=80, + rat=0.8 + } + |m + { + asc=b + { + bnd=(d{pass=40,type=b}|) + f{move=80,pass=-1,bal=0.05,type=b}, + org=f{move=80,pass=-1,bal=0.05,type=b}, + width=3 + }, + low=h{pass=10} + f{move=80,pass=-1,bal=0.05,type=b}, + vert=80, + rat=0.8 + } + ) + }, + pass=5, + vert=10000, + rat=0.8 + }, + seq=r + { + job=t, + bal=0.05, + map=t, + poli=S, + sep= + ( + m { - bnd=d{pass=40,dif=1,rem=1}f{move=80,pass=-1,bal=0.005}, - org=f{move=80,pass=-1,bal=0.005}, - width=3 - }, - low=h{pass=10}f{move=80,pass=-1,bal=0.0005}, - type=h, - vert=80, - rat=0.8 - } - ) + asc=b + { + bnd=(d{pass=40,type=b}|) + f{move=80,pass=-1,bal=0.05,type=b}, + org=f{move=80,pass=-1,bal=0.05,type=b}, + width=3 + }, + low=h{pass=10} + f{move=80,pass=-1,bal=0.05,type=b}, + vert=80, + rat=0.8 + } + |m + { + asc=b + { + bnd=(d{pass=40,type=b}|) + f{move=80,pass=-1,bal=0.05,type=b}, + org=f{move=80,pass=-1,bal=0.05,type=b}, + width=3 + }, + low=h{pass=10} + f{move=80,pass=-1,bal=0.05,type=b}, + vert=80, + rat=0.8 + } + ) + }, + bal=0.05 } - - Note: writeGraph=true : writes out .dgr files for debugging. Run with e.g. mpirun -np 4 dgpart 2 'region0_%r.dgr' diff --git a/src/parallel/decompose/scotchDecomp/scotchDecomp.C b/src/parallel/decompose/scotchDecomp/scotchDecomp.C index 464d12b28faeb1bd34dc55a057fc305454227611..c76b33edfb738a9ae98a91e73c04bdc6891b12d3 100644 --- a/src/parallel/decompose/scotchDecomp/scotchDecomp.C +++ b/src/parallel/decompose/scotchDecomp/scotchDecomp.C @@ -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. @@ -65,52 +65,54 @@ License The current default mapping strategy in Scotch can be seen by using the "-vs" option of program gmap. It is, to date: - r + m { - job=t, - map=t, - poli=S, - sep= - ( - m - { - asc=b + asc=b + { + width=3, + bnd=d{pass=40, dif=1, rem=0} + f{move=80, pass=-1, bal=0.01}, + org=f{move=80,pass=-1,bal=0.01} + }, + low=r + { + job=t, + bal=0.01, + map=t, + poli=S, + sep= + ( + m { - bnd= - ( - d{pass=40,dif=1,rem=1} - | - ) - f{move=80,pass=-1,bal=0.002491}, - org=f{move=80,pass=-1,bal=0.002491}, - width=3 - }, - low=h{pass=10} - f{move=80,pass=-1,bal=0.002491}, - type=h, - vert=80, - rat=0.8 - } - | m - { - asc=b + asc=b + { + bnd=f{move=120, pass=-1, bal=0.01, type=b}, + org=f{move=120,pass=-1,bal=0.01,type=b}, + width=3 + }, + low=h{pass=10} + f{move=120,pass=-1,bal=0.01,type=b}, + vert=120, + rat=0.8 + } + |m { - bnd= - ( - d{pass=40,dif=1,rem=1} - | - ) - f{move=80,pass=-1,bal=0.002491}, - org=f{move=80,pass=-1,bal=0.002491}, - width=3 - }, - low=h{pass=10} - f{move=80,pass=-1,bal=0.002491}, - type=h, - vert=80, - rat=0.8 - } - ) + asc=b + { + bnd=f{move=120,pass=-1,bal=0.01,type=b}, + org=f{move=120,pass=-1,bal=0.01,type=b}, + width=3 + }, + low=h{pass=10} + f{move=120,pass=-1,bal=0.01,type=b}, + vert=120, + rat=0.8 + } + ) + }, + vert=10000, + rat=0.8, + type=0 } diff --git a/src/parallel/distributed/Make/options b/src/parallel/distributed/Make/options index f003a7fed947de2f1c9d3b848fe1eec1cbc118e6..6753a2306c31eebb65871b16a17b2300eaee376c 100644 --- a/src/parallel/distributed/Make/options +++ b/src/parallel/distributed/Make/options @@ -1,5 +1,6 @@ EXE_INC = \ -I$(LIB_SRC)/triSurface/lnInclude \ + -I$(LIB_SRC)/surfMesh/lnInclude \ -I$(LIB_SRC)/parallel/decompose/decompositionMethods/lnInclude \ -I$(LIB_SRC)/meshTools/lnInclude diff --git a/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.C b/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.C index f17d26277ef99118fb25ab0b80f31b0b607301d2..90f3953f1829e6e9814b7fb6cea8d2d27283af82 100644 --- a/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.C +++ b/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.C @@ -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. @@ -38,6 +38,7 @@ License #include "vectorList.H" #include "PackedBoolList.H" #include "PatchTools.H" +#include "OBJstream.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -815,21 +816,46 @@ Foam::distributedTriSurfaceMesh::independentlyDistributedBbs { if (!decomposer_.valid()) { - // Use current decomposer. - // Note: or always use hierarchical? - IOdictionary decomposeDict + // Use singleton decomposeParDict. Cannot use decompositionModel + // here since we've only got Time and not a mesh. + if ( - IOobject + searchableSurface::time().foundObject<IOdictionary> ( - "decomposeParDict", - searchableSurface::time().system(), - searchableSurface::time(), - IOobject::MUST_READ_IF_MODIFIED, - IOobject::NO_WRITE, - false + "decomposeParDict" ) - ); - decomposer_ = decompositionMethod::New(decomposeDict); + ) + { + decomposer_ = decompositionMethod::New + ( + searchableSurface::time().lookupObject<IOdictionary> + ( + "decomposeParDict" + ) + ); + } + else + { + if (!decomposeParDict_.valid()) + { + decomposeParDict_.reset + ( + new IOdictionary + ( + IOobject + ( + "decomposeParDict", + searchableSurface::time().system(), + searchableSurface::time(), + IOobject::MUST_READ_IF_MODIFIED, + IOobject::NO_WRITE + ) + ) + ); + } + decomposer_ = decompositionMethod::New(decomposeParDict_()); + } + if (!decomposer_().parallelAware()) { @@ -2254,13 +2280,15 @@ void Foam::distributedTriSurfaceMesh::distribute // Send all // ~~~~~~~~ + PstreamBuffers pBufs(Pstream::defaultCommsType); + forAll(faceSendSizes, procI) { if (procI != Pstream::myProcNo()) { if (faceSendSizes[Pstream::myProcNo()][procI] > 0) { - OPstream str(Pstream::blocking, procI); + UOPstream str(procI, pBufs); labelList pointMap; triSurface subSurface @@ -2282,10 +2310,12 @@ void Foam::distributedTriSurfaceMesh::distribute //} str << subSurface; - } + } } } + pBufs.finishedSends(); // no-op for blocking + // Receive and merge all // ~~~~~~~~~~~~~~~~~~~~~ @@ -2296,7 +2326,7 @@ void Foam::distributedTriSurfaceMesh::distribute { if (faceSendSizes[procI][Pstream::myProcNo()] > 0) { - IPstream str(Pstream::blocking, procI); + UIPstream str(procI, pBufs); // Receive triSurface subSurface(str); @@ -2327,7 +2357,7 @@ void Foam::distributedTriSurfaceMesh::distribute // Pout<< "Current merged surface : faces:" << allTris.size() // << " points:" << allPoints.size() << endl << endl; //} - } + } } } @@ -2388,6 +2418,20 @@ void Foam::distributedTriSurfaceMesh::distribute Info<< '\t' << procI << '\t' << nTris[procI] << endl; } Info<< endl; + + OBJstream str(searchableSurface::time().path()/"after.obj"); + Info<< "Writing local bounding box to " << str.name() << endl; + const List<treeBoundBox>& myBbs = procBb_[Pstream::myProcNo()]; + forAll(myBbs, i) + { + pointField pts(myBbs[i].points()); + const edgeList& es = treeBoundBox::edges; + forAll(es, eI) + { + const edge& e = es[eI]; + str.write(linePointRef(pts[e[0]], pts[e[1]])); + } + } } } diff --git a/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.H b/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.H index 30c559f517211fa5f08eaed63df695e0930885fa..05d3c1948a06ba193851ee7d40d974f1d081844a 100644 --- a/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.H +++ b/src/parallel/distributed/distributedTriSurfaceMesh/distributedTriSurfaceMesh.H @@ -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. @@ -95,6 +95,8 @@ private: //- Merging distance scalar mergeDist_; + autoPtr<IOdictionary> decomposeParDict_; + //- Decomposition used when independently decomposing surface. autoPtr<decompositionMethod> decomposer_; diff --git a/src/parallel/reconstruct/reconstruct/processorMeshes.H b/src/parallel/reconstruct/reconstruct/processorMeshes.H index 44be3f7cd5e651a42f74258c5e89a49d37b1a08e..ed5a6601b84a2ec42a0b30712118f29c720713e4 100644 --- a/src/parallel/reconstruct/reconstruct/processorMeshes.H +++ b/src/parallel/reconstruct/reconstruct/processorMeshes.H @@ -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. @@ -103,6 +103,11 @@ public: //- Reconstruct point position after motion in parallel void reconstructPoints(fvMesh&); + const PtrList<fvMesh>& meshes() const + { + return meshes_; + } + PtrList<fvMesh>& meshes() { return meshes_; diff --git a/src/postProcessing/functionObjects/field/streamLine/streamLine.C b/src/postProcessing/functionObjects/field/streamLine/streamLine.C index 0017a338263d02c2a5fed9df1847e60bebffc49c..bd360cada69fcbfe606136d4ad010f3f8a4b3e9f 100644 --- a/src/postProcessing/functionObjects/field/streamLine/streamLine.C +++ b/src/postProcessing/functionObjects/field/streamLine/streamLine.C @@ -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. @@ -580,41 +580,55 @@ void Foam::streamLine::write() // Distribute the track positions. Note: use scheduled comms // to prevent buffering. - mapDistribute::distribute + allTracks_.shrink(); + mapDistributeBase::distribute ( Pstream::scheduled, distMap.schedule(), distMap.constructSize(), distMap.subMap(), + false, distMap.constructMap(), - allTracks_ + false, + allTracks_, + flipOp() ); // Distribute the scalars forAll(allScalars_, scalarI) { - mapDistribute::distribute + allScalars_[scalarI].shrink(); + mapDistributeBase::distribute ( Pstream::scheduled, distMap.schedule(), distMap.constructSize(), distMap.subMap(), + false, distMap.constructMap(), - allScalars_[scalarI] + false, + allScalars_[scalarI], + flipOp() ); + allScalars_[scalarI].setCapacity(allScalars_[scalarI].size()); } // Distribute the vectors forAll(allVectors_, vectorI) { - mapDistribute::distribute + allVectors_[vectorI].shrink(); + mapDistributeBase::distribute ( Pstream::scheduled, distMap.schedule(), distMap.constructSize(), distMap.subMap(), + false, distMap.constructMap(), - allVectors_[vectorI] + false, + allVectors_[vectorI], + flipOp() ); + allVectors_[vectorI].setCapacity(allVectors_[vectorI].size()); } } diff --git a/src/postProcessing/functionObjects/field/wallBoundedStreamLine/wallBoundedStreamLine.C b/src/postProcessing/functionObjects/field/wallBoundedStreamLine/wallBoundedStreamLine.C index 863221f220c4ab888c51e2b939047476a7f98aba..6b6823121e06eaca74a9d0ea77d853a6daa6eb6d 100644 --- a/src/postProcessing/functionObjects/field/wallBoundedStreamLine/wallBoundedStreamLine.C +++ b/src/postProcessing/functionObjects/field/wallBoundedStreamLine/wallBoundedStreamLine.C @@ -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. @@ -705,41 +705,55 @@ void Foam::wallBoundedStreamLine::write() // Distribute the track positions. Note: use scheduled comms // to prevent buffering. - mapDistribute::distribute + allTracks_.shrink(); + mapDistributeBase::distribute ( Pstream::scheduled, distMap.schedule(), distMap.constructSize(), distMap.subMap(), + false, distMap.constructMap(), - allTracks_ + false, + allTracks_, + flipOp() ); // Distribute the scalars forAll(allScalars_, scalarI) { - mapDistribute::distribute + allScalars_[scalarI].shrink(); + mapDistributeBase::distribute ( Pstream::scheduled, distMap.schedule(), distMap.constructSize(), distMap.subMap(), + false, distMap.constructMap(), - allScalars_[scalarI] + false, + allScalars_[scalarI], + flipOp() ); + allScalars_[scalarI].setCapacity(allScalars_[scalarI].size()); } // Distribute the vectors forAll(allVectors_, vectorI) { - mapDistribute::distribute + allVectors_[vectorI].shrink(); + mapDistributeBase::distribute ( Pstream::scheduled, distMap.schedule(), distMap.constructSize(), distMap.subMap(), + false, distMap.constructMap(), - allVectors_[vectorI] + false, + allVectors_[vectorI], + flipOp() ); + allVectors_[vectorI].setCapacity(allVectors_[vectorI].size()); } } diff --git a/src/renumber/renumberMethods/Make/options b/src/renumber/renumberMethods/Make/options index cc28bc2f00d0c12f1bf9380ef0f5c95bdcabf9ec..35bbb2cc5cc5838056d08649ee2d85cce598d99e 100644 --- a/src/renumber/renumberMethods/Make/options +++ b/src/renumber/renumberMethods/Make/options @@ -1,9 +1,11 @@ EXE_INC = \ -I$(LIB_SRC)/parallel/decompose/decompositionMethods/lnInclude \ -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/dynamicMesh/lnInclude \ -I$(LIB_SRC)/meshTools/lnInclude LIB_LIBS = \ -ldecompositionMethods \ -lfiniteVolume \ + -ldynamicMesh \ -lmeshTools diff --git a/src/sampling/Make/files b/src/sampling/Make/files index d5e75fd2ce30a662f7fb3e2c71bf100c26ff8b27..93f7b1594e797e35579be0c73f78d703c4355389 100644 --- a/src/sampling/Make/files +++ b/src/sampling/Make/files @@ -62,6 +62,7 @@ meshToMeshMethods = meshToMesh/calcMethod $(meshToMeshMethods)/meshToMeshMethod/meshToMeshMethod.C $(meshToMeshMethods)/meshToMeshMethod/meshToMeshMethodNew.C $(meshToMeshMethods)/cellVolumeWeight/cellVolumeWeightMethod.C +$(meshToMeshMethods)/correctedCellVolumeWeight/correctedCellVolumeWeightMethod.C $(meshToMeshMethods)/direct/directMethod.C $(meshToMeshMethods)/mapNearest/mapNearestMethod.C diff --git a/src/sampling/Make/options b/src/sampling/Make/options index 23e6bc81a7e708d69b5fd14d27073827646e14ef..8e006e099c47d8568a7fec736b44b74672557f50 100644 --- a/src/sampling/Make/options +++ b/src/sampling/Make/options @@ -4,6 +4,7 @@ EXE_INC = \ -I$(LIB_SRC)/surfMesh/lnInclude \ -I$(LIB_SRC)/fileFormats/lnInclude \ -I$(LIB_SRC)/triSurface/lnInclude \ + -I$(LIB_SRC)/dynamicMesh/lnInclude \ -I$(LIB_SRC)/conversion/lnInclude \ -I$(LIB_SRC)/lagrangian/basic/lnInclude @@ -14,4 +15,5 @@ LIB_LIBS = \ -lfileFormats \ -ltriSurface \ -llagrangian \ + -ldynamicMesh \ -lconversion diff --git a/src/sampling/meshToMesh/calcMethod/cellVolumeWeight/cellVolumeWeightMethod.C b/src/sampling/meshToMesh/calcMethod/cellVolumeWeight/cellVolumeWeightMethod.C index 863301bbce5a39e30f9d1cdb52ee9f98b875eb66..722521a71ef7c79c14ba5992b73d5c832f2b7128 100644 --- a/src/sampling/meshToMesh/calcMethod/cellVolumeWeight/cellVolumeWeightMethod.C +++ b/src/sampling/meshToMesh/calcMethod/cellVolumeWeight/cellVolumeWeightMethod.C @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2013-2015 OpenFOAM Foundation - \\/ M anipulation | + \\ / A nd | Copyright (C) 2013-2014 OpenFOAM Foundation + \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -186,6 +186,44 @@ void Foam::cellVolumeWeightMethod::calculateAddressing tgtToSrcCellAddr[i].transfer(tgtToSrcAddr[i]); tgtToSrcCellWght[i].transfer(tgtToSrcWght[i]); } + + + if (debug%2) + { + // At this point the overlaps are still in volume so we could + // get out the relative error + forAll(srcToTgtCellAddr, cellI) + { + scalar srcVol = src_.cellVolumes()[cellI]; + scalar tgtVol = sum(srcToTgtCellWght[cellI]); + + if (mag(srcVol) > ROOTVSMALL && mag((tgtVol-srcVol)/srcVol) > 1e-6) + { + WarningIn("cellVolumeWeightMethod::calculateAddressing(..)") + << "At cell " << cellI << " cc:" + << src_.cellCentres()[cellI] + << " vol:" << srcVol + << " total overlap volume:" << tgtVol + << endl; + } + } + + forAll(tgtToSrcCellAddr, cellI) + { + scalar tgtVol = tgt_.cellVolumes()[cellI]; + scalar srcVol = sum(tgtToSrcCellWght[cellI]); + + if (mag(tgtVol) > ROOTVSMALL && mag((srcVol-tgtVol)/tgtVol) > 1e-6) + { + WarningIn("cellVolumeWeightMethod::calculateAddressing(..)") + << "At cell " << cellI << " cc:" + << tgt_.cellCentres()[cellI] + << " vol:" << tgtVol + << " total overlap volume:" << srcVol + << endl; + } + } + } } @@ -315,8 +353,10 @@ void Foam::cellVolumeWeightMethod::calculate ( labelListList& srcToTgtAddr, scalarListList& srcToTgtWght, + pointListList& srcToTgtVec, labelListList& tgtToSrcAddr, - scalarListList& tgtToSrcWght + scalarListList& tgtToSrcWght, + pointListList& tgtToSrcVec ) { bool ok = initialise diff --git a/src/sampling/meshToMesh/calcMethod/cellVolumeWeight/cellVolumeWeightMethod.H b/src/sampling/meshToMesh/calcMethod/cellVolumeWeight/cellVolumeWeightMethod.H index 9e81715722006d1f2b55838637e5c9d5db18553e..c10946a1e7c66db07d3ad62455979d1d8db60b8b 100644 --- a/src/sampling/meshToMesh/calcMethod/cellVolumeWeight/cellVolumeWeightMethod.H +++ b/src/sampling/meshToMesh/calcMethod/cellVolumeWeight/cellVolumeWeightMethod.H @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2013-2015 OpenFOAM Foundation - \\/ M anipulation | + \\ / A nd | Copyright (C) 2013-2014 OpenFOAM Foundation + \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -116,13 +116,15 @@ public: // Evaluate - //- Calculate addressing and weights + //- Calculate addressing and weights and optionally offset vectors virtual void calculate ( labelListList& srcToTgtAddr, scalarListList& srcToTgtWght, - labelListList& tgtToTgtAddr, - scalarListList& tgtToTgtWght + pointListList& srcToTgtVec, + labelListList& tgtToSrcAddr, + scalarListList& tgtToSrcWght, + pointListList& tgtToSrcVec ); }; diff --git a/src/sampling/meshToMesh/calcMethod/correctedCellVolumeWeight/correctedCellVolumeWeightMethod.C b/src/sampling/meshToMesh/calcMethod/correctedCellVolumeWeight/correctedCellVolumeWeightMethod.C new file mode 100644 index 0000000000000000000000000000000000000000..2acc2b72c1d0ef196f2ad975e5e0a9b347049cab --- /dev/null +++ b/src/sampling/meshToMesh/calcMethod/correctedCellVolumeWeight/correctedCellVolumeWeightMethod.C @@ -0,0 +1,296 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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 "correctedCellVolumeWeightMethod.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + defineTypeNameAndDebug(correctedCellVolumeWeightMethod, 0); + addToRunTimeSelectionTable + ( + meshToMeshMethod, + correctedCellVolumeWeightMethod, + components + ); +} + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +void Foam::correctedCellVolumeWeightMethod::calculateAddressing +( + labelListList& srcToTgtCellAddr, + scalarListList& srcToTgtCellWght, + pointListList& srcToTgtCellVec, + labelListList& tgtToSrcCellAddr, + scalarListList& tgtToSrcCellWght, + pointListList& tgtToSrcCellVec, + const label srcSeedI, + const label tgtSeedI, + const labelList& srcCellIDs, + boolList& mapFlag, + label& startSeedI +) +{ + label srcCellI = srcSeedI; + label tgtCellI = tgtSeedI; + + List<DynamicList<label> > srcToTgtAddr(src_.nCells()); + List<DynamicList<scalar> > srcToTgtWght(src_.nCells()); + List<DynamicList<point> > srcToTgtVec(src_.nCells()); + + List<DynamicList<label> > tgtToSrcAddr(tgt_.nCells()); + List<DynamicList<scalar> > tgtToSrcWght(tgt_.nCells()); + List<DynamicList<point> > tgtToSrcVec(tgt_.nCells()); + + // list of tgt cell neighbour cells + DynamicList<label> nbrTgtCells(10); + + // list of tgt cells currently visited for srcCellI to avoid multiple hits + DynamicList<label> visitedTgtCells(10); + + // list to keep track of tgt cells used to seed src cells + labelList seedCells(src_.nCells(), -1); + seedCells[srcCellI] = tgtCellI; + + const scalarField& srcVol = src_.cellVolumes(); + const pointField& srcCc = src_.cellCentres(); + const pointField& tgtCc = tgt_.cellCentres(); + + do + { + nbrTgtCells.clear(); + visitedTgtCells.clear(); + + // append initial target cell and neighbours + nbrTgtCells.append(tgtCellI); + appendNbrCells(tgtCellI, tgt_, visitedTgtCells, nbrTgtCells); + + do + { + tgtCellI = nbrTgtCells.remove(); + visitedTgtCells.append(tgtCellI); + + Tuple2<scalar, point> vol = interVolAndCentroid + ( + srcCellI, + tgtCellI + ); + + // accumulate addressing and weights for valid intersection + if (vol.first()/srcVol[srcCellI] > tolerance_) + { + // store src/tgt cell pair + srcToTgtAddr[srcCellI].append(tgtCellI); + srcToTgtWght[srcCellI].append(vol.first()); + srcToTgtVec[srcCellI].append(vol.second()-tgtCc[tgtCellI]); + + tgtToSrcAddr[tgtCellI].append(srcCellI); + tgtToSrcWght[tgtCellI].append(vol.first()); + tgtToSrcVec[tgtCellI].append(vol.second()-srcCc[srcCellI]); + + appendNbrCells(tgtCellI, tgt_, visitedTgtCells, nbrTgtCells); + + // accumulate intersection volume + V_ += vol.first(); + } + } + while (!nbrTgtCells.empty()); + + mapFlag[srcCellI] = false; + + // find new source seed cell + setNextCells + ( + startSeedI, + srcCellI, + tgtCellI, + srcCellIDs, + mapFlag, + visitedTgtCells, + seedCells + ); + } + while (srcCellI != -1); + + // transfer addressing into persistent storage + forAll(srcToTgtCellAddr, i) + { + srcToTgtCellAddr[i].transfer(srcToTgtAddr[i]); + srcToTgtCellWght[i].transfer(srcToTgtWght[i]); + srcToTgtCellVec[i].transfer(srcToTgtVec[i]); + } + + forAll(tgtToSrcCellAddr, i) + { + tgtToSrcCellAddr[i].transfer(tgtToSrcAddr[i]); + tgtToSrcCellWght[i].transfer(tgtToSrcWght[i]); + tgtToSrcCellVec[i].transfer(tgtToSrcVec[i]); + } + + + if (debug%2) + { + // At this point the overlaps are still in volume so we could + // get out the relative error + forAll(srcToTgtCellAddr, cellI) + { + scalar srcVol = src_.cellVolumes()[cellI]; + scalar tgtVol = sum(srcToTgtCellWght[cellI]); + + if (mag(srcVol) > ROOTVSMALL && mag((tgtVol-srcVol)/srcVol) > 1e-6) + { + WarningIn + ( + "correctedCellVolumeWeightMethod::calculateAddressing(..)" + ) << "At cell " << cellI << " cc:" + << src_.cellCentres()[cellI] + << " vol:" << srcVol + << " total overlap volume:" << tgtVol + << endl; + } + } + + forAll(tgtToSrcCellAddr, cellI) + { + scalar tgtVol = tgt_.cellVolumes()[cellI]; + scalar srcVol = sum(tgtToSrcCellWght[cellI]); + + if (mag(tgtVol) > ROOTVSMALL && mag((srcVol-tgtVol)/tgtVol) > 1e-6) + { + WarningIn + ( + "correctedCellVolumeWeightMethod::calculateAddressing(..)" + ) << "At cell " << cellI << " cc:" + << tgt_.cellCentres()[cellI] + << " vol:" << tgtVol + << " total overlap volume:" << srcVol + << endl; + } + } + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::correctedCellVolumeWeightMethod::correctedCellVolumeWeightMethod +( + const polyMesh& src, + const polyMesh& tgt +) +: + cellVolumeWeightMethod(src, tgt) +{} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::correctedCellVolumeWeightMethod::~correctedCellVolumeWeightMethod() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::correctedCellVolumeWeightMethod::calculate +( + labelListList& srcToTgtAddr, + scalarListList& srcToTgtWght, + pointListList& srcToTgtVec, + + labelListList& tgtToSrcAddr, + scalarListList& tgtToSrcWght, + pointListList& tgtToSrcVec +) +{ + bool ok = initialise + ( + srcToTgtAddr, + srcToTgtWght, + tgtToSrcAddr, + tgtToSrcWght + ); + + if (!ok) + { + return; + } + + srcToTgtVec.setSize(srcToTgtAddr.size()); + tgtToSrcVec.setSize(tgtToSrcAddr.size()); + + + // (potentially) participating source mesh cells + const labelList srcCellIDs(maskCells()); + + // list to keep track of whether src cell can be mapped + boolList mapFlag(src_.nCells(), false); + UIndirectList<bool>(mapFlag, srcCellIDs) = true; + + // find initial point in tgt mesh + label srcSeedI = -1; + label tgtSeedI = -1; + label startSeedI = 0; + + bool startWalk = + findInitialSeeds + ( + srcCellIDs, + mapFlag, + startSeedI, + srcSeedI, + tgtSeedI + ); + + if (startWalk) + { + calculateAddressing + ( + srcToTgtAddr, + srcToTgtWght, + srcToTgtVec, + tgtToSrcAddr, + tgtToSrcWght, + tgtToSrcVec, + srcSeedI, + tgtSeedI, + srcCellIDs, + mapFlag, + startSeedI + ); + } + else + { + // if meshes are collocated, after inflating the source mesh bounding + // box tgt mesh cells may be transferred, but may still not overlap + // with the source mesh + return; + } +} + + +// ************************************************************************* // diff --git a/src/sampling/meshToMesh/calcMethod/correctedCellVolumeWeight/correctedCellVolumeWeightMethod.H b/src/sampling/meshToMesh/calcMethod/correctedCellVolumeWeight/correctedCellVolumeWeightMethod.H new file mode 100644 index 0000000000000000000000000000000000000000..b6b99d8923a30745d27d11745ad17fc12c39b377 --- /dev/null +++ b/src/sampling/meshToMesh/calcMethod/correctedCellVolumeWeight/correctedCellVolumeWeightMethod.H @@ -0,0 +1,119 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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::correctedCellVolumeWeightMethod + +Description + Cell-volume-weighted mesh-to-mesh interpolation class + + Volume conservative with calculated offset vectors + +SourceFiles + correctedCellVolumeWeightMethod.C + +\*---------------------------------------------------------------------------*/ + +#ifndef correctedCellVolumeWeightMethod_H +#define correctedCellVolumeWeightMethod_H + +#include "cellVolumeWeightMethod.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class correctedCellVolumeWeightMethod Declaration +\*---------------------------------------------------------------------------*/ + +class correctedCellVolumeWeightMethod +: + public cellVolumeWeightMethod +{ +protected: + + // Protected Member Functions + + //- Calculate the mesh-to-mesh addressing and weights + void calculateAddressing + ( + labelListList& srcToTgtCellAddr, + scalarListList& srcToTgtCellWght, + pointListList& srcToTgtCellVec, + labelListList& tgtToSrcCellAddr, + scalarListList& tgtToSrcCellWght, + pointListList& tgtToSrcCellVec, + const label srcSeedI, + const label tgtSeedI, + const labelList& srcCellIDs, + boolList& mapFlag, + label& startSeedI + ); + + //- Disallow default bitwise copy construct + correctedCellVolumeWeightMethod(const correctedCellVolumeWeightMethod&); + + //- Disallow default bitwise assignment + void operator=(const correctedCellVolumeWeightMethod&); + + +public: + + //- Run-time type information + TypeName("correctedCellVolumeWeight"); + + //- Construct from source and target meshes + correctedCellVolumeWeightMethod(const polyMesh& src, const polyMesh& tgt); + + //- Destructor + virtual ~correctedCellVolumeWeightMethod(); + + + // Member Functions + + // Evaluate + + //- Calculate addressing and weights and optionally offset vectors + virtual void calculate + ( + labelListList& srcToTgtAddr, + scalarListList& srcToTgtWght, + pointListList& srcToTgtVec, + labelListList& tgtToSrcAddr, + scalarListList& tgtToSrcWght, + pointListList& tgtToSrcVec + ); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/sampling/meshToMesh/calcMethod/direct/directMethod.C b/src/sampling/meshToMesh/calcMethod/direct/directMethod.C index 7468fd4fd0491995414e582580b456f754dba956..0b9a634881c93d2cba34b92c0944380a20b90960 100644 --- a/src/sampling/meshToMesh/calcMethod/direct/directMethod.C +++ b/src/sampling/meshToMesh/calcMethod/direct/directMethod.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2013-2015 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -72,21 +72,15 @@ bool Foam::directMethod::findInitialSeeds if (mapFlag[srcI]) { - const pointField - pts(srcCells[srcI].points(srcFaces, srcPts).xfer()); + const point srcCtr(srcCells[srcI].centre(srcPts, srcFaces)); + label tgtI = tgt_.cellTree().findInside(srcCtr); - forAll(pts, ptI) + if (tgtI != -1 && intersect(srcI, tgtI)) { - const point& pt = pts[ptI]; - label tgtI = tgt_.cellTree().findInside(pt); + srcSeedI = srcI; + tgtSeedI = tgtI; - if (tgtI != -1 && intersect(srcI, tgtI)) - { - srcSeedI = srcI; - tgtSeedI = tgtI; - - return true; - } + return true; } } } @@ -178,8 +172,6 @@ void Foam::directMethod::appendToDirectSeeds const labelList& srcNbr = src_.cellCells()[srcSeedI]; const labelList& tgtNbr = tgt_.cellCells()[tgtSeedI]; - const vectorField& srcCentre = src_.cellCentres(); - forAll(srcNbr, i) { label srcI = srcNbr[i]; @@ -194,15 +186,7 @@ void Foam::directMethod::appendToDirectSeeds { label tgtI = tgtNbr[j]; - if - ( - tgt_.pointInCell - ( - srcCentre[srcI], - tgtI, - polyMesh::FACE_PLANES - ) - ) + if (intersect(srcI, tgtI)) { // new match - append to lists found = true; @@ -251,14 +235,17 @@ Foam::directMethod::directMethod Foam::directMethod::~directMethod() {} + // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // void Foam::directMethod::calculate ( labelListList& srcToTgtAddr, scalarListList& srcToTgtWght, + pointListList& srcToTgtVec, labelListList& tgtToSrcAddr, - scalarListList& tgtToSrcWght + scalarListList& tgtToSrcWght, + pointListList& tgtToSrcVec ) { bool ok = initialise diff --git a/src/sampling/meshToMesh/calcMethod/direct/directMethod.H b/src/sampling/meshToMesh/calcMethod/direct/directMethod.H index ddbb2c208cefe137d4dde75635746028ba025044..8209c8153e41830078129698f49c25afea1db0a4 100644 --- a/src/sampling/meshToMesh/calcMethod/direct/directMethod.H +++ b/src/sampling/meshToMesh/calcMethod/direct/directMethod.H @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2013-2015 OpenFOAM Foundation - \\/ M anipulation | + \\ / A nd | Copyright (C) 2013-2014 OpenFOAM Foundation + \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -121,13 +121,15 @@ public: // Evaluate - //- Calculate addressing and weights + //- Calculate addressing and weights and optionally offset vectors virtual void calculate ( labelListList& srcToTgtAddr, scalarListList& srcToTgtWght, - labelListList& tgtToTgtAddr, - scalarListList& tgtToTgtWght + pointListList& srcToTgtVec, + labelListList& tgtToSrcAddr, + scalarListList& tgtToSrcWght, + pointListList& tgtToSrcVec ); }; diff --git a/src/sampling/meshToMesh/calcMethod/mapNearest/mapNearestMethod.C b/src/sampling/meshToMesh/calcMethod/mapNearest/mapNearestMethod.C index 27f1610d5c4d85c300e6e28e2813ede923bf5068..123d354b904ada610027f7f7e44d3fcd9e1b6bea 100644 --- a/src/sampling/meshToMesh/calcMethod/mapNearest/mapNearestMethod.C +++ b/src/sampling/meshToMesh/calcMethod/mapNearest/mapNearestMethod.C @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2013-2015 OpenFOAM Foundation - \\/ M anipulation | + \\ / A nd | Copyright (C) 2013-2014 OpenFOAM Foundation + \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -359,8 +359,10 @@ void Foam::mapNearestMethod::calculate ( labelListList& srcToTgtAddr, scalarListList& srcToTgtWght, + pointListList& srcToTgtVec, labelListList& tgtToSrcAddr, - scalarListList& tgtToSrcWght + scalarListList& tgtToSrcWght, + pointListList& tgtToSrcVec ) { bool ok = initialise diff --git a/src/sampling/meshToMesh/calcMethod/mapNearest/mapNearestMethod.H b/src/sampling/meshToMesh/calcMethod/mapNearest/mapNearestMethod.H index b26bc645ac450584d5aa45a0a405e13219326b8f..53ce116e32a6c03bc9ef4dcd268d014598d1f7f4 100644 --- a/src/sampling/meshToMesh/calcMethod/mapNearest/mapNearestMethod.H +++ b/src/sampling/meshToMesh/calcMethod/mapNearest/mapNearestMethod.H @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2013-2015 OpenFOAM Foundation - \\/ M anipulation | + \\ / A nd | Copyright (C) 2013-2014 OpenFOAM Foundation + \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -134,13 +134,15 @@ public: // Evaluate - //- Calculate addressing and weights + //- Calculate addressing and weights and optionally offset vectors virtual void calculate ( labelListList& srcToTgtAddr, scalarListList& srcToTgtWght, - labelListList& tgtToTgtAddr, - scalarListList& tgtToTgtWght + pointListList& srcToTgtVec, + labelListList& tgtToSrcAddr, + scalarListList& tgtToSrcWght, + pointListList& tgtToSrcVec ); }; diff --git a/src/sampling/meshToMesh/calcMethod/meshToMeshMethod/meshToMeshMethod.C b/src/sampling/meshToMesh/calcMethod/meshToMeshMethod/meshToMeshMethod.C index 11b0a5d5928a7e72695d9789228f1f66fa9b011e..4c34ebe43c1e5858250d2bcdfb0b72cceb169279 100644 --- a/src/sampling/meshToMesh/calcMethod/meshToMeshMethod/meshToMeshMethod.C +++ b/src/sampling/meshToMesh/calcMethod/meshToMeshMethod/meshToMeshMethod.C @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2013-2015 OpenFOAM Foundation - \\/ M anipulation | + \\ / A nd | Copyright (C) 2013-2014 OpenFOAM Foundation + \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -121,6 +121,42 @@ Foam::scalar Foam::meshToMeshMethod::interVol } +Foam::Tuple2<Foam::scalar, Foam::point> +Foam::meshToMeshMethod::interVolAndCentroid +( + const label srcCellI, + const label tgtCellI +) +{ + tetOverlapVolume overlapEngine; + + treeBoundBox bbTgtCell(tgt_.points(), tgt_.cellPoints()[tgtCellI]); + + Tuple2<scalar, point> volAndInertia = + overlapEngine.cellCellOverlapMomentMinDecomp + ( + src_, + srcCellI, + tgt_, + tgtCellI, + bbTgtCell + ); + + // Convert from inertia to centroid + if (volAndInertia.first() <= ROOTVSMALL) + { + volAndInertia.first() = 0.0; + volAndInertia.second() = vector::zero; + } + else + { + volAndInertia.second() /= volAndInertia.first(); + } + + return volAndInertia; +} + + void Foam::meshToMeshMethod::appendNbrCells ( const label cellI, diff --git a/src/sampling/meshToMesh/calcMethod/meshToMeshMethod/meshToMeshMethod.H b/src/sampling/meshToMesh/calcMethod/meshToMeshMethod/meshToMeshMethod.H index 7397673d54115197f3bc57624b41e1ceaedb5e38..4c906a993b9e073fb438aeeb593cfa6f2ebab6ed 100644 --- a/src/sampling/meshToMesh/calcMethod/meshToMeshMethod/meshToMeshMethod.H +++ b/src/sampling/meshToMesh/calcMethod/meshToMeshMethod/meshToMeshMethod.H @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2013-2015 OpenFOAM Foundation - \\/ M anipulation | + \\ / A nd | Copyright (C) 2013-2014 OpenFOAM Foundation + \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -36,8 +36,8 @@ SourceFiles #define meshToMeshMethod_H #include "polyMesh.H" - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +#include "pointList.H" +#include "Tuple2.H" namespace Foam { @@ -85,6 +85,13 @@ protected: const label tgtCellI ) const; + //- Return the intersection volume and centroid between two cells + virtual Tuple2<scalar, point> interVolAndCentroid + ( + const label srcCellI, + const label tgtCellI + ); + //- Append target cell neihgbour cells to cellIDs list virtual void appendNbrCells ( @@ -147,13 +154,15 @@ public: // Evaluate - //- Calculate addressing and weights + //- Calculate addressing and weights and optionally offset vectors virtual void calculate ( labelListList& srcToTgtAddr, scalarListList& srcToTgtWght, - labelListList& tgtToTgtAddr, - scalarListList& tgtToTgtWght + pointListList& srcToTgtVec, + labelListList& tgtToSrcAddr, + scalarListList& tgtToSrcWght, + pointListList& tgtToSrcVec ) = 0; diff --git a/src/sampling/meshToMesh/distributedWeightedFvPatchFieldMapper.H b/src/sampling/meshToMesh/distributedWeightedFvPatchFieldMapper.H new file mode 100644 index 0000000000000000000000000000000000000000..930c502ca1de9b2a29aa5cc67ecc357355e2583e --- /dev/null +++ b/src/sampling/meshToMesh/distributedWeightedFvPatchFieldMapper.H @@ -0,0 +1,170 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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::distributedWeightedFvPatchFieldMapper + +Description + FieldMapper with weighted mapping from (optionally remote) quantities. + +\*---------------------------------------------------------------------------*/ + +#ifndef distributedWeightedFvPatchFieldMapper_H +#define distributedWeightedFvPatchFieldMapper_H + +#include "fvPatchFieldMapper.H" +#include "mapDistributeBase.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class distributedWeightedFvPatchFieldMapper Declaration +\*---------------------------------------------------------------------------*/ + +class distributedWeightedFvPatchFieldMapper +: + public fvPatchFieldMapper +{ + const label singlePatchProc_; + + const mapDistributeBase* distMapPtr_; + + const labelListList& addressing_; + + const scalarListList& weights_; + + bool hasUnmapped_; + +public: + + // Constructors + + //- Construct given addressing + distributedWeightedFvPatchFieldMapper + ( + const label singlePatchProc, + const mapDistributeBase* distMapPtr, + const labelListList& addressing, + const scalarListList& weights + ) + : + singlePatchProc_(singlePatchProc), + distMapPtr_(distMapPtr), + addressing_(addressing), + weights_(weights), + hasUnmapped_(false) + { + forAll(addressing_, i) + { + if (addressing_[i].size() == 0) + { + hasUnmapped_ = true; + } + } + + if ((singlePatchProc_ == -1) != (distMapPtr_ != NULL)) + { + FatalErrorIn + ( + "distributedWeightedFvPatchFieldMapper::" + "distributedWeightedFvPatchFieldMapper(..)" + ) << "Supply a mapDistributeBase if and only if " + << "singlePatchProc is -1" + << " singlePatchProc_:" << singlePatchProc_ + << " distMapPtr_:" << (distMapPtr_ != NULL) + << exit(FatalError); + } + } + + //- Destructor + virtual ~distributedWeightedFvPatchFieldMapper() + {} + + + // Member Functions + + virtual label size() const + { + if (distributed()) + { + return distributeMap().constructSize(); + } + else + { + return addressing().size(); + } + } + + virtual bool direct() const + { + return false; + } + + virtual bool distributed() const + { + return singlePatchProc_ == -1; + } + + virtual const mapDistributeBase& distributeMap() const + { + if (!distMapPtr_) + { + FatalErrorIn + ( + "distributedWeightedFvPatchFieldMapper::" + "distributeMap()" + ) << "Cannot ask for distributeMap on a non-distributed" + << " mapper" << exit(FatalError); + } + return *distMapPtr_; + } + + virtual bool hasUnmapped() const + { + return hasUnmapped_; + } + + virtual const labelListList& addressing() const + { + return addressing_; + } + + virtual const scalarListList& weights() const + { + return weights_; + } + +}; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/sampling/meshToMesh/meshToMesh.C b/src/sampling/meshToMesh/meshToMesh.C index c03c3789d24426a65f5e1f9fb63db1cbbfdf9bff..0db03668e04e9c062c2783dde5799a8d0c56858e 100644 --- a/src/sampling/meshToMesh/meshToMesh.C +++ b/src/sampling/meshToMesh/meshToMesh.C @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2012-2015 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. @@ -38,21 +38,288 @@ namespace Foam const char* Foam::NamedEnum < Foam::meshToMesh::interpolationMethod, - 3 + 4 >::names[] = { "direct", "mapNearest", - "cellVolumeWeight" + "cellVolumeWeight", + "correctedCellVolumeWeight" }; - const NamedEnum<meshToMesh::interpolationMethod, 3> + const NamedEnum<meshToMesh::interpolationMethod, 4> meshToMesh::interpolationMethodNames_; } // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // +template<> +void Foam::meshToMesh::mapInternalSrcToTgt +( + const GeometricField<sphericalTensor, fvPatchField, volMesh>& field, + const plusEqOp<sphericalTensor>& cop, + GeometricField<sphericalTensor, fvPatchField, volMesh>& result, + const bool secondOrder +) const +{ + mapSrcToTgt(field, cop, result.internalField()); +} + + +template<> +void Foam::meshToMesh::mapInternalSrcToTgt +( + const GeometricField<sphericalTensor, fvPatchField, volMesh>& field, + const minusEqOp<sphericalTensor>& cop, + GeometricField<sphericalTensor, fvPatchField, volMesh>& result, + const bool secondOrder +) const +{ + mapSrcToTgt(field, cop, result.internalField()); +} + + +template<> +void Foam::meshToMesh::mapInternalSrcToTgt +( + const GeometricField<symmTensor, fvPatchField, volMesh>& field, + const plusEqOp<symmTensor>& cop, + GeometricField<symmTensor, fvPatchField, volMesh>& result, + const bool secondOrder +) const +{ + mapSrcToTgt(field, cop, result.internalField()); +} + + +template<> +void Foam::meshToMesh::mapInternalSrcToTgt +( + const GeometricField<symmTensor, fvPatchField, volMesh>& field, + const minusEqOp<symmTensor>& cop, + GeometricField<symmTensor, fvPatchField, volMesh>& result, + const bool secondOrder +) const +{ + mapSrcToTgt(field, cop, result.internalField()); +} + + +template<> +void Foam::meshToMesh::mapInternalSrcToTgt +( + const GeometricField<tensor, fvPatchField, volMesh>& field, + const plusEqOp<tensor>& cop, + GeometricField<tensor, fvPatchField, volMesh>& result, + const bool secondOrder +) const +{ + mapSrcToTgt(field, cop, result.internalField()); +} + + +template<> +void Foam::meshToMesh::mapInternalSrcToTgt +( + const GeometricField<tensor, fvPatchField, volMesh>& field, + const minusEqOp<tensor>& cop, + GeometricField<tensor, fvPatchField, volMesh>& result, + const bool secondOrder +) const +{ + mapSrcToTgt(field, cop, result.internalField()); +} + + +template<> +void Foam::meshToMesh::mapInternalTgtToSrc +( + const GeometricField<sphericalTensor, fvPatchField, volMesh>& field, + const plusEqOp<sphericalTensor>& cop, + GeometricField<sphericalTensor, fvPatchField, volMesh>& result, + const bool secondOrder +) const +{ + mapSrcToTgt(field, cop, result.internalField()); +} + + +template<> +void Foam::meshToMesh::mapInternalTgtToSrc +( + const GeometricField<sphericalTensor, fvPatchField, volMesh>& field, + const minusEqOp<sphericalTensor>& cop, + GeometricField<sphericalTensor, fvPatchField, volMesh>& result, + const bool secondOrder +) const +{ + mapSrcToTgt(field, cop, result.internalField()); +} + + +template<> +void Foam::meshToMesh::mapInternalTgtToSrc +( + const GeometricField<symmTensor, fvPatchField, volMesh>& field, + const plusEqOp<symmTensor>& cop, + GeometricField<symmTensor, fvPatchField, volMesh>& result, + const bool secondOrder +) const +{ + mapSrcToTgt(field, cop, result.internalField()); +} + + +template<> +void Foam::meshToMesh::mapInternalTgtToSrc +( + const GeometricField<symmTensor, fvPatchField, volMesh>& field, + const minusEqOp<symmTensor>& cop, + GeometricField<symmTensor, fvPatchField, volMesh>& result, + const bool secondOrder +) const +{ + mapSrcToTgt(field, cop, result.internalField()); +} + + +template<> +void Foam::meshToMesh::mapInternalTgtToSrc +( + const GeometricField<tensor, fvPatchField, volMesh>& field, + const plusEqOp<tensor>& cop, + GeometricField<tensor, fvPatchField, volMesh>& result, + const bool secondOrder +) const +{ + mapSrcToTgt(field, cop, result.internalField()); +} + + +template<> +void Foam::meshToMesh::mapInternalTgtToSrc +( + const GeometricField<tensor, fvPatchField, volMesh>& field, + const minusEqOp<tensor>& cop, + GeometricField<tensor, fvPatchField, volMesh>& result, + const bool secondOrder +) const +{ + mapSrcToTgt(field, cop, result.internalField()); +} + + +template<> +void Foam::meshToMesh::mapAndOpSrcToTgt +( + const AMIPatchToPatchInterpolation& AMI, + const Field<scalar>& srcField, + Field<scalar>& tgtField, + const plusEqOp<scalar>& cop +) const +{} + + +template<> +void Foam::meshToMesh::mapAndOpSrcToTgt +( + const AMIPatchToPatchInterpolation& AMI, + const Field<vector>& srcField, + Field<vector>& tgtField, + const plusEqOp<vector>& cop +) const +{} + + +template<> +void Foam::meshToMesh::mapAndOpSrcToTgt +( + const AMIPatchToPatchInterpolation& AMI, + const Field<sphericalTensor>& srcField, + Field<sphericalTensor>& tgtField, + const plusEqOp<sphericalTensor>& cop +) const +{} + + +template<> +void Foam::meshToMesh::mapAndOpSrcToTgt +( + const AMIPatchToPatchInterpolation& AMI, + const Field<symmTensor>& srcField, + Field<symmTensor>& tgtField, + const plusEqOp<symmTensor>& cop +) const +{} + + +template<> +void Foam::meshToMesh::mapAndOpSrcToTgt +( + const AMIPatchToPatchInterpolation& AMI, + const Field<tensor>& srcField, + Field<tensor>& tgtField, + const plusEqOp<tensor>& cop +) const +{} + + +template<> +void Foam::meshToMesh::mapAndOpTgtToSrc +( + const AMIPatchToPatchInterpolation& AMI, + Field<scalar>& srcField, + const Field<scalar>& tgtField, + const plusEqOp<scalar>& cop +) const +{} + + +template<> +void Foam::meshToMesh::mapAndOpTgtToSrc +( + const AMIPatchToPatchInterpolation& AMI, + Field<vector>& srcField, + const Field<vector>& tgtField, + const plusEqOp<vector>& cop +) const +{} + + +template<> +void Foam::meshToMesh::mapAndOpTgtToSrc +( + const AMIPatchToPatchInterpolation& AMI, + Field<sphericalTensor>& srcField, + const Field<sphericalTensor>& tgtField, + const plusEqOp<sphericalTensor>& cop +) const +{} + + +template<> +void Foam::meshToMesh::mapAndOpTgtToSrc +( + const AMIPatchToPatchInterpolation& AMI, + Field<symmTensor>& srcField, + const Field<symmTensor>& tgtField, + const plusEqOp<symmTensor>& cop +) const +{} + + +template<> +void Foam::meshToMesh::mapAndOpTgtToSrc +( + const AMIPatchToPatchInterpolation& AMI, + Field<tensor>& srcField, + const Field<tensor>& tgtField, + const plusEqOp<tensor>& cop +) const +{} + + Foam::labelList Foam::meshToMesh::maskCells ( const polyMesh& src, @@ -138,8 +405,10 @@ void Foam::meshToMesh::calcAddressing ( srcToTgtCellAddr_, srcToTgtCellWght_, + srcToTgtCellVec_, tgtToSrcCellAddr_, - tgtToSrcCellWght_ + tgtToSrcCellWght_, + tgtToSrcCellVec_ ); V_ = methodPtr->V(); @@ -265,28 +534,34 @@ void Foam::meshToMesh::calculate(const word& methodName) } // set up as a reverse distribute - mapDistribute::distribute + mapDistributeBase::distribute ( Pstream::nonBlocking, List<labelPair>(), tgtRegion_.nCells(), map.constructMap(), + false, map.subMap(), + false, tgtToSrcCellAddr_, ListPlusEqOp<label>(), + flipOp(), labelList() ); // set up as a reverse distribute - mapDistribute::distribute + mapDistributeBase::distribute ( Pstream::nonBlocking, List<labelPair>(), tgtRegion_.nCells(), map.constructMap(), + false, map.subMap(), + false, tgtToSrcCellWght_, ListPlusEqOp<scalar>(), + flipOp(), scalarList() ); @@ -358,6 +633,7 @@ Foam::meshToMesh::interpolationMethodAMI(const interpolationMethod method) break; } case imCellVolumeWeight: + case imCorrectedCellVolumeWeight: { return AMIPatchToPatchInterpolation::imFaceAreaWeight; break; @@ -493,23 +769,28 @@ void Foam::meshToMesh::constructFromCuttingPatches const wordList& cuttingPatches ) { - srcPatchID_.setSize(patchMap.size()); - tgtPatchID_.setSize(patchMap.size()); + DynamicList<label> srcIDs(patchMap.size()); + DynamicList<label> tgtIDs(patchMap.size()); - label i = 0; forAllConstIter(HashTable<word>, patchMap, iter) { const word& tgtPatchName = iter.key(); const word& srcPatchName = iter(); const polyPatch& srcPatch = srcRegion_.boundaryMesh()[srcPatchName]; - const polyPatch& tgtPatch = tgtRegion_.boundaryMesh()[tgtPatchName]; - srcPatchID_[i] = srcPatch.index(); - tgtPatchID_[i] = tgtPatch.index(); - i++; + if (!polyPatch::constraintType(srcPatch.type())) + { + const polyPatch& tgtPatch = tgtRegion_.boundaryMesh()[tgtPatchName]; + + srcIDs.append(srcPatch.index()); + tgtIDs.append(tgtPatch.index()); + } } + srcPatchID_.transfer(srcIDs); + tgtPatchID_.transfer(tgtIDs); + // calculate volume addressing and weights calculate(methodName); @@ -546,6 +827,8 @@ Foam::meshToMesh::meshToMesh tgtToSrcCellAddr_(), srcToTgtCellWght_(), tgtToSrcCellWght_(), + srcToTgtCellVec_(), + tgtToSrcCellVec_(), V_(0.0), singleMeshProc_(-1), srcMapPtr_(NULL), @@ -582,6 +865,8 @@ Foam::meshToMesh::meshToMesh tgtToSrcCellAddr_(), srcToTgtCellWght_(), tgtToSrcCellWght_(), + srcToTgtCellVec_(), + tgtToSrcCellVec_(), V_(0.0), singleMeshProc_(-1), srcMapPtr_(NULL), diff --git a/src/sampling/meshToMesh/meshToMesh.H b/src/sampling/meshToMesh/meshToMesh.H index 718270e4f5ed2313ce806481048bcf63d8ef1962..0e3e6259a5840d716315f30512db3c9f25196db4 100644 --- a/src/sampling/meshToMesh/meshToMesh.H +++ b/src/sampling/meshToMesh/meshToMesh.H @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2012-2015 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. @@ -43,11 +43,12 @@ SourceFiles #define meshToMesh_H #include "polyMesh.H" -#include "boundBox.H" +#include "treeBoundBox.H" #include "mapDistribute.H" #include "volFieldsFwd.H" #include "NamedEnum.H" #include "AMIPatchToPatchInterpolation.H" +#include "pointList.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -69,10 +70,11 @@ public: { imDirect, imMapNearest, - imCellVolumeWeight + imCellVolumeWeight, + imCorrectedCellVolumeWeight }; - static const NamedEnum<interpolationMethod, 3> + static const NamedEnum<interpolationMethod, 4> interpolationMethodNames_; private: @@ -109,6 +111,15 @@ private: //- Target to source cell interpolation weights scalarListList tgtToSrcCellWght_; + // Vectors from cell centre to overlap volume for 2nd order correction + // (only set for corrected methods) + + //- Source to target cell offset vectors + pointListList srcToTgtCellVec_; + + //- Target to source cell offset vectors + pointListList tgtToSrcCellVec_; + //- Cell total volume in overlap region [m3] scalar V_; @@ -129,6 +140,50 @@ private: template<class Type> void add(UList<Type>& fld, const label offset) const; + //- Helper function to interpolate internal field. Optionally uses + // gradient. Template specialisations for tensor types below + template<class Type, class CombineOp> + void mapInternalSrcToTgt + ( + const GeometricField<Type, fvPatchField, volMesh>& field, + const CombineOp& cop, + GeometricField<Type, fvPatchField, volMesh>& result, + const bool secondOrder + ) const; + + //- Helper function to interpolate internal field. Optionally uses + // gradient. Template specialisations for tensor types below + template<class Type, class CombineOp> + void mapInternalTgtToSrc + ( + const GeometricField<Type, fvPatchField, volMesh>& field, + const CombineOp& cop, + GeometricField<Type, fvPatchField, volMesh>& result, + const bool secondOrder + ) const; + + //- Helper function to interpolate patch field. Template + // specialisations below + template<class Type, class CombineOp> + void mapAndOpSrcToTgt + ( + const AMIPatchToPatchInterpolation& AMI, + const Field<Type>& srcField, + Field<Type>& tgtField, + const CombineOp& cop + ) const; + + //- Helper function to interpolate patch field. Template + // specialisations below + template<class Type, class CombineOp> + void mapAndOpTgtToSrc + ( + const AMIPatchToPatchInterpolation& AMI, + Field<Type>& srcField, + const Field<Type>& tgtField, + const CombineOp& cop + ) const; + //- Return src cell IDs for the overlap region labelList maskCells(const polyMesh& src, const polyMesh& tgt) const; @@ -172,11 +227,6 @@ private: const wordList& cuttingPatches ); - //- Return the list of AMIs between source and target patches - inline const PtrList<AMIPatchToPatchInterpolation>& - patchAMIs() const; - - // Parallel operations //- Determine whether the meshes are split across multiple pocessors @@ -189,7 +239,7 @@ private: //- Determine which processor bounding-boxes overlap label calcOverlappingProcs ( - const List<boundBox>& procBb, + const List<treeBoundBoxList>& procBb, const boundBox& bb, boolList& overlaps ) const; @@ -312,6 +362,12 @@ public: //- Return const access to the target to source cell weights inline const scalarListList& tgtToSrcCellWght() const; + //- Return const access to the source to target offset vectors + inline const pointListList& srcToTgtCellVec() const; + + //- Return const access to the target to source offset vectors + inline const pointListList& tgtToSrcCellVec() const; + //- Return const access to the overlap volume inline scalar V() const; @@ -322,12 +378,16 @@ public: const interpolationMethod method ); + //- Return the list of AMIs between source and target patches + inline const PtrList<AMIPatchToPatchInterpolation>& + patchAMIs() const; + // Evaluation // Source-to-target field mapping - //- Map field from src to tgt mesh with defined operation + //- Map field from src to tgt mesh with defined operation. // Values passed in via 'result' are used to initialise the // return value template<class Type, class CombineOp> @@ -338,8 +398,23 @@ public: List<Type>& result ) const; + //- Map extrapolated field (using gradient) from src to tgt + // mesh with defined operation. Falls back to non-extrapolated + // mapping (above) if not constructed with method that supports + // getting offset vectors. Extrapolation only for internal + // values. Values passed in via 'result' are used to + // initialise the return value. + template<class Type, class CombineOp> + void mapSrcToTgt + ( + const UList<Type>& srcField, + const UList<typename outerProduct<vector, Type>::type>&, + const CombineOp& cop, + List<Type>& result + ) const; + //- Return the src field mapped to the tgt mesh with a defined - // operation. Initial values of the result are set to zero + // operation. Initial values of the result are set to zero template<class Type, class CombineOp> tmp<Field<Type> > mapSrcToTgt ( @@ -386,8 +461,23 @@ public: List<Type>& result ) const; + //- Map extrapolated field (using gradient) from tgt to src + // mesh with defined operation. Falls back to non-extrapolated + // mapping (above) if not constructed with method that supports + // getting offset vectors. Extrapolation only for internal + // values. Values passed in via 'result' are used to + // initialise the return value + template<class Type, class CombineOp> + void mapTgtToSrc + ( + const UList<Type>& srcField, + const UList<typename outerProduct<vector, Type>::type>&, + const CombineOp& cop, + List<Type>& result + ) const; + //- Return the tgt field mapped to the src mesh with a defined - // operation. Initial values of the result are set to zero + // operation. Initial values of the result are set to zero template<class Type, class CombineOp> tmp<Field<Type> > mapTgtToSrc ( @@ -425,13 +515,15 @@ public: //- Interpolate a field with a defined operation. Values // passed in via 'result' are used to initialise the return - // value + // value. Optionallly uses gradient correction (internal + // field only) if interpolationMethod supports it template<class Type, class CombineOp> void mapSrcToTgt ( const GeometricField<Type, fvPatchField, volMesh>& field, const CombineOp& cop, - GeometricField<Type, fvPatchField, volMesh>& result + GeometricField<Type, fvPatchField, volMesh>& result, + const bool secondOrder = true ) const; //- Interpolate a field with a defined operation. The initial @@ -440,7 +532,8 @@ public: tmp<GeometricField<Type, fvPatchField, volMesh> > mapSrcToTgt ( const GeometricField<Type, fvPatchField, volMesh>& field, - const CombineOp& cop + const CombineOp& cop, + const bool secondOrder = true ) const; //- Interpolate a tmp field with a defined operation. The @@ -450,7 +543,8 @@ public: ( const tmp<GeometricField<Type, fvPatchField, volMesh> >& tfield, - const CombineOp& cop + const CombineOp& cop, + const bool secondOrder = true ) const; //- Convenience function to map a field with a default @@ -458,7 +552,8 @@ public: template<class Type> tmp<GeometricField<Type, fvPatchField, volMesh> > mapSrcToTgt ( - const GeometricField<Type, fvPatchField, volMesh>& field + const GeometricField<Type, fvPatchField, volMesh>& field, + const bool secondOrder = true ) const; //- Convenience function to map a tmp field with a default @@ -467,7 +562,8 @@ public: tmp<GeometricField<Type, fvPatchField, volMesh> > mapSrcToTgt ( const tmp<GeometricField<Type, fvPatchField, volMesh> >& - tfield + tfield, + const bool secondOrder = true ) const; @@ -475,13 +571,15 @@ public: //- Interpolate a field with a defined operation. Values // passed in via 'result' are used to initialise the return - // value + // value. Optionallly uses gradient correction (internal + // field only) if interpolationMethod supports it template<class Type, class CombineOp> void mapTgtToSrc ( const GeometricField<Type, fvPatchField, volMesh>& field, const CombineOp& cop, - GeometricField<Type, fvPatchField, volMesh>& result + GeometricField<Type, fvPatchField, volMesh>& result, + const bool secondOrder = true ) const; //- Interpolate a field with a defined operation. The initial @@ -490,7 +588,8 @@ public: tmp<GeometricField<Type, fvPatchField, volMesh> > mapTgtToSrc ( const GeometricField<Type, fvPatchField, volMesh>& field, - const CombineOp& cop + const CombineOp& cop, + const bool secondOrder = true ) const; //- Interpolate a tmp field with a defined operation. The @@ -500,7 +599,8 @@ public: ( const tmp<GeometricField<Type, fvPatchField, volMesh> >& tfield, - const CombineOp& cop + const CombineOp& cop, + const bool secondOrder = true ) const; //- Convenience function to map a field with a default @@ -508,7 +608,8 @@ public: template<class Type> tmp<GeometricField<Type, fvPatchField, volMesh> > mapTgtToSrc ( - const GeometricField<Type, fvPatchField, volMesh>& field + const GeometricField<Type, fvPatchField, volMesh>& field, + const bool secondOrder = true ) const; //- Convenience function to map a tmp field with a default @@ -517,13 +618,200 @@ public: tmp<GeometricField<Type, fvPatchField, volMesh> > mapTgtToSrc ( const tmp<GeometricField<Type, fvPatchField, volMesh> >& - tfield + tfield, + const bool secondOrder = true ) const; }; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Disable gradient 2nd order correction for tensor types + +template<> +void meshToMesh::mapInternalSrcToTgt +( + const GeometricField<sphericalTensor, fvPatchField, volMesh>&, + const plusEqOp<sphericalTensor>&, + GeometricField<sphericalTensor, fvPatchField, volMesh>&, + const bool +) const; +template<> +void meshToMesh::mapInternalSrcToTgt +( + const GeometricField<sphericalTensor, fvPatchField, volMesh>&, + const minusEqOp<sphericalTensor>&, + GeometricField<sphericalTensor, fvPatchField, volMesh>&, + const bool +) const; +template<> +void meshToMesh::mapInternalSrcToTgt +( + const GeometricField<symmTensor, fvPatchField, volMesh>&, + const plusEqOp<symmTensor>&, + GeometricField<symmTensor, fvPatchField, volMesh>&, + const bool +) const; +template<> +void meshToMesh::mapInternalSrcToTgt +( + const GeometricField<symmTensor, fvPatchField, volMesh>&, + const minusEqOp<symmTensor>&, + GeometricField<symmTensor, fvPatchField, volMesh>&, + const bool +) const; +template<> +void meshToMesh::mapInternalSrcToTgt +( + const GeometricField<tensor, fvPatchField, volMesh>&, + const plusEqOp<tensor>&, + GeometricField<tensor, fvPatchField, volMesh>&, + const bool +) const; +template<> +void meshToMesh::mapInternalSrcToTgt +( + const GeometricField<tensor, fvPatchField, volMesh>&, + const minusEqOp<tensor>&, + GeometricField<tensor, fvPatchField, volMesh>&, + const bool +) const; +template<> +void meshToMesh::mapInternalTgtToSrc +( + const GeometricField<sphericalTensor, fvPatchField, volMesh>&, + const plusEqOp<sphericalTensor>&, + GeometricField<sphericalTensor, fvPatchField, volMesh>&, + const bool +) const; +template<> +void meshToMesh::mapInternalTgtToSrc +( + const GeometricField<sphericalTensor, fvPatchField, volMesh>&, + const minusEqOp<sphericalTensor>&, + GeometricField<sphericalTensor, fvPatchField, volMesh>&, + const bool +) const; +template<> +void meshToMesh::mapInternalTgtToSrc +( + const GeometricField<symmTensor, fvPatchField, volMesh>&, + const plusEqOp<symmTensor>&, + GeometricField<symmTensor, fvPatchField, volMesh>&, + const bool +) const; +template<> +void meshToMesh::mapInternalTgtToSrc +( + const GeometricField<symmTensor, fvPatchField, volMesh>&, + const minusEqOp<symmTensor>&, + GeometricField<symmTensor, fvPatchField, volMesh>&, + const bool +) const; +template<> +void meshToMesh::mapInternalTgtToSrc +( + const GeometricField<tensor, fvPatchField, volMesh>&, + const plusEqOp<tensor>&, + GeometricField<tensor, fvPatchField, volMesh>&, + const bool +) const; +template<> +void meshToMesh::mapInternalTgtToSrc +( + const GeometricField<tensor, fvPatchField, volMesh>&, + const minusEqOp<tensor>&, + GeometricField<tensor, fvPatchField, volMesh>&, + const bool +) const; + + +// Disable fvPatchField value override after rmap + +template<> +void meshToMesh::mapAndOpSrcToTgt +( + const AMIPatchToPatchInterpolation& AMI, + const Field<scalar>& srcField, + Field<scalar>& tgtField, + const plusEqOp<scalar>& cop +) const; +template<> +void meshToMesh::mapAndOpSrcToTgt +( + const AMIPatchToPatchInterpolation& AMI, + const Field<vector>& srcField, + Field<vector>& tgtField, + const plusEqOp<vector>& cop +) const; +template<> +void meshToMesh::mapAndOpSrcToTgt +( + const AMIPatchToPatchInterpolation& AMI, + const Field<sphericalTensor>& srcField, + Field<sphericalTensor>& tgtField, + const plusEqOp<sphericalTensor>& cop +) const; +template<> +void meshToMesh::mapAndOpSrcToTgt +( + const AMIPatchToPatchInterpolation& AMI, + const Field<symmTensor>& srcField, + Field<symmTensor>& tgtField, + const plusEqOp<symmTensor>& cop +) const; +template<> +void meshToMesh::mapAndOpSrcToTgt +( + const AMIPatchToPatchInterpolation& AMI, + const Field<tensor>& srcField, + Field<tensor>& tgtField, + const plusEqOp<tensor>& cop +) const; + + +template<> +void meshToMesh::mapAndOpTgtToSrc +( + const AMIPatchToPatchInterpolation& AMI, + Field<scalar>& srcField, + const Field<scalar>& tgtField, + const plusEqOp<scalar>& cop +) const; +template<> +void meshToMesh::mapAndOpTgtToSrc +( + const AMIPatchToPatchInterpolation& AMI, + Field<vector>& srcField, + const Field<vector>& tgtField, + const plusEqOp<vector>& cop +) const; +template<> +void meshToMesh::mapAndOpTgtToSrc +( + const AMIPatchToPatchInterpolation& AMI, + Field<sphericalTensor>& srcField, + const Field<sphericalTensor>& tgtField, + const plusEqOp<sphericalTensor>& cop +) const; +template<> +void meshToMesh::mapAndOpTgtToSrc +( + const AMIPatchToPatchInterpolation& AMI, + Field<symmTensor>& srcField, + const Field<symmTensor>& tgtField, + const plusEqOp<symmTensor>& cop +) const; +template<> +void meshToMesh::mapAndOpTgtToSrc +( + const AMIPatchToPatchInterpolation& AMI, + Field<tensor>& srcField, + const Field<tensor>& tgtField, + const plusEqOp<tensor>& cop +) const; + + } // End namespace Foam // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/sampling/meshToMesh/meshToMeshI.H b/src/sampling/meshToMesh/meshToMeshI.H index a3d62675499f7ee941b5ad048f6c2296b75459fe..8804956d656348ebab8adb9d083e164582cfb31e 100644 --- a/src/sampling/meshToMesh/meshToMeshI.H +++ b/src/sampling/meshToMesh/meshToMeshI.H @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2012-2015 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. @@ -39,34 +39,42 @@ inline const Foam::polyMesh& Foam::meshToMesh::tgtRegion() const } -inline const Foam::labelListList& -Foam::meshToMesh::srcToTgtCellAddr() const +inline const Foam::labelListList& Foam::meshToMesh::srcToTgtCellAddr() const { return srcToTgtCellAddr_; } -inline const Foam::labelListList& -Foam::meshToMesh::tgtToSrcCellAddr() const +inline const Foam::labelListList& Foam::meshToMesh::tgtToSrcCellAddr() const { return tgtToSrcCellAddr_; } -inline const Foam::scalarListList& -Foam::meshToMesh::srcToTgtCellWght() const +inline const Foam::scalarListList& Foam::meshToMesh::srcToTgtCellWght() const { return srcToTgtCellWght_; } -inline const Foam::scalarListList& -Foam::meshToMesh::tgtToSrcCellWght() const +inline const Foam::scalarListList& Foam::meshToMesh::tgtToSrcCellWght() const { return tgtToSrcCellWght_; } +inline const Foam::pointListList& Foam::meshToMesh::srcToTgtCellVec() const +{ + return srcToTgtCellVec_; +} + + +inline const Foam::pointListList& Foam::meshToMesh::tgtToSrcCellVec() const +{ + return tgtToSrcCellVec_; +} + + inline Foam::scalar Foam::meshToMesh::V() const { return V_; diff --git a/src/sampling/meshToMesh/meshToMeshParallelOps.C b/src/sampling/meshToMesh/meshToMeshParallelOps.C index ce3fcc428c8af43b4a7e64b39a2debd1eeacce6e..6ba42edd449815db7dab4ec46334108b4acd9a1a 100644 --- a/src/sampling/meshToMesh/meshToMeshParallelOps.C +++ b/src/sampling/meshToMesh/meshToMeshParallelOps.C @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2012-2015 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. @@ -30,6 +30,7 @@ License #include "mergePoints.H" #include "processorPolyPatch.H" #include "SubField.H" +#include "AABBTree.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // @@ -84,7 +85,7 @@ Foam::label Foam::meshToMesh::calcDistribution Foam::label Foam::meshToMesh::calcOverlappingProcs ( - const List<boundBox>& procBb, + const List<treeBoundBoxList>& procBb, const boundBox& bb, boolList& overlaps ) const @@ -95,12 +96,16 @@ Foam::label Foam::meshToMesh::calcOverlappingProcs forAll(procBb, procI) { - const boundBox& bbp = procBb[procI]; + const treeBoundBoxList& bbp = procBb[procI]; - if (bbp.overlaps(bb)) + forAll(bbp, bbI) { - overlaps[procI] = true; - nOverlaps++; + if (bbp[bbI].overlaps(bb)) + { + overlaps[procI] = true; + nOverlaps++; + break; + } } } @@ -115,20 +120,20 @@ Foam::autoPtr<Foam::mapDistribute> Foam::meshToMesh::calcProcMap ) const { // get decomposition of cells on src mesh - List<boundBox> procBb(Pstream::nProcs()); + List<treeBoundBoxList> procBb(Pstream::nProcs()); if (src.nCells() > 0) { - // bounding box for my mesh - do not parallel reduce - procBb[Pstream::myProcNo()] = boundBox(src.points(), false); - - // slightly increase size of bounding boxes to allow for cases where - // bounding boxes are perfectly alligned - procBb[Pstream::myProcNo()].inflate(0.01); + procBb[Pstream::myProcNo()] = AABBTree<labelList> + ( + src.cellPoints(), + src.points(), + false + ).boundBoxes(); } else { - procBb[Pstream::myProcNo()] = boundBox(); + procBb[Pstream::myProcNo()] = treeBoundBoxList(); } @@ -417,7 +422,7 @@ void Foam::meshToMesh::distributeCells labelList globalElems(sendElems.size()); forAll(sendElems, i) { - if (debug) + if (debug > 1) { Pout<< "tgtProc:" << Pstream::myProcNo() << " sending tgt cell " << sendElems[i] @@ -605,7 +610,7 @@ void Foam::meshToMesh::distributeAndMergeCells } else { - if (debug) + if (debug > 1) { Pout<< "Additional internal face between procs:" << key[0] << " and " << key[1] @@ -732,7 +737,7 @@ void Foam::meshToMesh::distributeAndMergeCells label newNbr = fnd(); label tgtFaceI = internalFaceOffset[procI]++; - if (debug) + if (debug > 1) { Pout<< " proc " << procI << "\tinserting face:" << tgtFaceI @@ -812,7 +817,7 @@ void Foam::meshToMesh::distributeAndMergeCells label newOwn = cellOffset[procI] + faceOs[i]; label tgtFaceI = nIntFaces++; - if (debug) + if (debug > 1) { Pout<< " proc " << procI << "\tinserting boundary face:" << tgtFaceI diff --git a/src/sampling/meshToMesh/meshToMeshTemplates.C b/src/sampling/meshToMesh/meshToMeshTemplates.C index 9ed88a8ae572ff8c8ef7b497ee6a809bdac1a2ed..45429bd3ca2570c02cb6021acfb2faeded3a5df1 100644 --- a/src/sampling/meshToMesh/meshToMeshTemplates.C +++ b/src/sampling/meshToMesh/meshToMeshTemplates.C @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2012-2015 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. @@ -27,7 +27,8 @@ License #include "volFields.H" #include "directFvPatchFieldMapper.H" #include "calculatedFvPatchField.H" -#include "weightedFvPatchFieldMapper.H" +#include "fvcGrad.H" +#include "distributedWeightedFvPatchFieldMapper.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -118,7 +119,6 @@ void Foam::meshToMesh::mapSrcToTgt if (srcAddress.size()) { -// result[cellI] = pTraits<Type>::zero; result[cellI] *= (1.0 - sum(srcWeight)); forAll(srcAddress, i) { @@ -138,7 +138,6 @@ void Foam::meshToMesh::mapSrcToTgt if (srcAddress.size()) { -// result[cellI] = pTraits<Type>::zero; result[cellI] *= (1.0 - sum(srcWeight)); forAll(srcAddress, i) { @@ -152,6 +151,108 @@ void Foam::meshToMesh::mapSrcToTgt } +template<class Type, class CombineOp> +void Foam::meshToMesh::mapSrcToTgt +( + const UList<Type>& srcField, + const UList<typename outerProduct<vector, Type>::type>& srcGradField, + const CombineOp& cop, + List<Type>& result +) const +{ + if (result.size() != tgtToSrcCellAddr_.size()) + { + FatalErrorIn + ( + "void Foam::meshToMesh::mapSrcToTgt" + "(" + "const UList<Type>&, " + "const UList<typename outerProduct<vector, Type>::type>&, " + "const CombineOp&, " + "List<Type>&" + ") const" + ) << "Supplied field size is not equal to target mesh size" << nl + << " source mesh = " << srcToTgtCellAddr_.size() << nl + << " target mesh = " << tgtToSrcCellAddr_.size() << nl + << " supplied field = " << result.size() + << abort(FatalError); + } + + multiplyWeightedOp<Type, CombineOp> cbop(cop); + + if (singleMeshProc_ == -1) + { + if (returnReduce(tgtToSrcCellVec_.size(), sumOp<label>()) == 0) + { + // No correction vectors calculated. Fall back to first order. + mapSrcToTgt(srcField, cop, result); + return; + } + + const mapDistribute& map = srcMapPtr_(); + + List<Type> work(srcField); + map.distribute(work); + + List<typename outerProduct<vector, Type>::type> workGrad + ( + srcGradField + ); + map.distribute(workGrad); + + forAll(result, cellI) + { + const labelList& srcAddress = tgtToSrcCellAddr_[cellI]; + const scalarList& srcWeight = tgtToSrcCellWght_[cellI]; + const pointList& srcVec = tgtToSrcCellVec_[cellI]; + + if (srcAddress.size()) + { + result[cellI] *= (1.0 - sum(srcWeight)); + forAll(srcAddress, i) + { + label srcI = srcAddress[i]; + scalar w = srcWeight[i]; + const vector& v = srcVec[i]; + const Type srcVal = work[srcI]+(workGrad[srcI]&v); + cbop(result[cellI], cellI, srcVal, w); + } + } + } + } + else + { + if (tgtToSrcCellVec_.empty()) + { + // No correction vectors calculated. Fall back to first order. + mapSrcToTgt(srcField, cop, result); + return; + } + + forAll(result, cellI) + { + const labelList& srcAddress = tgtToSrcCellAddr_[cellI]; + const scalarList& srcWeight = tgtToSrcCellWght_[cellI]; + const pointList& srcVec = tgtToSrcCellVec_[cellI]; + + if (srcAddress.size()) + { + // Do non-conservative interpolation + result[cellI] *= (1.0 - sum(srcWeight)); + forAll(srcAddress, i) + { + label srcI = srcAddress[i]; + scalar w = srcWeight[i]; + const vector& v = srcVec[i]; + const Type srcVal = srcField[srcI]+(srcGradField[srcI]&v); + cbop(result[cellI], cellI, srcVal, w); + } + } + } + } +} + + template<class Type, class CombineOp> Foam::tmp<Foam::Field<Type> > Foam::meshToMesh::mapSrcToTgt ( @@ -278,6 +379,100 @@ void Foam::meshToMesh::mapTgtToSrc } +template<class Type, class CombineOp> +void Foam::meshToMesh::mapTgtToSrc +( + const UList<Type>& tgtField, + const UList<typename outerProduct<vector, Type>::type>& tgtGradField, + const CombineOp& cop, + List<Type>& result +) const +{ + if (result.size() != srcToTgtCellAddr_.size()) + { + FatalErrorIn + ( + "void Foam::meshToMesh::mapTgtToSrc" + "(" + "const UList<Type>&, " + "const UList<typename outerProduct<vector, Type>::type>&, " + "const CombineOp&, " + "List<Type>&" + ") const" + ) << "Supplied field size is not equal to source mesh size" << nl + << " source mesh = " << srcToTgtCellAddr_.size() << nl + << " target mesh = " << tgtToSrcCellAddr_.size() << nl + << " supplied field = " << result.size() + << abort(FatalError); + } + + multiplyWeightedOp<Type, CombineOp> cbop(cop); + + if (singleMeshProc_ == -1) + { + if (returnReduce(srcToTgtCellVec_.size(), sumOp<label>()) == 0) + { + // No correction vectors calculated. Fall back to first order. + mapTgtToSrc(tgtField, cop, result); + return; + } + + const mapDistribute& map = tgtMapPtr_(); + + List<Type> work(tgtField); + map.distribute(work); + + List<typename outerProduct<vector, Type>::type> workGrad + ( + tgtGradField + ); + map.distribute(workGrad); + + forAll(result, cellI) + { + const labelList& tgtAddress = srcToTgtCellAddr_[cellI]; + const scalarList& tgtWeight = srcToTgtCellWght_[cellI]; + const pointList& tgtVec = srcToTgtCellVec_[cellI]; + + if (tgtAddress.size()) + { + result[cellI] *= (1.0 - sum(tgtWeight)); + forAll(tgtAddress, i) + { + label tgtI = tgtAddress[i]; + scalar w = tgtWeight[i]; + const vector& v = tgtVec[i]; + const Type tgtVal = work[tgtI]+(workGrad[tgtI]&v); + cbop(result[cellI], cellI, tgtVal, w); + } + } + } + } + else + { + forAll(result, cellI) + { + const labelList& tgtAddress = srcToTgtCellAddr_[cellI]; + const scalarList& tgtWeight = srcToTgtCellWght_[cellI]; + const pointList& tgtVec = srcToTgtCellVec_[cellI]; + + if (tgtAddress.size()) + { + result[cellI] *= (1.0 - sum(tgtWeight)); + forAll(tgtAddress, i) + { + label tgtI = tgtAddress[i]; + scalar w = tgtWeight[i]; + const vector& v = tgtVec[i]; + const Type tgtVal = tgtField[tgtI]+(tgtGradField[tgtI]&v); + cbop(result[cellI], cellI, tgtVal, w); + } + } + } + } +} + + template<class Type, class CombineOp> Foam::tmp<Foam::Field<Type> > Foam::meshToMesh::mapTgtToSrc ( @@ -331,15 +526,64 @@ Foam::tmp<Foam::Field<Type> > Foam::meshToMesh::mapTgtToSrc } +template<class Type, class CombineOp> +void Foam::meshToMesh::mapInternalSrcToTgt +( + const GeometricField<Type, fvPatchField, volMesh>& field, + const CombineOp& cop, + GeometricField<Type, fvPatchField, volMesh>& result, + const bool secondOrder +) const +{ + if (secondOrder && returnReduce(tgtToSrcCellVec_.size(), sumOp<label>())) + { + mapSrcToTgt + ( + field, + fvc::grad(field)().internalField(), + cop, + result.internalField() + ); + } + else + { + mapSrcToTgt(field, cop, result.internalField()); + } +} + + +template<class Type, class CombineOp> +void Foam::meshToMesh::mapAndOpSrcToTgt +( + const AMIPatchToPatchInterpolation& AMI, + const Field<Type>& srcField, + Field<Type>& tgtField, + const CombineOp& cop +) const +{ + tgtField = pTraits<Type>::zero; + + AMI.interpolateToTarget + ( + srcField, + multiplyWeightedOp<Type, CombineOp>(cop), + tgtField, + UList<Type>::null() + ); +} + + template<class Type, class CombineOp> void Foam::meshToMesh::mapSrcToTgt ( const GeometricField<Type, fvPatchField, volMesh>& field, const CombineOp& cop, - GeometricField<Type, fvPatchField, volMesh>& result + GeometricField<Type, fvPatchField, volMesh>& result, + const bool secondOrder ) const { - mapSrcToTgt(field, cop, result.internalField()); + mapInternalSrcToTgt(field, cop, result, secondOrder); + const PtrList<AMIPatchToPatchInterpolation>& AMIList = patchAMIs(); @@ -351,40 +595,37 @@ void Foam::meshToMesh::mapSrcToTgt const fvPatchField<Type>& srcField = field.boundaryField()[srcPatchI]; fvPatchField<Type>& tgtField = result.boundaryField()[tgtPatchI]; - // 2.3 does not do distributed mapping yet so only do if - // running on single processor - if (AMIList[i].singlePatchProc() != -1) - { - // Clone and map (since rmap does not do general mapping) - tmp<fvPatchField<Type> > tnewTgt + + // Clone and map (since rmap does not do general mapping) + tmp<fvPatchField<Type> > tnewTgt + ( + fvPatchField<Type>::New ( - fvPatchField<Type>::New + srcField, + tgtField.patch(), + result.dimensionedInternalField(), + distributedWeightedFvPatchFieldMapper ( - srcField, - tgtField.patch(), - result.dimensionedInternalField(), - weightedFvPatchFieldMapper + AMIList[i].singlePatchProc(), ( - AMIList[i].tgtAddress(), - AMIList[i].tgtWeights() - ) + AMIList[i].singlePatchProc() == -1 + ? &AMIList[i].srcMap() + : NULL + ), + AMIList[i].tgtAddress(), + AMIList[i].tgtWeights() ) - ); + ) + ); - // Transfer all mapped quantities (value and e.g. gradient) onto - // tgtField. Value will get overwritten below. - tgtField.rmap(tnewTgt(), identity(tgtField.size())); - } + // Transfer all mapped quantities (value and e.g. gradient) onto + // tgtField + tgtField.rmap(tnewTgt(), identity(tgtField.size())); - tgtField == pTraits<Type>::zero; - AMIList[i].interpolateToTarget - ( - srcField, - multiplyWeightedOp<Type, CombineOp>(cop), - tgtField, - UList<Type>::null() - ); + // Override value to account for CombineOp (note: is dummy template + // specialisation for plusEqOp) + mapAndOpSrcToTgt(AMIList[i], srcField, tgtField, cop); } forAll(cuttingPatches_, i) @@ -401,7 +642,8 @@ Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> > Foam::meshToMesh::mapSrcToTgt ( const GeometricField<Type, fvPatchField, volMesh>& field, - const CombineOp& cop + const CombineOp& cop, + const bool secondOrder ) const { typedef GeometricField<Type, fvPatchField, volMesh> fieldType; @@ -480,7 +722,7 @@ Foam::meshToMesh::mapSrcToTgt ) ); - mapSrcToTgt(field, cop, tresult()); + mapSrcToTgt(field, cop, tresult(), secondOrder); return tresult; } @@ -491,10 +733,11 @@ Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> > Foam::meshToMesh::mapSrcToTgt ( const tmp<GeometricField<Type, fvPatchField, volMesh> >& tfield, - const CombineOp& cop + const CombineOp& cop, + const bool secondOrder ) const { - return mapSrcToTgt(tfield(), cop); + return mapSrcToTgt(tfield(), cop, secondOrder); } @@ -502,10 +745,11 @@ template<class Type> Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> > Foam::meshToMesh::mapSrcToTgt ( - const GeometricField<Type, fvPatchField, volMesh>& field + const GeometricField<Type, fvPatchField, volMesh>& field, + const bool secondOrder ) const { - return mapSrcToTgt(field, plusEqOp<Type>()); + return mapSrcToTgt(field, plusEqOp<Type>(), secondOrder); } @@ -513,10 +757,58 @@ template<class Type> Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> > Foam::meshToMesh::mapSrcToTgt ( - const tmp<GeometricField<Type, fvPatchField, volMesh> >& tfield + const tmp<GeometricField<Type, fvPatchField, volMesh> >& tfield, + const bool secondOrder ) const { - return mapSrcToTgt(tfield(), plusEqOp<Type>()); + return mapSrcToTgt(tfield(), plusEqOp<Type>(), secondOrder); +} + + +template<class Type, class CombineOp> +void Foam::meshToMesh::mapInternalTgtToSrc +( + const GeometricField<Type, fvPatchField, volMesh>& field, + const CombineOp& cop, + GeometricField<Type, fvPatchField, volMesh>& result, + const bool secondOrder +) const +{ + if (secondOrder && returnReduce(srcToTgtCellVec_.size(), sumOp<label>())) + { + mapTgtToSrc + ( + field, + fvc::grad(field)().internalField(), + cop, + result.internalField() + ); + } + else + { + mapTgtToSrc(field, cop, result.internalField()); + } +} + + +template<class Type, class CombineOp> +void Foam::meshToMesh::mapAndOpTgtToSrc +( + const AMIPatchToPatchInterpolation& AMI, + Field<Type>& srcField, + const Field<Type>& tgtField, + const CombineOp& cop +) const +{ + srcField = pTraits<Type>::zero; + + AMI.interpolateToSource + ( + tgtField, + multiplyWeightedOp<Type, CombineOp>(cop), + srcField, + UList<Type>::null() + ); } @@ -525,10 +817,12 @@ void Foam::meshToMesh::mapTgtToSrc ( const GeometricField<Type, fvPatchField, volMesh>& field, const CombineOp& cop, - GeometricField<Type, fvPatchField, volMesh>& result + GeometricField<Type, fvPatchField, volMesh>& result, + const bool secondOrder ) const { - mapTgtToSrc(field, cop, result.internalField()); + mapInternalTgtToSrc(field, cop, result, secondOrder); + const PtrList<AMIPatchToPatchInterpolation>& AMIList = patchAMIs(); @@ -540,40 +834,37 @@ void Foam::meshToMesh::mapTgtToSrc fvPatchField<Type>& srcField = result.boundaryField()[srcPatchI]; const fvPatchField<Type>& tgtField = field.boundaryField()[tgtPatchI]; - // 2.3 does not do distributed mapping yet so only do if - // running on single processor - if (AMIList[i].singlePatchProc() != -1) - { - // Clone and map (since rmap does not do general mapping) - tmp<fvPatchField<Type> > tnewSrc + + // Clone and map (since rmap does not do general mapping) + tmp<fvPatchField<Type> > tnewSrc + ( + fvPatchField<Type>::New ( - fvPatchField<Type>::New + tgtField, + srcField.patch(), + result.dimensionedInternalField(), + distributedWeightedFvPatchFieldMapper ( - tgtField, - srcField.patch(), - result.dimensionedInternalField(), - weightedFvPatchFieldMapper + AMIList[i].singlePatchProc(), ( - AMIList[i].srcAddress(), - AMIList[i].srcWeights() - ) + AMIList[i].singlePatchProc() == -1 + ? &AMIList[i].tgtMap() + : NULL + ), + AMIList[i].srcAddress(), + AMIList[i].srcWeights() ) - ); + ) + ); - // Transfer all mapped quantities (value and e.g. gradient) onto - // srcField. Value will get overwritten below - srcField.rmap(tnewSrc(), identity(srcField.size())); - } + // Transfer all mapped quantities (value and e.g. gradient) onto + // tgtField + srcField.rmap(tnewSrc(), identity(srcField.size())); - srcField == pTraits<Type>::zero; - AMIList[i].interpolateToSource - ( - tgtField, - multiplyWeightedOp<Type, CombineOp>(cop), - srcField, - UList<Type>::null() - ); + // Override value to account for CombineOp (could be dummy for + // plusEqOp) + mapAndOpTgtToSrc(AMIList[i], srcField, tgtField, cop); } forAll(cuttingPatches_, i) @@ -590,7 +881,8 @@ Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> > Foam::meshToMesh::mapTgtToSrc ( const GeometricField<Type, fvPatchField, volMesh>& field, - const CombineOp& cop + const CombineOp& cop, + const bool secondOrder ) const { typedef GeometricField<Type, fvPatchField, volMesh> fieldType; @@ -669,7 +961,7 @@ Foam::meshToMesh::mapTgtToSrc ) ); - mapTgtToSrc(field, cop, tresult()); + mapTgtToSrc(field, cop, tresult(), secondOrder); return tresult; } @@ -680,10 +972,11 @@ Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> > Foam::meshToMesh::mapTgtToSrc ( const tmp<GeometricField<Type, fvPatchField, volMesh> >& tfield, - const CombineOp& cop + const CombineOp& cop, + const bool secondOrder ) const { - return mapTgtToSrc(tfield(), cop); + return mapTgtToSrc(tfield(), cop, secondOrder); } @@ -691,10 +984,11 @@ template<class Type> Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> > Foam::meshToMesh::mapTgtToSrc ( - const GeometricField<Type, fvPatchField, volMesh>& field + const GeometricField<Type, fvPatchField, volMesh>& field, + const bool secondOrder ) const { - return mapTgtToSrc(field, plusEqOp<Type>()); + return mapTgtToSrc(field, plusEqOp<Type>(), secondOrder); } @@ -702,10 +996,11 @@ template<class Type> Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> > Foam::meshToMesh::mapTgtToSrc ( - const tmp<GeometricField<Type, fvPatchField, volMesh> >& tfield + const tmp<GeometricField<Type, fvPatchField, volMesh> >& tfield, + const bool secondOrder ) const { - return mapTgtToSrc(tfield(), plusEqOp<Type>()); + return mapTgtToSrc(tfield(), plusEqOp<Type>(), secondOrder); } diff --git a/tutorials/mesh/parallel/cavity/0/U b/tutorials/mesh/parallel/cavity/0/U new file mode 100644 index 0000000000000000000000000000000000000000..711702f9871ed36f0695ef53bedb90b80c345a78 --- /dev/null +++ b/tutorials/mesh/parallel/cavity/0/U @@ -0,0 +1,41 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + object U; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -1 0 0 0 0]; + +internalField uniform (0 0 0); + +boundaryField +{ + movingWall + { + type fixedValue; + value uniform (1 0 0); + } + + fixedWalls + { + type fixedValue; + value uniform (0 0 0); + } + + frontAndBack + { + type empty; + } +} + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/cavity/0/p b/tutorials/mesh/parallel/cavity/0/p new file mode 100644 index 0000000000000000000000000000000000000000..3e00d9eb3198e7c3d1d96d37378ad5ab6466637b --- /dev/null +++ b/tutorials/mesh/parallel/cavity/0/p @@ -0,0 +1,39 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -2 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + movingWall + { + type zeroGradient; + } + + fixedWalls + { + type zeroGradient; + } + + frontAndBack + { + type empty; + } +} + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/cavity/Allclean b/tutorials/mesh/parallel/cavity/Allclean new file mode 100755 index 0000000000000000000000000000000000000000..48fe2ebdabb09a97773012cebda63363e0dd5546 --- /dev/null +++ b/tutorials/mesh/parallel/cavity/Allclean @@ -0,0 +1,12 @@ +#!/bin/sh + +# Source tutorial clean functions +. $WM_PROJECT_DIR/bin/tools/CleanFunctions + +# Restore default dictionaries +cp system/decomposeParDict-2 system/decomposeParDict +cp system/controlDict-startTime system/controlDict + +cleanCase +rm -f constant/polyMesh/boundary +rm -f constant/polyMesh/procAddressing diff --git a/tutorials/mesh/parallel/cavity/Allrun b/tutorials/mesh/parallel/cavity/Allrun new file mode 100755 index 0000000000000000000000000000000000000000..e6c76345f9983f9b07e23b1e05dac7371ac24f6d --- /dev/null +++ b/tutorials/mesh/parallel/cavity/Allrun @@ -0,0 +1,35 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory + +# Source tutorial run functions +. $WM_PROJECT_DIR/bin/tools/RunFunctions + +runApplication blockMesh + +#cp system/decomposeParDict-2 system/decomposeParDict +#runApplication decomposePar + +#- redistributePar to do decomposition +runParallel redistributePar 2 -decompose + +#- bit of renumbering and running +runParallel -l log.renumberMesh-CuthillMcKee renumberMesh 2 -overwrite +runParallel -l log.icoFoam-CuthillMcKee icoFoam 2 + +#- bit of bad renumbering and running +runParallel -l log.renumberMesh-parallel renumberMesh 2 -overwrite -dict system/renumberMeshDict-random +runParallel -l log.icoFoam-random icoFoam 2 + +#- pick up last result +cp system/controlDict-latestTime system/controlDict + +#- redistribute to 5 processors +runParallel -l log.redistributePar-5 redistributePar 5 -decomposeParDict system/decomposeParDict-5 -cellDist +#- run a bit more +runParallel -l log.icoFoam-5 icoFoam 5 -decomposeParDict system/decomposeParDict-5 + +#- reconstruct mesh and results +runParallel -l log.redistributePar-1 redistributePar 5 -reconstruct -decomposeParDict system/decomposeParDict + + +# ----------------------------------------------------------------- end-of-file diff --git a/tutorials/mesh/parallel/cavity/constant/polyMesh/blockMeshDict b/tutorials/mesh/parallel/cavity/constant/polyMesh/blockMeshDict new file mode 100644 index 0000000000000000000000000000000000000000..165a600c7b4a929aaa62ad1750bfbb9d279c2e65 --- /dev/null +++ b/tutorials/mesh/parallel/cavity/constant/polyMesh/blockMeshDict @@ -0,0 +1,75 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +convertToMeters 0.1; + +vertices +( + (0 0 0) + (1 0 0) + (1 1 0) + (0 1 0) + (0 0 0.1) + (1 0 0.1) + (1 1 0.1) + (0 1 0.1) +); + +blocks +( + hex (0 1 2 3 4 5 6 7) (20 20 1) simpleGrading (1 1 1) +); + +edges +( +); + +boundary +( + movingWall + { + type wall; + faces + ( + (3 7 6 2) + ); + } + fixedWalls + { + type wall; + faces + ( + (0 4 7 3) + (2 6 5 1) + (1 5 4 0) + ); + } + frontAndBack + { + type empty; + faces + ( + (0 3 2 1) + (4 5 6 7) + ); + } +); + +mergePatchPairs +( +); + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/cavity/constant/transportProperties b/tutorials/mesh/parallel/cavity/constant/transportProperties new file mode 100644 index 0000000000000000000000000000000000000000..fa1c1ca0b14b50fa06f4c8577b4998addd44b1f3 --- /dev/null +++ b/tutorials/mesh/parallel/cavity/constant/transportProperties @@ -0,0 +1,21 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object transportProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +nu nu [ 0 2 -1 0 0 0 0 ] 0.01; + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/cavity/system/controlDict b/tutorials/mesh/parallel/cavity/system/controlDict new file mode 100644 index 0000000000000000000000000000000000000000..d2fa09cc526b96181407595f79c0968a81be7c44 --- /dev/null +++ b/tutorials/mesh/parallel/cavity/system/controlDict @@ -0,0 +1,49 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object controlDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +application icoFoam; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 0.5; + +deltaT 0.005; + +writeControl timeStep; + +writeInterval 20; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable true; + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/cavity/system/controlDict-latestTime b/tutorials/mesh/parallel/cavity/system/controlDict-latestTime new file mode 100644 index 0000000000000000000000000000000000000000..e1dacd67678f639d0dbbc438f9450dea63506d3b --- /dev/null +++ b/tutorials/mesh/parallel/cavity/system/controlDict-latestTime @@ -0,0 +1,49 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object controlDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +application icoFoam; + +startFrom latestTime; + +startTime 0; + +stopAt endTime; + +endTime 1.0; + +deltaT 0.005; + +writeControl timeStep; + +writeInterval 20; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable true; + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/cavity/system/controlDict-startTime b/tutorials/mesh/parallel/cavity/system/controlDict-startTime new file mode 100644 index 0000000000000000000000000000000000000000..d2fa09cc526b96181407595f79c0968a81be7c44 --- /dev/null +++ b/tutorials/mesh/parallel/cavity/system/controlDict-startTime @@ -0,0 +1,49 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object controlDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +application icoFoam; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 0.5; + +deltaT 0.005; + +writeControl timeStep; + +writeInterval 20; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable true; + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/cavity/system/decomposeParDict b/tutorials/mesh/parallel/cavity/system/decomposeParDict new file mode 100644 index 0000000000000000000000000000000000000000..39483a01e3eddb5f08b4cdd9dcf91438baf93d8f --- /dev/null +++ b/tutorials/mesh/parallel/cavity/system/decomposeParDict @@ -0,0 +1,143 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + note "mesh decomposition control dictionary"; + object decomposeParDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +numberOfSubdomains 2; + +//- 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) +//preservePatches (cyclic_half0 cyclic_half1); + +//- 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). +//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. +// weightField dsmcRhoNMean; + +method scotch; +//method hierarchical; +// method simple; +// method metis; +// method manual; +// method multiLevel; +// method structured; // does 2D decomposition of structured mesh + +multiLevelCoeffs +{ + // Decomposition methods to apply in turn. This is like hierarchical but + // fully general - every method can be used at every level. + + level0 + { + numberOfSubdomains 64; + //method simple; + //simpleCoeffs + //{ + // n (2 1 1); + // delta 0.001; + //} + method scotch; + } + level1 + { + numberOfSubdomains 4; + method scotch; + } +} + +// Desired output + +simpleCoeffs +{ + n (2 1 1); + delta 0.001; +} + +hierarchicalCoeffs +{ + n (1 2 1); + delta 0.001; + order xyz; +} + +metisCoeffs +{ + /* + processorWeights + ( + 1 + 1 + 1 + 1 + ); + */ +} + +scotchCoeffs +{ + //processorWeights + //( + // 1 + // 1 + // 1 + // 1 + //); + //writeGraph true; + //strategy "b"; +} + +manualCoeffs +{ + dataFile "decompositionData"; +} + +structuredCoeffs +{ + // Patches to do 2D decomposition on. Structured mesh only; cells have + // to be in 'columns' on top of patches. + patches (movingWall); + + // Method to use on the 2D subset + method scotch; +} + +//// Is the case distributed? Note: command-line argument -roots takes +//// precedence +//distributed yes; +//// Per slave (so nProcs-1 entries) the directory above the case. +//roots +//( +// "/tmp" +// "/tmp" +//); + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/cavity/system/decomposeParDict-2 b/tutorials/mesh/parallel/cavity/system/decomposeParDict-2 new file mode 100644 index 0000000000000000000000000000000000000000..39483a01e3eddb5f08b4cdd9dcf91438baf93d8f --- /dev/null +++ b/tutorials/mesh/parallel/cavity/system/decomposeParDict-2 @@ -0,0 +1,143 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + note "mesh decomposition control dictionary"; + object decomposeParDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +numberOfSubdomains 2; + +//- 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) +//preservePatches (cyclic_half0 cyclic_half1); + +//- 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). +//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. +// weightField dsmcRhoNMean; + +method scotch; +//method hierarchical; +// method simple; +// method metis; +// method manual; +// method multiLevel; +// method structured; // does 2D decomposition of structured mesh + +multiLevelCoeffs +{ + // Decomposition methods to apply in turn. This is like hierarchical but + // fully general - every method can be used at every level. + + level0 + { + numberOfSubdomains 64; + //method simple; + //simpleCoeffs + //{ + // n (2 1 1); + // delta 0.001; + //} + method scotch; + } + level1 + { + numberOfSubdomains 4; + method scotch; + } +} + +// Desired output + +simpleCoeffs +{ + n (2 1 1); + delta 0.001; +} + +hierarchicalCoeffs +{ + n (1 2 1); + delta 0.001; + order xyz; +} + +metisCoeffs +{ + /* + processorWeights + ( + 1 + 1 + 1 + 1 + ); + */ +} + +scotchCoeffs +{ + //processorWeights + //( + // 1 + // 1 + // 1 + // 1 + //); + //writeGraph true; + //strategy "b"; +} + +manualCoeffs +{ + dataFile "decompositionData"; +} + +structuredCoeffs +{ + // Patches to do 2D decomposition on. Structured mesh only; cells have + // to be in 'columns' on top of patches. + patches (movingWall); + + // Method to use on the 2D subset + method scotch; +} + +//// Is the case distributed? Note: command-line argument -roots takes +//// precedence +//distributed yes; +//// Per slave (so nProcs-1 entries) the directory above the case. +//roots +//( +// "/tmp" +// "/tmp" +//); + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/cavity/system/decomposeParDict-5 b/tutorials/mesh/parallel/cavity/system/decomposeParDict-5 new file mode 100644 index 0000000000000000000000000000000000000000..3d64ff6c1adabe442d49c6920520348961ee3d63 --- /dev/null +++ b/tutorials/mesh/parallel/cavity/system/decomposeParDict-5 @@ -0,0 +1,143 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + note "mesh decomposition control dictionary"; + object decomposeParDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +numberOfSubdomains 5; + +//- 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) +//preservePatches (cyclic_half0 cyclic_half1); + +//- 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). +//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. +// weightField dsmcRhoNMean; + +method scotch; +//method hierarchical; +// method simple; +// method metis; +// method manual; +// method multiLevel; +// method structured; // does 2D decomposition of structured mesh + +multiLevelCoeffs +{ + // Decomposition methods to apply in turn. This is like hierarchical but + // fully general - every method can be used at every level. + + level0 + { + numberOfSubdomains 64; + //method simple; + //simpleCoeffs + //{ + // n (2 1 1); + // delta 0.001; + //} + method scotch; + } + level1 + { + numberOfSubdomains 4; + method scotch; + } +} + +// Desired output + +simpleCoeffs +{ + n (2 1 1); + delta 0.001; +} + +hierarchicalCoeffs +{ + n (1 2 1); + delta 0.001; + order xyz; +} + +metisCoeffs +{ + /* + processorWeights + ( + 1 + 1 + 1 + 1 + ); + */ +} + +scotchCoeffs +{ + //processorWeights + //( + // 1 + // 1 + // 1 + // 1 + //); + //writeGraph true; + //strategy "b"; +} + +manualCoeffs +{ + dataFile "decompositionData"; +} + +structuredCoeffs +{ + // Patches to do 2D decomposition on. Structured mesh only; cells have + // to be in 'columns' on top of patches. + patches (movingWall); + + // Method to use on the 2D subset + method scotch; +} + +//// Is the case distributed? Note: command-line argument -roots takes +//// precedence +//distributed yes; +//// Per slave (so nProcs-1 entries) the directory above the case. +//roots +//( +// "/tmp" +// "/tmp" +//); + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/cavity/system/fvSchemes b/tutorials/mesh/parallel/cavity/system/fvSchemes new file mode 100644 index 0000000000000000000000000000000000000000..dede0a6cba11d8bd3422d7320ce5bc9cfb52a932 --- /dev/null +++ b/tutorials/mesh/parallel/cavity/system/fvSchemes @@ -0,0 +1,57 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSchemes; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; + grad(p) Gauss linear; +} + +divSchemes +{ + default none; + div(phi,U) Gauss linear; +} + +laplacianSchemes +{ + default Gauss linear orthogonal; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default orthogonal; +} + +fluxRequired +{ + default no; + p ; +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/cavity/system/fvSolution b/tutorials/mesh/parallel/cavity/system/fvSolution new file mode 100644 index 0000000000000000000000000000000000000000..f9e556f1552624746aadc41e4765e263e8824aac --- /dev/null +++ b/tutorials/mesh/parallel/cavity/system/fvSolution @@ -0,0 +1,46 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSolution; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +solvers +{ + p + { + solver PCG; + preconditioner DIC; + tolerance 1e-06; + relTol 0; + } + + U + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-05; + relTol 0; + } +} + +PISO +{ + nCorrectors 2; + nNonOrthogonalCorrectors 0; + pRefCell 0; + pRefValue 0; +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/cavity/system/renumberMeshDict-random b/tutorials/mesh/parallel/cavity/system/renumberMeshDict-random new file mode 100644 index 0000000000000000000000000000000000000000..0409293decd8e648a1f5af5cabf45ddcbc4f1d71 --- /dev/null +++ b/tutorials/mesh/parallel/cavity/system/renumberMeshDict-random @@ -0,0 +1,112 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + note "mesh renumbering dictionary"; + object renumberMeshDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Write maps from renumbered back to original mesh +writeMaps true; + +// Optional entry: sort cells on coupled boundaries to last for use with +// e.g. nonBlockingGaussSeidel. +sortCoupledFaceCells false; + +// Optional entry: renumber on a block-by-block basis. It uses a +// blockCoeffs dictionary to construct a decompositionMethod to do +// a block subdivision) and then applies the renumberMethod to each +// block in turn. This can be used in large cases to keep the blocks +// fitting in cache with all the the cache misses bunched at the end. +// This number is the approximate size of the blocks - this gets converted +// to a number of blocks that is the input to the decomposition method. +//blockSize 1000; + +// Optional entry: sort points into internal and boundary points +//orderPoints false; + +// Optional: suppress renumbering cellSets,faceSets,pointSets +//renumberSets false; + + +//method CuthillMcKee; +//method Sloan; +//method manual; +method random; +//method structured; +//method spring; +//method zoltan; // only if compiled with zoltan support + +//CuthillMcKeeCoeffs +//{ +// // Reverse CuthillMcKee (RCM) or plain +// reverse true; +//} + +manualCoeffs +{ + // In system directory: new-to-original (i.e. order) labelIOList + dataFile "cellMap"; +} + + +// For extruded (i.e. structured in one direction) meshes +structuredCoeffs +{ + // Patches that mesh was extruded from. These determine the starting + // layer of cells + patches (movingWall); + // Method to renumber the starting layer of cells + method random; + + // Renumber in columns (depthFirst) or in layers + depthFirst true; + + // Reverse ordering + reverse false; +} + + +springCoeffs +{ + // Maximum jump of cell indices. Is fraction of number of cells + maxCo 0.01; + + // Limit the amount of movement; the fraction maxCo gets decreased + // with every iteration + freezeFraction 0.999; + + // Maximum number of iterations + maxIter 1000; +} + + +blockCoeffs +{ + method scotch; + //method hierarchical; + //hierarchicalCoeffs + //{ + // n (1 2 1); + // delta 0.001; + // order xyz; + //} +} + + +zoltanCoeffs +{ + ORDER_METHOD LOCAL_HSFC; +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/0.org/G b/tutorials/mesh/parallel/filter/0.org/G new file mode 100644 index 0000000000000000000000000000000000000000..5bfc6d009169bcf47ec4627addf938527f2ddeb5 --- /dev/null +++ b/tutorials/mesh/parallel/filter/0.org/G @@ -0,0 +1,73 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + location "1"; + object G; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [ 1 0 -3 0 0 0 0 ]; + +internalField uniform 0; + +boundaryField +{ + walls + { + type MarshakRadiation; + T T; + emissivityMode lookup; + emissivity uniform 1; + value uniform 0; + refValue uniform 0; + refGradient uniform 0; + valueFraction uniform 0; + } + inlet + { + type MarshakRadiation; + T T; + emissivityMode lookup; + emissivity uniform 1; + value uniform 0; + refValue uniform 0; + refGradient uniform 0; + valueFraction uniform 0; + } + outlet + { + type zeroGradient; + } + cycLeft_half0 + { + type cyclic; + } + cycRight_half0 + { + type cyclic; + } + frontAndBack + { + type empty; + } + cycLeft_half1 + { + type cyclic; + } + cycRight_half1 + { + type cyclic; + } +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/0.org/H2O b/tutorials/mesh/parallel/filter/0.org/H2O new file mode 100644 index 0000000000000000000000000000000000000000..615f83b6225e89e95cbda96c0882224294300325 --- /dev/null +++ b/tutorials/mesh/parallel/filter/0.org/H2O @@ -0,0 +1,60 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + location "1"; + object H2O; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [ 0 0 0 0 0 0 0 ]; + +internalField uniform 0; + +boundaryField +{ + walls + { + type zeroGradient; + } + inlet + { + type fixedValue; + value uniform 0; + } + outlet + { + type zeroGradient; + } + cycLeft_half0 + { + type cyclic; + } + cycRight_half0 + { + type cyclic; + } + frontAndBack + { + type empty; + } + cycLeft_half1 + { + type cyclic; + } + cycRight_half1 + { + type cyclic; + } +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/0.org/N2 b/tutorials/mesh/parallel/filter/0.org/N2 new file mode 100644 index 0000000000000000000000000000000000000000..46857fe937b85940dce3dbe1e61f8a508e05dee1 --- /dev/null +++ b/tutorials/mesh/parallel/filter/0.org/N2 @@ -0,0 +1,60 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + location "1"; + object N2; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [ 0 0 0 0 0 0 0 ]; + +internalField uniform 0.79; + +boundaryField +{ + walls + { + type zeroGradient; + } + inlet + { + type fixedValue; + value uniform 0.79; + } + outlet + { + type zeroGradient; + } + cycLeft_half0 + { + type cyclic; + } + cycRight_half0 + { + type cyclic; + } + frontAndBack + { + type empty; + } + cycLeft_half1 + { + type cyclic; + } + cycRight_half1 + { + type cyclic; + } +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/0.org/O2 b/tutorials/mesh/parallel/filter/0.org/O2 new file mode 100644 index 0000000000000000000000000000000000000000..20654933447eedc5f993d6a76ab69ea339cc1244 --- /dev/null +++ b/tutorials/mesh/parallel/filter/0.org/O2 @@ -0,0 +1,60 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + location "1"; + object O2; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [ 0 0 0 0 0 0 0 ]; + +internalField uniform 0.21; + +boundaryField +{ + walls + { + type zeroGradient; + } + inlet + { + type fixedValue; + value uniform 0.21; + } + outlet + { + type zeroGradient; + } + cycLeft_half0 + { + type cyclic; + } + cycRight_half0 + { + type cyclic; + } + frontAndBack + { + type empty; + } + cycLeft_half1 + { + type cyclic; + } + cycRight_half1 + { + type cyclic; + } +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/0.org/T b/tutorials/mesh/parallel/filter/0.org/T new file mode 100644 index 0000000000000000000000000000000000000000..3fb56a7a7b05636dbdeb12ee10a2710414543d99 --- /dev/null +++ b/tutorials/mesh/parallel/filter/0.org/T @@ -0,0 +1,61 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + location "1"; + object T; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [ 0 0 0 1 0 0 0 ]; + +internalField uniform 350; + +boundaryField +{ + walls + { + type fixedValue; + value uniform 400; + } + inlet + { + type fixedValue; + value uniform 350; + } + outlet + { + type zeroGradient; + } + cycLeft_half0 + { + type cyclic; + } + cycRight_half0 + { + type cyclic; + } + frontAndBack + { + type empty; + } + cycLeft_half1 + { + type cyclic; + } + cycRight_half1 + { + type cyclic; + } +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/0.org/U b/tutorials/mesh/parallel/filter/0.org/U new file mode 100644 index 0000000000000000000000000000000000000000..bac859d6245a39f21773407fbb28d1a548729426 --- /dev/null +++ b/tutorials/mesh/parallel/filter/0.org/U @@ -0,0 +1,61 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + location "1"; + object U; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [ 0 1 -1 0 0 0 0 ]; + +internalField uniform ( 0 0 0 ); + +boundaryField +{ + walls + { + type fixedValue; + value uniform ( 0 0 0 ); + } + inlet + { + type fixedValue; + value uniform ( 5 0 0 ); + } + outlet + { + type zeroGradient; + } + cycLeft_half0 + { + type cyclic; + } + cycRight_half0 + { + type cyclic; + } + frontAndBack + { + type empty; + } + cycLeft_half1 + { + type cyclic; + } + cycRight_half1 + { + type cyclic; + } +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/0.org/alphat b/tutorials/mesh/parallel/filter/0.org/alphat new file mode 100644 index 0000000000000000000000000000000000000000..62d54f2cbeba274399df6c4a53d16dbb93b58ee9 --- /dev/null +++ b/tutorials/mesh/parallel/filter/0.org/alphat @@ -0,0 +1,62 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + location "1"; + object alphat; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [ 1 -1 -1 0 0 0 0 ]; + +internalField uniform 0; + +boundaryField +{ + walls + { + type compressible::alphatWallFunction; + value uniform 0; + } + inlet + { + type calculated; + value uniform 0; + } + outlet + { + type calculated; + value uniform 0; + } + cycLeft_half0 + { + type cyclic; + } + cycRight_half0 + { + type cyclic; + } + frontAndBack + { + type empty; + } + cycLeft_half1 + { + type cyclic; + } + cycRight_half1 + { + type cyclic; + } +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/0.org/epsilon b/tutorials/mesh/parallel/filter/0.org/epsilon new file mode 100644 index 0000000000000000000000000000000000000000..448a7a0858360aab277ccd6a63ade402fd2e8dab --- /dev/null +++ b/tutorials/mesh/parallel/filter/0.org/epsilon @@ -0,0 +1,61 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + location "1"; + object epsilon; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [ 0 2 -3 0 0 0 0 ]; + +internalField uniform 0.0449; + +boundaryField +{ + walls + { + type epsilonWallFunction; + value uniform 0.0449; + } + inlet + { + type fixedValue; + value uniform 0.0449; + } + outlet + { + type zeroGradient; + } + cycLeft_half0 + { + type cyclic; + } + cycRight_half0 + { + type cyclic; + } + frontAndBack + { + type empty; + } + cycLeft_half1 + { + type cyclic; + } + cycRight_half1 + { + type cyclic; + } +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/0.org/k b/tutorials/mesh/parallel/filter/0.org/k new file mode 100644 index 0000000000000000000000000000000000000000..7d79256b2a21ea0c1b3d0bf7b1208da1b312a7f8 --- /dev/null +++ b/tutorials/mesh/parallel/filter/0.org/k @@ -0,0 +1,61 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + location "1"; + object k; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [ 0 2 -2 0 0 0 0 ]; + +internalField uniform 0.0938; + +boundaryField +{ + walls + { + type kqRWallFunction; + value uniform 0.0938; + } + inlet + { + type fixedValue; + value uniform 0.0938; + } + outlet + { + type zeroGradient; + } + cycLeft_half0 + { + type cyclic; + } + cycRight_half0 + { + type cyclic; + } + frontAndBack + { + type empty; + } + cycLeft_half1 + { + type cyclic; + } + cycRight_half1 + { + type cyclic; + } +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/0.org/nut b/tutorials/mesh/parallel/filter/0.org/nut new file mode 100644 index 0000000000000000000000000000000000000000..37d486043dbe6fcaf0ccb2243fc0805163f9f170 --- /dev/null +++ b/tutorials/mesh/parallel/filter/0.org/nut @@ -0,0 +1,45 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + location "0"; + object nut; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -1 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + //- Set patchGroups for constraint patches + #include "${WM_PROJECT_DIR}/etc/caseDicts/setConstraintTypes" + + walls + { + type nutkWallFunction; + value uniform 0; + } + inlet + { + type calculated; + value uniform 0; + } + outlet + { + type calculated; + value uniform 0; + } +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/0.org/p b/tutorials/mesh/parallel/filter/0.org/p new file mode 100644 index 0000000000000000000000000000000000000000..3ebd756ac38e80ec9f7d8e4c63069dc7e5ffa0ed --- /dev/null +++ b/tutorials/mesh/parallel/filter/0.org/p @@ -0,0 +1,60 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + location "1"; + object p; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [ 1 -1 -2 0 0 0 0 ]; + +internalField uniform 100000; + +boundaryField +{ + walls + { + type zeroGradient; + } + inlet + { + type zeroGradient; + } + outlet + { + type fixedValue; + value uniform 100000; + } + cycLeft_half0 + { + type cyclic; + } + cycRight_half0 + { + type cyclic; + } + frontAndBack + { + type empty; + } + cycLeft_half1 + { + type cyclic; + } + cycRight_half1 + { + type cyclic; + } +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/Allclean b/tutorials/mesh/parallel/filter/Allclean new file mode 100755 index 0000000000000000000000000000000000000000..48ffd679aa10c6021edb1306c5b98879657b5243 --- /dev/null +++ b/tutorials/mesh/parallel/filter/Allclean @@ -0,0 +1,15 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory + +# Source tutorial clean functions +. $WM_PROJECT_DIR/bin/tools/CleanFunctions + +cleanCase + +# remove 0 directory +rm -rf 0 + +# remove post-processing directory +rm -rf postProcessing + +# ----------------------------------------------------------------- end-of-file diff --git a/tutorials/mesh/parallel/filter/Allrun b/tutorials/mesh/parallel/filter/Allrun new file mode 100755 index 0000000000000000000000000000000000000000..47c1667d510282c8f93410cd64b57ca108dc4672 --- /dev/null +++ b/tutorials/mesh/parallel/filter/Allrun @@ -0,0 +1,33 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory + +# Source tutorial run functions +. $WM_PROJECT_DIR/bin/tools/RunFunctions + +application=`getApplication` + +# create mesh +runApplication blockMesh + +# copy 0.org to 0 +cp -r 0.org 0 + +# create sets +runApplication topoSet + +# create baffles and fields +runApplication createBaffles -overwrite + +runApplication $application + +#- redistributePar to do decomposition +runParallel redistributePar 3 -decompose -cellDist + +#- Continue running for a bit more +runParallel -l log.reactingParcelFoam-par $application 3 + +#- Reconstruct all times +runParallel -l log.redistributePar-1 redistributePar 3 -reconstruct + + +# ----------------------------------------------------------------- end-of-file diff --git a/tutorials/mesh/parallel/filter/constant/chemistryProperties b/tutorials/mesh/parallel/filter/constant/chemistryProperties new file mode 100644 index 0000000000000000000000000000000000000000..502724fef5d5e17f8be2a326e56404616cba2e60 --- /dev/null +++ b/tutorials/mesh/parallel/filter/constant/chemistryProperties @@ -0,0 +1,41 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object chemistryProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +chemistryType +{ + chemistrySolver noChemistrySolver; + chemistryThermo rho; +} + +chemistry off; + +initialChemicalTimeStep 1e-07; + +EulerImplicitCoeffs +{ + cTauChem 0.05; + equilibriumRateLimiter off; +} + +odeCoeffs +{ + solver seulex; + eps 0.05; +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/constant/combustionProperties b/tutorials/mesh/parallel/filter/constant/combustionProperties new file mode 100644 index 0000000000000000000000000000000000000000..334391590cc303976e6e72e1e1c8ca7d474ada5a --- /dev/null +++ b/tutorials/mesh/parallel/filter/constant/combustionProperties @@ -0,0 +1,29 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object combustionProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +combustionModel PaSR<rhoChemistryCombustion>; + +active false; + +PaSRCoeffs +{ + Cmix 1.0; + turbulentReaction off; +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/constant/g b/tutorials/mesh/parallel/filter/constant/g new file mode 100644 index 0000000000000000000000000000000000000000..057403310a4dba8dc69f1470dd26d8a7d6d6b978 --- /dev/null +++ b/tutorials/mesh/parallel/filter/constant/g @@ -0,0 +1,22 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class uniformDimensionedVectorField; + location "constant"; + object g; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -2 0 0 0 0]; +value ( 0 0 0 ); + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/constant/parcelInjectionProperties b/tutorials/mesh/parallel/filter/constant/parcelInjectionProperties new file mode 100644 index 0000000000000000000000000000000000000000..71671c99ddbe4b503abf57c3c3c6386db7c3b073 --- /dev/null +++ b/tutorials/mesh/parallel/filter/constant/parcelInjectionProperties @@ -0,0 +1,26 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object scalarListList; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// (x y z) (u v w) d rho mDot T Cp (Y0..Y2) (Yg0..YgN) (Yl0..YlN) (Ys0..YsN) +( + (0.1 0.32 0.0) (0.5 0.25 0.0) 0.001 1000 0.2 300 4200 (0 1 0) () (1) () + (0.1 0.44 0.0) (0.5 0.10 0.0) 0.001 1000 0.2 300 4200 (0 1 0) () (1) () + (0.1 0.56 0.0) (0.5 -0.10 0.0) 0.001 1000 0.2 300 4200 (0 1 0) () (1) () + (0.1 0.68 0.0) (0.5 -0.25 0.0) 0.001 1000 0.2 300 4200 (0 1 0) () (1) () +); + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/constant/particleTrackProperties b/tutorials/mesh/parallel/filter/constant/particleTrackProperties new file mode 100644 index 0000000000000000000000000000000000000000..1c436933ea70ad50b20791ab8fabe48d7438330b --- /dev/null +++ b/tutorials/mesh/parallel/filter/constant/particleTrackProperties @@ -0,0 +1,25 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object particleTrackProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +cloudName reactingCloud1; + +sampleFrequency 1; + +maxPositions 1000000; + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/constant/polyMesh/blockMeshDict b/tutorials/mesh/parallel/filter/constant/polyMesh/blockMeshDict new file mode 100644 index 0000000000000000000000000000000000000000..ae16964f9352790d20bc408641b3027323f09503 --- /dev/null +++ b/tutorials/mesh/parallel/filter/constant/polyMesh/blockMeshDict @@ -0,0 +1,123 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant/polyMesh"; + object blockMeshDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +convertToMeters 1; + +vertices +( + (0.00 0.25 0) // 0 + (1.00 0.25 0) // 1 + (1.25 0.00 0) // 2 + (2.25 0.00 0) // 3 + (2.50 0.25 0) // 4 + (4.00 0.25 0) // 5 + + (4.00 0.75 0) // 6 + (2.50 0.75 0) // 7 + (2.25 1.00 0) // 8 + (1.25 1.00 0) // 9 + (1.00 0.75 0) // 10 + (0.00 0.75 0) // 11 + + + (0.00 0.25 0.1) // 12 + (1.00 0.25 0.1) // 13 + (1.25 0.00 0.1) // 14 + (2.25 0.00 0.1) // 15 + (2.50 0.25 0.1) // 16 + (4.00 0.25 0.1) // 17 + + (4.00 0.75 0.1) // 18 + (2.50 0.75 0.1) // 19 + (2.25 1.00 0.1) // 20 + (1.25 1.00 0.1) // 21 + (1.00 0.75 0.1) // 22 + (0.00 0.75 0.1) // 23 +); + +blocks +( + hex ( 0 1 10 11 12 13 22 23) (20 20 1) simpleGrading (1 1 1) + hex ( 1 2 9 10 13 14 21 22) ( 8 20 1) simpleGrading (1 1 1) + hex ( 2 3 8 9 14 15 20 21) (20 20 1) simpleGrading (1 1 1) + hex ( 3 4 7 8 15 16 19 20) ( 8 20 1) simpleGrading (1 1 1) + hex ( 4 5 6 7 16 17 18 19) (30 20 1) simpleGrading (1 1 1) +); + +edges +( +); + +boundary +( + walls + { + type wall; + faces + ( + ( 0 1 13 12) + ( 1 2 14 13) + ( 2 3 15 14) + ( 3 4 16 15) + ( 4 5 17 16) + ( 6 7 19 18) + ( 7 8 20 19) + ( 8 9 21 20) + ( 9 10 22 21) + (10 11 23 22) + ); + } + + inlet + { + type patch; + faces + ( + (11 0 12 23) + ); + } + + outlet + { + type patch; + faces + ( + ( 5 6 18 17) + ); + } + + frontAndBack + { + type empty; + faces + ( + ( 0 11 10 1) + ( 1 10 9 2) + ( 2 9 8 3) + ( 3 8 7 4) + ( 4 7 6 5) + (12 13 22 23) + (13 14 21 22) + (14 15 20 21) + (15 16 19 20) + (16 17 18 19) + ); + } +); + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/constant/radiationProperties b/tutorials/mesh/parallel/filter/constant/radiationProperties new file mode 100644 index 0000000000000000000000000000000000000000..6981f2ccb7c8ab4a41a1f031d142715ad8ba82c4 --- /dev/null +++ b/tutorials/mesh/parallel/filter/constant/radiationProperties @@ -0,0 +1,24 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object radiationProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +radiation off; + +radiationModel none; + + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/constant/reactingCloud1Properties b/tutorials/mesh/parallel/filter/constant/reactingCloud1Properties new file mode 100644 index 0000000000000000000000000000000000000000..86af4d3474bf0c4b3f0cb1ebafe35842752d06a3 --- /dev/null +++ b/tutorials/mesh/parallel/filter/constant/reactingCloud1Properties @@ -0,0 +1,188 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object reactingCloud1Properties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +solution +{ + active true; + coupled true; + transient yes; + cellValueSourceCorrection on; + maxCo 0.3; + + sourceTerms + { + schemes + { + rho explicit 1; + U explicit 1; + Yi explicit 1; + h explicit 1; + radiation explicit 1; + } + } + + interpolationSchemes + { + rho cell; + U cellPoint; + thermo:mu cell; + T cell; + Cp cell; + kappa cell; + p cell; + } + + integrationSchemes + { + U Euler; + T analytical; + } +} + + +constantProperties +{ + rho0 1000; + T0 300; + Cp0 4100; + + constantVolume false; +} + + +subModels +{ + particleForces + { + sphereDrag; + gravity; + } + + injectionModels + { + model1 + { + type reactingMultiphaseLookupTableInjection; + massTotal 1e-2; + parcelBasisType mass; + SOI 0.1; + inputFile "parcelInjectionProperties"; + duration 1.0; + parcelsPerSecond 250; + randomise true; + } + } + + dispersionModel none; + + patchInteractionModel localInteraction; + + heatTransferModel RanzMarshall; + + compositionModel singleMixtureFraction; + + phaseChangeModel liquidEvaporation; + + devolatilisationModel none; + + surfaceReactionModel none; + + stochasticCollisionModel none; + + surfaceFilmModel none; + + radiation off; + + localInteractionCoeffs + { + patches + ( + "(walls|cyc.*)" + { + type rebound; + } + + "inlet|outlet" + { + type escape; + } + ); + } + + RanzMarshallCoeffs + { + BirdCorrection true; + } + + singleMixtureFractionCoeffs + { + phases + ( + gas + { + } + liquid + { + H2O 1; + } + solid + { + } + ); + YGasTot0 0; + YLiquidTot0 1; + YSolidTot0 0; + } + + liquidEvaporationCoeffs + { + enthalpyTransfer enthalpyDifference; + + activeLiquids ( H2O ); + } +} + + +cloudFunctions +{ + patchPostProcessing1 + { + type patchPostProcessing; + maxStoredParcels 20; + patches + ( + cycLeft_half0 + cycLeft_half1 + ); + } + + facePostProcessing1 + { + type facePostProcessing; + surfaceFormat vtk; + resetOnWrite no; + log yes; + + faceZones + ( + cycLeft + ); + } +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/constant/reactions b/tutorials/mesh/parallel/filter/constant/reactions new file mode 100644 index 0000000000000000000000000000000000000000..cdc9995d9ea11a66fc071dfe13da64e8226e4951 --- /dev/null +++ b/tutorials/mesh/parallel/filter/constant/reactions @@ -0,0 +1,9 @@ +species +( + N2 + O2 + H2O +); + +reactions +{} diff --git a/tutorials/mesh/parallel/filter/constant/thermo.incompressiblePoly b/tutorials/mesh/parallel/filter/constant/thermo.incompressiblePoly new file mode 100644 index 0000000000000000000000000000000000000000..ec4289e97755098f968898fe3b1cb389e311a9a5 --- /dev/null +++ b/tutorials/mesh/parallel/filter/constant/thermo.incompressiblePoly @@ -0,0 +1,115 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object thermo.incompressiblePoly; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +N2 +{ + specie + { + nMoles 1; + molWeight 28.0134; + } + equationOfState + { + rhoCoeffs<8> ( 3.8936 -0.016463 3.2101e-05 -2.9174e-08 9.9889e-12 0 0 0 ); + } + thermodynamics + { + Hf 0; + Sf 0; + CpCoeffs<8> ( 979.08 0.41787 -0.0011761 1.6742e-06 -7.2559e-10 0 0 0 ); + } + transport + { + muCoeffs<8> ( 1.5068e-06 6.1598e-08 -1.8188e-11 0 0 0 0 0 ); + kappaCoeffs<8> ( 0.0031494 8.4997e-05 -1.2621e-08 0 0 0 0 0 ); + } +} + +O2 +{ + specie + { + nMoles 1; + molWeight 31.9988; + } + equationOfState + { + rhoCoeffs<8> ( 4.4475 -0.018805 3.6667e-05 -3.3323e-08 1.141e-11 0 0 0 ); + } + thermodynamics + { + Hf 0; + Sf 0; + CpCoeffs<8> ( 834.84 0.29297 -0.00014959 3.4143e-07 -2.2786e-10 0 0 0 ); + } + transport + { + muCoeffs<8> ( 1.5068e-06 6.1598e-08 -1.8188e-11 0 0 0 0 0 ); + kappaCoeffs<8> ( 0.00016082 8.5301e-05 -1.4998e-08 0 0 0 0 0 ); + } +} + +H2O +{ + specie + { + nMoles 1; + molWeight 18.0153; + } + equationOfState + { + rhoCoeffs<8> ( 2.5039 -0.010587 2.0643e-05 -1.8761e-08 6.4237e-12 0 0 0 ); + } + thermodynamics + { + Hf -13423000; + Sf 10482; + CpCoeffs<8> ( 1563.1 1.604 -0.0029334 3.2168e-06 -1.1571e-09 0 0 0 ); + } + transport + { + muCoeffs<8> ( 1.5068e-06 6.1598e-08 -1.8188e-11 0 0 0 0 0 ); + kappaCoeffs<8> ( 0.0037972 0.00015336 -1.1859e-08 0 0 0 0 0 ); + } +} + +air +{ + specie + { + nMoles 1; + molWeight 28.85; + } + equationOfState + { + rhoCoeffs<8> ( 4.0097 -0.016954 3.3057e-05 -3.0042e-08 1.0286e-11 0 0 0 ); + } + thermodynamics + { + Hf 0; + Sf 0; + CpCoeffs<8> ( 948.76 0.39171 -0.00095999 1.393e-06 -6.2029e-10 0 0 0 ); + } + transport + { + muCoeffs<8> ( 1.5061e-06 6.16e-08 -1.819e-11 0 0 0 0 0 ); + kappaCoeffs<8> ( 0.0025219 8.506e-05 -1.312e-08 0 0 0 0 0 ); + } +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/constant/thermophysicalProperties b/tutorials/mesh/parallel/filter/constant/thermophysicalProperties new file mode 100644 index 0000000000000000000000000000000000000000..a703f9908a6cdd8c3c13996b1e37a6c821dceec2 --- /dev/null +++ b/tutorials/mesh/parallel/filter/constant/thermophysicalProperties @@ -0,0 +1,53 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object thermophysicalProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +thermoType +{ + type heRhoThermo; + mixture reactingMixture; + transport polynomial; + thermo hPolynomial; + energy sensibleEnthalpy; + equationOfState icoPolynomial; + specie specie; +} + +dpdt no; + +chemistryReader foamChemistryReader; + +foamChemistryFile "$FOAM_CASE/constant/reactions"; + +foamChemistryThermoFile "$FOAM_CASE/constant/thermo.incompressiblePoly"; + +liquids +{ + H2O + { + defaultCoeffs yes; + } +} + +solids +{ + // none +} + +inertSpecie N2; + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/constant/turbulenceProperties b/tutorials/mesh/parallel/filter/constant/turbulenceProperties new file mode 100644 index 0000000000000000000000000000000000000000..394dee14e23480cd2cf083c7d2a59e8208d740d5 --- /dev/null +++ b/tutorials/mesh/parallel/filter/constant/turbulenceProperties @@ -0,0 +1,28 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object turbulenceProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +simulationType RAS; + +RAS +{ + RASModel kEpsilon; + + turbulence on; + + printCoeffs on; +} + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/system/controlDict b/tutorials/mesh/parallel/filter/system/controlDict new file mode 100644 index 0000000000000000000000000000000000000000..6d8a57f2fdb492591982dac782ff393f33bd731b --- /dev/null +++ b/tutorials/mesh/parallel/filter/system/controlDict @@ -0,0 +1,54 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object controlDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +application reactingParcelFoam; + +startFrom latestTime; + +startTime 0; + +stopAt nextWrite; + +endTime 5; + +deltaT 0.001; + +writeControl adjustableRunTime; + +writeInterval 0.4; + +purgeWrite 0; + +writeFormat binary; + +writePrecision 10; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable true; + +adjustTimeStep yes; + +maxCo 1.0; + +maxDeltaT 1; + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/system/createBafflesDict b/tutorials/mesh/parallel/filter/system/createBafflesDict new file mode 100644 index 0000000000000000000000000000000000000000..1caf47dc89d7e6df43b99af09865fe4827778ce3 --- /dev/null +++ b/tutorials/mesh/parallel/filter/system/createBafflesDict @@ -0,0 +1,81 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object createBafflesDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Whether to convert internal faces only (so leave boundary faces intact). +// This is only relevant if your face selection type can pick up boundary +// faces. +internalFacesOnly true; + +// Baffles to create. +baffles +{ + cycLeft + { + //- Use predefined faceZone to select faces and orientation. + type faceZone; + zoneName cycLeft; + + patches + { + master + { + //- Master side patch + + name cycLeft_half0; + type cyclic; + neighbourPatch cycLeft_half1; + } + slave + { + //- Slave side patch + + name cycLeft_half1; + type cyclic; + neighbourPatch cycLeft_half0; + } + } + } + + cycRight + { + //- Use predefined faceZone to select faces and orientation. + type faceZone; + zoneName cycRight; + + patches + { + master + { + //- Master side patch + + name cycRight_half0; + type cyclic; + neighbourPatch cycRight_half1; + } + slave + { + //- Slave side patch + + name cycRight_half1; + type cyclic; + neighbourPatch cycRight_half0; + } + } + } +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/system/decomposeParDict b/tutorials/mesh/parallel/filter/system/decomposeParDict new file mode 100644 index 0000000000000000000000000000000000000000..debb64837ec982ed9914ae1e43bc7bfa2325db88 --- /dev/null +++ b/tutorials/mesh/parallel/filter/system/decomposeParDict @@ -0,0 +1,47 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object decomposeParDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +numberOfSubdomains 3; + +method scotch; + +preserveFaceZones +( + cycLeft + cycRight +); + +simpleCoeffs +{ + n ( 2 2 1 ); + delta 0.001; +} + +hierarchicalCoeffs +{ + n ( 1 1 1 ); + delta 0.001; + order xyz; +} + +manualCoeffs +{ + dataFile ""; +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/system/fvOptions b/tutorials/mesh/parallel/filter/system/fvOptions new file mode 100644 index 0000000000000000000000000000000000000000..01546fe13756b353a0c002bb64345dc0762c4636 --- /dev/null +++ b/tutorials/mesh/parallel/filter/system/fvOptions @@ -0,0 +1,124 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object fvOptions; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +filter1 +{ + type explicitPorositySource; + active yes; + + explicitPorositySourceCoeffs + { + selectionMode cellZone; + cellZone filter; + + type DarcyForchheimer; + + DarcyForchheimerCoeffs + { + d d [0 -2 0 0 0 0 0] (500000 -1000 -1000); + f f [0 -1 0 0 0 0 0] (0 0 0); + + coordinateSystem + { + type cartesian; + origin (0 0 0); + coordinateRotation + { + type axesRotation; + e1 (1 0 0); + e2 (0 1 0); + } + } + } + } +} + + +massSource1 +{ + type scalarSemiImplicitSource; + active yes; + + scalarSemiImplicitSourceCoeffs + { + timeStart 0.2; + duration 2.0; + selectionMode points; + points + ( + (2.75 0.5 0) + ); + + volumeMode absolute; + injectionRateSuSp + { + rho (1e-4 0); // kg/s + H2O (1e-4 0); // kg/s + } + } +} + + +momentumSource1 +{ + type vectorSemiImplicitSource; + active yes; + + vectorSemiImplicitSourceCoeffs + { + timeStart 0.2; + duration 2.0; + selectionMode points; + points + ( + (2.75 0.5 0) + ); + + volumeMode absolute; + injectionRateSuSp + { + U ((0 0.005 0) 0); + } + } +} + + +energySource1 +{ + type scalarSemiImplicitSource; + active yes; + + scalarSemiImplicitSourceCoeffs + { + timeStart 0.2; + duration 2.0; + selectionMode points; + points + ( + (2.75 0.5 0) + ); + + volumeMode absolute; + injectionRateSuSp + { + h (10 0); + } + } +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/system/fvSchemes b/tutorials/mesh/parallel/filter/system/fvSchemes new file mode 100644 index 0000000000000000000000000000000000000000..536c43de095c206e1866c384029cdb477362f86f --- /dev/null +++ b/tutorials/mesh/parallel/filter/system/fvSchemes @@ -0,0 +1,65 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSchemes; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; +} + +divSchemes +{ + default none; + + div(phi,U) Gauss upwind; + div(phid,p) Gauss upwind; + div(phi,K) Gauss linear; + div(phi,h) Gauss upwind; + div(phi,k) Gauss upwind; + div(phi,epsilon) Gauss upwind; + div(U) Gauss linear; + div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear; + div(phi,Yi_h) Gauss upwind; +} + +laplacianSchemes +{ + default Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} + +fluxRequired +{ + default no; + p ; +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/system/fvSolution b/tutorials/mesh/parallel/filter/system/fvSolution new file mode 100644 index 0000000000000000000000000000000000000000..1ec56c204c6ccaa0faf6c47a36ad67a1509c7751 --- /dev/null +++ b/tutorials/mesh/parallel/filter/system/fvSolution @@ -0,0 +1,112 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSolution; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +solvers +{ + rho + { + solver PCG; + preconditioner DIC; + tolerance 1e-05; + relTol 0.1; + } + + rhoFinal + { + $rho; + tolerance 1e-05; + relTol 0; + } + + "(U|k|epsilon)" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-06; + relTol 0.1; + } + + "(U|k|epsilon)Final" + { + $U; + tolerance 1e-06; + relTol 0; + } + + p + { + solver GAMG; + tolerance 0; + relTol 0.1; + smoother GaussSeidel; + nPreSweeps 0; + nPostSweeps 2; + cacheAgglomeration true; + nCellsInCoarsestLevel 10; + agglomerator faceAreaPair; + mergeLevels 1; + } + + pFinal + { + $p; + tolerance 1e-06; + relTol 0; + } + + "(Yi|O2|N2|H2O)" + { + solver PBiCG; + preconditioner DILU; + tolerance 1e-6; + relTol 0; + } + + h + { + $Yi; + relTol 0.1; + } + + hFinal + { + $Yi; + } +} + +PIMPLE +{ + transonic no; + nOuterCorrectors 1; + nCorrectors 2; + nNonOrthogonalCorrectors 0; + momentumPredictor yes; +} + +relaxationFactors +{ + fields + { + } + equations + { + ".*Final" 1; + } +} + + +// ************************************************************************* // diff --git a/tutorials/mesh/parallel/filter/system/topoSetDict b/tutorials/mesh/parallel/filter/system/topoSetDict new file mode 100644 index 0000000000000000000000000000000000000000..3ba9ba8ec6404a3cfdff25b8af4dbb2cc983236d --- /dev/null +++ b/tutorials/mesh/parallel/filter/system/topoSetDict @@ -0,0 +1,157 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: dev | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object topoSetDict; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +actions +( + // filter + { + name filterCells; + type cellSet; + action new; + source boxToCell; + sourceInfo + { + box (1.5 -10 -10) (2 10 10); + } + } + { + name filter; + type cellZoneSet; + action new; + source setToCellZone; + sourceInfo + { + set filterCells; + } + } + + + { + name leftFluidCells; + type cellSet; + action new; + source boxToCell; + sourceInfo + { + box (-10 -10 -10) (1.5 10 10); + } + } + { + name leftFluid; + type cellZoneSet; + action new; + source setToCellZone; + sourceInfo + { + set leftFluidCells; + } + } + { + name rightFluidCells; + type cellSet; + action new; + source boxToCell; + sourceInfo + { + box (2 -1 -1) (10 10 10); + } + } + { + name rightFluid; + type cellZoneSet; + action new; + source setToCellZone; + sourceInfo + { + set rightFluidCells; + } + } + + + // cycLeft + { + name cycLeftFaces; + type faceSet; + action new; + source cellToFace; + sourceInfo + { + set filterCells; + option all; + } + } + { + name cycLeftFaces; + type faceSet; + action subset; + source cellToFace; + sourceInfo + { + set leftFluidCells; + option all; + } + } + // Create faceZone from cycLeft + { + name cycLeft; + type faceZoneSet; + action new; + source setToFaceZone; + sourceInfo + { + faceSet cycLeftFaces; // name of faceSet + } + } + + // cycRight + { + name cycRightFaces; + type faceSet; + action new; + source cellToFace; + sourceInfo + { + set filterCells; + option all; + } + } + { + name cycRightFaces; + type faceSet; + action subset; + source cellToFace; + sourceInfo + { + set rightFluidCells; + option all; + } + } + // Create faceZone from cycRight + { + name cycRight; + type faceZoneSet; + action new; + source setToFaceZone; + sourceInfo + { + faceSet cycRightFaces; // name of faceSet + } + } + +); + +// ************************************************************************* //