mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
Merge branch 'feature-map-constraint' into 'develop'
ENH: Moving electric sources mapped from external meshes See merge request Development/openfoam!630
This commit is contained in:
@ -217,6 +217,7 @@ Foam::functionObjects::electricPotential::electricPotential
|
||||
IOobject::scopedName(typeName, "E")
|
||||
)
|
||||
),
|
||||
fvOptions_(mesh_),
|
||||
nCorr_(1),
|
||||
writeDerivedFields_(false),
|
||||
electricField_(false)
|
||||
@ -341,7 +342,12 @@ bool Foam::functionObjects::electricPotential::read(const dictionary& dict)
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
if (const dictionary* dictptr = dict.findDict("fvOptions"))
|
||||
{
|
||||
fvOptions_.reset(*dictptr);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -363,6 +369,8 @@ bool Foam::functionObjects::electricPotential::execute()
|
||||
|
||||
eVEqn.relax();
|
||||
|
||||
fvOptions_.constrain(eVEqn);
|
||||
|
||||
eVEqn.solve();
|
||||
}
|
||||
|
||||
|
||||
@ -123,6 +123,7 @@ Usage
|
||||
V <word>;
|
||||
electricField <bool>;
|
||||
E <word>;
|
||||
fvOptions <dict>;
|
||||
|
||||
// Inherited entries
|
||||
...
|
||||
@ -141,10 +142,12 @@ Usage
|
||||
V | Name of electric potential field | word | no | electricPotential:V
|
||||
electricField | Flag to calculate electric field | bool | no | false
|
||||
E | Name of electric field | word | no | electricPotential:E
|
||||
fvOptions | List of finite-volume options | dict | no | -
|
||||
\endtable
|
||||
|
||||
The inherited entries are elaborated in:
|
||||
- \link functionObject.H \endlink
|
||||
- \link fvOption.H \endlink
|
||||
|
||||
Fields written out when the \c writeDerivedFields entry is \c true:
|
||||
\table
|
||||
@ -153,6 +156,9 @@ Usage
|
||||
Charge density | volScalarField | \<time\>/electricPotential:rho
|
||||
\endtable
|
||||
|
||||
Note
|
||||
- Only constraint-type finite-volume options can be used.
|
||||
|
||||
SourceFiles
|
||||
electricPotential.C
|
||||
|
||||
@ -163,6 +169,7 @@ SourceFiles
|
||||
|
||||
#include "fvMeshFunctionObject.H"
|
||||
#include "volFields.H"
|
||||
#include "fvOptionList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -208,6 +215,9 @@ class electricPotential
|
||||
//- Name of electric field
|
||||
word Ename_;
|
||||
|
||||
//- Run-time selectable finite volume options
|
||||
fv::optionList fvOptions_;
|
||||
|
||||
//- Number of corrector iterations
|
||||
int nCorr_;
|
||||
|
||||
|
||||
@ -56,6 +56,7 @@ $(interRegion)/interRegionExplicitPorositySource/interRegionExplicitPorositySour
|
||||
/* Constraints */
|
||||
generalConstraints=constraints/general
|
||||
$(generalConstraints)/fixedValueConstraint/fixedValueConstraints.C
|
||||
$(generalConstraints)/mapFieldConstraint/mapFieldConstraints.C
|
||||
|
||||
derivedConstraints=constraints/derived
|
||||
$(derivedConstraints)/fixedTemperatureConstraint/fixedTemperatureConstraint.C
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2017-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2023 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -52,6 +52,7 @@ Foam::fv::cellSetOption::selectionModeTypeNames_
|
||||
{ selectionModeType::smAll, "all" },
|
||||
{ selectionModeType::smGeometric, "geometric" },
|
||||
{ selectionModeType::smPoints, "points" },
|
||||
{ selectionModeType::smMovingPoints, "movingPoints" },
|
||||
{ selectionModeType::smCellSet, "cellSet" },
|
||||
{ selectionModeType::smCellZone, "cellZone" },
|
||||
{ selectionModeType::smCellType, "cellType" }
|
||||
@ -80,6 +81,31 @@ void Foam::fv::cellSetOption::setSelection(const dictionary& dict)
|
||||
dict.readEntry("points", points_);
|
||||
break;
|
||||
}
|
||||
case smMovingPoints:
|
||||
{
|
||||
const dictionary& mpsDict = dict.subDict("movingPoints");
|
||||
|
||||
movingPoints_.resize_null(mpsDict.size());
|
||||
|
||||
label pointi = 0;
|
||||
for (const entry& dEntry : mpsDict)
|
||||
{
|
||||
const word& key = dEntry.keyword();
|
||||
|
||||
movingPoints_.set
|
||||
(
|
||||
pointi,
|
||||
Function1<point>::New
|
||||
(
|
||||
key,
|
||||
mpsDict,
|
||||
&mesh_
|
||||
)
|
||||
);
|
||||
++pointi;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case smCellSet:
|
||||
{
|
||||
selectionNames_.resize(1);
|
||||
@ -196,6 +222,50 @@ void Foam::fv::cellSetOption::setCellSelection()
|
||||
cells_ = selectedCells.sortedToc();
|
||||
break;
|
||||
}
|
||||
case smMovingPoints:
|
||||
{
|
||||
Info<< indent << "- selecting cells using moving points" << endl;
|
||||
|
||||
const scalar t = mesh_.time().timeOutputValue();
|
||||
|
||||
labelHashSet selectedCells;
|
||||
|
||||
forAll(movingPoints_, i)
|
||||
{
|
||||
if (!movingPoints_.set(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const point p(movingPoints_[i].value(t));
|
||||
|
||||
const label celli = mesh_.findCell(p);
|
||||
|
||||
const bool found = (celli >= 0);
|
||||
|
||||
// Ensure that only one processor inserts this cell
|
||||
label proci = -1;
|
||||
if (found)
|
||||
{
|
||||
proci = Pstream::myProcNo();
|
||||
}
|
||||
reduce(proci, maxOp<label>());
|
||||
|
||||
if (found && (proci == Pstream::myProcNo()))
|
||||
{
|
||||
selectedCells.insert(celli);
|
||||
}
|
||||
|
||||
if (!returnReduceOr(found))
|
||||
{
|
||||
WarningInFunction
|
||||
<< "No owner cell found for point " << p << endl;
|
||||
}
|
||||
}
|
||||
|
||||
cells_ = selectedCells.sortedToc();
|
||||
break;
|
||||
}
|
||||
case smCellSet:
|
||||
{
|
||||
Info<< indent
|
||||
@ -266,7 +336,11 @@ void Foam::fv::cellSetOption::setCellSelection()
|
||||
}
|
||||
}
|
||||
|
||||
if (smAll != selectionMode_ && returnReduceAnd(cells_.empty()))
|
||||
if
|
||||
(
|
||||
!(smAll == selectionMode_ || smMovingPoints == selectionMode_)
|
||||
&& returnReduceAnd(cells_.empty())
|
||||
)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "No cells selected!" << endl;
|
||||
@ -285,11 +359,13 @@ Foam::fv::cellSetOption::cellSetOption
|
||||
)
|
||||
:
|
||||
fv::option(name, modelType, dict, mesh),
|
||||
selectionMode_(selectionModeTypeNames_.get("selectionMode", coeffs_)),
|
||||
updateSelection_(false),
|
||||
timeStart_(-1),
|
||||
duration_(0),
|
||||
selectionMode_(selectionModeTypeNames_.get("selectionMode", coeffs_)),
|
||||
selectionNames_(),
|
||||
points_(),
|
||||
movingPoints_(),
|
||||
geometricSelection_(),
|
||||
V_(0)
|
||||
{
|
||||
@ -322,6 +398,7 @@ bool Foam::fv::cellSetOption::isActive()
|
||||
selectionMode_ == smGeometric
|
||||
|| selectionMode_ == smPoints
|
||||
|| selectionMode_ == smCellType
|
||||
|| selectionMode_ == smMovingPoints
|
||||
)
|
||||
{
|
||||
// Geometric selection mode(s)
|
||||
@ -331,6 +408,12 @@ bool Foam::fv::cellSetOption::isActive()
|
||||
// Report new volume (if changed)
|
||||
setVol();
|
||||
}
|
||||
else if (selectionMode_ == smMovingPoints)
|
||||
{
|
||||
// Update the cell selection if it moves
|
||||
setCellSelection();
|
||||
setVol();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -341,19 +424,29 @@ bool Foam::fv::cellSetOption::isActive()
|
||||
|
||||
bool Foam::fv::cellSetOption::read(const dictionary& dict)
|
||||
{
|
||||
if (fv::option::read(dict))
|
||||
if (!fv::option::read(dict))
|
||||
{
|
||||
timeStart_ = -1;
|
||||
|
||||
if (coeffs_.readIfPresent("timeStart", timeStart_))
|
||||
{
|
||||
coeffs_.readEntry("duration", duration_);
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
timeStart_ = -1;
|
||||
|
||||
if (coeffs_.readIfPresent("timeStart", timeStart_))
|
||||
{
|
||||
coeffs_.readEntry("duration", duration_);
|
||||
}
|
||||
|
||||
// Do not read and set selections unless users request
|
||||
updateSelection_ = coeffs_.getOrDefault("updateSelection", false);
|
||||
|
||||
if (updateSelection_)
|
||||
{
|
||||
setSelection(coeffs_);
|
||||
setCellSelection();
|
||||
setVol();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2017-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2023 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -34,36 +34,46 @@ Description
|
||||
Usage
|
||||
Minimal example by using \c constant/fvOptions:
|
||||
\verbatim
|
||||
<userDefinedName1>
|
||||
fvOption1
|
||||
{
|
||||
// Mandatory/Optional (inherited) entries
|
||||
...
|
||||
// Mandatory entries
|
||||
selectionMode <word>;
|
||||
|
||||
// Mandatory entries (unmodifiable)
|
||||
selectionMode all;
|
||||
// Optional entries
|
||||
timeStart <scalar>;
|
||||
updateSelection <bool>;
|
||||
|
||||
// Optional entries (runtime modifiable)
|
||||
timeStart 1.0;
|
||||
|
||||
// Conditional mandatory entries (runtime modifiable)
|
||||
// Conditional entries
|
||||
|
||||
// when timeStart entry is present
|
||||
duration 1.4;
|
||||
duration <scalar>;
|
||||
|
||||
// when selectionMode=cellSet
|
||||
cellSet <name>;
|
||||
cellSet <word>;
|
||||
|
||||
// when selectionMode=cellZone
|
||||
cellZone <name>;
|
||||
cellZone <word>;
|
||||
|
||||
//OR: cellZones (<name> ...);
|
||||
//OR: cellZones (<word> ...);
|
||||
|
||||
// when selectionMode=points
|
||||
points (<point1> <point2> ... <pointN>);
|
||||
|
||||
// when selectionMode=movingPoints
|
||||
movingPoints
|
||||
(
|
||||
<word> <Function1<vector>>;
|
||||
// e.g.
|
||||
point1 <Function1<vector>>;
|
||||
pointN <Function1<vector>>;
|
||||
...
|
||||
);
|
||||
|
||||
// when selectionMode=geometric
|
||||
selection
|
||||
{
|
||||
topoSet1 <dictionary>;
|
||||
|
||||
box1
|
||||
{
|
||||
action use;
|
||||
@ -81,24 +91,27 @@ Usage
|
||||
...
|
||||
}
|
||||
|
||||
// Mandatory/Optional (derived) entries
|
||||
// Inherited entries
|
||||
...
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
where the entries mean:
|
||||
\table
|
||||
Property | Description | Type | Reqd | Dflt
|
||||
Property | Description | Type | Reqd | Deflt
|
||||
selectionMode | Mode of cell selection - see below | word | yes | -
|
||||
timeStart | Start time of fvOption | scalar | no | -1
|
||||
timeStart | Start time of fvOption | scalar | no | -1
|
||||
updateSelection | Flag to enable selection updates | bool | no | false
|
||||
duration | Duration of fvOption execution <!--
|
||||
--> starting from timeStart | scalar | cndtnl | 0
|
||||
cellSet | Name of operand cellSet | word | cndtnl | -
|
||||
cellZone | Name of operand cellZone | wordRe | cndtnl | -
|
||||
cellZones | Name of operand cellZones | wordRes | cndtnl | -
|
||||
--> starting from timeStart | scalar | choice | 0
|
||||
cellSet | Name of operand cellSet | word | choice | -
|
||||
cellZone | Name of operand cellZone | wordRe | choice | -
|
||||
cellZones | Name of operand cellZones | wordRes | choice | -
|
||||
points | Set of points in global coordinate <!--
|
||||
--> system | vectorList | cndtnl | -
|
||||
selection | Dictionary of geometric selections | dict | cndtnl | -
|
||||
--> system | vectorList | choice | -
|
||||
movingPoints | Set of moving points in global coordinate system <!--
|
||||
--> | Function1\<vector\> | choice | -
|
||||
selection | Dictionary of geometric selections | dict | choice | -
|
||||
\endtable
|
||||
|
||||
Options for the \c selectionMode entry:
|
||||
@ -107,18 +120,19 @@ Usage
|
||||
cellZone | Use specified cellZone
|
||||
cellSet | Use specified cellSet
|
||||
points | Use cells containing a given set of points
|
||||
movingPoints | Use cells containing a given set of moving points
|
||||
geometric | Select cells based on topoSetCellSource actions
|
||||
\endverbatim
|
||||
|
||||
The inherited entries are elaborated in:
|
||||
- \link fvOption.H \endlink
|
||||
|
||||
The geometric selection uses topoSetCellSource to select cells.
|
||||
Any searchableSurface selections must describe a closed volume.
|
||||
Ie, its hasVolumeType() method must be true.
|
||||
- \link Function1.H \endlink
|
||||
|
||||
Note
|
||||
- Source/sink options are to be added to the right-hand side of equations.
|
||||
- The geometric selection uses \c topoSetCellSource to select cells.
|
||||
Any \c searchableSurface selections must describe a closed volume.
|
||||
Ie, its \c hasVolumeType() method must be \c true.
|
||||
|
||||
See also
|
||||
Foam::cellBitSet::select
|
||||
@ -135,6 +149,7 @@ SourceFiles
|
||||
#include "fvMesh.H"
|
||||
#include "dictionary.H"
|
||||
#include "Time.H"
|
||||
#include "Function1.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -156,12 +171,13 @@ public:
|
||||
// Public Data
|
||||
|
||||
//- Enumeration for selection mode types
|
||||
enum selectionModeType
|
||||
enum selectionModeType : char
|
||||
{
|
||||
smAll, //!< "all" cells
|
||||
smCellSet, //!< "cellSet"
|
||||
smCellZone, //!< "cellZone"
|
||||
smPoints, //!< "points"
|
||||
smMovingPoints, //!< "movingPoints"
|
||||
smGeometric, //!< "geometric"
|
||||
smCellType //!< "overset type cells"
|
||||
};
|
||||
@ -174,21 +190,27 @@ protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- Cell selection mode
|
||||
selectionModeType selectionMode_;
|
||||
|
||||
//- Flag to enable dictionary-based updates of selections
|
||||
bool updateSelection_;
|
||||
|
||||
//- Start time of fvOption
|
||||
scalar timeStart_;
|
||||
|
||||
//- Duration of fvOption execution starting from timeStart
|
||||
scalar duration_;
|
||||
|
||||
//- Cell selection mode
|
||||
selectionModeType selectionMode_;
|
||||
|
||||
//- Face selection names (for set or zone selections)
|
||||
wordRes selectionNames_;
|
||||
|
||||
//- List of points for "points" selectionMode
|
||||
List<point> points_;
|
||||
|
||||
//- List of points for "movingPoints" selectionMode
|
||||
PtrList<Function1<point>> movingPoints_;
|
||||
|
||||
//- Dictionary entries for "geometric" (topoSetCellSource) selection
|
||||
dictionary geometricSelection_;
|
||||
|
||||
@ -265,6 +287,12 @@ public:
|
||||
//- Return const access to the cell selection
|
||||
inline const labelList& cells() const noexcept;
|
||||
|
||||
//- Return flag for selection updates
|
||||
bool isSelectionUpdated() const noexcept
|
||||
{
|
||||
return updateSelection_;
|
||||
}
|
||||
|
||||
|
||||
// Edit
|
||||
|
||||
|
||||
@ -0,0 +1,459 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023 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 "MapFieldConstraint.H"
|
||||
#include "fvMatrices.H"
|
||||
#include "meshToMesh.H"
|
||||
#include "Function1.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace fv
|
||||
{
|
||||
static inline tmp<volScalarField> createField
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const scalar val
|
||||
)
|
||||
{
|
||||
return tmp<volScalarField>::New
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
polyMesh::defaultRegion,
|
||||
mesh.time().timeName(),
|
||||
mesh,
|
||||
IOobjectOption::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
IOobject::NO_REGISTER
|
||||
),
|
||||
mesh,
|
||||
dimensionedScalar(dimless, val)
|
||||
);
|
||||
}
|
||||
} // End namespace fv
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
void Foam::fv::MapFieldConstraint<Type>::setSourceMesh
|
||||
(
|
||||
refPtr<fvMesh>& meshRef,
|
||||
const autoPtr<Time>& runTimePtr
|
||||
)
|
||||
{
|
||||
const Time& runTime = runTimePtr();
|
||||
const word meshName(polyMesh::defaultRegion);
|
||||
|
||||
// Fetch mesh from Time database
|
||||
meshRef.cref
|
||||
(
|
||||
runTime.cfindObject<fvMesh>(meshName)
|
||||
);
|
||||
|
||||
if (!meshRef)
|
||||
{
|
||||
// Fallback: load mesh from disk and cache it
|
||||
meshRef.reset
|
||||
(
|
||||
new fvMesh
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
meshName,
|
||||
runTime.timeName(),
|
||||
runTime,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE,
|
||||
IOobject::REGISTER
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::fv::MapFieldConstraint<Type>::createInterpolation
|
||||
(
|
||||
const fvMesh& srcMesh,
|
||||
const fvMesh& tgtMesh
|
||||
)
|
||||
{
|
||||
if (consistent_)
|
||||
{
|
||||
interpPtr_.reset
|
||||
(
|
||||
new meshToMesh
|
||||
(
|
||||
srcMesh,
|
||||
tgtMesh,
|
||||
mapMethodName_,
|
||||
patchMapMethodName_
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
interpPtr_.reset
|
||||
(
|
||||
new meshToMesh
|
||||
(
|
||||
srcMesh,
|
||||
tgtMesh,
|
||||
mapMethodName_,
|
||||
patchMapMethodName_,
|
||||
patchMap_,
|
||||
cuttingPatches_
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
template<class VolFieldType>
|
||||
VolFieldType& Foam::fv::MapFieldConstraint<Type>::getOrReadField
|
||||
(
|
||||
const fvMesh& thisMesh,
|
||||
const word& fieldName
|
||||
) const
|
||||
{
|
||||
auto* ptr = thisMesh.getObjectPtr<VolFieldType>(fieldName);
|
||||
|
||||
if (!ptr)
|
||||
{
|
||||
ptr = new VolFieldType
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
fieldName,
|
||||
thisMesh.time().timeName(),
|
||||
thisMesh,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE,
|
||||
IOobject::REGISTER
|
||||
),
|
||||
thisMesh
|
||||
);
|
||||
thisMesh.objectRegistry::store(ptr);
|
||||
}
|
||||
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::labelList Foam::fv::MapFieldConstraint<Type>::tgtCellIDs() const
|
||||
{
|
||||
const fvMesh& srcMesh = srcMeshPtr_();
|
||||
const fvMesh& tgtMesh = mesh_;
|
||||
|
||||
// Create mask fields
|
||||
const volScalarField srcFld(createField(srcMesh, 1));
|
||||
volScalarField tgtFld(createField(tgtMesh, 0));
|
||||
|
||||
// Map the mask field of 1s onto the mask field of 0s
|
||||
interpPtr_->mapSrcToTgt(srcFld, plusEqOp<scalar>(), tgtFld);
|
||||
|
||||
// Identify and collect cell indices whose values were changed from 0 to 1
|
||||
DynamicList<label> cells;
|
||||
forAll(tgtFld, i)
|
||||
{
|
||||
if (tgtFld[i] != 0)
|
||||
{
|
||||
cells.append(i);
|
||||
}
|
||||
}
|
||||
|
||||
return cells;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::fv::MapFieldConstraint<Type>::transform::transform()
|
||||
:
|
||||
positionPtr_(),
|
||||
directionPtr_(),
|
||||
points_(),
|
||||
origin_(),
|
||||
normal_(),
|
||||
active_(false)
|
||||
{}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::fv::MapFieldConstraint<Type>::MapFieldConstraint
|
||||
(
|
||||
const word& name,
|
||||
const word& modelType,
|
||||
const dictionary& dict,
|
||||
const fvMesh& mesh
|
||||
)
|
||||
:
|
||||
fv::option(name, modelType, dict, mesh),
|
||||
transform_(),
|
||||
srcTimePtr_(),
|
||||
srcMeshPtr_(),
|
||||
interpPtr_(),
|
||||
patchMap_(),
|
||||
cells_(),
|
||||
cuttingPatches_(),
|
||||
mapMethodName_(),
|
||||
patchMapMethodName_(),
|
||||
consistent_(false)
|
||||
{
|
||||
read(dict);
|
||||
|
||||
setSourceMesh(srcMeshPtr_, srcTimePtr_);
|
||||
|
||||
const fvMesh& srcMesh = srcMeshPtr_();
|
||||
const fvMesh& tgtMesh = mesh_;
|
||||
createInterpolation(srcMesh, tgtMesh);
|
||||
|
||||
cells_ = tgtCellIDs();
|
||||
|
||||
if (returnReduceAnd(cells_.empty()))
|
||||
{
|
||||
WarningInFunction
|
||||
<< "No cells selected!" << endl;
|
||||
}
|
||||
|
||||
transform_.initialize(srcMesh, dict);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
bool Foam::fv::MapFieldConstraint<Type>::transform::initialize
|
||||
(
|
||||
const fvMesh& srcMesh,
|
||||
const dictionary& dict
|
||||
)
|
||||
{
|
||||
const dictionary* subDictPtr = dict.findDict("transform");
|
||||
|
||||
if (!subDictPtr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
positionPtr_.reset
|
||||
(
|
||||
Function1<point>::NewIfPresent
|
||||
(
|
||||
"position",
|
||||
*subDictPtr,
|
||||
word::null,
|
||||
&srcMesh
|
||||
)
|
||||
);
|
||||
|
||||
directionPtr_.reset
|
||||
(
|
||||
Function1<point>::NewIfPresent
|
||||
(
|
||||
"direction",
|
||||
*subDictPtr,
|
||||
word::null,
|
||||
&srcMesh
|
||||
)
|
||||
);
|
||||
|
||||
if (positionPtr_)
|
||||
{
|
||||
subDictPtr->readIfPresent("origin", origin_);
|
||||
}
|
||||
|
||||
if (directionPtr_)
|
||||
{
|
||||
subDictPtr->readIfPresent("normal", normal_);
|
||||
normal_.normalise();
|
||||
}
|
||||
|
||||
points_ = srcMesh.points();
|
||||
|
||||
active_ = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::fv::MapFieldConstraint<Type>::transform::translate
|
||||
(
|
||||
refPtr<fvMesh>& srcMeshPtr,
|
||||
const scalar t
|
||||
)
|
||||
{
|
||||
if (!positionPtr_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const pointField translate
|
||||
(
|
||||
points_ + (positionPtr_->value(t) - origin_)
|
||||
);
|
||||
|
||||
fvMesh& srcMesh = srcMeshPtr.ref();
|
||||
srcMesh.movePoints(translate);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::fv::MapFieldConstraint<Type>::transform::rotate
|
||||
(
|
||||
refPtr<fvMesh>& srcMeshPtr,
|
||||
const scalar t
|
||||
)
|
||||
{
|
||||
if (!directionPtr_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const vector dir(normalised(directionPtr_->value(t)));
|
||||
|
||||
const tensor rot(rotationTensor(normal_, dir));
|
||||
|
||||
pointField rotate(points_);
|
||||
|
||||
Foam::transform(rotate, rot, rotate);
|
||||
|
||||
fvMesh& srcMesh = srcMeshPtr.ref();
|
||||
srcMesh.movePoints(rotate);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
bool Foam::fv::MapFieldConstraint<Type>::read(const dictionary& dict)
|
||||
{
|
||||
if (!fv::option::read(dict))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
fieldNames_.resize(1, coeffs_.getWord("field"));
|
||||
|
||||
fv::option::resetApplied();
|
||||
|
||||
// Load the time database for the source mesh once per simulation
|
||||
if (!srcTimePtr_)
|
||||
{
|
||||
fileName srcMesh(coeffs_.get<fileName>("srcMesh").expand());
|
||||
srcMesh.clean();
|
||||
|
||||
srcTimePtr_.reset(Time::New(srcMesh));
|
||||
|
||||
// Set time-step of source database to an arbitrary yet safe value
|
||||
srcTimePtr_().setDeltaT(1.0);
|
||||
}
|
||||
|
||||
coeffs_.readEntry("mapMethod", mapMethodName_);
|
||||
if (!meshToMesh::interpolationMethodNames_.found(mapMethodName_))
|
||||
{
|
||||
FatalIOErrorInFunction(coeffs_)
|
||||
<< type() << " " << name() << ": unknown map method "
|
||||
<< mapMethodName_ << nl
|
||||
<< "Available methods include: "
|
||||
<< meshToMesh::interpolationMethodNames_
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
coeffs_.readIfPresent("consistent", consistent_);
|
||||
coeffs_.readIfPresent("patchMap", patchMap_);
|
||||
coeffs_.readIfPresent("cuttingPatches", cuttingPatches_);
|
||||
|
||||
if (!coeffs_.readIfPresent("patchMapMethod", patchMapMethodName_))
|
||||
{
|
||||
meshToMesh::interpolationMethod mapMethod
|
||||
(
|
||||
meshToMesh::interpolationMethodNames_[mapMethodName_]
|
||||
);
|
||||
patchMapMethodName_ = meshToMesh::interpolationMethodAMI(mapMethod);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::fv::MapFieldConstraint<Type>::constrain
|
||||
(
|
||||
fvMatrix<Type>& eqn,
|
||||
const label
|
||||
)
|
||||
{
|
||||
DebugInfo
|
||||
<< "MapFieldConstraint<"
|
||||
<< pTraits<Type>::typeName
|
||||
<< ">::constrain for source " << name_ << endl;
|
||||
|
||||
// Translate and/or rotate source mesh if requested
|
||||
if (transform_.isActive())
|
||||
{
|
||||
// Use time from mesh_ since source mesh does not advance in time
|
||||
const scalar t = mesh_.time().timeOutputValue();
|
||||
transform_.translate(srcMeshPtr_, t);
|
||||
transform_.rotate(srcMeshPtr_, t);
|
||||
}
|
||||
|
||||
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
|
||||
|
||||
const word& fldName = fieldNames_[0];
|
||||
|
||||
const fvMesh& srcMesh = srcMeshPtr_();
|
||||
const fvMesh& tgtMesh = mesh_;
|
||||
|
||||
// Fetch source and target fields
|
||||
const VolFieldType& srcFld = getOrReadField<VolFieldType>(srcMesh, fldName);
|
||||
VolFieldType& tgtFld = tgtMesh.lookupObjectRef<VolFieldType>(fldName);
|
||||
|
||||
// When mesh/src changes, reinitilize mesh-to-mesh members
|
||||
if (tgtMesh.changing() || transform_.isActive())
|
||||
{
|
||||
createInterpolation(srcMesh, tgtMesh);
|
||||
cells_ = tgtCellIDs();
|
||||
}
|
||||
|
||||
// Map source-mesh field onto target-mesh field
|
||||
interpPtr_->mapSrcToTgt(srcFld, plusEqOp<Type>(), tgtFld);
|
||||
|
||||
// Constrain mapped field in target mesh to avoid overwrite by solver
|
||||
eqn.setValues(cells_, UIndirectList<Type>(tgtFld, cells_));
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,315 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023 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::fv::MapFieldConstraint
|
||||
|
||||
Group
|
||||
grpFvOptionsConstraints
|
||||
|
||||
Description
|
||||
The \c MapFieldConstraint constrains values of given fields of \c Type
|
||||
with a source field from an external mesh, where
|
||||
\c \<Type\>={scalar,vector,sphericalTensor,symmTensor,tensor}.
|
||||
Optionally, the source field can be translated and/or rotated as a function
|
||||
of time.
|
||||
|
||||
Usage
|
||||
Minimal example by using \c constant/fvOptions:
|
||||
\verbatim
|
||||
\<Type\>MapFieldConstraint1
|
||||
{
|
||||
// Mandatory entries
|
||||
type \<Type\>MapFieldConstraint;
|
||||
field <word>;
|
||||
srcMesh <fileName>;
|
||||
mapMethod <word>;
|
||||
|
||||
// Optional entries
|
||||
consistent <bool>;
|
||||
patchMapMethod <word>;
|
||||
transform
|
||||
{
|
||||
// Optional entries
|
||||
position <Function1<vector>>;
|
||||
origin <vector>;
|
||||
|
||||
direction <Function1<vector>>;
|
||||
normal <vector>;
|
||||
}
|
||||
|
||||
// Conditional entries
|
||||
|
||||
// when consistent=false
|
||||
patchMap <HashTable<word>>; // (<patchSrc> <patchTgt>);
|
||||
cuttingPatches <wordList>; // (<patchTgt1> ... <patchTgtN>);
|
||||
|
||||
// Inherited entries
|
||||
...
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
where the entries mean:
|
||||
\table
|
||||
Property | Description | Type | Reqd | Deflt
|
||||
type | Type name: \<Type\>MapFieldConstraint | word | yes | -
|
||||
field | Name of operand field | word | yes | -
|
||||
srcMesh | Directory path to mesh to map from | fileName | yes | -
|
||||
mapMethod | Mapping method | word | yes | -
|
||||
consistent | Flag to determine if meshes have consistent boundaries <!--
|
||||
--> | bool | no | false
|
||||
patchMapMethod | Name of patch-map method | word | no | -
|
||||
patchMap | Coincident source/target patches in two cases <!--
|
||||
--> | wordHashTable | no | -
|
||||
cuttingPatches | Target patches cutting the source domain <!--
|
||||
--> | wordList | no | -
|
||||
transform | Transform settings for source mesh points <!--
|
||||
--> | dict | no | -
|
||||
position | Position of source mesh as a function of time <!--
|
||||
--> | Function1\<vector\> | no | -
|
||||
direction | Direction of source mesh as a function of time <!--
|
||||
--> | Function1\<vector\> | no | -
|
||||
origin | Origin of source mesh | vector | no | -
|
||||
normal | Normal of reference plane representing source mesh <!--
|
||||
--> | vector | no | -
|
||||
\endtable
|
||||
|
||||
The inherited entries are elaborated in:
|
||||
- \link fvOption.H \endlink
|
||||
- \link Function1.H \endlink
|
||||
|
||||
SourceFiles
|
||||
MapFieldConstraint.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_fv_MapFieldConstraint_H
|
||||
#define Foam_fv_MapFieldConstraint_H
|
||||
|
||||
#include "fvOption.H"
|
||||
#include "fvMesh.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward Declarations
|
||||
class meshToMesh;
|
||||
template<class Type> class Function1;
|
||||
|
||||
namespace fv
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class MapFieldConstraint Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Type>
|
||||
class MapFieldConstraint
|
||||
:
|
||||
public fv::option
|
||||
{
|
||||
// Private Classes
|
||||
|
||||
class transform
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- Position of source mesh as a function of time
|
||||
autoPtr<Function1<point>> positionPtr_;
|
||||
|
||||
//- Direction of source mesh as a function of time
|
||||
autoPtr<Function1<point>> directionPtr_;
|
||||
|
||||
//- Cached points of source mesh
|
||||
pointField points_;
|
||||
|
||||
//- Origin of source mesh
|
||||
point origin_;
|
||||
|
||||
//- Normal of reference plane representing source mesh
|
||||
vector normal_;
|
||||
|
||||
//- Flag to deduce if transformation is active
|
||||
bool active_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
transform();
|
||||
|
||||
//- No copy construct
|
||||
transform(const transform&) = delete;
|
||||
|
||||
//- No copy assignment
|
||||
void operator=(const transform&) = delete;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
//- Return flag to deduce if transformation is active
|
||||
bool isActive() const noexcept { return active_; }
|
||||
|
||||
|
||||
// Evaluation
|
||||
|
||||
//- Translate source mesh as a function of time
|
||||
void translate(refPtr<fvMesh>& srcMeshPtr, const scalar time);
|
||||
|
||||
//- Rotate source mesh as a function of time
|
||||
void rotate(refPtr<fvMesh>& srcMeshPtr, const scalar time);
|
||||
|
||||
|
||||
// I-O
|
||||
|
||||
//- Initialize the class members
|
||||
bool initialize(const fvMesh& srcMesh, const dictionary& dict);
|
||||
};
|
||||
|
||||
|
||||
// Private Data
|
||||
|
||||
//- Transformation settings for source mesh
|
||||
transform transform_;
|
||||
|
||||
//- Time database for source mesh to map from
|
||||
autoPtr<Time> srcTimePtr_;
|
||||
|
||||
//- Source mesh to map from
|
||||
refPtr<fvMesh> srcMeshPtr_;
|
||||
|
||||
//- Mesh-to-mesh interpolation from source mesh to target mesh
|
||||
autoPtr<meshToMesh> interpPtr_;
|
||||
|
||||
//- List of coincident source/target patches in two cases
|
||||
HashTable<word> patchMap_;
|
||||
|
||||
//- Set of cells to apply source to
|
||||
labelList cells_;
|
||||
|
||||
//- List of names of target patches cutting the source domain
|
||||
wordList cuttingPatches_;
|
||||
|
||||
//- Name of map method
|
||||
word mapMethodName_;
|
||||
|
||||
//- Name of patch-map method
|
||||
word patchMapMethodName_;
|
||||
|
||||
//- Flag to determine if meshes have consistent boundaries
|
||||
bool consistent_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Helper function to set source mesh
|
||||
// Fetch fvMesh from a given Time database
|
||||
// Otherwise, load it from disk and cache it to the database
|
||||
void setSourceMesh
|
||||
(
|
||||
refPtr<fvMesh>& meshRef,
|
||||
const autoPtr<Time>& runTimePtr
|
||||
);
|
||||
|
||||
//- Helper function to create the mesh-to-mesh interpolation
|
||||
void createInterpolation
|
||||
(
|
||||
const fvMesh& srcMesh,
|
||||
const fvMesh& tgtMesh
|
||||
);
|
||||
|
||||
//- Return requested field from object registry
|
||||
//- otherwise read it from disk and register it to the object registry
|
||||
template<class VolFieldType>
|
||||
VolFieldType& getOrReadField
|
||||
(
|
||||
const fvMesh& thisMesh,
|
||||
const word& fieldName
|
||||
) const;
|
||||
|
||||
//- Return the local cell indices of the target mesh
|
||||
labelList tgtCellIDs() const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("MapFieldConstraint");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
MapFieldConstraint
|
||||
(
|
||||
const word& name,
|
||||
const word& modelType,
|
||||
const dictionary& dict,
|
||||
const fvMesh& mesh
|
||||
);
|
||||
|
||||
//- No copy construct
|
||||
MapFieldConstraint(const MapFieldConstraint&) = delete;
|
||||
|
||||
//- No copy assignment
|
||||
void operator=(const MapFieldConstraint&) = delete;
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~MapFieldConstraint() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Read source dictionary
|
||||
virtual bool read(const dictionary& dict);
|
||||
|
||||
//- Set value on field
|
||||
virtual void constrain(fvMatrix<Type>& eqn, const label);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace fv
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "MapFieldConstraint.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,39 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023 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 "makeFvOption.H"
|
||||
#include "MapFieldConstraint.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
makeFvOption(MapFieldConstraint, scalar);
|
||||
makeFvOption(MapFieldConstraint, vector);
|
||||
makeFvOption(MapFieldConstraint, sphericalTensor);
|
||||
makeFvOption(MapFieldConstraint, symmTensor);
|
||||
makeFvOption(MapFieldConstraint, tensor);
|
||||
|
||||
// ************************************************************************* //
|
||||
Reference in New Issue
Block a user