From baa8dccb0a3ade8a8a2e544924f58bdd001db7c4 Mon Sep 17 00:00:00 2001 From: mattijs Date: Mon, 10 Jun 2024 11:22:50 +0100 Subject: [PATCH] ENH: cellDecomposer: functionObject to map fields. Left out original files --- .../field/cellDecomposer/cellDecomposer.C | 415 ++++++++++++++++++ .../field/cellDecomposer/cellDecomposer.H | 226 ++++++++++ .../cellDecomposer/cellDecomposerTemplates.C | 364 +++++++++++++++ 3 files changed, 1005 insertions(+) create mode 100644 src/functionObjects/field/cellDecomposer/cellDecomposer.C create mode 100644 src/functionObjects/field/cellDecomposer/cellDecomposer.H create mode 100644 src/functionObjects/field/cellDecomposer/cellDecomposerTemplates.C diff --git a/src/functionObjects/field/cellDecomposer/cellDecomposer.C b/src/functionObjects/field/cellDecomposer/cellDecomposer.C new file mode 100644 index 0000000000..446c3d8881 --- /dev/null +++ b/src/functionObjects/field/cellDecomposer/cellDecomposer.C @@ -0,0 +1,415 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2024 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 . + +\*---------------------------------------------------------------------------*/ + +#include "cellDecomposer.H" +#include "addToRunTimeSelectionTable.H" +#include "polyTopoChange.H" +#include "mapPolyMesh.H" +#include "tetDecomposer.H" +#include "syncTools.H" +#include "dummyTransform.H" +#include "ReadFields.H" +#include "surfaceFields.H" +#include "PackedBoolList.H" +#include "fvMeshTools.H" +#include "cellSetOption.H" +#include "cellBitSet.H" +#include "cellSet.H" +#include "hexMatcher.H" +#include "prismMatcher.H" +#include "pyrMatcher.H" +#include "tetMatcher.H" + +#include "OBJstream.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace functionObjects +{ + defineTypeNameAndDebug(cellDecomposer, 0); + addToRunTimeSelectionTable(functionObject, cellDecomposer, dictionary); +} +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::functionObjects::cellDecomposer::makeMesh +( + const dictionary& dict, + const word& regionName +) +{ + Info<< name() << ':' << nl + << " Decomposing cells to region " << regionName << endl; + + Info<< incrIndent; + + const fv::cellSetOption::selectionModeType selectionMode + ( + fv::cellSetOption::selectionModeTypeNames_.get + ( + "selectionMode", + dict + ) + ); + + + // Start off from existing mesh + polyTopoChange meshMod(mesh_); + + tetDecompPtr_.reset(new Foam::tetDecomposer(mesh_)); + + // Default values + bitSet decomposeCell(mesh_.nCells()); + autoPtr decomposeFacePtr; + tetDecomposer::decompositionType decompType + ( + tetDecomposer::FACE_CENTRE_TRIS + ); + + + switch (selectionMode) + { + case fv::cellSetOption::smAll: + { + Info<< indent << "- selecting all cells" << endl; + + decomposeCell = true; + break; + } + case fv::cellSetOption::smGeometric: + { + Info<< indent << "- selecting cells geometrically" << endl; + + decomposeCell = + cellBitSet::select(mesh_, dict.subDict("selection"), true); + break; + } + case fv::cellSetOption::smCellSet: + { + const word selectionName(dict.get("cellSet")); + + Info<< indent + << "- selecting cells using cellSet " + << selectionName << endl; + + decomposeCell.set + ( + cellSet(mesh_, selectionName, IOobject::MUST_READ).toc() + ); + break; + } + case fv::cellSetOption::smCellZone: + { + wordRes selectionNames; + if + ( + !dict.readIfPresent("cellZones", selectionNames) + || selectionNames.empty() + ) + { + selectionNames.resize(1); + dict.readEntry("cellZone", selectionNames.first()); + } + + Info<< indent + << "- selecting cells using cellZones " + << flatOutput(selectionNames) << nl; + + const auto& zones = mesh_.cellZones(); + + // Also handles groups, multiple zones etc ... + labelList zoneIDs = zones.indices(selectionNames); + + if (zoneIDs.empty()) + { + FatalErrorInFunction + << "No matching cellZones: " + << flatOutput(selectionNames) << nl + << "Valid zones : " + << flatOutput(zones.names()) << nl + << "Valid groups: " + << flatOutput(zones.groupNames()) + << nl + << exit(FatalError); + } + + if (zoneIDs.size() == 1) + { + decomposeCell.set(zones[zoneIDs.first()]); + // TBD: Foam::sort(cells_); + } + else + { + decomposeCell.set(zones.selection(zoneIDs).sortedToc()); + } + break; + } + default: + { + FatalErrorInFunction + << "Unsupported selectionMode " + << fv::cellSetOption::selectionModeTypeNames_[selectionMode] + << ". Valid selectionMode types are " + << fv::cellSetOption::selectionModeTypeNames_ + << exit(FatalError); + } + } + + word decompTypeName; + if (dict.readIfPresent("decomposeType", decompTypeName)) + { + if (decompTypeName == "polyhedral") + { + // Automatic selection to generate hex/prism/tet only + // - subset decomposeCell to exclude hex/prism/tet + // - set faces to FACE_DIAG_QUADS + // Usually start with cellSetOption::smAll + decomposeFacePtr.reset(new bitSet(mesh_.nFaces())); + auto& decomposeFace = decomposeFacePtr(); + + decompType = tetDecomposer::FACE_DIAG_QUADS; + bitSet oldDecomposeCell(decomposeCell); + decomposeCell = false; + + // Construct shape recognizers + prismMatcher prism; + + for (const label celli : oldDecomposeCell) + { + if + ( + !hexMatcher::test(mesh_, celli) + && !tetMatcher::test(mesh_, celli) + && !pyrMatcher::test(mesh_, celli) + && !prism.isA(mesh_, celli) + ) + { + decomposeCell.set(celli); + decomposeFace.set(mesh_.cells()[celli]); + } + } + + // Sync boundary info + syncTools::syncFaceList + ( + mesh_, + decomposeFace, + orEqOp() + ); + } + else + { + decompType = tetDecomposer::decompositionTypeNames[decompTypeName]; + } + } + + + // Insert all changes to create tets + if (decomposeFacePtr) + { + if (debug) + { + OBJstream os(mesh_.time().path()/"orig_faces.obj"); + os.write + ( + UIndirectList + ( + mesh_.faces(), + decomposeFacePtr().sortedToc() + )(), + mesh_.points(), + false + ); + Pout<< "Written " << meshMod.faces().size() + << " faces to " << os.name() << endl; + } + + tetDecompPtr_().setRefinement + ( + decompType, //Foam::tetDecomposer::FACE_CENTRE_TRIS, + decomposeCell, + decomposeFacePtr(), + meshMod + ); + } + else + { + tetDecompPtr_().setRefinement + ( + decompType, //Foam::tetDecomposer::FACE_CENTRE_TRIS, + decomposeCell, + meshMod + ); + } + + + if (debug) + { + OBJstream os(mesh_.time().path()/"faces.obj"); + os.write(meshMod.faces(), pointField(meshMod.points()), false); + Pout<< "Written " << meshMod.faces().size() + << " faces to " << os.name() << endl; + } + + + autoPtr tetMeshPtr; + + mapPtr_ = meshMod.makeMesh + ( + tetMeshPtr, + IOobject + ( + regionName, + mesh_.facesInstance(), // same instance as original mesh + mesh_.time(), //? why same database? TBD. + IOobject::READ_IF_PRESENT, // Read fv* if present + IOobject::AUTO_WRITE, + IOobject::REGISTER + ), + mesh_ + ); + + + //- Update numbering on tet-decomposition engine + tetDecompPtr_().updateMesh(mapPtr_()); + + Info<< indent << "Writing decomposed mesh to " + << tetMeshPtr().objectRegistry::objectRelPath() + << endl; + tetMeshPtr().write(); + + fvMeshTools::createDummyFvMeshFiles(mesh_.time(), regionName, true); + + // Store new mesh on object registry + tetMeshPtr.ptr()->polyMesh::store(); + + Info<< decrIndent; +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::functionObjects::cellDecomposer::cellDecomposer +( + const word& name, + const Time& runTime, + const dictionary& dict +) +: + fvMeshFunctionObject(name, runTime, dict) +{ + read(dict); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::functionObjects::cellDecomposer::read(const dictionary& dict) +{ + if (fvMeshFunctionObject::read(dict)) + { + // Generate new tet equivalent mesh. TBD: why meshObject? + //meshObjects::tetDecomposition::New(mesh, dict); + + dict_ = dict.optionalSubDict(typeName + "Coeffs"); + dict_.readEntry("mapRegion", mapRegion_); + dict_.readEntry("fields", fieldNames_); + makeMesh(dict_, mapRegion_); + } + + return true; +} + + +bool Foam::functionObjects::cellDecomposer::execute() +{ + Log << type() << " " << name() << " execute:" << nl; + + bool ok = false; + + if (mesh_.changing()) + { + // Re-do mesh. Currently rebuilds whole mesh. Could move points only + // for mesh motion. + tetDecompPtr_.clear(); + mapPtr_.clear(); + const_cast(this->mesh_.time()).erase(mapRegion_); + makeMesh(dict_, mapRegion_); + } + + + // Look up + ok = mapFieldType() || ok; + ok = mapFieldType() || ok; + ok = mapFieldType() || ok; + ok = mapFieldType() || ok; + ok = mapFieldType() || ok; + + if (log) + { + if (!ok) + { + Info<< " none" << nl; + } + + Info<< endl; + } + return true; +} + + +bool Foam::functionObjects::cellDecomposer::write() +{ + Log << type() << " " << name() << " write:" << nl; + + bool ok = false; + + ok = writeFieldType() || ok; + ok = writeFieldType() || ok; + ok = writeFieldType() || ok; + ok = writeFieldType() || ok; + ok = writeFieldType() || ok; + + if (log) + { + if (!ok) + { + Info<< " none" << nl; + } + + Info<< endl; + } + + return true; +} + + +// ************************************************************************* // diff --git a/src/functionObjects/field/cellDecomposer/cellDecomposer.H b/src/functionObjects/field/cellDecomposer/cellDecomposer.H new file mode 100644 index 0000000000..0e3363bfc0 --- /dev/null +++ b/src/functionObjects/field/cellDecomposer/cellDecomposer.H @@ -0,0 +1,226 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2024 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 . + +Class + Foam::functionObjects::cellDecomposer + +Group + grpFieldFunctionObjects + +Description + Maps input fields from local mesh to a secondary mesh at runtime. + + The secondary mesh gets created on-the-fly by decomposing the current mesh. + + + Operands: + \table + Operand | Type | Location + input | {vol,surface}\Field | $FOAM_CASE/\/\ + output file | - | - + output field | {vol,surface}\Field | $FOAM_CASE/\/\ + \endtable + + where \c \=Scalar/Vector/SphericalTensor/SymmTensor/Tensor. + +Usage + Minimal example by using \c system/controlDict.functions: + \verbatim + cellDecomposer1 + { + // Mandatory entries (unmodifiable) + type cellDecomposer; + libs (fieldFunctionObjects); + + // Mandatory (inherited) entries (runtime modifiable) + fields ( ... ); + mapRegion myTetMesh; + ... + // Mandatory entries + // Decompose type: + decomposeType polyhedral; + // Cell set to decompose + selectionMode all; + } + \endverbatim + + where the entries mean: + \table + Property | Description | Type | Req'd | Dflt + type | Type name: cellDecomposer | word | yes | - + libs | Library name: fieldFunctionObjects | word | yes | - + fields | Names of operand fields | wordList | yes | - + mapRegion | Name of region to map to | word | yes | - + decomposeType | How to decompose cells | word | yes | - + selectionMode | How to select cells (see fvOption)| word | yes | - + \endtable + + decomposeType: + - faceCentre : decompose cells into tets using face centre and cell centre. + (hex becomes 6*4 tets) + - faceDiagonal : decompose cells into tets using face diagonal, similar + to implicit decomposition inside lagrangian tracking. + (hex becomes 6*2 tets) + - pyramid : keep faces intact but create (polygonal-base) pyramids using + cell centre (hex becomes 6 pyramids) + - faceDiagonalQuads : like faceDiagonal but split faces into quads and + triangles instead of just triangles + - polyhedral : like faceDiagonalQuads but only decompose non-hex/prism/tet + cells in selected set. Used to convert polyhedral mesh into + 'simple' mesh. + + The inherited entries are elaborated in: + - \link functionObject.H \endlink + +See also + - Foam::functionObjects::mapFields + +SourceFiles + cellDecomposer.C + +\*---------------------------------------------------------------------------*/ + +#ifndef functionObjects_cellDecomposer_H +#define functionObjects_cellDecomposer_H + +#include "fvMeshFunctionObject.H" +#include "volFieldsFwd.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +class tetDecomposer; +class mapPolyMesh; + +namespace functionObjects +{ + +/*---------------------------------------------------------------------------*\ + Class cellDecomposer Declaration +\*---------------------------------------------------------------------------*/ + +class cellDecomposer +: + public fvMeshFunctionObject +{ + // Private Data + + //- Parameter dictionary + dictionary dict_; + + //- Name of new mesh + word mapRegion_; + + //- List of field names to interpolate + wordRes fieldNames_; + + //- Tet decomposer + autoPtr tetDecompPtr_; + + //- Map from polyMesh to tet-mesh + autoPtr mapPtr_; + + + // Private Member Functions + + //- Generate mesh + void makeMesh(const dictionary& dict, const word& name); + + //- Helper function to map the \ fields + template + bool mapFieldType() const; + + //- Helper function to write the \ fields + template + bool writeFieldType() const; + + template + tmp> + interpolate + ( + const GeometricField& vf, + const fvMesh& sMesh, + const labelUList& patchMap, + const labelUList& cellMap, + const labelUList& faceMap, + const bool allowUnmapped + ) const; + + +public: + + + //- Runtime type information + TypeName("cellDecomposer"); + + + // Constructors + + //- Construct from Time and dictionary + cellDecomposer + ( + const word& name, + const Time& runTime, + const dictionary& dict + ); + + + //- Destructor + virtual ~cellDecomposer() = default; + + + // Member Functions + + //- Read the cellDecomposer data + virtual bool read(const dictionary& dict); + + //- Execute + virtual bool execute(); + + //- Write + virtual bool write(); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace functionObjects +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository + #include "cellDecomposerTemplates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/functionObjects/field/cellDecomposer/cellDecomposerTemplates.C b/src/functionObjects/field/cellDecomposer/cellDecomposerTemplates.C new file mode 100644 index 0000000000..e982aeff5b --- /dev/null +++ b/src/functionObjects/field/cellDecomposer/cellDecomposerTemplates.C @@ -0,0 +1,364 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2024 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 . + +\*---------------------------------------------------------------------------*/ + +#include "fvMesh.H" +#include "emptyFvPatchFields.H" +#include "directFvPatchFieldMapper.H" +#include "mapPolyMesh.H" +//#include "polyPatch.H" +//#include "lduSchedule.H" +//#include "meshToMesh.H" + +//template +//void Foam::functionObjects::cellDecomposer::evaluateConstraintTypes +//( +// GeometricField& fld +//) const +//{ +// auto& fldBf = fld.boundaryFieldRef(); +// +// const UPstream::commsTypes commsType = UPstream::defaultCommsType; +// const label startOfRequests = UPstream::nRequests(); +// +// if +// ( +// commsType == UPstream::commsTypes::blocking +// || commsType == UPstream::commsTypes::nonBlocking +// ) +// { +// forAll(fldBf, patchi) +// { +// fvPatchField& tgtField = fldBf[patchi]; +// +// if +// ( +// tgtField.type() == tgtField.patch().patch().type() +// && polyPatch::constraintType(tgtField.patch().patch().type()) +// ) +// { +// tgtField.initEvaluate(commsType); +// } +// } +// +// // Wait for outstanding requests +// if (commsType == UPstream::commsTypes::nonBlocking) +// { +// UPstream::waitRequests(startOfRequests); +// } +// +// forAll(fldBf, patchi) +// { +// fvPatchField& tgtField = fldBf[patchi]; +// +// if +// ( +// tgtField.type() == tgtField.patch().patch().type() +// && polyPatch::constraintType(tgtField.patch().patch().type()) +// ) +// { +// tgtField.evaluate(commsType); +// } +// } +// } +// else if (commsType == UPstream::commsTypes::scheduled) +// { +// const lduSchedule& patchSchedule = +// fld.mesh().globalData().patchSchedule(); +// +// for (const auto& schedEval : patchSchedule) +// { +// const label patchi = schedEval.patch; +// +// fvPatchField& tgtField = fldBf[patchi]; +// +// if +// ( +// tgtField.type() == tgtField.patch().patch().type() +// && polyPatch::constraintType(tgtField.patch().patch().type()) +// ) +// { +// if (schedEval.init) +// { +// tgtField.initEvaluate(commsType); +// } +// else +// { +// tgtField.evaluate(commsType); +// } +// } +// } +// } +//} + +template +Foam::tmp +< + Foam::GeometricField +> +Foam::functionObjects::cellDecomposer::interpolate +( + const GeometricField& vf, + const fvMesh& sMesh, + const labelUList& patchMap, + const labelUList& cellMap, + const labelUList& faceMap, + const bool allowUnmapped +) const +{ + // 1. Create the complete field with dummy patch fields + PtrList> patchFields(patchMap.size()); + + forAll(patchFields, patchi) + { + // Set the first one by hand as it corresponds to the + // exposed internal faces. Additional interpolation can be put here + // as necessary. + if (patchMap[patchi] == -1) + { + patchFields.set + ( + patchi, + new emptyFvPatchField + ( + sMesh.boundary()[patchi], + fvPatchField::Internal::null() + ) + ); + } + else + { + patchFields.set + ( + patchi, + fvPatchField::New + ( + fvPatchFieldBase::calculatedType(), + sMesh.boundary()[patchi], + fvPatchField::Internal::null() + ) + ); + } + } + + auto tresult = tmp>::New + ( + IOobject + ( + "subset"+vf.name(), + sMesh.time().timeName(), + sMesh, + IOobject::NO_READ, + IOobject::NO_WRITE + ), + sMesh, + vf.dimensions(), + Field(vf.primitiveField(), cellMap), + patchFields + ); + auto& result = tresult.ref(); + result.oriented() = vf.oriented(); + + + // 2. Change the fvPatchFields to the correct type using a mapper + // constructor (with reference to the now correct internal field) + + auto& bf = result.boundaryFieldRef(); + + forAll(bf, patchi) + { + const label basePatchId = patchMap[patchi]; + + if (basePatchId != -1) + { + // Construct addressing + const fvPatch& subPatch = sMesh.boundary()[patchi]; + const fvPatch& basePatch = vf.mesh().boundary()[basePatchId]; + const label baseStart = basePatch.start(); + const label baseSize = basePatch.size(); + + labelList directAddressing(subPatch.size()); + + forAll(directAddressing, i) + { + const label baseFacei = faceMap[subPatch.start()+i]; + + if (baseFacei >= baseStart && baseFacei < baseStart+baseSize) + { + directAddressing[i] = baseFacei-baseStart; + } + else + { + // Mapped from internal face. Do what? Leave up to + // fvPatchField + directAddressing[i] = -1; + } + } + + + directFvPatchFieldMapper mapper(directAddressing); + + // allowUnmapped : special mode for if we do not want to be + // warned for unmapped faces (e.g. from fvMeshDistribute). + + const bool hasUnmapped = mapper.hasUnmapped(); + if (allowUnmapped) + { + mapper.hasUnmapped() = false; + } + + bf.set + ( + patchi, + fvPatchField::New + ( + vf.boundaryField()[basePatchId], + subPatch, + result.internalField(), + mapper + ) + ); + + if (allowUnmapped && hasUnmapped) + { + // Set unmapped values to zeroGradient. This is the default + // action for unmapped fvPatchFields. Note that this bypasses + // any special logic for handling unmapped fvPatchFields but + // since this is only used inside fvMeshDistribute ... + + tmp> tfld(bf[patchi].patchInternalField()); + const Field& fld = tfld(); + + Field value(bf[patchi]); + forAll(directAddressing, i) + { + if (directAddressing[i] == -1) + { + value[i] = fld[i]; + } + } + bf[patchi].fvPatchField::operator=(value); + } + } + } + + return tresult; +} + + +template +bool Foam::functionObjects::cellDecomposer::mapFieldType() const +{ + typedef GeometricField VolFieldType; + + const fvMesh& mapRegion = + this->mesh_.time().lookupObject(mapRegion_); + + const labelList patchMap(identity(mapRegion.boundaryMesh().size())); + + const wordList fieldNames + ( + this->mesh_.sortedNames(fieldNames_) + ); + + const bool processed = !fieldNames.empty(); + + for (const word& fieldName : fieldNames) + { + const VolFieldType& field = lookupObject(fieldName); + + auto* mapFieldPtr = mapRegion.getObjectPtr(fieldName); + + if (!mapFieldPtr) + { + mapFieldPtr = new VolFieldType + ( + IOobject + ( + fieldName, + time_.timeName(), + mapRegion, + IOobject::NO_READ, + IOobject::NO_WRITE, + IOobject::REGISTER + ), + mapRegion, + dimensioned(field.dimensions(), Zero) + ); + + mapFieldPtr->store(); + } + + auto& mappedField = *mapFieldPtr; + + mappedField = interpolate + ( + field, + mapRegion, + patchMap, + mapPtr_().cellMap(), + mapPtr_().faceMap(), + false //allowUnmapped + ); + Log << " " << fieldName << ": interpolated"; + + //evaluateConstraintTypes(mappedField); + } + + return processed; +} + + +template +bool Foam::functionObjects::cellDecomposer::writeFieldType() const +{ + typedef GeometricField VolFieldType; + + const fvMesh& mapRegion = + this->mesh_.time().lookupObject(mapRegion_); + + const wordList fieldNames + ( + this->mesh_.sortedNames(fieldNames_) + ); + + const bool processed = !fieldNames.empty(); + + for (const word& fieldName : fieldNames) + { + const VolFieldType& mappedField = + mapRegion.template lookupObject(fieldName); + + mappedField.write(); + + Log << " " << fieldName << ": written"; + } + + return processed; +} + + +// ************************************************************************* //