Cell-to-cell interpolation has been moved to a hierarchy separate from meshToMesh, called cellsToCells. The meshToMesh class is now a combination of a cellsToCells object and multiple patchToPatch objects. This means that when only cell-to-cell interpolation is needed a basic cellsToCells object can be selected. Cell-to-cell and vol-field-to-vol-field interpolation now has two well defined sets of functions, with a clear distinction in how weights that do not sum to unity are handled. Non-unity weights are either normalised, or a left-over field is provided with which to complete the weighted sum. The left-over approach is now consistently applied in mapFieldsPar, across both the internal and patch fields, if mapping onto an existing field in the target case. Warning are now generated for invalid combinations of settings, such as mapping between inconsistent meshes without a pre-existing target field. All mapping functions now take fields as const references and return tmp fields. This avoids the pattern in which non-const fields are provided which relate to the source, and at some point in the function transfer to the target. This pattern is difficult to reason about and does not provide any actual computational advantage, as the fields invariably get re-allocated as part of the process anyway. MeshToMesh no longer stores the cutting patches. The set of cutting patches is not needed anywhere except at the point of mapping a field, so it is now supplied to the mapping functions as an argument. The meshToMesh topology changer no longer supports cutting patch information. This did not previously work. Cutting patches either get generated as calculated, or they require a pre-existing field to specify their boundary condition. Neither of these options is suitable for a run-time mesh change. More code has been shared with patchToPatch, reducing duplication.
281 lines
6.8 KiB
C++
281 lines
6.8 KiB
C++
/*---------------------------------------------------------------------------*\
|
|
========= |
|
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
\\ / O peration | Website: https://openfoam.org
|
|
\\ / A nd | Copyright (C) 2011-2023 OpenFOAM Foundation
|
|
\\/ M anipulation |
|
|
-------------------------------------------------------------------------------
|
|
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/>.
|
|
|
|
Application
|
|
mapFieldsPar
|
|
|
|
Description
|
|
Maps volume fields from one mesh to another, reading and
|
|
interpolating all fields present in the time directory of both cases.
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
|
|
#include "argList.H"
|
|
#include "fvMeshToFvMesh.H"
|
|
#include "mapGeometricFields.H"
|
|
#include "mapClouds.H"
|
|
#include "intersectionCellsToCells.H"
|
|
|
|
using namespace Foam;
|
|
|
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
|
|
void mapConsistentMesh
|
|
(
|
|
const fvMesh& srcMesh,
|
|
const fvMesh& tgtMesh,
|
|
const word& mapMethod,
|
|
const HashSet<word>& selectedFields,
|
|
const bool noLagrangian
|
|
)
|
|
{
|
|
Info<< nl << "Consistently creating and mapping fields for time "
|
|
<< srcMesh.time().name() << nl << endl;
|
|
|
|
fvMeshToFvMesh interp(srcMesh, tgtMesh, mapMethod);
|
|
|
|
Info<< nl << "Mapping geometric fields" << endl;
|
|
|
|
mapGeometricFields(interp, wordReList(), selectedFields, noLagrangian);
|
|
|
|
if (!noLagrangian)
|
|
{
|
|
mapClouds(interp);
|
|
}
|
|
}
|
|
|
|
|
|
void mapMesh
|
|
(
|
|
const fvMesh& srcMesh,
|
|
const fvMesh& tgtMesh,
|
|
const HashTable<word>& patchMap,
|
|
const wordReList& cuttingPatches,
|
|
const word& mapMethod,
|
|
const HashSet<word>& selectedFields,
|
|
const bool noLagrangian
|
|
)
|
|
{
|
|
Info<< nl << "Creating and mapping fields for time "
|
|
<< srcMesh.time().name() << nl << endl;
|
|
|
|
fvMeshToFvMesh interp(srcMesh, tgtMesh, mapMethod, patchMap);
|
|
|
|
Info<< nl << "Mapping geometric fields" << endl;
|
|
|
|
mapGeometricFields(interp, cuttingPatches, selectedFields, noLagrangian);
|
|
|
|
if (!noLagrangian)
|
|
{
|
|
mapClouds(interp);
|
|
}
|
|
}
|
|
|
|
|
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
argList::addNote
|
|
(
|
|
"map volume fields from one mesh to another"
|
|
);
|
|
|
|
argList::validArgs.append("sourceCase");
|
|
|
|
argList::addOption
|
|
(
|
|
"sourceTime",
|
|
"scalar|'latestTime'",
|
|
"specify the source time"
|
|
);
|
|
argList::addOption
|
|
(
|
|
"sourceRegion",
|
|
"word",
|
|
"specify the source region"
|
|
);
|
|
argList::addOption
|
|
(
|
|
"targetRegion",
|
|
"word",
|
|
"specify the target region"
|
|
);
|
|
argList::addBoolOption
|
|
(
|
|
"consistent",
|
|
"source and target geometry and boundary conditions identical"
|
|
);
|
|
argList::addOption
|
|
(
|
|
"mapMethod",
|
|
"word",
|
|
"specify the mapping method"
|
|
);
|
|
argList::addOption
|
|
(
|
|
"fields",
|
|
"list",
|
|
"specify a list of fields to be mapped. Eg, '(U T p)' - "
|
|
"regular expressions not currently supported"
|
|
);
|
|
argList::addBoolOption
|
|
(
|
|
"noLagrangian",
|
|
"skip mapping lagrangian positions and fields"
|
|
);
|
|
|
|
#include "setRootCase.H"
|
|
|
|
fileName rootDirTarget(args.rootPath());
|
|
fileName caseDirTarget(args.globalCaseName());
|
|
|
|
const fileName casePath = args[1];
|
|
const fileName rootDirSource = casePath.path();
|
|
const fileName caseDirSource = casePath.name();
|
|
|
|
Info<< "Source: " << rootDirSource << " " << caseDirSource << endl;
|
|
word sourceRegion = fvMesh::defaultRegion;
|
|
if (args.optionFound("sourceRegion"))
|
|
{
|
|
sourceRegion = args["sourceRegion"];
|
|
Info<< "Source region: " << sourceRegion << endl;
|
|
}
|
|
|
|
Info<< "Target: " << rootDirTarget << " " << caseDirTarget << endl;
|
|
word targetRegion = fvMesh::defaultRegion;
|
|
if (args.optionFound("targetRegion"))
|
|
{
|
|
targetRegion = args["targetRegion"];
|
|
Info<< "Target region: " << targetRegion << endl;
|
|
}
|
|
|
|
const bool consistent = args.optionFound("consistent");
|
|
|
|
const word mapMethod
|
|
(
|
|
args.optionLookupOrDefault<word>
|
|
(
|
|
"mapMethod",
|
|
cellsToCellss::intersection::typeName
|
|
)
|
|
);
|
|
Info<< "Mapping method: " << mapMethod << endl;
|
|
|
|
HashSet<word> selectedFields;
|
|
if (args.optionFound("fields"))
|
|
{
|
|
args.optionLookup("fields")() >> selectedFields;
|
|
}
|
|
|
|
const bool noLagrangian = args.optionFound("noLagrangian");
|
|
|
|
#include "createTimes.H"
|
|
|
|
HashTable<word> patchMap;
|
|
wordReList cuttingPatches;
|
|
|
|
if (!consistent)
|
|
{
|
|
IOdictionary mapFieldsDict
|
|
(
|
|
IOobject
|
|
(
|
|
"mapFieldsDict",
|
|
runTimeTarget.system(),
|
|
runTimeTarget,
|
|
IOobject::MUST_READ_IF_MODIFIED,
|
|
IOobject::NO_WRITE,
|
|
false
|
|
)
|
|
);
|
|
|
|
mapFieldsDict.lookup("patchMap") >> patchMap;
|
|
mapFieldsDict.lookup("cuttingPatches") >> cuttingPatches;
|
|
}
|
|
|
|
#include "setTimeIndex.H"
|
|
|
|
Info<< "\nCreate meshes\n" << endl;
|
|
|
|
fvMesh srcMesh
|
|
(
|
|
IOobject
|
|
(
|
|
sourceRegion,
|
|
runTimeSource.name(),
|
|
runTimeSource
|
|
),
|
|
false
|
|
);
|
|
|
|
fvMesh tgtMesh
|
|
(
|
|
IOobject
|
|
(
|
|
targetRegion,
|
|
runTimeTarget.name(),
|
|
runTimeTarget
|
|
),
|
|
false
|
|
);
|
|
|
|
Info<< "Source mesh size: "
|
|
<< returnReduce(srcMesh.nCells(), sumOp<label>())
|
|
<< ", Target mesh size: "
|
|
<< returnReduce(tgtMesh.nCells(), sumOp<label>())
|
|
<< endl;
|
|
|
|
if (consistent)
|
|
{
|
|
mapConsistentMesh
|
|
(
|
|
srcMesh,
|
|
tgtMesh,
|
|
mapMethod,
|
|
selectedFields,
|
|
noLagrangian
|
|
);
|
|
}
|
|
else
|
|
{
|
|
mapMesh
|
|
(
|
|
srcMesh,
|
|
tgtMesh,
|
|
patchMap,
|
|
cuttingPatches,
|
|
mapMethod,
|
|
selectedFields,
|
|
noLagrangian
|
|
);
|
|
}
|
|
|
|
Info<< "\nEnd\n" << endl;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
// ************************************************************************* //
|