ENH: DMD: add multi-patch input functionality

This commit is contained in:
Kutalmis Bercin
2022-02-28 13:50:05 +00:00
committed by Andrew Heather
parent d2e2533546
commit f12399c39b
6 changed files with 101 additions and 62 deletions

View File

@ -91,22 +91,21 @@ void Foam::functionObjects::DMD::initialise()
{ {
const label nComps = nComponents(fieldName_); const label nComps = nComponents(fieldName_);
if (patch_.empty()) if (patches_.empty())
{ {
nSnap_ = nComps*mesh_.nCells(); nSnap_ = nComps*mesh_.nCells();
} }
else else
{ {
const label patchi = mesh_.boundaryMesh().findPatchID(patch_); const labelList patchis
(
mesh_.boundaryMesh().patchSet(patches_).sortedToc()
);
if (patchi < 0) for (const label patchi : patchis)
{ {
FatalErrorInFunction nSnap_ += nComps*(mesh_.C().boundaryField()[patchi]).size();
<< "Cannot find patch " << patch_
<< exit(FatalError);
} }
nSnap_ = nComps*(mesh_.C().boundaryField()[patchi]).size();
} }
const label nSnapTotal = returnReduce(nSnap_, sumOp<label>()); const label nSnapTotal = returnReduce(nSnap_, sumOp<label>());
@ -141,8 +140,15 @@ Foam::functionObjects::DMD::DMD
fvMeshFunctionObject(name, runTime, dict), fvMeshFunctionObject(name, runTime, dict),
DMDModelPtr_(DMDModel::New(mesh_, name, dict)), DMDModelPtr_(DMDModel::New(mesh_, name, dict)),
z_(), z_(),
patches_
(
dict.getOrDefault<wordRes>
(
"patches",
dict.found("patch") ? wordRes(1,dict.get<word>("patch")) : wordRes()
)
),
fieldName_(dict.get<word>("field")), fieldName_(dict.get<word>("field")),
patch_(dict.getOrDefault<word>("patch", word::null)),
nSnap_(0), nSnap_(0),
step_(0) step_(0)
{ {

View File

@ -87,16 +87,21 @@ Usage
\verbatim \verbatim
DMD1 DMD1
{ {
// Mandatory entries (unmodifiable) // Mandatory entries
type DMD; type DMD;
libs (fieldFunctionObjects); libs (fieldFunctionObjects);
DMDModel <DMDModel>; DMDModel <DMDModel>;
field <inputField>; field <word>;
// Optional entries (unmodifiable) // Optional entries
patch <patchName>;
// Mandatory/Optional (inherited) entries // Option-1
patch <word>;
// Option-2
patches (<wordRes>);
// Inherited entries
... ...
} }
\endverbatim \endverbatim
@ -109,6 +114,7 @@ Usage
DMDModel | Name of specified DMD model | word | yes | - DMDModel | Name of specified DMD model | word | yes | -
field | Name of operand field | word | yes | - field | Name of operand field | word | yes | -
patch | Name of operand patch | word | no | null patch | Name of operand patch | word | no | null
patches | Names of operand patches | wordRes | no | null
\endtable \endtable
Options for the \c DMDModel entry: Options for the \c DMDModel entry:
@ -181,12 +187,12 @@ class DMD
// time step, an augmented snapshot is constructed of two snapshots // time step, an augmented snapshot is constructed of two snapshots
RMatrix z_; RMatrix z_;
//- Names of operand patches
const wordRes patches_;
//- Name of operand field //- Name of operand field
const word fieldName_; const word fieldName_;
//- Name of operand patch
const word patch_;
//- Number of elements in a snapshot //- Number of elements in a snapshot
label nSnap_; label nSnap_;

View File

@ -834,8 +834,15 @@ Foam::DMDModels::STDMD::STDMD
amps_(Zero), amps_(Zero),
mags_(Zero), mags_(Zero),
magsi_(Zero), magsi_(Zero),
patches_
(
dict.getOrDefault<wordRes>
(
"patches",
dict.found("patch") ? wordRes(1,dict.get<word>("patch")) : wordRes()
)
),
fieldName_(dict.get<word>("field")), fieldName_(dict.get<word>("field")),
patch_(dict.getOrDefault<word>("patch", word::null)),
timeName0_(), timeName0_(),
minBasis_(0), minBasis_(0),
minEval_(0), minEval_(0),

View File

@ -275,12 +275,12 @@ class STDMD
//- Indices of 'mags' //- Indices of 'mags'
List<label> magsi_; List<label> magsi_;
//- Names of operand patches
const wordRes patches_;
//- Name of operand field //- Name of operand field
const word fieldName_; const word fieldName_;
//- Name of operand patch
const word patch_;
//- First-processed snapshot required by the mode-sorting //- First-processed snapshot required by the mode-sorting
//- algorithms at the final output computations (K:p. 43) //- algorithms at the final output computations (K:p. 43)
word timeName0_; word timeName0_;
@ -411,7 +411,8 @@ class STDMD
GeoFieldType& modeRe, GeoFieldType& modeRe,
GeoFieldType& modeIm, GeoFieldType& modeIm,
const RMatrix& primitiveMode, const RMatrix& primitiveMode,
const label i const label magi,
const label rowi = 0
); );
//- Compute a mode for a given non-scalar-based input field //- Compute a mode for a given non-scalar-based input field
@ -425,7 +426,8 @@ class STDMD
GeoFieldType& modeRe, GeoFieldType& modeRe,
GeoFieldType& modeIm, GeoFieldType& modeIm,
const RMatrix& primitiveMode, const RMatrix& primitiveMode,
const label i const label magi,
const label rowi = 0
); );

View File

@ -109,7 +109,7 @@ bool Foam::DMDModels::STDMD::calcModes()
RxInv_.clear(); RxInv_.clear();
label modei = 0; label modei = 0;
for (const label i : magsi_) for (const label magi : magsi_)
{ {
GeoFieldType modeRe GeoFieldType modeRe
( (
@ -147,21 +147,30 @@ bool Foam::DMDModels::STDMD::calcModes()
if (modeRe.size() != 0 && !empty_) if (modeRe.size() != 0 && !empty_)
{ {
if (patch_.empty()) if (patches_.empty())
{ {
auto& re = modeRe.primitiveFieldRef(); auto& re = modeRe.primitiveFieldRef();
auto& im = modeIm.primitiveFieldRef(); auto& im = modeIm.primitiveFieldRef();
calcMode(re, im, primitiveMode, i); calcMode(re, im, primitiveMode, magi);
} }
else else
{ {
const label patchi = mesh_.boundaryMesh().findPatchID(patch_); label rowi = 0;
const labelList patchis
(
mesh_.boundaryMesh().patchSet(patches_).sortedToc()
);
auto& re = modeRe.boundaryFieldRef()[patchi]; for (const label patchi : patchis)
auto& im = modeIm.boundaryFieldRef()[patchi]; {
auto& re = modeRe.boundaryFieldRef()[patchi];
auto& im = modeIm.boundaryFieldRef()[patchi];
calcMode(re, im, primitiveMode, i); calcMode(re, im, primitiveMode, magi, rowi);
rowi += re.size()*pTraits<Type>::nComponents;
}
} }
} }
@ -184,21 +193,22 @@ typename std::enable_if
GeoFieldType& modeRe, GeoFieldType& modeRe,
GeoFieldType& modeIm, GeoFieldType& modeIm,
const RMatrix& primitiveMode, const RMatrix& primitiveMode,
const label i const label magi,
const label rowi
) )
{ {
const label fieldSize = modeRe.size(); const label szfld = modeRe.size();
for (label p = 0; p < primitiveMode.m(); ++p) for (label i = rowi; i < szfld + rowi; ++i)
{ {
complex mode(Zero); complex mode(Zero);
for (label q = 0; q < evecs_.m(); ++q) for (label j = 0; j < evecs_.m(); ++j)
{ {
mode += primitiveMode(p, q)*evecs_(q, i); mode += primitiveMode(i, j)*evecs_(j, magi);
} }
label p1 = p%fieldSize; const label k = (i-rowi)%szfld;
modeRe[p1] = mode.real(); modeRe[k] = mode.real();
modeIm[p1] = mode.imag(); modeIm[k] = mode.imag();
} }
} }
@ -213,22 +223,25 @@ typename std::enable_if
GeoFieldType& modeRe, GeoFieldType& modeRe,
GeoFieldType& modeIm, GeoFieldType& modeIm,
const RMatrix& primitiveMode, const RMatrix& primitiveMode,
const label i const label magi,
const label rowi
) )
{ {
const label fieldSize = modeRe.size(); const label szfld = modeRe.size();
const label szfldcmps =
szfld*pTraits<typename GeoFieldType::value_type>::nComponents;
for (label p = 0; p < primitiveMode.m(); ++p) for (label i = rowi; i < szfldcmps + rowi; ++i)
{ {
complex mode(Zero); complex mode(Zero);
for (label q = 0; q < evecs_.m(); ++q) for (label j = 0; j < evecs_.m(); ++j)
{ {
mode += primitiveMode(p, q)*evecs_(q, i); mode += primitiveMode(i, j)*evecs_(j, magi);
} }
label p1 = p%fieldSize; const label k = (i-rowi)%szfld;
label p2 = p/fieldSize; const label m = (i-rowi)/szfld;
modeRe[p1][p2] = mode.real(); modeRe[k][m] = mode.real();
modeIm[p1][p2] = mode.imag(); modeIm[k][m] = mode.imag();
} }
} }

View File

@ -73,35 +73,40 @@ bool Foam::functionObjects::DMD::storeSnapshot()
const GeoFieldType& field = lookupObject<GeoFieldType>(fieldName_); const GeoFieldType& field = lookupObject<GeoFieldType>(fieldName_);
if (patch_.empty()) label rowi = nSnap_;
if (patches_.empty())
{ {
const label nField = field.size(); const label nField = field.size();
for (direction dir = 0; dir < nComps; ++dir) for (direction dir = 0; dir < nComps; ++dir)
{ {
z_.subColumn(0, nSnap_ + dir*nField, nField) = field.component(dir); z_.subColumn(0, rowi, nField) = field.component(dir);
rowi += nField;
} }
} }
else else
{ {
const label patchi = mesh_.boundaryMesh().findPatchID(patch_); const labelList patchis
(
mesh_.boundaryMesh().patchSet(patches_).sortedToc()
);
if (patchi < 0) for (const label patchi : patchis)
{ {
FatalErrorInFunction const typename GeoFieldType::Boundary& bf = field.boundaryField();
<< "Cannot find patch " << patch_
<< exit(FatalError);
}
const typename GeoFieldType::Boundary& bf = field.boundaryField(); const Field<typename GeoFieldType::value_type>& pbf = bf[patchi];
const Field<typename GeoFieldType::value_type>& pbf = bf[patchi]; const label nField = pbf.size();
const label nField = pbf.size(); if (nField > 0)
{
for (direction dir = 0; dir < nComps; ++dir) for (direction dir = 0; dir < nComps; ++dir)
{ {
z_.subColumn(0, nSnap_ + dir*nField, nField) = pbf.component(dir); z_.subColumn(0, rowi, nField) = pbf.component(dir);
rowi += nField;
}
}
} }
} }