diff --git a/applications/utilities/parallelProcessing/redistributePar/Make/files b/applications/utilities/parallelProcessing/redistributePar/Make/files index 3447baa3d827dac259a561af26c9b1b35024cb1a..6e45d2d8cc66dbe1e97b35afc59eeb6dbf998428 100644 --- a/applications/utilities/parallelProcessing/redistributePar/Make/files +++ b/applications/utilities/parallelProcessing/redistributePar/Make/files @@ -1,6 +1,8 @@ passivePositionParticleCloud.C parLagrangianRedistributor.C +parPointFieldDistributor.C parFvFieldReconstructor.C + loadOrCreateMesh.C redistributePar.C diff --git a/applications/utilities/parallelProcessing/redistributePar/parPointFieldDistributor.C b/applications/utilities/parallelProcessing/redistributePar/parPointFieldDistributor.C new file mode 100644 index 0000000000000000000000000000000000000000..ade2b7a2378d3579a37f9b28f6e6397ef9e6992f --- /dev/null +++ b/applications/utilities/parallelProcessing/redistributePar/parPointFieldDistributor.C @@ -0,0 +1,238 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2022 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "parPointFieldDistributor.H" +#include "processorPointPatch.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +int Foam::parPointFieldDistributor::verbose_ = 0; + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::parPointFieldDistributor::parPointFieldDistributor +( + const pointMesh& srcMesh, + const bool savePoints, + const bool isWriteProc +) +: + srcMesh_(srcMesh), + nOldPoints_(srcMesh.size()), + patchMeshPoints_(), + tgtMeshRef_(nullptr), + distMapRef_(nullptr), + patchPointMaps_(), + isWriteProc_(isWriteProc) +{ + if (savePoints) + { + saveMeshPoints(); + } +} + + +Foam::parPointFieldDistributor::parPointFieldDistributor +( + const pointMesh& srcMesh, + const pointMesh& tgtMesh, + const mapDistributePolyMesh& distMap, + const bool savePoints, + const bool isWriteProc +) +: + srcMesh_(srcMesh), + nOldPoints_(srcMesh.size()), + patchMeshPoints_(), + tgtMeshRef_(tgtMesh), + distMapRef_(distMap), + patchPointMaps_(), + isWriteProc_(isWriteProc) +{ + if (savePoints) + { + saveMeshPoints(); + } +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::parPointFieldDistributor::hasMeshPoints() const +{ + return !patchMeshPoints_.empty(); +} + + +bool Foam::parPointFieldDistributor::hasPatchPointMaps() const +{ + return !patchPointMaps_.empty(); +} + + +bool Foam::parPointFieldDistributor::hasTarget() const +{ + return (tgtMeshRef_ && distMapRef_); +} + + +void Foam::parPointFieldDistributor::clearMeshPoints() +{ + patchMeshPoints_.clear(); +} + +void Foam::parPointFieldDistributor::clearPatchPointMaps() +{ + patchPointMaps_.clear(); +} + + +void Foam::parPointFieldDistributor::saveMeshPoints() +{ + const pointBoundaryMesh& patches = srcMesh_.boundary(); + + patchMeshPoints_.clear(); + patchMeshPoints_.resize(patches.size()); + + forAll(patches, patchi) + { + if (!isA<processorPointPatch>(patches[patchi])) + { + // Copy meshPoints + patchMeshPoints_.set + ( + patchi, + new labelList(patches[patchi].meshPoints()) + ); + } + } +} + + +void Foam::parPointFieldDistributor::createPatchPointMaps() +{ + if (!tgtMeshRef_ || !distMapRef_) + { + FatalErrorInFunction + << "Cannot create maps without target mesh and/or distribution!" + << abort(FatalError); + } + + const auto& tgtMesh = tgtMeshRef_(); + const auto& distMap = distMapRef_(); + + const auto& newPatches = tgtMesh.boundary(); + const auto& oldPatches = srcMesh_.boundary(); + + patchPointMaps_.clear(); + patchPointMaps_.resize(oldPatches.size()); + + // if (patchPointMaps_.size() != patchMeshPoints_.size()) + // { + // // Warn? + // } + + forAll(oldPatches, patchi) + { + if (!isA<processorPointPatch>(oldPatches[patchi])) + { + // Create map for patch points only + labelList oldToNewSub; + labelList oldToNewConstruct; + + // Copy point map + patchPointMaps_.set + ( + patchi, + new mapDistributeBase(distMap.pointMap()) + ); + + const labelList& oldMeshPoints = + ( + patchMeshPoints_.test(patchi) + ? patchMeshPoints_[patchi] + : oldPatches[patchi].meshPoints() // <- Questionable! + ); + + patchPointMaps_[patchi].compactData + ( + oldMeshPoints, + newPatches[patchi].meshPoints(), + oldToNewSub, + oldToNewConstruct, + nOldPoints_, + UPstream::msgType() + ); + } + } +} + + +void Foam::parPointFieldDistributor::resetTarget() +{ + tgtMeshRef_.reset(nullptr); + distMapRef_.reset(nullptr); + + // Old maps are now invalid + clearPatchPointMaps(); +} + + +void Foam::parPointFieldDistributor::resetTarget +( + const pointMesh& tgtMesh, + const mapDistributePolyMesh& distMap +) +{ + tgtMeshRef_.cref(tgtMesh); + distMapRef_.cref(distMap); + + // Old maps are now invalid + clearPatchPointMaps(); +} + + +Foam::label Foam::parPointFieldDistributor::distributeAllFields +( + const IOobjectList& objects, + const wordRes& selected +) const +{ + label nTotal = 0; + + nTotal += distributePointFields<scalar>(objects, selected); + nTotal += distributePointFields<vector>(objects, selected); + nTotal += distributePointFields<symmTensor>(objects, selected); + nTotal += distributePointFields<sphericalTensor>(objects, selected); + nTotal += distributePointFields<tensor>(objects, selected); + + return nTotal; +} + + +// ************************************************************************* // diff --git a/applications/utilities/parallelProcessing/redistributePar/parPointFieldDistributor.H b/applications/utilities/parallelProcessing/redistributePar/parPointFieldDistributor.H new file mode 100644 index 0000000000000000000000000000000000000000..70307d7e2832deb8bcf27439d663616fe92c0618 --- /dev/null +++ b/applications/utilities/parallelProcessing/redistributePar/parPointFieldDistributor.H @@ -0,0 +1,255 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2022 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::parPointFieldDistributor + +Description + Distributor/redistributor for point fields, + uses a two (or three) stage construction. + + The inconvenient multi-stage construction is needed since the + pointMesh is directly associated with a polyMesh, which will probably + have changed while creating the target mesh. This means that it is + necessary to save the size of the source mesh and all of its + patch meshPoints prior to making any changes (eg, creating the target + mesh). + + -# Create with specified source mesh + -# Save the meshPoints (per boundary) for the source mesh + -# Attach a target mesh and mesh distribution + -# Map the point fields + . + + Runs in parallel. Redistributes from srcMesh to tgtMesh. + +SourceFiles + parPointFieldDistributor.C + parPointFieldDistributorTemplates.C + +\*---------------------------------------------------------------------------*/ + +#ifndef Foam_parPointFieldDistributor_H +#define Foam_parPointFieldDistributor_H + +#include "PtrList.H" +#include "pointMesh.H" +#include "pointFieldsFwd.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward Declarations +class mapDistributePolyMesh; +class mapDistributeBase; +class IOobjectList; + +/*---------------------------------------------------------------------------*\ + Class parPointFieldDistributor Declaration +\*---------------------------------------------------------------------------*/ + +class parPointFieldDistributor +{ + // Private Data + + //- The source mesh reference + const pointMesh& srcMesh_; + + //- Number of points in the old (source) mesh + const label nOldPoints_; + + //- The pointPatch mesh points + PtrList<labelList> patchMeshPoints_; + + //- The target (destination) mesh reference + refPtr<pointMesh> tgtMeshRef_; + + //- Distribution map reference + refPtr<mapDistributePolyMesh> distMapRef_; + + //- Point patch mappers + PtrList<mapDistributeBase> patchPointMaps_; + + //- Do I need to write (eg, master only for reconstruct) + bool isWriteProc_; + + + // Private Member Functions + + //- No copy construct + parPointFieldDistributor(const parPointFieldDistributor&) = delete; + + //- No copy assignment + void operator=(const parPointFieldDistributor&) = delete; + + +public: + + //- Output verbosity when writing + static int verbose_; + + + // Constructors + + //- Basic construction + // + // \param srcMesh The source pointMesh + // \param savePoints Call saveMeshPoints() immediately + // \param isWriteProc Tagged for output writing (on this proc) + explicit parPointFieldDistributor + ( + const pointMesh& srcMesh, + const bool savePoints = false, + const bool isWriteProc = false + ); + + //- Full construction of source/target + // + // \param srcMesh The source pointMesh + // \param tgtMesh The target pointMesh + // \param distMap The distribution map + // \param savePoints Call saveMeshPoints() immediately + // \param isWriteProc Tagged for output writing (on this proc) + explicit parPointFieldDistributor + ( + const pointMesh& srcMesh, + const pointMesh& tgtMesh, + const mapDistributePolyMesh& distMap, + const bool savePoints = false, + const bool isWriteProc = false + ); + + + // Member Functions + + //- True if meshPoints (per boundary) for the source mesh + //- have been saved + bool hasMeshPoints() const; + + //- True if patch maps (per boundary) exist + bool hasPatchPointMaps() const; + + //- True if a target mesh/distribution map has been attached + bool hasTarget() const; + + //- Clear out meshPoints (per boundary) for the source mesh + void clearMeshPoints(); + + //- Clear out patch maps (per boundary) + void clearPatchPointMaps(); + + //- Create/recreate meshPoints (per boundary) for the source mesh + void saveMeshPoints(); + + //- Construct per-patch addressing + void createPatchPointMaps(); + + //- Clear target mesh / distribution map + void resetTarget(); + + //- Reset target mesh / distribution map + void resetTarget + ( + const pointMesh& tgtMesh, + const mapDistributePolyMesh& distMap + ); + + //- Get status of write enabled (on this proc) + bool isWriteProc() const noexcept + { + return isWriteProc_; + } + + //- Change status of write enabled (on this proc) + bool isWriteProc(const bool on) noexcept + { + bool old(isWriteProc_); + isWriteProc_ = on; + return old; + } + + + // Field Mapping + + //- Read, distribute and write all/selected point field types + //- (scalar, vector, ... types) + label distributeAllFields + ( + const IOobjectList& objects, + const wordRes& selectedFields = wordRes() + ) const; + + + //- Distribute point field + template<class Type> + tmp<GeometricField<Type, pointPatchField, pointMesh>> + distributeField + ( + const GeometricField<Type, pointPatchField, pointMesh>& fld + ) const; + + //- Read and distribute point field + template<class Type> + tmp<GeometricField<Type, pointPatchField, pointMesh>> + distributePointField + ( + const IOobject& fieldObject + ) const; + + //- Read, distribute and write all/selected point fields + template<class Type> + label distributePointFields + ( + const IOobjectList& objects, + const wordRes& selectedFields = wordRes() + ) const; + + //- Distributed each (unregistered!) point field + //- and store the result on its objectRegistry + template<class Type> + void distributeAndStore + ( + const PtrList<GeometricField<Type, pointPatchField, pointMesh>>& + ) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository +# include "parPointFieldDistributorTemplates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/utilities/parallelProcessing/redistributePar/parPointFieldDistributorTemplates.C b/applications/utilities/parallelProcessing/redistributePar/parPointFieldDistributorTemplates.C new file mode 100644 index 0000000000000000000000000000000000000000..d7c73ea218e5743954a413eefc8d3c3198cab3b8 --- /dev/null +++ b/applications/utilities/parallelProcessing/redistributePar/parPointFieldDistributorTemplates.C @@ -0,0 +1,239 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2022 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "Time.H" +#include "emptyPointPatchField.H" +#include "IOobjectList.H" +#include "mapDistributePolyMesh.H" +#include "distributedFieldMapper.H" +#include "distributedPointPatchFieldMapper.H" +#include "pointFields.H" + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +template<class Type> +Foam::tmp<Foam::GeometricField<Type, Foam::pointPatchField, Foam::pointMesh>> +Foam::parPointFieldDistributor::distributeField +( + const GeometricField<Type, pointPatchField, pointMesh>& fld +) const +{ + if (!tgtMeshRef_ || !distMapRef_) + { + FatalErrorInFunction + << "Cannot map field without target mesh and/or distribution!" + << abort(FatalError); + } + if (!hasPatchPointMaps()) + { + const_cast<parPointFieldDistributor&>(*this).createPatchPointMaps(); + } + + const auto& tgtMesh = tgtMeshRef_(); + const auto& distMap = distMapRef_(); + + // Create internalField by remote mapping + distributedFieldMapper mapper + ( + labelUList::null(), + distMap.pointMap() + ); + + DimensionedField<Type, pointMesh> internalField + ( + IOobject + ( + fld.name(), + tgtMesh.time().timeName(), + fld.local(), + tgtMesh.thisDb(), + IOobject::NO_READ, + IOobject::NO_WRITE + ), + tgtMesh, + fld.dimensions(), + Field<Type>(fld.internalField(), mapper) + ); + + internalField.oriented() = fld.oriented(); + + + // Create patchFields by remote mapping + + PtrList<pointPatchField<Type>> newPatchFields(tgtMesh.boundary().size()); + + const auto& bfld = fld.boundaryField(); + + forAll(bfld, patchi) + { + if (patchPointMaps_.set(patchi)) + { + // Clone local patch field + + const distributedPointPatchFieldMapper mapper + ( + labelUList::null(), + patchPointMaps_[patchi] + ); + + // Map into local copy + newPatchFields.set + ( + patchi, + pointPatchField<Type>::New + ( + bfld[patchi], + tgtMesh.boundary()[patchi], // pointPatch + DimensionedField<Type, pointMesh>::null(), + mapper + ) + ); + + // Note: below alternative, 'clone' method will not work since + // there is no clone to reset both internalField reference and + // patch reference. TBD. + //newPatchFields.set + //( + // patchi, + // bfld[patchi].clone + // ( + // tgtMesh.boundary()[patchi], + // DimensionedField<Type, pointMesh>::null(), + // mapper + // ) + //); + } + } + + // Add some empty patchFields on remaining patches (this also handles + // e.g. processorPatchFields or any other constraint type patches) + forAll(newPatchFields, patchi) + { + if (!newPatchFields.set(patchi)) + { + newPatchFields.set + ( + patchi, + pointPatchField<Type>::New + ( + emptyPointPatchField<Type>::typeName, + tgtMesh.boundary()[patchi], + DimensionedField<Type, pointMesh>::null() + ) + ); + } + } + + return + tmp<GeometricField<Type, pointPatchField, pointMesh>>::New + ( + std::move(internalField), + newPatchFields + ); +} + + +template<class Type> +Foam::tmp<Foam::GeometricField<Type, Foam::pointPatchField, Foam::pointMesh>> +Foam::parPointFieldDistributor::distributePointField +( + const IOobject& fieldObject +) const +{ + // Read field + GeometricField<Type, pointPatchField, pointMesh> fld + ( + fieldObject, + srcMesh_ + ); + + // Redistribute + return distributeField(fld); +} + + +template<class Type> +Foam::label Foam::parPointFieldDistributor::distributePointFields +( + const IOobjectList& objects, + const wordRes& selectedFields +) const +{ + typedef GeometricField<Type, pointPatchField, pointMesh> fieldType; + + UPtrList<const IOobject> fieldObjects + ( + selectedFields.empty() + ? objects.sorted<fieldType>() + : objects.sorted<fieldType>(selectedFields) + ); + + label nFields = 0; + for (const IOobject& io : fieldObjects) + { + if (verbose_) + { + if (!nFields) + { + Info<< " Reconstructing " + << fieldType::typeName << "s\n" << nl; + } + Info<< " " << io.name() << nl; + } + ++nFields; + + tmp<fieldType> tfld(distributePointField<Type>(io)); + if (isWriteProc_) + { + tfld().write(); + } + } + + if (nFields && verbose_) Info<< endl; + return nFields; +} + + +template<class Type> +void Foam::parPointFieldDistributor::distributeAndStore +( + const PtrList<GeometricField<Type, pointPatchField, pointMesh>>& fields +) const +{ + for (const auto& fld : fields) + { + // Distribute and store + auto tfld = distributeField(fld); + + tfld.ref().writeOpt(IOobject::AUTO_WRITE); + + tfld().mesh().thisDb().store(tfld); + } +} + + +// ************************************************************************* // diff --git a/applications/utilities/parallelProcessing/redistributePar/redistributePar.C b/applications/utilities/parallelProcessing/redistributePar/redistributePar.C index 01ae1c7338569329f95532680714274700b976a7..c148c3d9e8ccb927e26d44133a517e30c8ea270c 100644 --- a/applications/utilities/parallelProcessing/redistributePar/redistributePar.C +++ b/applications/utilities/parallelProcessing/redistributePar/redistributePar.C @@ -95,6 +95,7 @@ Usage #include "regionProperties.H" #include "parFvFieldReconstructor.H" +#include "parPointFieldDistributor.H" #include "parLagrangianRedistributor.H" #include "unmappedPassivePositionParticleCloud.H" #include "hexRef8Data.H" @@ -535,7 +536,7 @@ void determineDecomposition // Variant of GeometricField::correctBoundaryConditions that only // evaluates selected patch fields -template<class GeoField, class CoupledPatchType> +template<class CoupledPatchType, class GeoField> void correctCoupledBoundaryConditions(fvMesh& mesh) { HashTable<GeoField*> flds @@ -576,6 +577,7 @@ autoPtr<mapDistributePolyMesh> redistributeAndWrite //Info<< "Before distribution:" << endl; //printMeshData(mesh); + // Storage of fields PtrList<volScalarField> volScalarFields; PtrList<volVectorField> volVectorFields; @@ -595,7 +597,24 @@ autoPtr<mapDistributePolyMesh> redistributeAndWrite PtrList<DimensionedField<symmTensor, volMesh>> dimSymmTensorFields; PtrList<DimensionedField<tensor, volMesh>> dimTensorFields; - DynamicList<word> pointFieldNames; + PtrList<pointScalarField> pointScalarFields; + PtrList<pointVectorField> pointVectorFields; + PtrList<pointTensorField> pointTensorFields; + PtrList<pointSphericalTensorField> pointSphTensorFields; + PtrList<pointSymmTensorField> pointSymmTensorFields; + + // Self-contained pointMesh for reading pointFields + const pointMesh oldPointMesh(mesh); + + // Track how many (if any) pointFields are read/mapped + label nPointFields = 0; + + parPointFieldDistributor pointDistributor + ( + oldPointMesh, // source mesh + false, // savePoints=false (ie, delay until later) + false // Do not write + ); if (doReadFields) @@ -656,189 +675,67 @@ autoPtr<mapDistributePolyMesh> redistributeAndWrite } - // volFields - if (Pstream::master() && decompose) { runTime.caseName() = baseRunTime.caseName(); runTime.processorCase(false); } - fieldsDistributor::readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - volScalarFields - ); - - fieldsDistributor::readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - volVectorFields - ); - - fieldsDistributor::readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - volSphereTensorFields - ); - - fieldsDistributor::readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - volSymmTensorFields - ); - - fieldsDistributor::readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - volTensorFields - ); - - - // surfaceFields - - fieldsDistributor::readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - surfScalarFields - ); + // Field reading - fieldsDistributor::readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - surfVectorFields - ); - - fieldsDistributor::readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - surfSphereTensorFields - ); - - fieldsDistributor::readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - surfSymmTensorFields - ); + #undef doFieldReading + #define doFieldReading(Storage) \ + { \ + fieldsDistributor::readFields \ + ( \ + haveMesh, mesh, subsetterPtr, objects, Storage \ + ); \ + } - fieldsDistributor::readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - surfTensorFields - ); + // volField + doFieldReading(volScalarFields); + doFieldReading(volVectorFields); + doFieldReading(volSphereTensorFields); + doFieldReading(volSymmTensorFields); + doFieldReading(volTensorFields); + // surfaceField + doFieldReading(surfScalarFields); + doFieldReading(surfVectorFields); + doFieldReading(surfSphereTensorFields); + doFieldReading(surfSymmTensorFields); + doFieldReading(surfTensorFields); // Dimensioned internal fields - fieldsDistributor::readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - dimScalarFields - ); - - fieldsDistributor::readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - dimVectorFields - ); - - fieldsDistributor::readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - dimSphereTensorFields - ); - - fieldsDistributor::readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - dimSymmTensorFields - ); - - fieldsDistributor::readFields - ( - haveMesh, - mesh, - subsetterPtr, - objects, - dimTensorFields - ); + doFieldReading(dimScalarFields); + doFieldReading(dimVectorFields); + doFieldReading(dimSphereTensorFields); + doFieldReading(dimSymmTensorFields); + doFieldReading(dimTensorFields); + + // pointFields + nPointFields = 0; + + #undef doFieldReading + #define doFieldReading(Storage) \ + { \ + fieldsDistributor::readFields \ + ( \ + haveMesh, oldPointMesh, subsetterPtr, objects, Storage, \ + true /* (deregister field) */ \ + ); \ + nPointFields += Storage.size(); \ + } + doFieldReading(pointScalarFields); + doFieldReading(pointVectorFields); + doFieldReading(pointSphTensorFields); + doFieldReading(pointSymmTensorFields); + doFieldReading(pointTensorFields); + #undef doFieldReading - // pointFields currently not supported. Read their names so we - // can delete them. - { - // Get my objects of type - pointFieldNames.append - ( - objects.lookupClass(pointScalarField::typeName).sortedNames() - ); - pointFieldNames.append - ( - objects.lookupClass(pointVectorField::typeName).sortedNames() - ); - pointFieldNames.append - ( - objects.lookupClass - ( - pointSphericalTensorField::typeName - ).sortedNames() - ); - pointFieldNames.append - ( - objects.lookupClass - ( - pointSymmTensorField::typeName - ).sortedNames() - ); - pointFieldNames.append - ( - objects.lookupClass(pointTensorField::typeName).sortedNames() - ); - // Make sure all processors have the same set - Pstream::scatter(pointFieldNames); - } + // Done reading if (Pstream::master() && decompose) { @@ -847,6 +744,12 @@ autoPtr<mapDistributePolyMesh> redistributeAndWrite } } + // Save pointMesh information before any topology changes occur! + if (nPointFields) + { + pointDistributor.saveMeshPoints(); + } + // Mesh distribution engine fvMeshDistribute distributor(mesh); @@ -859,34 +762,40 @@ autoPtr<mapDistributePolyMesh> redistributeAndWrite printMeshData(mesh); // Get other side of processor boundaries - correctCoupledBoundaryConditions - < - volScalarField, - processorFvPatch - >(mesh); - correctCoupledBoundaryConditions - < - volVectorField, - processorFvPatch - >(mesh); - correctCoupledBoundaryConditions - < - volSphericalTensorField, - processorFvPatch - >(mesh); - correctCoupledBoundaryConditions - < - volSymmTensorField, - processorFvPatch - >(mesh); - correctCoupledBoundaryConditions - < - volTensorField, - processorFvPatch - >(mesh); + do + { + #undef doCorrectCoupled + #define doCorrectCoupled(FieldType) \ + correctCoupledBoundaryConditions<processorFvPatch, FieldType>(mesh); + + doCorrectCoupled(volScalarField); + doCorrectCoupled(volVectorField); + doCorrectCoupled(volSphericalTensorField); + doCorrectCoupled(volSymmTensorField); + doCorrectCoupled(volTensorField); + #undef doCorrectCoupled + } + while (false); + // No update surface fields + // Map pointFields + if (nPointFields) + { + // Construct new pointMesh from distributed mesh + const pointMesh& newPointMesh = pointMesh::New(mesh); + + pointDistributor.resetTarget(newPointMesh, rawMap()); + + pointDistributor.distributeAndStore(pointScalarFields); + pointDistributor.distributeAndStore(pointVectorFields); + pointDistributor.distributeAndStore(pointSphTensorFields); + pointDistributor.distributeAndStore(pointSymmTensorFields); + pointDistributor.distributeAndStore(pointTensorFields); + } + + // Set the minimum write precision IOstream::defaultPrecision(max(10u, IOstream::defaultPrecision())); @@ -925,24 +834,9 @@ autoPtr<mapDistributePolyMesh> redistributeAndWrite << " to write reconstructed mesh and fields." << endl; runTime.caseName() = baseRunTime.caseName(); const bool oldProcCase(runTime.processorCase(false)); - const bool oldParRun = Pstream::parRun(false); mesh.write(); topoSet::removeFiles(mesh); - for (const word& fieldName : pointFieldNames) - { - IOobject io - ( - fieldName, - runTime.timeName(), - mesh - ); - - const fileName fieldFile(io.objectPath()); - if (topoSet::debug) DebugVar(fieldFile); - rm(fieldFile); - } - Pstream::parRun(oldParRun); // Now we've written all. Reset caseName on master Info<< "Restoring caseName to " << proc0CaseName << endl; @@ -965,19 +859,6 @@ autoPtr<mapDistributePolyMesh> redistributeAndWrite writeHandler = fileHandler(std::move(defaultHandler)); } topoSet::removeFiles(mesh); - for (const word& fieldName : pointFieldNames) - { - IOobject io - ( - fieldName, - runTime.timeName(), - mesh - ); - - const fileName fieldFile(io.objectPath()); - if (topoSet::debug) DebugVar(fieldFile); - rm(fieldFile); - } } Info<< "Written redistributed mesh to " << mesh.facesInstance() << nl << endl; @@ -1724,6 +1605,7 @@ int main(int argc, char *argv[]) #include "addOverwriteOption.H" argList::addBoolOption("decompose", "Decompose case"); argList::addBoolOption("reconstruct", "Reconstruct case"); + argList::addVerboseOption("Additional verbosity"); argList::addDryRunOption ( "Test without writing the decomposition. " @@ -1794,6 +1676,12 @@ int main(int argc, char *argv[]) const bool dryrun = args.dryRun(); const bool newTimes = args.found("newTimes"); + if (args.verbose()) + { + // Report on output + parPointFieldDistributor::verbose_ = 1; + } + bool decompose = args.found("decompose"); bool overwrite = args.found("overwrite"); @@ -2240,17 +2128,28 @@ int main(int argc, char *argv[]) distMap = fvMeshTools::readProcAddressing(mesh, baseMeshPtr); // Construct field mapper - autoPtr<parFvFieldReconstructor> fvReconstructorPtr - ( - new parFvFieldReconstructor + auto fvReconstructorPtr = + autoPtr<parFvFieldReconstructor>::New ( baseMeshPtr(), mesh, distMap(), Pstream::master() // do I need to write? - ) - ); + ); + // Construct point field mapper + const auto& basePointMesh = pointMesh::New(baseMeshPtr()); + const auto& procPointMesh = pointMesh::New(mesh); + + auto pointFieldDistributorPtr = + autoPtr<parPointFieldDistributor>::New + ( + procPointMesh, // source + basePointMesh, // target + distMap(), + false, // delay + UPstream::master() // Write reconstructed on master + ); // Since we start from Times[0] and not runTime.timeName() we @@ -2324,7 +2223,8 @@ int main(int argc, char *argv[]) distMap = fvMeshTools::readProcAddressing(mesh, baseMeshPtr); - // Reset field mapper + // Reset field mappers + fvReconstructorPtr.reset ( new parFvFieldReconstructor @@ -2335,6 +2235,23 @@ int main(int argc, char *argv[]) Pstream::master() ) ); + + // Construct point field mapper + const auto& basePointMesh = pointMesh::New(baseMeshPtr()); + const auto& procPointMesh = pointMesh::New(mesh); + + pointFieldDistributorPtr.reset + ( + new parPointFieldDistributor + ( + procPointMesh, // source + basePointMesh, // target + distMap(), + false, // delay until later + UPstream::master() // Write reconstruct on master + ) + ); + lagrangianReconstructorPtr.clear(); } @@ -2351,6 +2268,12 @@ int main(int argc, char *argv[]) selectedFields ); + // pointfields + // - distribute and write (verbose) + pointFieldDistributorPtr() + .distributeAllFields(objects, selectedFields); + + // Clouds (note: might not be present on all processors) reconstructLagrangian (