mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: DMD: add multi-patch input functionality
This commit is contained in:
committed by
Andrew Heather
parent
d2e2533546
commit
f12399c39b
@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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_;
|
||||||
|
|
||||||
|
|||||||
@ -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),
|
||||||
|
|||||||
@ -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
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user