ENH: cellDecomposer: functionObject to map fields.
Left out original files
This commit is contained in:
parent
5059e1ddec
commit
baa8dccb0a
415
src/functionObjects/field/cellDecomposer/cellDecomposer.C
Normal file
415
src/functionObjects/field/cellDecomposer/cellDecomposer.C
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#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<bitSet> 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<word>("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<unsigned int>()
|
||||
);
|
||||
}
|
||||
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<face>
|
||||
(
|
||||
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<fvMesh> 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<Time&>(this->mesh_.time()).erase(mapRegion_);
|
||||
makeMesh(dict_, mapRegion_);
|
||||
}
|
||||
|
||||
|
||||
// Look up
|
||||
ok = mapFieldType<scalar>() || ok;
|
||||
ok = mapFieldType<vector>() || ok;
|
||||
ok = mapFieldType<sphericalTensor>() || ok;
|
||||
ok = mapFieldType<symmTensor>() || ok;
|
||||
ok = mapFieldType<tensor>() || 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<scalar>() || ok;
|
||||
ok = writeFieldType<vector>() || ok;
|
||||
ok = writeFieldType<sphericalTensor>() || ok;
|
||||
ok = writeFieldType<symmTensor>() || ok;
|
||||
ok = writeFieldType<tensor>() || ok;
|
||||
|
||||
if (log)
|
||||
{
|
||||
if (!ok)
|
||||
{
|
||||
Info<< " none" << nl;
|
||||
}
|
||||
|
||||
Info<< endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
226
src/functionObjects/field/cellDecomposer/cellDecomposer.H
Normal file
226
src/functionObjects/field/cellDecomposer/cellDecomposer.H
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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}\<Type\>Field <!--
|
||||
--> | $FOAM_CASE/\<time\>/\<inpField\>
|
||||
output file | - | -
|
||||
output field | {vol,surface}\<Type\>Field <!--
|
||||
--> | $FOAM_CASE/\<time\>/\<outField\>
|
||||
\endtable
|
||||
|
||||
where \c \<Type\>=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 (<field1> <field2> ... <fieldN>);
|
||||
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<tetDecomposer> tetDecompPtr_;
|
||||
|
||||
//- Map from polyMesh to tet-mesh
|
||||
autoPtr<mapPolyMesh> mapPtr_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Generate mesh
|
||||
void makeMesh(const dictionary& dict, const word& name);
|
||||
|
||||
//- Helper function to map the \<Type\> fields
|
||||
template<class Type>
|
||||
bool mapFieldType() const;
|
||||
|
||||
//- Helper function to write the \<Type\> fields
|
||||
template<class Type>
|
||||
bool writeFieldType() const;
|
||||
|
||||
template<class Type>
|
||||
tmp<GeometricField<Type, fvPatchField, volMesh>>
|
||||
interpolate
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& 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
|
||||
|
||||
// ************************************************************************* //
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "fvMesh.H"
|
||||
#include "emptyFvPatchFields.H"
|
||||
#include "directFvPatchFieldMapper.H"
|
||||
#include "mapPolyMesh.H"
|
||||
//#include "polyPatch.H"
|
||||
//#include "lduSchedule.H"
|
||||
//#include "meshToMesh.H"
|
||||
|
||||
//template<class Type>
|
||||
//void Foam::functionObjects::cellDecomposer::evaluateConstraintTypes
|
||||
//(
|
||||
// GeometricField<Type, fvPatchField, volMesh>& 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<Type>& 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<Type>& 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<Type>& 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<class Type>
|
||||
Foam::tmp
|
||||
<
|
||||
Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh>
|
||||
>
|
||||
Foam::functionObjects::cellDecomposer::interpolate
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& 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<fvPatchField<Type>> 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<Type>
|
||||
(
|
||||
sMesh.boundary()[patchi],
|
||||
fvPatchField<Type>::Internal::null()
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
patchFields.set
|
||||
(
|
||||
patchi,
|
||||
fvPatchField<Type>::New
|
||||
(
|
||||
fvPatchFieldBase::calculatedType(),
|
||||
sMesh.boundary()[patchi],
|
||||
fvPatchField<Type>::Internal::null()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
auto tresult = tmp<GeometricField<Type, fvPatchField, volMesh>>::New
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"subset"+vf.name(),
|
||||
sMesh.time().timeName(),
|
||||
sMesh,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
sMesh,
|
||||
vf.dimensions(),
|
||||
Field<Type>(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<Type>::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<Field<Type>> tfld(bf[patchi].patchInternalField());
|
||||
const Field<Type>& fld = tfld();
|
||||
|
||||
Field<Type> value(bf[patchi]);
|
||||
forAll(directAddressing, i)
|
||||
{
|
||||
if (directAddressing[i] == -1)
|
||||
{
|
||||
value[i] = fld[i];
|
||||
}
|
||||
}
|
||||
bf[patchi].fvPatchField<Type>::operator=(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tresult;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
bool Foam::functionObjects::cellDecomposer::mapFieldType() const
|
||||
{
|
||||
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
|
||||
|
||||
const fvMesh& mapRegion =
|
||||
this->mesh_.time().lookupObject<fvMesh>(mapRegion_);
|
||||
|
||||
const labelList patchMap(identity(mapRegion.boundaryMesh().size()));
|
||||
|
||||
const wordList fieldNames
|
||||
(
|
||||
this->mesh_.sortedNames<VolFieldType>(fieldNames_)
|
||||
);
|
||||
|
||||
const bool processed = !fieldNames.empty();
|
||||
|
||||
for (const word& fieldName : fieldNames)
|
||||
{
|
||||
const VolFieldType& field = lookupObject<VolFieldType>(fieldName);
|
||||
|
||||
auto* mapFieldPtr = mapRegion.getObjectPtr<VolFieldType>(fieldName);
|
||||
|
||||
if (!mapFieldPtr)
|
||||
{
|
||||
mapFieldPtr = new VolFieldType
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
fieldName,
|
||||
time_.timeName(),
|
||||
mapRegion,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
IOobject::REGISTER
|
||||
),
|
||||
mapRegion,
|
||||
dimensioned<Type>(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<class Type>
|
||||
bool Foam::functionObjects::cellDecomposer::writeFieldType() const
|
||||
{
|
||||
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
|
||||
|
||||
const fvMesh& mapRegion =
|
||||
this->mesh_.time().lookupObject<fvMesh>(mapRegion_);
|
||||
|
||||
const wordList fieldNames
|
||||
(
|
||||
this->mesh_.sortedNames<VolFieldType>(fieldNames_)
|
||||
);
|
||||
|
||||
const bool processed = !fieldNames.empty();
|
||||
|
||||
for (const word& fieldName : fieldNames)
|
||||
{
|
||||
const VolFieldType& mappedField =
|
||||
mapRegion.template lookupObject<VolFieldType>(fieldName);
|
||||
|
||||
mappedField.write();
|
||||
|
||||
Log << " " << fieldName << ": written";
|
||||
}
|
||||
|
||||
return processed;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
Loading…
Reference in New Issue
Block a user