mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
Merge branch 'feature-refactoring-dmd' into 'develop'
ENH: DMD: refactor dynamic mode decomposition FO See merge request Development/openfoam!440
This commit is contained in:
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2016 OpenFOAM Foundation
|
Copyright (C) 2016 OpenFOAM Foundation
|
||||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
Copyright (C) 2019-2021 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -492,9 +492,10 @@ template<class MatrixType>
|
|||||||
MatrixType Foam::pinv
|
MatrixType Foam::pinv
|
||||||
(
|
(
|
||||||
const MatrixType& A,
|
const MatrixType& A,
|
||||||
const scalar tol
|
const scalar tolerance
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
scalar tol = tolerance;
|
||||||
typedef typename MatrixType::cmptType cmptType;
|
typedef typename MatrixType::cmptType cmptType;
|
||||||
|
|
||||||
if (A.empty())
|
if (A.empty())
|
||||||
@ -506,7 +507,12 @@ MatrixType Foam::pinv
|
|||||||
|
|
||||||
if (A.size() == 1)
|
if (A.size() == 1)
|
||||||
{
|
{
|
||||||
return MatrixType({1, 1}, cmptType(1.0)/(A(0,0) + cmptType(VSMALL)));
|
if (A(0,0) == cmptType(0))
|
||||||
|
{
|
||||||
|
return MatrixType({1, 1}, cmptType(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return MatrixType({1, 1}, cmptType(1)/(A(0,0) + cmptType(VSMALL)));
|
||||||
}
|
}
|
||||||
|
|
||||||
QRMatrix<MatrixType> QRM
|
QRMatrix<MatrixType> QRM
|
||||||
@ -521,27 +527,47 @@ MatrixType Foam::pinv
|
|||||||
// R1 (KP:p. 648)
|
// R1 (KP:p. 648)
|
||||||
// Find the first diagonal element index with (almost) zero value in R
|
// Find the first diagonal element index with (almost) zero value in R
|
||||||
label firstZeroElemi = 0;
|
label firstZeroElemi = 0;
|
||||||
|
label i = 0;
|
||||||
|
while (i < 2)
|
||||||
{
|
{
|
||||||
const List<cmptType> diag(R.diag());
|
const List<cmptType> diag(R.diag());
|
||||||
|
|
||||||
auto lessT = [&](const cmptType& x) { return mag(x) < tol; };
|
auto lessThan = [=](const cmptType& x) { return tol > mag(x); };
|
||||||
|
|
||||||
firstZeroElemi =
|
firstZeroElemi =
|
||||||
std::distance
|
std::distance
|
||||||
(
|
(
|
||||||
diag.cbegin(),
|
diag.cbegin(),
|
||||||
std::find_if(diag.cbegin(), diag.cend(), lessT)
|
std::find_if(diag.cbegin(), diag.cend(), lessThan)
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
if (firstZeroElemi == 0)
|
if (firstZeroElemi == 0)
|
||||||
|
{
|
||||||
|
if (i == 0)
|
||||||
{
|
{
|
||||||
WarningInFunction
|
WarningInFunction
|
||||||
<< "The largest (magnitude) diagonal element is (almost) zero."
|
<< "The largest diagonal element magnitude is nearly zero. "
|
||||||
<< nl << "Returning a zero matrix."
|
<< "Tightening the tolerance."
|
||||||
<< endl;
|
<< endl;
|
||||||
|
|
||||||
return MatrixType(A.sizes(), Zero);
|
tol = 1e-13;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WarningInFunction
|
||||||
|
<< "The largest diagonal element magnitude is nearly zero. "
|
||||||
|
<< "Returning a zero matrix."
|
||||||
|
<< endl;
|
||||||
|
++i;
|
||||||
|
|
||||||
|
return MatrixType({A.n(), A.m()}, Zero);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exclude the first (almost) zero diagonal row and the rows below
|
// Exclude the first (almost) zero diagonal row and the rows below
|
||||||
@ -599,4 +625,5 @@ MatrixType Foam::pinv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2016 OpenFOAM Foundation
|
Copyright (C) 2016 OpenFOAM Foundation
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
Copyright (C) 2019-2021 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
|
|||||||
234
src/functionObjects/field/DMD/DMD.C
Normal file
234
src/functionObjects/field/DMD/DMD.C
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2020-2021 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 "DMD.H"
|
||||||
|
#include "DMDModel.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
namespace functionObjects
|
||||||
|
{
|
||||||
|
defineTypeNameAndDebug(DMD, 0);
|
||||||
|
addToRunTimeSelectionTable(functionObject, DMD, dictionary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::functionObjects::DMD::snapshot()
|
||||||
|
{
|
||||||
|
bool processed = false;
|
||||||
|
processed = processed || getSnapshot<scalar>();
|
||||||
|
processed = processed || getSnapshot<vector>();
|
||||||
|
processed = processed || getSnapshot<sphericalTensor>();
|
||||||
|
processed = processed || getSnapshot<symmTensor>();
|
||||||
|
processed = processed || getSnapshot<tensor>();
|
||||||
|
|
||||||
|
if (!processed)
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< " functionObjects::" << type() << " " << name() << ":"
|
||||||
|
<< " cannot find required input field during snapshot loading: "
|
||||||
|
<< fieldName_ << nl
|
||||||
|
<< " Do you execute required functionObjects"
|
||||||
|
<< " before executing DMD, e.g. mapFields?"
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::functionObjects::DMD::initialise()
|
||||||
|
{
|
||||||
|
const label nComps = DMDModelPtr_->nComponents(fieldName_);
|
||||||
|
|
||||||
|
if (patch_.empty())
|
||||||
|
{
|
||||||
|
nSnap_ = nComps*mesh_.nCells();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const label patchi = mesh_.boundaryMesh().findPatchID(patch_);
|
||||||
|
|
||||||
|
if (patchi < 0)
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "Cannot find patch " << patch_
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
nSnap_ = nComps*(mesh_.C().boundaryField()[patchi]).size();
|
||||||
|
}
|
||||||
|
|
||||||
|
const label nSnapTotal = returnReduce(nSnap_, sumOp<label>());
|
||||||
|
|
||||||
|
if (nSnapTotal <= 0)
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< " # Zero-size input field = " << fieldName_ << " #"
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nSnap_ > 0)
|
||||||
|
{
|
||||||
|
z_ = RMatrix(2*nSnap_, 1, Zero);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
z_ = RMatrix(1, 1, Zero);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::functionObjects::DMD::DMD
|
||||||
|
(
|
||||||
|
const word& name,
|
||||||
|
const Time& runTime,
|
||||||
|
const dictionary& dict
|
||||||
|
)
|
||||||
|
:
|
||||||
|
fvMeshFunctionObject(name, runTime, dict),
|
||||||
|
DMDModelPtr_(DMDModel::New(mesh_, name, dict)),
|
||||||
|
z_(),
|
||||||
|
fieldName_(dict.get<word>("field")),
|
||||||
|
patch_(dict.getOrDefault<word>("patch", word::null)),
|
||||||
|
nSnap_(0),
|
||||||
|
step_(0)
|
||||||
|
{
|
||||||
|
// Check if computation time-step is varying
|
||||||
|
if (runTime.isAdjustTimeStep())
|
||||||
|
{
|
||||||
|
WarningInFunction
|
||||||
|
<< " # DMD: Available only for fixed time-step computations. #"
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if mesh topology is changing
|
||||||
|
if (mesh_.topoChanging())
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< " # DMD: Available only for non-changing mesh topology. #"
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
read(dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
bool Foam::functionObjects::DMD::read(const dictionary& dict)
|
||||||
|
{
|
||||||
|
Info<< type() << " " << name() << ":" << endl;
|
||||||
|
|
||||||
|
if (fvMeshFunctionObject::read(dict) && DMDModelPtr_->read(dict))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::functionObjects::DMD::execute()
|
||||||
|
{
|
||||||
|
Log << type() << " " << name() << " execute:" << endl;
|
||||||
|
|
||||||
|
snapshot();
|
||||||
|
|
||||||
|
if (step_ == 1)
|
||||||
|
{
|
||||||
|
DMDModelPtr_->initialise(z_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (step_ > 1)
|
||||||
|
{
|
||||||
|
DMDModelPtr_->update(z_);
|
||||||
|
}
|
||||||
|
|
||||||
|
++step_;
|
||||||
|
|
||||||
|
Log << tab << "Execution index = " << step_ << " for field: " << fieldName_
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::functionObjects::DMD::write()
|
||||||
|
{
|
||||||
|
if (postProcess)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::functionObjects::DMD::end()
|
||||||
|
{
|
||||||
|
if (step_ == 0)
|
||||||
|
{
|
||||||
|
// Avoid double execution of write() when writeControl=onEnd
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log << type() << " " << name() << " write:" << endl;
|
||||||
|
|
||||||
|
if (step_ < 2)
|
||||||
|
{
|
||||||
|
WarningInFunction
|
||||||
|
<< " # DMD needs at least three snapshots to produce output #"
|
||||||
|
<< nl
|
||||||
|
<< " # Only " << step_ + 1 << " snapshots are available #"
|
||||||
|
<< nl
|
||||||
|
<< " # Skipping DMD output calculation and write #"
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
z_.clear();
|
||||||
|
|
||||||
|
DMDModelPtr_->fit();
|
||||||
|
|
||||||
|
mesh_.time().printExecutionTime(Info);
|
||||||
|
|
||||||
|
// Restart the incremental orthonormal basis update
|
||||||
|
step_ = 0;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
278
src/functionObjects/field/DMD/DMD.H
Normal file
278
src/functionObjects/field/DMD/DMD.H
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2020-2021 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::DMD
|
||||||
|
|
||||||
|
Group
|
||||||
|
grpFieldFunctionObjects
|
||||||
|
|
||||||
|
Description
|
||||||
|
Computes a dynamic mode decomposition model on a specified field.
|
||||||
|
|
||||||
|
Dynamic mode decomposition (i.e. DMD) is a data-driven
|
||||||
|
dimensionality reduction method. DMD is being used as a mathematical
|
||||||
|
processing tool to reveal dominant modes out of a given field (or dataset)
|
||||||
|
each of which is associated with a constant frequency and decay rate,
|
||||||
|
so that dynamic features of a given flow may become interpretable,
|
||||||
|
tractable, and even reproducible without computing simulations.
|
||||||
|
DMD only relies on input data, therefore it is an equation-free approach.
|
||||||
|
|
||||||
|
References:
|
||||||
|
\verbatim
|
||||||
|
DMD characteristics:
|
||||||
|
Brunton S. L. (2018).
|
||||||
|
Dynamic mode decomposition overview.
|
||||||
|
Seattle, Washington: University of Washington.
|
||||||
|
youtu.be/sQvrK8AGCAo (Retrieved:24-04-20)
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
Operands:
|
||||||
|
\table
|
||||||
|
Operand | Type | Location
|
||||||
|
input | {vol,surface}\<Type\>Field(s) <!--
|
||||||
|
--> | \<time\>/\<inputField\>(s)
|
||||||
|
output file | dat | postProcessing/\<FO\>/\<time\>/\<file\>(s)
|
||||||
|
output field | volVectorField(s) | \<time\>/\<outputField\>(s)
|
||||||
|
\endtable
|
||||||
|
|
||||||
|
where \c \<Type\>=Scalar/Vector/SphericalTensor/SymmTensor/Tensor.
|
||||||
|
|
||||||
|
Output fields:
|
||||||
|
\verbatim
|
||||||
|
modeRe_<modeIndex>_<field>_<FO> | Real part of a mode field
|
||||||
|
modeIm_<modeIndex>_<field>_<FO> | Imaginary part of a mode field
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
Output files:
|
||||||
|
\verbatim
|
||||||
|
dynamics_<field>.dat | Dynamics data for each mode
|
||||||
|
filteredDynamics_<field>.dat | Filtered dynamics data for each mode
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
wherein for each mode, the following quantities are output into files:
|
||||||
|
\vartable
|
||||||
|
freq | Frequency
|
||||||
|
mag | Magnitude
|
||||||
|
ampRe | Amplitude coefficients (real part)
|
||||||
|
ampIm | Amplitude coefficients (imaginary part)
|
||||||
|
evalRe | Eigenvalue (real part)
|
||||||
|
evalIm | Eigenvalue (imaginary part)
|
||||||
|
\endvartable
|
||||||
|
|
||||||
|
Usage
|
||||||
|
Minimal example by using \c system/controlDict.functions:
|
||||||
|
\verbatim
|
||||||
|
DMD1
|
||||||
|
{
|
||||||
|
// Mandatory entries (unmodifiable)
|
||||||
|
type DMD;
|
||||||
|
libs (fieldFunctionObjects);
|
||||||
|
DMDModel <DMDModel>;
|
||||||
|
field <inputField>;
|
||||||
|
|
||||||
|
// Optional entries (unmodifiable)
|
||||||
|
patch <patchName>;
|
||||||
|
|
||||||
|
// Mandatory/Optional (inherited) entries
|
||||||
|
...
|
||||||
|
}
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
where the entries mean:
|
||||||
|
\table
|
||||||
|
Property | Description | Type | Reqd | Deflt
|
||||||
|
type | Type name: DMD | word | yes | -
|
||||||
|
libs | Library name: fieldFunctionObjects | word | yes | -
|
||||||
|
DMDModel | Name of specified DMD model | word | yes | -
|
||||||
|
field | Name of operand field | word | yes | -
|
||||||
|
patch | Name of operand patch | word | no | null
|
||||||
|
\endtable
|
||||||
|
|
||||||
|
Options for the \c DMDModel entry:
|
||||||
|
\verbatim
|
||||||
|
STDMD | Streaming total dynamic mode decomposition
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
The inherited entries are elaborated in:
|
||||||
|
- \link functionObject.H \endlink
|
||||||
|
- \link writeFile.H \endlink
|
||||||
|
|
||||||
|
Minimal example by using the \c postProcess utility:
|
||||||
|
\verbatim
|
||||||
|
<solver> -postProcess -fields '(U p)' -time '10:'
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
Note
|
||||||
|
- Warning: DMD is an active research area at the time of writing;
|
||||||
|
therefore, there could be cases whereat oddities can be seen.
|
||||||
|
|
||||||
|
See also
|
||||||
|
- Foam::functionObjects::fvMeshFunctionObject
|
||||||
|
- Foam::functionObjects::writeFile
|
||||||
|
- Foam::DMDModel
|
||||||
|
- Foam::DMDModels::STDMD
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
DMD.C
|
||||||
|
DMDTemplates.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef functionObjects_DMD_H
|
||||||
|
#define functionObjects_DMD_H
|
||||||
|
|
||||||
|
#include "fvMeshFunctionObject.H"
|
||||||
|
#include "RectangularMatrix.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// Forward Declarations
|
||||||
|
class DMDModel;
|
||||||
|
|
||||||
|
namespace functionObjects
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class DMD Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class DMD
|
||||||
|
:
|
||||||
|
public fvMeshFunctionObject
|
||||||
|
{
|
||||||
|
typedef RectangularMatrix<scalar> RMatrix;
|
||||||
|
|
||||||
|
// Private Data
|
||||||
|
|
||||||
|
//- Dynamic mode decomposition model
|
||||||
|
autoPtr<DMDModel> DMDModelPtr_;
|
||||||
|
|
||||||
|
//- Snapshot matrix (effectively a column vector)
|
||||||
|
// Upper half = current-time snapshot slot
|
||||||
|
// Lower half = previous-time snapshot slot
|
||||||
|
// A snapshot is an input dataset to be processed per execution step
|
||||||
|
RMatrix z_;
|
||||||
|
|
||||||
|
//- Name of operand field
|
||||||
|
const word fieldName_;
|
||||||
|
|
||||||
|
//- Name of operand patch
|
||||||
|
const word patch_;
|
||||||
|
|
||||||
|
//- Number of elements in a snapshot
|
||||||
|
label nSnap_;
|
||||||
|
|
||||||
|
//- Current execution-step index of DMD,
|
||||||
|
//- not necessarily that of the simulation
|
||||||
|
label step_;
|
||||||
|
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
// Process
|
||||||
|
|
||||||
|
//- Initialise snapshot at the first-execution step
|
||||||
|
// Initialisation at the ctor or read level is not possible
|
||||||
|
// since the operand field is not available in the database
|
||||||
|
void initialise();
|
||||||
|
|
||||||
|
//- Create operand snapshot by using
|
||||||
|
//- current-time and previous-time operand fields
|
||||||
|
void snapshot();
|
||||||
|
|
||||||
|
//- Get operand field based on its base type
|
||||||
|
template<class Type>
|
||||||
|
bool getSnapshot();
|
||||||
|
|
||||||
|
//- Get operand field based on its geometric field type
|
||||||
|
// Move previous-time field into previous-time slot in snapshot
|
||||||
|
// copy new current-time field into current-time slot in snapshot
|
||||||
|
template<class GeoFieldType>
|
||||||
|
bool getSnapshotField();
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("DMD");
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from Time and dictionary
|
||||||
|
DMD
|
||||||
|
(
|
||||||
|
const word& name,
|
||||||
|
const Time& runTime,
|
||||||
|
const dictionary& dict
|
||||||
|
);
|
||||||
|
|
||||||
|
//- No copy construct
|
||||||
|
DMD(const DMD&) = delete;
|
||||||
|
|
||||||
|
//- No copy assignment
|
||||||
|
void operator=(const DMD&) = delete;
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
virtual ~DMD() = default;
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
//- Read DMD settings
|
||||||
|
virtual bool read(const dictionary& dict);
|
||||||
|
|
||||||
|
//- Execute DMD
|
||||||
|
virtual bool execute();
|
||||||
|
|
||||||
|
//- Write DMD results
|
||||||
|
virtual bool write();
|
||||||
|
|
||||||
|
//- Write DMD results
|
||||||
|
virtual bool end();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace functionObjects
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#ifdef NoRepository
|
||||||
|
#include "DMDTemplates.C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
78
src/functionObjects/field/DMD/DMDModels/DMDModel/DMDModel.C
Normal file
78
src/functionObjects/field/DMD/DMDModels/DMDModel/DMDModel.C
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2020-2021 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 "DMDModel.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
defineTypeNameAndDebug(DMDModel, 0);
|
||||||
|
defineRunTimeSelectionTable(DMDModel, dictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::DMDModel::DMDModel
|
||||||
|
(
|
||||||
|
const fvMesh& mesh,
|
||||||
|
const word& name,
|
||||||
|
const dictionary& dict
|
||||||
|
)
|
||||||
|
:
|
||||||
|
writeFile(mesh, name, typeName, dict, false),
|
||||||
|
mesh_(mesh),
|
||||||
|
name_(name)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::label Foam::DMDModel::nComponents(const word& fieldName) const
|
||||||
|
{
|
||||||
|
label nComps = 0;
|
||||||
|
bool processed = false;
|
||||||
|
processed = processed || nComponents<scalar>(fieldName, nComps);
|
||||||
|
processed = processed || nComponents<vector>(fieldName, nComps);
|
||||||
|
processed = processed || nComponents<sphericalTensor>(fieldName, nComps);
|
||||||
|
processed = processed || nComponents<symmTensor>(fieldName, nComps);
|
||||||
|
processed = processed || nComponents<tensor>(fieldName, nComps);
|
||||||
|
|
||||||
|
if (!processed)
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< " # Unknown type of input field during initialisation = "
|
||||||
|
<< fieldName << " #" << nl
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nComps;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
203
src/functionObjects/field/DMD/DMDModels/DMDModel/DMDModel.H
Normal file
203
src/functionObjects/field/DMD/DMDModels/DMDModel/DMDModel.H
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2020-2021 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/>.
|
||||||
|
|
||||||
|
Namespace
|
||||||
|
Foam::DMDModels
|
||||||
|
|
||||||
|
Description
|
||||||
|
A namespace for various dynamic mode
|
||||||
|
decomposition (DMD) model implementations.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::DMDModel
|
||||||
|
|
||||||
|
Description
|
||||||
|
Abstract base class for DMD models to handle DMD
|
||||||
|
characteristics for the \c DMD function object.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
DMDModel.C
|
||||||
|
DMDModelNew.C
|
||||||
|
DMDModelTemplates.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef DMDModel_H
|
||||||
|
#define DMDModel_H
|
||||||
|
|
||||||
|
#include "fvMesh.H"
|
||||||
|
#include "dictionary.H"
|
||||||
|
#include "HashSet.H"
|
||||||
|
#include "runTimeSelectionTables.H"
|
||||||
|
#include "writeFile.H"
|
||||||
|
#include "OFstream.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class DMDModel Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class DMDModel
|
||||||
|
:
|
||||||
|
public functionObjects::writeFile
|
||||||
|
{
|
||||||
|
typedef SquareMatrix<scalar> SMatrix;
|
||||||
|
typedef RectangularMatrix<scalar> RMatrix;
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Protected Data
|
||||||
|
|
||||||
|
//- Reference to the mesh
|
||||||
|
const fvMesh& mesh_;
|
||||||
|
|
||||||
|
//- Name of operand function object
|
||||||
|
const word name_;
|
||||||
|
|
||||||
|
|
||||||
|
// Protected Member Functions
|
||||||
|
|
||||||
|
// Evaluation
|
||||||
|
|
||||||
|
//- Compute and write mode dynamics
|
||||||
|
virtual bool dynamics() = 0;
|
||||||
|
|
||||||
|
//- Compute and write modes
|
||||||
|
virtual bool modes() = 0;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("DMDModel");
|
||||||
|
|
||||||
|
|
||||||
|
// Declare runtime constructor selection table
|
||||||
|
|
||||||
|
declareRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
autoPtr,
|
||||||
|
DMDModel,
|
||||||
|
dictionary,
|
||||||
|
(
|
||||||
|
const fvMesh& mesh,
|
||||||
|
const word& name,
|
||||||
|
const dictionary& dict
|
||||||
|
),
|
||||||
|
(mesh, name, dict)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Selectors
|
||||||
|
|
||||||
|
//- Return a reference to the selected DMD model
|
||||||
|
static autoPtr<DMDModel> New
|
||||||
|
(
|
||||||
|
const fvMesh& mesh,
|
||||||
|
const word& name,
|
||||||
|
const dictionary& dict
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from components
|
||||||
|
DMDModel
|
||||||
|
(
|
||||||
|
const fvMesh& mesh,
|
||||||
|
const word& name,
|
||||||
|
const dictionary& dict
|
||||||
|
);
|
||||||
|
|
||||||
|
//- No copy construct
|
||||||
|
DMDModel(const DMDModel&) = delete;
|
||||||
|
|
||||||
|
//- No copy assignment
|
||||||
|
void operator=(const DMDModel&) = delete;
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
virtual ~DMDModel() = default;
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
// Process
|
||||||
|
|
||||||
|
//- Initialise model data members with a given snapshot
|
||||||
|
virtual bool initialise(const RMatrix& snapshot) = 0;
|
||||||
|
|
||||||
|
//- Update model data members with a given snapshot
|
||||||
|
virtual bool update(const RMatrix& snapshot) = 0;
|
||||||
|
|
||||||
|
//- Compute and write modes and
|
||||||
|
//- mode dynamics of model data members
|
||||||
|
virtual bool fit() = 0;
|
||||||
|
|
||||||
|
//- Compute and write a reconstruction of flow field
|
||||||
|
//- based on given modes and mode dynamics (currently no-op)
|
||||||
|
virtual void reconstruct(const wordList modes)
|
||||||
|
{
|
||||||
|
NotImplemented;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Access
|
||||||
|
|
||||||
|
//- Return number of components of the base type of a given field
|
||||||
|
label nComponents(const word& fieldName) const;
|
||||||
|
|
||||||
|
//- Get the number of components of the base type of a given field
|
||||||
|
template<class Type>
|
||||||
|
bool nComponents(const word& fieldName, label& nComps) const;
|
||||||
|
|
||||||
|
|
||||||
|
// IO
|
||||||
|
|
||||||
|
//- Read model settings
|
||||||
|
virtual bool read(const dictionary& dict) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#ifdef NoRepository
|
||||||
|
#include "DMDModelTemplates.C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2020-2021 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 "DMDModel.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::autoPtr<Foam::DMDModel> Foam::DMDModel::New
|
||||||
|
(
|
||||||
|
const fvMesh& mesh,
|
||||||
|
const word& name,
|
||||||
|
const dictionary& dict
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const word modelType(dict.get<word>("DMDModel"));
|
||||||
|
|
||||||
|
auto cstrIter = dictionaryConstructorTablePtr_->cfind(modelType);
|
||||||
|
|
||||||
|
if (!cstrIter.found())
|
||||||
|
{
|
||||||
|
FatalIOErrorInLookup
|
||||||
|
(
|
||||||
|
dict,
|
||||||
|
"DMDModel",
|
||||||
|
modelType,
|
||||||
|
*dictionaryConstructorTablePtr_
|
||||||
|
) << exit(FatalIOError);
|
||||||
|
}
|
||||||
|
|
||||||
|
return autoPtr<DMDModel>(cstrIter()(mesh, name, dict));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2021 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 "volFields.H"
|
||||||
|
#include "surfaceFields.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
bool Foam::DMDModel::nComponents(const word& fieldName, label& nComps) const
|
||||||
|
{
|
||||||
|
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
|
||||||
|
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
|
||||||
|
|
||||||
|
if (mesh_.foundObject<VolFieldType>(fieldName))
|
||||||
|
{
|
||||||
|
nComps = pTraits<typename VolFieldType::value_type>::nComponents;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (mesh_.foundObject<SurfaceFieldType>(fieldName))
|
||||||
|
{
|
||||||
|
nComps = pTraits<typename SurfaceFieldType::value_type>::nComponents;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
988
src/functionObjects/field/DMD/DMDModels/derived/STDMD/STDMD.C
Normal file
988
src/functionObjects/field/DMD/DMDModels/derived/STDMD/STDMD.C
Normal file
@ -0,0 +1,988 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2020-2021 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 "STDMD.H"
|
||||||
|
#include "EigenMatrix.H"
|
||||||
|
#include "QRMatrix.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
|
||||||
|
using namespace Foam::constant::mathematical;
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
namespace DMDModels
|
||||||
|
{
|
||||||
|
defineTypeNameAndDebug(STDMD, 0);
|
||||||
|
addToRunTimeSelectionTable(DMDModel, STDMD, dictionary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Foam::Enum
|
||||||
|
<
|
||||||
|
Foam::DMDModels::STDMD::modeSorterType
|
||||||
|
>
|
||||||
|
Foam::DMDModels::STDMD::modeSorterTypeNames
|
||||||
|
({
|
||||||
|
{ modeSorterType::FIRST_SNAPSHOT, "firstSnapshot" },
|
||||||
|
{ modeSorterType::KIEWAT , "kiewat" },
|
||||||
|
{ modeSorterType::KOU_ZHANG , "kouZhang" }
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::scalar Foam::DMDModels::STDMD::L2norm(const RMatrix& z) const
|
||||||
|
{
|
||||||
|
#ifdef FULLDEBUG
|
||||||
|
// Check if the given RectangularMatrix is effectively a column vector
|
||||||
|
if (z.n() != 1)
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< " # Input matrix is not a column vector. #"
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
const bool noSqrt = true;
|
||||||
|
scalar result = z.columnNorm(0, noSqrt);
|
||||||
|
reduce(result, sumOp<scalar>());
|
||||||
|
|
||||||
|
// Heuristic addition to avoid very small or zero norm
|
||||||
|
return max(SMALL, Foam::sqrt(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::RectangularMatrix<Foam::scalar> Foam::DMDModels::STDMD::orthonormalise
|
||||||
|
(
|
||||||
|
RMatrix ez
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
RMatrix dz(Q_.n(), 1, Zero);
|
||||||
|
|
||||||
|
for (label i = 0; i < nGramSchmidt_; ++i)
|
||||||
|
{
|
||||||
|
dz = Q_ & ez;
|
||||||
|
reduce(dz, sumOp<RMatrix>());
|
||||||
|
ez -= Q_*dz;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ez;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::DMDModels::STDMD::expand(const RMatrix& ez, const scalar ezNorm)
|
||||||
|
{
|
||||||
|
Info<< tab << "Expanding orthonormal basis for field: " << fieldName_
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
// Stack a column "(ez/ezNorm)" to "Q"
|
||||||
|
Q_.resize(Q_.m(), Q_.n() + 1);
|
||||||
|
Q_.subColumn(Q_.n() - 1) = ez/ezNorm;
|
||||||
|
|
||||||
|
// Stack a row (Zero) and column (Zero) to "G"
|
||||||
|
G_.resize(G_.m() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::DMDModels::STDMD::compress()
|
||||||
|
{
|
||||||
|
Info<< tab << "Compressing orthonormal basis for field: " << fieldName_
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
RMatrix q(1, 1, Zero);
|
||||||
|
|
||||||
|
if (Pstream::master())
|
||||||
|
{
|
||||||
|
const bool symmetric = true;
|
||||||
|
const EigenMatrix<scalar> EM(G_, symmetric);
|
||||||
|
const SquareMatrix<scalar>& EVecs = EM.EVecs();
|
||||||
|
DiagonalMatrix<scalar> EVals(EM.EValsRe());
|
||||||
|
|
||||||
|
// Sort eigenvalues in descending order, and track indices
|
||||||
|
const auto descend = [&](scalar a, scalar b){ return a > b; };
|
||||||
|
const List<label> permutation(EVals.sortPermutation(descend));
|
||||||
|
EVals.applyPermutation(permutation);
|
||||||
|
EVals.resize(EVals.size() - 1);
|
||||||
|
|
||||||
|
// Update "G"
|
||||||
|
G_ = SMatrix(maxRank_, Zero);
|
||||||
|
G_.diag(EVals);
|
||||||
|
|
||||||
|
q.resize(Q_.n(), maxRank_);
|
||||||
|
for (label i = 0; i < maxRank_; ++i)
|
||||||
|
{
|
||||||
|
q.subColumn(i) = EVecs.subColumn(permutation[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Pstream::scatter(G_);
|
||||||
|
Pstream::scatter(q);
|
||||||
|
|
||||||
|
// Update "Q"
|
||||||
|
Q_ = Q_*q;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::SquareMatrix<Foam::scalar> Foam::DMDModels::STDMD::
|
||||||
|
reducedKoopmanOperator()
|
||||||
|
{
|
||||||
|
Info<< tab << "Computing Atilde" << endl;
|
||||||
|
|
||||||
|
Info<< tab << "Computing local Rx" << endl;
|
||||||
|
|
||||||
|
RMatrix Rx(1, 1, Zero);
|
||||||
|
{
|
||||||
|
QRMatrix<RMatrix> QRM
|
||||||
|
(
|
||||||
|
Qupper_,
|
||||||
|
QRMatrix<RMatrix>::outputTypes::REDUCED_R,
|
||||||
|
QRMatrix<RMatrix>::colPivoting::FALSE
|
||||||
|
);
|
||||||
|
Rx = QRM.R();
|
||||||
|
}
|
||||||
|
Rx.round();
|
||||||
|
|
||||||
|
// Convenience objects A1, A2, A3 to compute "Atilde"
|
||||||
|
RMatrix A1(1, 1, Zero);
|
||||||
|
|
||||||
|
if (Pstream::parRun())
|
||||||
|
{
|
||||||
|
// Parallel direct tall-skinny QR decomposition
|
||||||
|
// (BGD:Fig. 5) & (DGHL:Fig. 2)
|
||||||
|
// Tests revealed that the distribution of "Q" does not affect
|
||||||
|
// the final outcome of TSQR decomposition up to sign
|
||||||
|
|
||||||
|
PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
|
||||||
|
|
||||||
|
const label myProcNo = Pstream::myProcNo();
|
||||||
|
const label procNoInSubset = myProcNo % nAgglomerationProcs_;
|
||||||
|
|
||||||
|
// Send Rx from sender subset neighbours to receiver subset master
|
||||||
|
if (procNoInSubset != 0)
|
||||||
|
{
|
||||||
|
const label procNoSubsetMaster = myProcNo - procNoInSubset;
|
||||||
|
|
||||||
|
UOPstream toSubsetMaster(procNoSubsetMaster, pBufs);
|
||||||
|
toSubsetMaster << Rx;
|
||||||
|
|
||||||
|
Rx.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
pBufs.finishedSends();
|
||||||
|
|
||||||
|
// Receive Rx by receiver subset masters
|
||||||
|
if (procNoInSubset == 0)
|
||||||
|
{
|
||||||
|
// Accept only subset masters possessing sender subset neighbours
|
||||||
|
if (myProcNo + 1 < Pstream::nProcs())
|
||||||
|
{
|
||||||
|
for
|
||||||
|
(
|
||||||
|
label nbr = myProcNo + 1;
|
||||||
|
(
|
||||||
|
nbr < myProcNo + nAgglomerationProcs_
|
||||||
|
&& nbr < Pstream::nProcs()
|
||||||
|
);
|
||||||
|
++nbr
|
||||||
|
)
|
||||||
|
{
|
||||||
|
RMatrix recvMtrx;
|
||||||
|
|
||||||
|
UIPstream fromNbr(nbr, pBufs);
|
||||||
|
fromNbr >> recvMtrx;
|
||||||
|
|
||||||
|
// Append received Rx to Rx of receiver subset masters
|
||||||
|
if (recvMtrx.size() > 0)
|
||||||
|
{
|
||||||
|
Rx.resize(Rx.m() + recvMtrx.m(), Rx.n());
|
||||||
|
Rx.subMatrix
|
||||||
|
(
|
||||||
|
Rx.m() - recvMtrx.m(),
|
||||||
|
Rx.n() - recvMtrx.n()
|
||||||
|
) = recvMtrx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply interim QR decomposition on Rx of receiver subset masters
|
||||||
|
QRMatrix<RMatrix> QRM
|
||||||
|
(
|
||||||
|
Rx,
|
||||||
|
QRMatrix<RMatrix>::outputTypes::REDUCED_R,
|
||||||
|
QRMatrix<RMatrix>::storeMethods::IN_PLACE,
|
||||||
|
QRMatrix<RMatrix>::colPivoting::FALSE
|
||||||
|
);
|
||||||
|
Rx.round();
|
||||||
|
}
|
||||||
|
|
||||||
|
pBufs.clear();
|
||||||
|
|
||||||
|
// Send interim Rx from subset masters to the master
|
||||||
|
if (procNoInSubset == 0)
|
||||||
|
{
|
||||||
|
if (!Pstream::master())
|
||||||
|
{
|
||||||
|
UOPstream toMaster(Pstream::masterNo(), pBufs);
|
||||||
|
toMaster << Rx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pBufs.finishedSends();
|
||||||
|
|
||||||
|
// Receive interim Rx by the master, and apply final operations
|
||||||
|
if (Pstream::master())
|
||||||
|
{
|
||||||
|
for
|
||||||
|
(
|
||||||
|
label nbr = Pstream::masterNo() + nAgglomerationProcs_;
|
||||||
|
nbr < Pstream::nProcs();
|
||||||
|
nbr += nAgglomerationProcs_
|
||||||
|
)
|
||||||
|
{
|
||||||
|
RMatrix recvMtrx;
|
||||||
|
|
||||||
|
UIPstream fromSubsetMaster(nbr, pBufs);
|
||||||
|
fromSubsetMaster >> recvMtrx;
|
||||||
|
|
||||||
|
// Append received Rx to Rx of the master
|
||||||
|
if (recvMtrx.size() > 0)
|
||||||
|
{
|
||||||
|
Rx.resize(Rx.m() + recvMtrx.m(), Rx.n());
|
||||||
|
Rx.subMatrix
|
||||||
|
(
|
||||||
|
Rx.m() - recvMtrx.m(),
|
||||||
|
Rx.n() - recvMtrx.n()
|
||||||
|
) = recvMtrx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Info<< tab << "Computing TSQR" << endl;
|
||||||
|
QRMatrix<RMatrix> QRM
|
||||||
|
(
|
||||||
|
Rx,
|
||||||
|
QRMatrix<RMatrix>::outputTypes::REDUCED_R,
|
||||||
|
QRMatrix<RMatrix>::storeMethods::IN_PLACE,
|
||||||
|
QRMatrix<RMatrix>::colPivoting::FALSE
|
||||||
|
);
|
||||||
|
Rx.round();
|
||||||
|
|
||||||
|
// Rx produced by TSQR is unique up to the sign, hence the revert
|
||||||
|
for (scalar& x : Rx)
|
||||||
|
{
|
||||||
|
x *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Info<< tab << "Computing RxInv" << endl;
|
||||||
|
RxInv_ = pinv(Rx);
|
||||||
|
|
||||||
|
Info<< tab << "Computing A1" << endl;
|
||||||
|
A1 = RxInv_*RMatrix(pinv(Rx*(G_^Rx)));
|
||||||
|
Rx.clear();
|
||||||
|
}
|
||||||
|
Pstream::scatter(RxInv_);
|
||||||
|
Pstream::scatter(A1);
|
||||||
|
|
||||||
|
Info<< tab << "Computing A2" << endl;
|
||||||
|
SMatrix A2(Qupper_ & Qlower_);
|
||||||
|
reduce(A2, sumOp<SMatrix>());
|
||||||
|
Qlower_.clear();
|
||||||
|
|
||||||
|
Info<< tab << "Computing A3" << endl;
|
||||||
|
SMatrix A3(Qupper_ & Qupper_);
|
||||||
|
reduce(A3, sumOp<SMatrix>());
|
||||||
|
|
||||||
|
Info<< tab << "Computing Atilde" << endl;
|
||||||
|
// by optimized matrix chain multiplication
|
||||||
|
// obtained by dynamic programming memoisation
|
||||||
|
return SMatrix(RxInv_ & ((A2*(G_*A3))*A1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Info<< tab << "Computing RxInv" << endl;
|
||||||
|
RxInv_ = pinv(Rx);
|
||||||
|
|
||||||
|
Info<< tab << "Computing A1" << endl;
|
||||||
|
A1 = RxInv_*RMatrix(pinv(Rx*(G_^Rx)));
|
||||||
|
Rx.clear();
|
||||||
|
|
||||||
|
Info<< tab << "Computing A2" << endl;
|
||||||
|
SMatrix A2(Qupper_ & Qlower_);
|
||||||
|
Qlower_.clear();
|
||||||
|
|
||||||
|
Info<< tab << "Computing A3" << endl;
|
||||||
|
SMatrix A3(Qupper_ & Qupper_);
|
||||||
|
|
||||||
|
Info<< tab << "Computing Atilde" << endl;
|
||||||
|
return SMatrix(RxInv_ & ((A2*(G_*A3))*A1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::DMDModels::STDMD::eigendecomposition(SMatrix& Atilde)
|
||||||
|
{
|
||||||
|
bool fail = false;
|
||||||
|
|
||||||
|
// Compute eigenvalues, and clip eigenvalues with values < "minEval"
|
||||||
|
if (Pstream::master())
|
||||||
|
{
|
||||||
|
Info<< tab << "Computing eigendecomposition" << endl;
|
||||||
|
|
||||||
|
// Replace "Atilde" by eigenvalues (in-place eigendecomposition)
|
||||||
|
const EigenMatrix<scalar> EM(Atilde);
|
||||||
|
const DiagonalMatrix<scalar>& evalsRe = EM.EValsRe();
|
||||||
|
const DiagonalMatrix<scalar>& evalsIm = EM.EValsIm();
|
||||||
|
|
||||||
|
evals_.resize(evalsRe.size());
|
||||||
|
evecs_ = RCMatrix(EM.complexEVecs());
|
||||||
|
|
||||||
|
// Convert scalar eigenvalue pairs to complex eigenvalues
|
||||||
|
label i = 0;
|
||||||
|
for (auto& eval : evals_)
|
||||||
|
{
|
||||||
|
eval = complex(evalsRe[i], evalsIm[i]);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
Info<< tab << "Filtering eigenvalues" << endl;
|
||||||
|
|
||||||
|
List<complex> cp(evals_.size());
|
||||||
|
auto it =
|
||||||
|
std::copy_if
|
||||||
|
(
|
||||||
|
evals_.cbegin(),
|
||||||
|
evals_.cend(),
|
||||||
|
cp.begin(),
|
||||||
|
[&](const complex& x){ return mag(x) > minEval_; }
|
||||||
|
);
|
||||||
|
cp.resize(std::distance(cp.begin(), it));
|
||||||
|
|
||||||
|
if (cp.size() == 0)
|
||||||
|
{
|
||||||
|
WarningInFunction
|
||||||
|
<< "No eigenvalue with mag(eigenvalue) larger than "
|
||||||
|
<< "minEval = " << minEval_ << " was found." << nl
|
||||||
|
<< " Input field may contain only zero-value elements," << nl
|
||||||
|
<< " e.g. no-slip velocity condition on a given patch." << nl
|
||||||
|
<< " Otherwise, please decrease the value of minEval." << nl
|
||||||
|
<< " Skipping further dynamics/mode computations." << nl
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
fail = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
evals_ = cp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Pstream::scatter(fail);
|
||||||
|
|
||||||
|
if (fail)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pstream::scatter(evals_);
|
||||||
|
Pstream::scatter(evecs_);
|
||||||
|
|
||||||
|
Atilde.clear();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::DMDModels::STDMD::frequencies()
|
||||||
|
{
|
||||||
|
if (Pstream::master())
|
||||||
|
{
|
||||||
|
Info<< tab << "Computing frequencies" << endl;
|
||||||
|
|
||||||
|
freqs_.resize(evals_.size());
|
||||||
|
|
||||||
|
// Frequency equation (K:Eq. 81)
|
||||||
|
auto frequencyEquation =
|
||||||
|
[&](const complex& eval)
|
||||||
|
{
|
||||||
|
return Foam::log(max(eval, complex(SMALL))).imag()/(twoPi*dt_);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Compute frequencies
|
||||||
|
std::transform
|
||||||
|
(
|
||||||
|
evals_.cbegin(),
|
||||||
|
evals_.cend(),
|
||||||
|
freqs_.begin(),
|
||||||
|
frequencyEquation
|
||||||
|
);
|
||||||
|
|
||||||
|
Info<< tab << "Computing frequency indices" << endl;
|
||||||
|
|
||||||
|
// Initialise iterator by the first search
|
||||||
|
auto margin = [&](const scalar& x){ return (fMin_ <= x && x < fMax_); };
|
||||||
|
|
||||||
|
auto it = std::find_if(freqs_.cbegin(), freqs_.cend(), margin);
|
||||||
|
|
||||||
|
while (it != freqs_.end())
|
||||||
|
{
|
||||||
|
freqsi_.append(std::distance(freqs_.cbegin(), it));
|
||||||
|
it = std::find_if(std::next(it), freqs_.cend(), margin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Pstream::scatter(freqs_);
|
||||||
|
Pstream::scatter(freqsi_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::DMDModels::STDMD::amplitudes()
|
||||||
|
{
|
||||||
|
const IOField<scalar> snapshot0
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"snapshot0_" + name_ + "_" + fieldName_,
|
||||||
|
timeName0_,
|
||||||
|
mesh_,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
RMatrix snapshot(1, 1, Zero);
|
||||||
|
if (!empty_)
|
||||||
|
{
|
||||||
|
snapshot.resize(Qupper_.m(), 1);
|
||||||
|
std::copy(snapshot0.cbegin(), snapshot0.cend(), snapshot.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
RMatrix R((RxInv_.T()^Qupper_)*snapshot);
|
||||||
|
reduce(R, sumOp<RMatrix>());
|
||||||
|
|
||||||
|
if (Pstream::master())
|
||||||
|
{
|
||||||
|
Info<< tab << "Computing amplitudes" << endl;
|
||||||
|
|
||||||
|
amps_.resize(R.m());
|
||||||
|
const RCMatrix pEvecs(pinv(evecs_));
|
||||||
|
|
||||||
|
// amps_ = pEvecs*R;
|
||||||
|
for (label i = 0; i < amps_.size(); ++i)
|
||||||
|
{
|
||||||
|
for (label j = 0; j < R.m(); ++j)
|
||||||
|
{
|
||||||
|
amps_[i] += pEvecs(i, j)*R(j, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Pstream::scatter(amps_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::DMDModels::STDMD::magnitudes()
|
||||||
|
{
|
||||||
|
if (Pstream::master())
|
||||||
|
{
|
||||||
|
Info<< tab << "Computing magnitudes" << endl;
|
||||||
|
|
||||||
|
mags_.resize(amps_.size());
|
||||||
|
|
||||||
|
Info<< tab << "Sorting modes with ";
|
||||||
|
|
||||||
|
switch (modeSorter_)
|
||||||
|
{
|
||||||
|
case modeSorterType::FIRST_SNAPSHOT:
|
||||||
|
{
|
||||||
|
Info<< "method of first snapshot" << endl;
|
||||||
|
|
||||||
|
std::transform
|
||||||
|
(
|
||||||
|
amps_.cbegin(),
|
||||||
|
amps_.cend(),
|
||||||
|
mags_.begin(),
|
||||||
|
[&](const complex& val){ return mag(val); }
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case modeSorterType::KIEWAT:
|
||||||
|
{
|
||||||
|
Info<< "modified weighted amplitude scaling method" << endl;
|
||||||
|
|
||||||
|
// Eigendecomposition returns evecs with
|
||||||
|
// the unity norm, hence "modeNorm = 1"
|
||||||
|
const scalar modeNorm = 1;
|
||||||
|
const scalar pr = 1;
|
||||||
|
List<scalar> w(step_);
|
||||||
|
std::iota(w.begin(), w.end(), 1);
|
||||||
|
w = sin(twoPi/step_*(w - 1 - 0.25*step_))*pr + pr;
|
||||||
|
|
||||||
|
forAll(amps_, i)
|
||||||
|
{
|
||||||
|
mags_[i] = sorter(w, amps_[i], evals_[i], modeNorm);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case modeSorterType::KOU_ZHANG:
|
||||||
|
{
|
||||||
|
Info<< "weighted amplitude scaling method" << endl;
|
||||||
|
|
||||||
|
const scalar modeNorm = 1;
|
||||||
|
const List<scalar> w(step_, 1.0);
|
||||||
|
|
||||||
|
forAll(amps_, i)
|
||||||
|
{
|
||||||
|
mags_[i] = sorter(w, amps_[i], evals_[i], modeNorm);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Info<< tab << "Computing magnitude indices" << endl;
|
||||||
|
|
||||||
|
magsi_ = freqsi_;
|
||||||
|
|
||||||
|
auto descend =
|
||||||
|
[&](const label i1, const label i2)
|
||||||
|
{
|
||||||
|
return !(mags_[i1] < mags_[i2]);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::sort(magsi_.begin(), magsi_.end(), descend);
|
||||||
|
}
|
||||||
|
Pstream::scatter(mags_);
|
||||||
|
Pstream::scatter(magsi_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::scalar Foam::DMDModels::STDMD::sorter
|
||||||
|
(
|
||||||
|
const List<scalar>& weight,
|
||||||
|
const complex& amplitude,
|
||||||
|
const complex& eigenvalue,
|
||||||
|
const scalar modeNorm
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
// Omit eigenvalues with very large or very small mags
|
||||||
|
if (!(mag(eigenvalue) < GREAT && mag(eigenvalue) > VSMALL))
|
||||||
|
{
|
||||||
|
Info<< " Returning zero magnitude for mag(eigenvalue) = "
|
||||||
|
<< mag(eigenvalue) << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Omit eigenvalue-STDMD step combinations that pose a risk of overflow
|
||||||
|
if (mag(eigenvalue)*step_ > sortLimiter_)
|
||||||
|
{
|
||||||
|
Info<< " Returning zero magnitude for"
|
||||||
|
<< " mag(eigenvalue) = " << mag(eigenvalue)
|
||||||
|
<< " current index = " << step_
|
||||||
|
<< " sortLimiter = " << sortLimiter_
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
scalar magnitude = 0;
|
||||||
|
|
||||||
|
for (label j = 0; j < step_; ++j)
|
||||||
|
{
|
||||||
|
magnitude += weight[j]*modeNorm*mag(amplitude*pow(eigenvalue, j + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return magnitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::DMDModels::STDMD::dynamics()
|
||||||
|
{
|
||||||
|
SMatrix Atilde(reducedKoopmanOperator());
|
||||||
|
G_.clear();
|
||||||
|
|
||||||
|
if(!eigendecomposition(Atilde))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
frequencies();
|
||||||
|
|
||||||
|
amplitudes();
|
||||||
|
|
||||||
|
magnitudes();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::DMDModels::STDMD::modes()
|
||||||
|
{
|
||||||
|
Info<< tab << "Computing modes" << endl;
|
||||||
|
|
||||||
|
bool processed = false;
|
||||||
|
processed = processed || modes<scalar>();
|
||||||
|
processed = processed || modes<vector>();
|
||||||
|
processed = processed || modes<sphericalTensor>();
|
||||||
|
processed = processed || modes<symmTensor>();
|
||||||
|
processed = processed || modes<tensor>();
|
||||||
|
|
||||||
|
if (!processed)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::DMDModels::STDMD::writeToFile(const word& fileName) const
|
||||||
|
{
|
||||||
|
Info<< tab << "Writing objects of dynamics" << endl;
|
||||||
|
|
||||||
|
// Write objects of dynamics
|
||||||
|
{
|
||||||
|
autoPtr<OFstream> osPtr =
|
||||||
|
createFile
|
||||||
|
(
|
||||||
|
fileName + "_" + fieldName_,
|
||||||
|
mesh_.time().timeOutputValue()
|
||||||
|
);
|
||||||
|
OFstream& os = osPtr.ref();
|
||||||
|
|
||||||
|
writeFileHeader(os);
|
||||||
|
|
||||||
|
for (const auto& i : labelRange(0, freqs_.size()))
|
||||||
|
{
|
||||||
|
os << freqs_[i] << tab
|
||||||
|
<< mags_[i] << tab
|
||||||
|
<< amps_[i].real() << tab
|
||||||
|
<< amps_[i].imag() << tab
|
||||||
|
<< evals_[i].real() << tab
|
||||||
|
<< evals_[i].imag() << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Info<< tab << "Ends output processing for field: " << fieldName_
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::DMDModels::STDMD::writeFileHeader(Ostream& os) const
|
||||||
|
{
|
||||||
|
writeHeader(os, "DMD output");
|
||||||
|
writeCommented(os, "Frequency");
|
||||||
|
writeTabbed(os, "Magnitude");
|
||||||
|
writeTabbed(os, "Amplitude (real)");
|
||||||
|
writeTabbed(os, "Amplitude (imag)");
|
||||||
|
writeTabbed(os, "Eigenvalue (real)");
|
||||||
|
writeTabbed(os, "Eigenvalue (imag)");
|
||||||
|
os << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::DMDModels::STDMD::filter()
|
||||||
|
{
|
||||||
|
Info<< tab << "Filtering objects of dynamics" << endl;
|
||||||
|
|
||||||
|
// Filter objects according to iMags
|
||||||
|
filterIndexed(evals_, magsi_);
|
||||||
|
filterIndexed(evecs_, magsi_);
|
||||||
|
filterIndexed(freqs_, magsi_);
|
||||||
|
filterIndexed(amps_, magsi_);
|
||||||
|
filterIndexed(mags_, magsi_);
|
||||||
|
|
||||||
|
// Clip objects if need be (assuming objects have the same len)
|
||||||
|
if (freqs_.size() > nModes_)
|
||||||
|
{
|
||||||
|
evals_.resize(nModes_);
|
||||||
|
evecs_.resize(evecs_.m(), nModes_);
|
||||||
|
freqs_.resize(nModes_);
|
||||||
|
amps_.resize(nModes_);
|
||||||
|
mags_.resize(nModes_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::DMDModels::STDMD::STDMD
|
||||||
|
(
|
||||||
|
const fvMesh& mesh,
|
||||||
|
const word& name,
|
||||||
|
const dictionary& dict
|
||||||
|
)
|
||||||
|
:
|
||||||
|
DMDModel(mesh, name, dict),
|
||||||
|
modeSorter_
|
||||||
|
(
|
||||||
|
modeSorterTypeNames.getOrDefault
|
||||||
|
(
|
||||||
|
"modeSorter",
|
||||||
|
dict,
|
||||||
|
modeSorterType::FIRST_SNAPSHOT
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Q_(),
|
||||||
|
G_(),
|
||||||
|
Qupper_(1, 1, Zero),
|
||||||
|
Qlower_(1, 1, Zero),
|
||||||
|
RxInv_(1, 1, Zero),
|
||||||
|
evals_(Zero),
|
||||||
|
evecs_(1, 1, Zero),
|
||||||
|
freqs_(Zero),
|
||||||
|
freqsi_(),
|
||||||
|
amps_(Zero),
|
||||||
|
mags_(Zero),
|
||||||
|
magsi_(Zero),
|
||||||
|
fieldName_(dict.get<word>("field")),
|
||||||
|
patch_(dict.getOrDefault<word>("patch", word::null)),
|
||||||
|
timeName0_(),
|
||||||
|
minBasis_(0),
|
||||||
|
minEval_(0),
|
||||||
|
dt_(0),
|
||||||
|
sortLimiter_(500),
|
||||||
|
fMin_(0),
|
||||||
|
fMax_(pTraits<label>::max),
|
||||||
|
nGramSchmidt_(5),
|
||||||
|
maxRank_(pTraits<label>::max),
|
||||||
|
step_(0),
|
||||||
|
nModes_(pTraits<label>::max),
|
||||||
|
nAgglomerationProcs_(20),
|
||||||
|
empty_(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
bool Foam::DMDModels::STDMD::read(const dictionary& dict)
|
||||||
|
{
|
||||||
|
writeToFile_ = dict.getOrDefault<bool>("writeToFile", true);
|
||||||
|
|
||||||
|
modeSorter_ =
|
||||||
|
modeSorterTypeNames.getOrDefault
|
||||||
|
(
|
||||||
|
"modeSorter",
|
||||||
|
dict,
|
||||||
|
modeSorterType::FIRST_SNAPSHOT
|
||||||
|
);
|
||||||
|
|
||||||
|
minBasis_ =
|
||||||
|
dict.getCheckOrDefault<scalar>("minBasis", 1e-8, scalarMinMax::ge(0));
|
||||||
|
|
||||||
|
minEval_ =
|
||||||
|
dict.getCheckOrDefault<scalar>("minEVal", 1e-8, scalarMinMax::ge(0));
|
||||||
|
|
||||||
|
dt_ =
|
||||||
|
dict.getCheckOrDefault<scalar>
|
||||||
|
(
|
||||||
|
"interval",
|
||||||
|
(
|
||||||
|
dict.getCheck<label>("executeInterval", labelMinMax::ge(1))
|
||||||
|
*mesh_.time().deltaT().value()
|
||||||
|
),
|
||||||
|
scalarMinMax::ge(0)
|
||||||
|
);
|
||||||
|
|
||||||
|
sortLimiter_ =
|
||||||
|
dict.getCheckOrDefault<scalar>("sortLimiter", 500, scalarMinMax::ge(1));
|
||||||
|
|
||||||
|
nGramSchmidt_ =
|
||||||
|
dict.getCheckOrDefault<label>("nGramSchmidt", 5, labelMinMax::ge(1));
|
||||||
|
|
||||||
|
maxRank_ =
|
||||||
|
dict.getCheckOrDefault<label>
|
||||||
|
(
|
||||||
|
"maxRank",
|
||||||
|
pTraits<label>::max,
|
||||||
|
labelMinMax::ge(1)
|
||||||
|
);
|
||||||
|
|
||||||
|
nModes_ =
|
||||||
|
dict.getCheckOrDefault<label>
|
||||||
|
(
|
||||||
|
"nModes",
|
||||||
|
pTraits<label>::max,
|
||||||
|
labelMinMax::ge(1)
|
||||||
|
);
|
||||||
|
|
||||||
|
fMin_ = dict.getCheckOrDefault<label>("fMin", 0, labelMinMax::ge(0));
|
||||||
|
|
||||||
|
fMax_ =
|
||||||
|
dict.getCheckOrDefault<label>
|
||||||
|
(
|
||||||
|
"fMax",
|
||||||
|
pTraits<label>::max,
|
||||||
|
labelMinMax::ge(fMin_ + 1)
|
||||||
|
);
|
||||||
|
|
||||||
|
nAgglomerationProcs_ =
|
||||||
|
dict.getCheckOrDefault<label>
|
||||||
|
(
|
||||||
|
"nAgglomerationProcs",
|
||||||
|
20,
|
||||||
|
labelMinMax::ge(1)
|
||||||
|
);
|
||||||
|
|
||||||
|
Info<< tab << "Settings are read for:" << nl
|
||||||
|
<< " field: " << fieldName_ << nl
|
||||||
|
<< " modeSorter: " << modeSorterTypeNames[modeSorter_] << nl
|
||||||
|
<< " nModes: " << nModes_ << nl
|
||||||
|
<< " maxRank: " << maxRank_ << nl
|
||||||
|
<< " nGramSchmidt: " << nGramSchmidt_ << nl
|
||||||
|
<< " fMin: " << fMin_ << nl
|
||||||
|
<< " fMax: " << fMax_ << nl
|
||||||
|
<< " minBasis: " << minBasis_ << nl
|
||||||
|
<< " minEVal: " << minEval_ << nl
|
||||||
|
<< " sortLimiter: " << sortLimiter_ << nl
|
||||||
|
<< " nAgglomerationProcs: " << nAgglomerationProcs_ << nl
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::DMDModels::STDMD::initialise(const RMatrix& z)
|
||||||
|
{
|
||||||
|
const scalar norm = L2norm(z);
|
||||||
|
|
||||||
|
if (mag(norm) > 0)
|
||||||
|
{
|
||||||
|
// First-processed snapshot required by the mode-sorting
|
||||||
|
// algorithms at the final output computations (K:p. 43)
|
||||||
|
{
|
||||||
|
const label nSnap = z.m()/2;
|
||||||
|
|
||||||
|
if (nSnap == 0)
|
||||||
|
{
|
||||||
|
empty_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
scalarField snapshot0(nSnap);
|
||||||
|
std::copy(z.cbegin(), z.cbegin() + nSnap, snapshot0.begin());
|
||||||
|
timeName0_ = mesh_.time().timeName();
|
||||||
|
|
||||||
|
IOField<scalar>
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"snapshot0_" + name_ + "_" + fieldName_,
|
||||||
|
timeName0_,
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
snapshot0
|
||||||
|
).write();
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_ = z/norm;
|
||||||
|
G_ = SMatrix(1);
|
||||||
|
G_(0,0) = sqr(norm);
|
||||||
|
|
||||||
|
++step_;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::DMDModels::STDMD::update(const RMatrix& z)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
//- Working copy of the augmented snapshot matrix "z"
|
||||||
|
//- being used in the classical Gram-Schmidt process
|
||||||
|
const RMatrix ez(orthonormalise(z));
|
||||||
|
|
||||||
|
// Check basis for "z" and, if necessary, expand "Q" and "G"
|
||||||
|
const scalar ezNorm = L2norm(ez);
|
||||||
|
const scalar zNorm = L2norm(z);
|
||||||
|
|
||||||
|
if (ezNorm/zNorm > minBasis_)
|
||||||
|
{
|
||||||
|
expand(ez, ezNorm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update "G" before the potential orthonormal basis compression
|
||||||
|
{
|
||||||
|
RMatrix zTilde(Q_ & z);
|
||||||
|
reduce(zTilde, sumOp<RMatrix>());
|
||||||
|
|
||||||
|
G_ += SMatrix(zTilde^zTilde);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compress the orthonormal basis if required
|
||||||
|
if (Q_.n() >= maxRank_)
|
||||||
|
{
|
||||||
|
compress();
|
||||||
|
}
|
||||||
|
|
||||||
|
++step_;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::DMDModels::STDMD::fit()
|
||||||
|
{
|
||||||
|
// DMD statistics and mode evaluation (K:Fig. 16)
|
||||||
|
const label nSnap = Q_.m()/2;
|
||||||
|
|
||||||
|
// Move upper and lower halves of "Q" to new containers
|
||||||
|
Qupper_ = RMatrix(Q_.subMatrix(0, 0, max(nSnap, 1)));
|
||||||
|
Qlower_ = RMatrix(Q_.subMatrix(nSnap, 0, max(nSnap, 1)));
|
||||||
|
Q_.clear();
|
||||||
|
|
||||||
|
if (!dynamics())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
modes();
|
||||||
|
|
||||||
|
if (Pstream::master() && writeToFile_)
|
||||||
|
{
|
||||||
|
writeToFile(word("dynamics"));
|
||||||
|
|
||||||
|
filter();
|
||||||
|
|
||||||
|
writeToFile(word("filteredDynamics"));
|
||||||
|
}
|
||||||
|
|
||||||
|
step_ = 0;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
530
src/functionObjects/field/DMD/DMDModels/derived/STDMD/STDMD.H
Normal file
530
src/functionObjects/field/DMD/DMDModels/derived/STDMD/STDMD.H
Normal file
@ -0,0 +1,530 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2020-2021 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::DMDModels::STDMD
|
||||||
|
|
||||||
|
Description
|
||||||
|
Streaming Total Dynamic Mode Decomposition (i.e. \c STDMD)
|
||||||
|
is a variant of dynamic mode decomposition.
|
||||||
|
|
||||||
|
Among other Dynamic Mode Decomposition (DMD) variants, \c STDMD is
|
||||||
|
presumed to provide the general DMD method capabilities alongside
|
||||||
|
economised and feasible memory and CPU usage.
|
||||||
|
|
||||||
|
The code implementation corresponds to Figs. 15-16 of the first citation
|
||||||
|
below, more broadly to Section 2.4.
|
||||||
|
|
||||||
|
References:
|
||||||
|
\verbatim
|
||||||
|
DMD and mode-sorting algorithms (tags:K, HRDC, KZ, HWR):
|
||||||
|
Kiewat, M. (2019).
|
||||||
|
Streaming modal decomposition approaches for vehicle aerodynamics.
|
||||||
|
PhD thesis. Munich: Technical University of Munich.
|
||||||
|
URL:mediatum.ub.tum.de/doc/1482652/1482652.pdf
|
||||||
|
|
||||||
|
Hemati, M. S., Rowley, C. W.,
|
||||||
|
Deem, E. A., & Cattafesta, L. N. (2017).
|
||||||
|
De-biasing the dynamic mode decomposition
|
||||||
|
for applied Koopman spectral analysis of noisy datasets.
|
||||||
|
Theoretical and Computational Fluid Dynamics, 31(4), 349-368.
|
||||||
|
DOI:10.1007/s00162-017-0432-2
|
||||||
|
|
||||||
|
Kou, J., & Zhang, W. (2017).
|
||||||
|
An improved criterion to select
|
||||||
|
dominant modes from dynamic mode decomposition.
|
||||||
|
European Journal of Mechanics-B/Fluids, 62, 109-129.
|
||||||
|
DOI:10.1016/j.euromechflu.2016.11.015
|
||||||
|
|
||||||
|
Hemati, M. S., Williams, M. O., & Rowley, C. W. (2014).
|
||||||
|
Dynamic mode decomposition for large and streaming datasets.
|
||||||
|
Physics of Fluids, 26(11), 111701.
|
||||||
|
DOI:10.1063/1.4901016
|
||||||
|
|
||||||
|
Parallel classical Gram-Schmidt process (tag:Ka):
|
||||||
|
Katagiri, T. (2003).
|
||||||
|
Performance evaluation of parallel
|
||||||
|
Gram-Schmidt re-orthogonalization methods.
|
||||||
|
In: Palma J. M. L. M., Sousa A. A., Dongarra J., Hernández V. (eds)
|
||||||
|
High Performance Computing for Computational Science — VECPAR 2002.
|
||||||
|
Lecture Notes in Computer Science, vol 2565, p. 302-314.
|
||||||
|
Berlin, Heidelberg: Springer.
|
||||||
|
DOI:10.1007/3-540-36569-9_19
|
||||||
|
|
||||||
|
Parallel direct tall-skinny QR decomposition (tags:BGD, DGHL):
|
||||||
|
Benson, A. R., Gleich, D. F., & Demmel, J. (2013).
|
||||||
|
Direct QR factorizations for
|
||||||
|
tall-and-skinny matrices in MapReduce architectures.
|
||||||
|
2013 IEEE International Conference on Big Data.
|
||||||
|
DOI:10.1109/bigdata.2013.6691583
|
||||||
|
|
||||||
|
Demmel, J., Grigori, L., Hoemmen, M., & Langou, J. (2012).
|
||||||
|
Communication-optimal parallel
|
||||||
|
and sequential QR and LU factorizations.
|
||||||
|
SIAM Journal on Scientific Computing, 34(1), A206-A239.
|
||||||
|
DOI:10.1137/080731992
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
Usage
|
||||||
|
Minimal example by using \c system/controlDict.functions:
|
||||||
|
\verbatim
|
||||||
|
DMD1
|
||||||
|
{
|
||||||
|
// Mandatory/Optional entries
|
||||||
|
...
|
||||||
|
|
||||||
|
// Mandatory entries (unmodifiable)
|
||||||
|
DMDModel STDMD;
|
||||||
|
|
||||||
|
// Conditional mandatory entries (runtime modifiable)
|
||||||
|
|
||||||
|
// Option-1
|
||||||
|
interval 5.5;
|
||||||
|
|
||||||
|
// Option-2
|
||||||
|
executeInterval 10;
|
||||||
|
|
||||||
|
// Optional entries (runtime modifiable)
|
||||||
|
modeSorter kiewat;
|
||||||
|
nGramSchmidt 5;
|
||||||
|
maxRank 50;
|
||||||
|
nModes 50;
|
||||||
|
fMin 0;
|
||||||
|
fMax 1000000000;
|
||||||
|
nAgglomerationProcs 20;
|
||||||
|
|
||||||
|
// Optional entries (runtime modifiable, yet not recommended)
|
||||||
|
minBasis 0.00000001;
|
||||||
|
minEVal 0.00000001;
|
||||||
|
sortLimiter 500.0;
|
||||||
|
|
||||||
|
// Mandatory/Optional (inherited) entries
|
||||||
|
...
|
||||||
|
}
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
where the entries mean:
|
||||||
|
\table
|
||||||
|
Property | Description | Type | Reqd | Deflt
|
||||||
|
DMDModel | Type: STDMD | word | yes | -
|
||||||
|
interval | STDMD time-step size [s] | scalar | cndtnl <!--
|
||||||
|
--> | executeInterval*(current time-step of the simulation)
|
||||||
|
modeSorter | Mode-sorting algorithm model | word | no <!--
|
||||||
|
--> | firstSnapshot
|
||||||
|
nModes | Number of output modes in input frequency range <!--
|
||||||
|
--> | label | no | GREAT
|
||||||
|
maxRank | Max columns in accumulated matrices | label | no | GREAT
|
||||||
|
nGramSchmidt | Number of Gram-Schmidt iterations | label | no | 5
|
||||||
|
fMin | Min (non-negative) output frequency | label | no | 0
|
||||||
|
fMax | Max output frequency | label | no | GREAT
|
||||||
|
nAgglomerationProcs | Number of processors at each agglomeration <!--
|
||||||
|
--> unit during the computation of reduced Koopman <!--
|
||||||
|
--> operator | label | no | 20
|
||||||
|
minBasis | Orthogonal basis expansion threshold | scalar| no | 1e-8
|
||||||
|
minEVal | Min eigenvalue for below eigenvalues are omitted <!--
|
||||||
|
--> | scalar| no | 1e-8
|
||||||
|
sortLimiter | Max allowable magnitude for <!--
|
||||||
|
--> mag(eigenvalue)*(number of DMD steps) to be used in <!--
|
||||||
|
--> modeSorter={kiewat,kouZhang} to avoid overflow errors <!--
|
||||||
|
--> | scalar | no | 500.0
|
||||||
|
\endtable
|
||||||
|
|
||||||
|
Options for the \c modeSorter entry:
|
||||||
|
\verbatim
|
||||||
|
kiewat | Modified weighted-amplitude scaling method
|
||||||
|
kouZhang | Weighted-amplitude scaling method
|
||||||
|
firstSnapshot | First-snapshot amplitude magnitude method
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
Note
|
||||||
|
- To specify the STDMD time-step size (not necessarily equal to the
|
||||||
|
time step of the simulation), entries of either \c interval or
|
||||||
|
\c executeInterval must be available (highest to lowest precedence). While
|
||||||
|
\c interval allows users to directly specify the STDMD time-step size
|
||||||
|
in seconds, in absence of \c interval, for convenience,
|
||||||
|
\c executeInterval allows users to compute the STDMD time-step internally
|
||||||
|
by multiplying itself with the current time-step size of the simulation.
|
||||||
|
- Limitation: Restart is currently not available since intermediate writing
|
||||||
|
of STDMD matrices are not supported.
|
||||||
|
- Limitation: Non-physical input (e.g. full-zero fields) can upset STDMD.
|
||||||
|
- Warning: In \c modeSorter algorithms of \c kiewat and \c kouZhang, a
|
||||||
|
function of \f$power(x,y)\f$ exists where \c x is the magnitude of an
|
||||||
|
eigenvalue, and \c y is the number of STDMD snapshots. This function poses
|
||||||
|
a risk of overflow errors since, for example, if \c x ends up above 1.5 with
|
||||||
|
500 snapshots or more, this function automatically throws the floating point
|
||||||
|
error meaning overflow. Therefore, the domain-range of this function is
|
||||||
|
heuristically constrained by the optional entry \c sortLimiter which skips
|
||||||
|
the evaluation of this function for a given
|
||||||
|
mag(eigenvalue)*(no. of STDMD steps), i.e. x*y, whose magnitude is larger
|
||||||
|
than \c sortLimiter.
|
||||||
|
|
||||||
|
See also
|
||||||
|
- Foam::functionObjects::DMD
|
||||||
|
- Foam::DMDModel
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
STDMD.C
|
||||||
|
STDMDTemplates.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef DMDModels_STDMD_H
|
||||||
|
#define DMDModels_STDMD_H
|
||||||
|
|
||||||
|
#include "DMDModel.H"
|
||||||
|
#include "SquareMatrix.H"
|
||||||
|
#include "RectangularMatrix.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
namespace DMDModels
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class STDMD Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class STDMD
|
||||||
|
:
|
||||||
|
public DMDModel
|
||||||
|
{
|
||||||
|
typedef SquareMatrix<scalar> SMatrix;
|
||||||
|
typedef RectangularMatrix<scalar> RMatrix;
|
||||||
|
typedef RectangularMatrix<complex> RCMatrix;
|
||||||
|
|
||||||
|
|
||||||
|
// Private Enumerations
|
||||||
|
|
||||||
|
//- Options for the mode-sorting algorithm
|
||||||
|
enum modeSorterType : char
|
||||||
|
{
|
||||||
|
FIRST_SNAPSHOT = 0, //!< "First-snapshot amplitude magnitude method"
|
||||||
|
KIEWAT, //!< "Modified weighted-amplitude scaling method"
|
||||||
|
KOU_ZHANG //!< "Weighted-amplitude scaling method"
|
||||||
|
};
|
||||||
|
|
||||||
|
//- Names for modeSorterType
|
||||||
|
static const Enum<modeSorterType> modeSorterTypeNames;
|
||||||
|
|
||||||
|
|
||||||
|
// Private Data
|
||||||
|
|
||||||
|
//- Mode-sorting algorithm
|
||||||
|
enum modeSorterType modeSorter_;
|
||||||
|
|
||||||
|
//- Accumulated-in-time unitary similarity matrix produced by the
|
||||||
|
//- orthonormal decomposition of the augmented snapshot matrix 'z'
|
||||||
|
// (K:Eq. 60)
|
||||||
|
RMatrix Q_;
|
||||||
|
|
||||||
|
//- Accumulated-in-time (squared) upper triangular matrix produced by
|
||||||
|
//- the orthonormal decomposition of the augmented snapshot matrix 'z'
|
||||||
|
// (K:Eq. 64)
|
||||||
|
SMatrix G_;
|
||||||
|
|
||||||
|
//- Upper half of 'Q'
|
||||||
|
RMatrix Qupper_;
|
||||||
|
|
||||||
|
//- Lower half of 'Q'
|
||||||
|
RMatrix Qlower_;
|
||||||
|
|
||||||
|
//- Moore-Penrose pseudo-inverse of 'R' produced by
|
||||||
|
//- the QR decomposition of the last time-step 'Q'
|
||||||
|
RMatrix RxInv_;
|
||||||
|
|
||||||
|
//- Eigenvalues of modes
|
||||||
|
List<complex> evals_;
|
||||||
|
|
||||||
|
//- Eigenvectors of modes
|
||||||
|
RCMatrix evecs_;
|
||||||
|
|
||||||
|
//- (Non-negative) frequencies of modes
|
||||||
|
List<scalar> freqs_;
|
||||||
|
|
||||||
|
//- Indices of 'freqs' where frequencies are
|
||||||
|
//- non-negative and within ['fMin', 'fMax']
|
||||||
|
DynamicList<label> freqsi_;
|
||||||
|
|
||||||
|
//- Amplitudes of modes
|
||||||
|
List<complex> amps_;
|
||||||
|
|
||||||
|
//- (Descending) magnitudes of (complex) amplitudes of modes
|
||||||
|
List<scalar> mags_;
|
||||||
|
|
||||||
|
//- Indices of 'mags'
|
||||||
|
List<label> magsi_;
|
||||||
|
|
||||||
|
//- Name of operand field
|
||||||
|
const word fieldName_;
|
||||||
|
|
||||||
|
//- Name of operand patch
|
||||||
|
const word patch_;
|
||||||
|
|
||||||
|
//- First-processed snapshot required by the mode-sorting
|
||||||
|
//- algorithms at the final output computations (K:p. 43)
|
||||||
|
word timeName0_;
|
||||||
|
|
||||||
|
//- Min value to execute orthogonal basis expansion of 'Q' and 'G'
|
||||||
|
scalar minBasis_;
|
||||||
|
|
||||||
|
//- Min eigenvalue magnitude below where 'evals' are omitted
|
||||||
|
scalar minEval_;
|
||||||
|
|
||||||
|
//- STDMD time-step size that equals to
|
||||||
|
//- (executeInterval of DMD)*(deltaT of simulation) [s]
|
||||||
|
scalar dt_;
|
||||||
|
|
||||||
|
//- Maximum allowable magnitude for mag(eigenvalue)*(number of
|
||||||
|
//- STDMD steps) to be used in modeSorter={kiewat,kouZhang} to
|
||||||
|
//- avoid overflow errors
|
||||||
|
scalar sortLimiter_;
|
||||||
|
|
||||||
|
//- Min frequency: Output only entries corresponding to freqs >= 'fMin'
|
||||||
|
label fMin_;
|
||||||
|
|
||||||
|
//- Max frequency: Output only entries corresponding to freqs <= 'fMax'
|
||||||
|
label fMax_;
|
||||||
|
|
||||||
|
//- Number of maximum iterations of the classical
|
||||||
|
//- Gram-Schmidt procedure for the orthonormalisation
|
||||||
|
label nGramSchmidt_;
|
||||||
|
|
||||||
|
//- Maximum allowable matrix column for 'Q' and 'G'
|
||||||
|
// 'Q' is assumed to always have full-rank, thus 'Q.n() = rank'
|
||||||
|
label maxRank_;
|
||||||
|
|
||||||
|
//- Current execution-step index of STDMD,
|
||||||
|
//- not necessarily that of the simulation
|
||||||
|
label step_;
|
||||||
|
|
||||||
|
//- Number of output modes within input frequency range
|
||||||
|
//- starting from the most energetic mode
|
||||||
|
label nModes_;
|
||||||
|
|
||||||
|
//- Number of processors at each agglomeration unit
|
||||||
|
//- during the computation of reduced Koopman operator
|
||||||
|
label nAgglomerationProcs_;
|
||||||
|
|
||||||
|
//- (Internal) Flag to tag snapshots which are effectively empty
|
||||||
|
bool empty_;
|
||||||
|
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
// Process
|
||||||
|
|
||||||
|
//- Return (parallel) L2-norm of a given column vector
|
||||||
|
scalar L2norm(const RMatrix& z) const;
|
||||||
|
|
||||||
|
//- Execute (parallel) classical Gram-Schmidt
|
||||||
|
//- process to orthonormalise 'ez' (Ka:Fig. 5)
|
||||||
|
RMatrix orthonormalise(RMatrix ez) const;
|
||||||
|
|
||||||
|
//- Expand orthonormal bases 'Q' and 'G' by stacking a column
|
||||||
|
//- '(ez/ezNorm)' to 'Q', and a row (Zero) and column (Zero)
|
||||||
|
//- to 'G' if '(ezNorm/zNorm > minBasis)'
|
||||||
|
void expand(const RMatrix& ez, const scalar ezNorm);
|
||||||
|
|
||||||
|
//- Compress orthonormal basis for 'Q' and 'G' if '(Q.n()>maxRank)'
|
||||||
|
void compress();
|
||||||
|
|
||||||
|
|
||||||
|
// Evaluation
|
||||||
|
|
||||||
|
//- Return reduced Koopman operator 'Atilde' (K:Eq. 78)
|
||||||
|
// Also fills 'RxInv'.
|
||||||
|
// The function was not divided into subsections to ensure
|
||||||
|
// minimal usage of memory, hence the complexity of the function
|
||||||
|
SMatrix reducedKoopmanOperator();
|
||||||
|
|
||||||
|
//- Compute eigenvalues and eigenvectors of 'Atilde'
|
||||||
|
// Remove any eigenvalues whose magnitude is smaller than
|
||||||
|
// 'minEVal' while keeping the order of elements the same
|
||||||
|
bool eigendecomposition(SMatrix& Atilde);
|
||||||
|
|
||||||
|
//- Compute and filter frequencies and its indices (K:Eq. 81)
|
||||||
|
// Indices of 'freqs' where frequencies are
|
||||||
|
// non-negative and within ['fMin', 'fMax']
|
||||||
|
void frequencies();
|
||||||
|
|
||||||
|
//- Compute amplitudes
|
||||||
|
void amplitudes();
|
||||||
|
|
||||||
|
//- Compute magnitudes and ordered magnitude indices
|
||||||
|
// Includes advanced sorting methods using
|
||||||
|
// the chosen weighted amplitude scaling method
|
||||||
|
void magnitudes();
|
||||||
|
|
||||||
|
//- Eigenvalue weighted amplitude scaling (KZ:Eq. 33)
|
||||||
|
//- Modified eigenvalue weighted amplitude scaling (K)
|
||||||
|
scalar sorter
|
||||||
|
(
|
||||||
|
const List<scalar>& weight,
|
||||||
|
const complex& amplitude,
|
||||||
|
const complex& eigenvalue,
|
||||||
|
const scalar modeNorm
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Compute and write mode dynamics
|
||||||
|
virtual bool dynamics();
|
||||||
|
|
||||||
|
//- Compute and write modes
|
||||||
|
virtual bool modes();
|
||||||
|
|
||||||
|
//- Select field type for modes
|
||||||
|
template<class Type>
|
||||||
|
bool modes();
|
||||||
|
|
||||||
|
//- Compute modes based on input field type
|
||||||
|
template<class GeoFieldType>
|
||||||
|
bool calcModes();
|
||||||
|
|
||||||
|
//- Compute a mode for a given scalar-based input field
|
||||||
|
template<class GeoFieldType>
|
||||||
|
typename std::enable_if
|
||||||
|
<
|
||||||
|
std::is_same<scalar, typename GeoFieldType::value_type>::value,
|
||||||
|
void
|
||||||
|
>::type calcMode
|
||||||
|
(
|
||||||
|
GeoFieldType& modeRe,
|
||||||
|
GeoFieldType& modeIm,
|
||||||
|
const RMatrix& primitiveMode,
|
||||||
|
const label i
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Compute a mode for a given non-scalar-based input field
|
||||||
|
template<class GeoFieldType>
|
||||||
|
typename std::enable_if
|
||||||
|
<
|
||||||
|
!std::is_same<scalar, typename GeoFieldType::value_type>::value,
|
||||||
|
void
|
||||||
|
>::type calcMode
|
||||||
|
(
|
||||||
|
GeoFieldType& modeRe,
|
||||||
|
GeoFieldType& modeIm,
|
||||||
|
const RMatrix& primitiveMode,
|
||||||
|
const label i
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// IO
|
||||||
|
|
||||||
|
//- Write objects of dynamics
|
||||||
|
void writeToFile(const word& fileName) const;
|
||||||
|
|
||||||
|
// Notifying the compiler that we want both writeToFile functions
|
||||||
|
using Foam::functionObjects::writeFile::writeToFile;
|
||||||
|
|
||||||
|
//- Write file header information
|
||||||
|
void writeFileHeader(Ostream& os) const;
|
||||||
|
|
||||||
|
//- Filter objects of dynamics according to 'freqsi' and 'magsi'
|
||||||
|
void filter();
|
||||||
|
|
||||||
|
//- Return a new List containing elems of List at 'indices'
|
||||||
|
template<class Type>
|
||||||
|
void filterIndexed
|
||||||
|
(
|
||||||
|
List<Type>& lst,
|
||||||
|
const UList<label>& indices
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Return a new Matrix containing columns of Matrix at 'indices'
|
||||||
|
template<class MatrixType>
|
||||||
|
void filterIndexed
|
||||||
|
(
|
||||||
|
MatrixType& lst,
|
||||||
|
const UList<label>& indices
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("STDMD");
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from components
|
||||||
|
STDMD
|
||||||
|
(
|
||||||
|
const fvMesh& mesh,
|
||||||
|
const word& name,
|
||||||
|
const dictionary& dict
|
||||||
|
);
|
||||||
|
|
||||||
|
//- No copy construct
|
||||||
|
STDMD(const STDMD&) = delete;
|
||||||
|
|
||||||
|
//- No copy assignment
|
||||||
|
void operator=(const STDMD&) = delete;
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
virtual ~STDMD() = default;
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
// Evaluation
|
||||||
|
|
||||||
|
//- Initialise 'Q' and 'G' (both require the first two snapshots)
|
||||||
|
virtual bool initialise(const RMatrix& z);
|
||||||
|
|
||||||
|
//- Incremental orthonormal basis update (K:Fig. 15)
|
||||||
|
virtual bool update(const RMatrix& z);
|
||||||
|
|
||||||
|
//- Compute and write modes and
|
||||||
|
//- mode dynamics of model data members
|
||||||
|
virtual bool fit();
|
||||||
|
|
||||||
|
|
||||||
|
// IO
|
||||||
|
|
||||||
|
//- Read STDMD settings
|
||||||
|
virtual bool read(const dictionary& dict);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace DMDModels
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#ifdef NoRepository
|
||||||
|
#include "STDMDTemplates.C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,236 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2020-2021 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 "volFields.H"
|
||||||
|
#include "surfaceFields.H"
|
||||||
|
#include "fixedValueFvPatchField.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
void Foam::DMDModels::STDMD::filterIndexed
|
||||||
|
(
|
||||||
|
List<Type>& lst,
|
||||||
|
const UList<label>& indices
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Elements within [a, b]
|
||||||
|
List<Type> lstWithin(indices.size());
|
||||||
|
|
||||||
|
// Copy if frequency of element is within [a, b]
|
||||||
|
label j = 0;
|
||||||
|
for (const auto& i : indices)
|
||||||
|
{
|
||||||
|
lstWithin[j] = lst[i];
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
lst.transfer(lstWithin);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class MatrixType>
|
||||||
|
void Foam::DMDModels::STDMD::filterIndexed
|
||||||
|
(
|
||||||
|
MatrixType& mat,
|
||||||
|
const UList<label>& indices
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Elements within [a, b]
|
||||||
|
MatrixType matWithin(labelPair(mat.m(), indices.size()));
|
||||||
|
|
||||||
|
// Copy if frequency of element is within [a, b]
|
||||||
|
label j = 0;
|
||||||
|
for (const auto& i : indices)
|
||||||
|
{
|
||||||
|
matWithin.subColumn(j) = mat.subColumn(i);
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
mat.transfer(matWithin);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
bool Foam::DMDModels::STDMD::modes()
|
||||||
|
{
|
||||||
|
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
|
||||||
|
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
|
||||||
|
|
||||||
|
if (mesh_.foundObject<VolFieldType>(fieldName_))
|
||||||
|
{
|
||||||
|
return calcModes<VolFieldType>();
|
||||||
|
}
|
||||||
|
else if (mesh_.foundObject<SurfaceFieldType>(fieldName_))
|
||||||
|
{
|
||||||
|
return calcModes<SurfaceFieldType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class GeoFieldType>
|
||||||
|
bool Foam::DMDModels::STDMD::calcModes()
|
||||||
|
{
|
||||||
|
typedef typename GeoFieldType::value_type Type;
|
||||||
|
|
||||||
|
// Resize the number of output variables to "nModes" if requested
|
||||||
|
if (magsi_.size() > nModes_)
|
||||||
|
{
|
||||||
|
magsi_.resize(nModes_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute and write modes one by one
|
||||||
|
const RMatrix primitiveMode(Qupper_*RxInv_);
|
||||||
|
Qupper_.clear();
|
||||||
|
RxInv_.clear();
|
||||||
|
|
||||||
|
label modei = 0;
|
||||||
|
for (const label i : magsi_)
|
||||||
|
{
|
||||||
|
GeoFieldType modeRe
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"modeRe_" + std::to_string(modei)
|
||||||
|
+ "_" + fieldName_ + "_" + name_,
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
false
|
||||||
|
),
|
||||||
|
mesh_,
|
||||||
|
dimensioned<Type>(dimless, Zero),
|
||||||
|
fixedValueFvPatchField<Type>::typeName
|
||||||
|
);
|
||||||
|
|
||||||
|
GeoFieldType modeIm
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"modeIm_" + std::to_string(modei)
|
||||||
|
+ "_" + fieldName_ + "_" + name_,
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
false
|
||||||
|
),
|
||||||
|
mesh_,
|
||||||
|
dimensioned<Type>(dimless, Zero),
|
||||||
|
fixedValueFvPatchField<Type>::typeName
|
||||||
|
);
|
||||||
|
|
||||||
|
if (modeRe.size() != 0 && !empty_)
|
||||||
|
{
|
||||||
|
if (patch_.empty())
|
||||||
|
{
|
||||||
|
auto& inModeRe = modeRe.primitiveFieldRef();
|
||||||
|
auto& inModeIm = modeIm.primitiveFieldRef();
|
||||||
|
|
||||||
|
calcMode(inModeRe, inModeIm, primitiveMode, i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const label patchi = mesh_.boundaryMesh().findPatchID(patch_);
|
||||||
|
|
||||||
|
auto& bfModeRe = modeRe.boundaryFieldRef()[patchi];
|
||||||
|
auto& bfModeIm = modeIm.boundaryFieldRef()[patchi];
|
||||||
|
|
||||||
|
calcMode(bfModeRe, bfModeIm, primitiveMode, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
modeRe.write();
|
||||||
|
modeIm.write();
|
||||||
|
++modei;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class GeoFieldType>
|
||||||
|
typename std::enable_if
|
||||||
|
<
|
||||||
|
std::is_same<Foam::scalar, typename GeoFieldType::value_type>::value,
|
||||||
|
void
|
||||||
|
>::type Foam::DMDModels::STDMD::calcMode
|
||||||
|
(
|
||||||
|
GeoFieldType& modeRe,
|
||||||
|
GeoFieldType& modeIm,
|
||||||
|
const RMatrix& primitiveMode,
|
||||||
|
const label i
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const label fieldSize = modeRe.size();
|
||||||
|
|
||||||
|
for (label p = 0; p < primitiveMode.m(); ++p)
|
||||||
|
{
|
||||||
|
complex mode(Zero);
|
||||||
|
for (label q = 0; q < evecs_.m(); ++q)
|
||||||
|
{
|
||||||
|
mode += primitiveMode(p, q)*evecs_(q, i);
|
||||||
|
}
|
||||||
|
label p1 = p%fieldSize;
|
||||||
|
modeRe[p1] = mode.real();
|
||||||
|
modeIm[p1] = mode.imag();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class GeoFieldType>
|
||||||
|
typename std::enable_if
|
||||||
|
<
|
||||||
|
!std::is_same<Foam::scalar, typename GeoFieldType::value_type>::value,
|
||||||
|
void
|
||||||
|
>::type Foam::DMDModels::STDMD::calcMode
|
||||||
|
(
|
||||||
|
GeoFieldType& modeRe,
|
||||||
|
GeoFieldType& modeIm,
|
||||||
|
const RMatrix& primitiveMode,
|
||||||
|
const label i
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const label fieldSize = modeRe.size();
|
||||||
|
|
||||||
|
for (label p = 0; p < primitiveMode.m(); ++p)
|
||||||
|
{
|
||||||
|
complex mode(Zero);
|
||||||
|
for (label q = 0; q < evecs_.m(); ++q)
|
||||||
|
{
|
||||||
|
mode += primitiveMode(p, q)*evecs_(q, i);
|
||||||
|
}
|
||||||
|
label p1 = p%fieldSize;
|
||||||
|
label p2 = p/fieldSize;
|
||||||
|
modeRe[p1][p2] = mode.real();
|
||||||
|
modeIm[p1][p2] = mode.imag();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -5,7 +5,7 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2020 OpenCFD Ltd.
|
Copyright (C) 2020-2021 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -30,112 +30,83 @@ License
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
template<class GeoFieldType>
|
template<class Type>
|
||||||
bool Foam::functionObjects::STDMD::getSnapshot()
|
bool Foam::functionObjects::DMD::getSnapshot()
|
||||||
{
|
{
|
||||||
if (!initialised_)
|
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
|
||||||
|
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
|
||||||
|
|
||||||
|
if (foundObject<VolFieldType>(fieldName_))
|
||||||
{
|
{
|
||||||
init();
|
return getSnapshotField<VolFieldType>();
|
||||||
|
}
|
||||||
|
else if (foundObject<SurfaceFieldType>(fieldName_))
|
||||||
|
{
|
||||||
|
return getSnapshotField<SurfaceFieldType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move previous-time snapshot into previous-time slot in z_
|
return false;
|
||||||
// Effectively moves the lower half of z_ to its upper half
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class GeoFieldType>
|
||||||
|
bool Foam::functionObjects::DMD::getSnapshotField()
|
||||||
|
{
|
||||||
|
if (step_ == 0)
|
||||||
|
{
|
||||||
|
initialise();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (z_.size() == 1)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move previous-time snapshot into previous-time slot in "z"
|
||||||
|
// Effectively moves the lower half of "z" to its upper half
|
||||||
std::rotate(z_.begin(), z_.begin() + nSnap_, z_.end());
|
std::rotate(z_.begin(), z_.begin() + nSnap_, z_.end());
|
||||||
|
|
||||||
// Copy new current-time snapshot into current-time slot in z_
|
// Copy new current-time snapshot into current-time slot in "z"
|
||||||
// Effectively copies the new field elements into the lower half of z_
|
// Effectively copies the new field elements into the lower half of "z"
|
||||||
const GeoFieldType& Field = lookupObject<GeoFieldType>(fieldName_);
|
const label nComps =
|
||||||
const label nField = Field.size();
|
pTraits<typename GeoFieldType::value_type>::nComponents;
|
||||||
|
|
||||||
for (direction dir = 0; dir < nComps_; ++dir)
|
const GeoFieldType& field = lookupObject<GeoFieldType>(fieldName_);
|
||||||
|
|
||||||
|
if (patch_.empty())
|
||||||
{
|
{
|
||||||
z_.subColumn(0, nSnap_ + dir*nField, nField) = Field.component(dir);
|
const label nField = field.size();
|
||||||
|
|
||||||
|
for (direction dir = 0; dir < nComps; ++dir)
|
||||||
|
{
|
||||||
|
z_.subColumn(0, nSnap_ + dir*nField, nField) = field.component(dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const label patchi = mesh_.boundaryMesh().findPatchID(patch_);
|
||||||
|
|
||||||
|
if (patchi < 0)
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "Cannot find patch " << patch_
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
const typename GeoFieldType::Boundary& bf = field.boundaryField();
|
||||||
|
|
||||||
|
const Field<typename GeoFieldType::value_type>& pbf = bf[patchi];
|
||||||
|
|
||||||
|
const label nField = pbf.size();
|
||||||
|
|
||||||
|
for (direction dir = 0; dir < nComps; ++dir)
|
||||||
|
{
|
||||||
|
z_.subColumn(0, nSnap_ + dir*nField, nField) = pbf.component(dir);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class Type>
|
|
||||||
bool Foam::functionObjects::STDMD::getSnapshotType()
|
|
||||||
{
|
|
||||||
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
|
|
||||||
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
|
|
||||||
|
|
||||||
if (foundObject<VolFieldType>(fieldName_))
|
|
||||||
{
|
|
||||||
return getSnapshot<VolFieldType>();
|
|
||||||
}
|
|
||||||
else if (foundObject<SurfaceFieldType>(fieldName_))
|
|
||||||
{
|
|
||||||
return getSnapshot<SurfaceFieldType>();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class Type>
|
|
||||||
bool Foam::functionObjects::STDMD::getComps()
|
|
||||||
{
|
|
||||||
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
|
|
||||||
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
|
|
||||||
|
|
||||||
if (foundObject<VolFieldType>(fieldName_))
|
|
||||||
{
|
|
||||||
nComps_ = pTraits<typename VolFieldType::value_type>::nComponents;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (foundObject<SurfaceFieldType>(fieldName_))
|
|
||||||
{
|
|
||||||
nComps_ = pTraits<typename SurfaceFieldType::value_type>::nComponents;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class Type>
|
|
||||||
void Foam::functionObjects::STDMD::filterIndexed
|
|
||||||
(
|
|
||||||
List<Type>& lst,
|
|
||||||
const UList<label>& indices
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Elems within [a, b]
|
|
||||||
List<Type> lstWithin(indices.size());
|
|
||||||
|
|
||||||
// Copy if frequency of elem is within [a, b]
|
|
||||||
label j = 0;
|
|
||||||
for (const auto& i : indices)
|
|
||||||
{
|
|
||||||
lstWithin[j] = lst[i];
|
|
||||||
++j;
|
|
||||||
}
|
|
||||||
lst.transfer(lstWithin);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class MatrixType>
|
|
||||||
void Foam::functionObjects::STDMD::filterIndexed
|
|
||||||
(
|
|
||||||
MatrixType& mat,
|
|
||||||
const UList<label>& indices
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Elems within [a, b]
|
|
||||||
MatrixType matWithin(labelPair(mat.m(), indices.size()));
|
|
||||||
|
|
||||||
// Copy if frequency of elem is within [a, b]
|
|
||||||
label j = 0;
|
|
||||||
for (const auto& i : indices)
|
|
||||||
{
|
|
||||||
matWithin.subColumn(j) = mat.subColumn(i);
|
|
||||||
++j;
|
|
||||||
}
|
|
||||||
mat.transfer(matWithin);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
@ -121,6 +121,9 @@ stabilityBlendingFactor/stabilityBlendingFactor.C
|
|||||||
|
|
||||||
interfaceHeight/interfaceHeight.C
|
interfaceHeight/interfaceHeight.C
|
||||||
|
|
||||||
STDMD/STDMD.C
|
DMD/DMD.C
|
||||||
|
DMD/DMDModels/DMDModel/DMDModel.C
|
||||||
|
DMD/DMDModels/DMDModel/DMDModelNew.C
|
||||||
|
DMD/DMDModels/derived/STDMD/STDMD.C
|
||||||
|
|
||||||
LIB = $(FOAM_LIBBIN)/libfieldFunctionObjects
|
LIB = $(FOAM_LIBBIN)/libfieldFunctionObjects
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
EXE_INC = \
|
EXE_INC = \
|
||||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
|
-I$(LIB_SRC)/finiteArea/lnInclude \
|
||||||
-I$(LIB_SRC)/fileFormats/lnInclude \
|
-I$(LIB_SRC)/fileFormats/lnInclude \
|
||||||
-I$(LIB_SRC)/surfMesh/lnInclude \
|
-I$(LIB_SRC)/surfMesh/lnInclude \
|
||||||
-I$(LIB_SRC)/meshTools/lnInclude \
|
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||||
@ -22,6 +23,7 @@ EXE_INC = \
|
|||||||
|
|
||||||
LIB_LIBS = \
|
LIB_LIBS = \
|
||||||
-lfiniteVolume \
|
-lfiniteVolume \
|
||||||
|
-lfiniteArea \
|
||||||
-lfileFormats \
|
-lfileFormats \
|
||||||
-lsurfMesh \
|
-lsurfMesh \
|
||||||
-lmeshTools \
|
-lmeshTools \
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,645 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | www.openfoam.com
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Copyright (C) 2020 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::STDMD
|
|
||||||
|
|
||||||
Group
|
|
||||||
grpFieldFunctionObjects
|
|
||||||
|
|
||||||
Description
|
|
||||||
(Beta Release) STDMD (i.e. Streaming Total Dynamic Mode Decomposition) is
|
|
||||||
a variant of a data-driven dimensionality reduction method.
|
|
||||||
|
|
||||||
STDMD is being used as a mathematical post-processing tool to compute
|
|
||||||
a set of dominant modes out of a given flow (or dataset) each of which is
|
|
||||||
associated with a constant frequency and decay rate, so that dynamic
|
|
||||||
features of a given flow may become interpretable, and tractable.
|
|
||||||
Among other Dynamic Mode Decomposition (DMD) variants, STDMD is presumed
|
|
||||||
to provide the general DMD method capabilities alongside economised and
|
|
||||||
feasible memory and CPU usage.
|
|
||||||
|
|
||||||
The code implementation corresponds to Figs. 15-16 of the first citation
|
|
||||||
below, more broadly to Section 2.4.
|
|
||||||
|
|
||||||
References:
|
|
||||||
\verbatim
|
|
||||||
STDMD and mode-sorting algorithms (tags:K, HRDC, KZ, HWR):
|
|
||||||
Kiewat, M. (2019).
|
|
||||||
Streaming modal decomposition approaches for vehicle aerodynamics.
|
|
||||||
PhD thesis. Munich: Technical University of Munich.
|
|
||||||
URL:mediatum.ub.tum.de/doc/1482652/1482652.pdf
|
|
||||||
|
|
||||||
Hemati, M. S., Rowley, C. W.,
|
|
||||||
Deem, E. A., & Cattafesta, L. N. (2017).
|
|
||||||
De-biasing the dynamic mode decomposition
|
|
||||||
for applied Koopman spectral analysis of noisy datasets.
|
|
||||||
Theoretical and Computational Fluid Dynamics, 31(4), 349-368.
|
|
||||||
DOI:10.1007/s00162-017-0432-2
|
|
||||||
|
|
||||||
Kou, J., & Zhang, W. (2017).
|
|
||||||
An improved criterion to select
|
|
||||||
dominant modes from dynamic mode decomposition.
|
|
||||||
European Journal of Mechanics-B/Fluids, 62, 109-129.
|
|
||||||
DOI:10.1016/j.euromechflu.2016.11.015
|
|
||||||
|
|
||||||
Hemati, M. S., Williams, M. O., & Rowley, C. W. (2014).
|
|
||||||
Dynamic mode decomposition for large and streaming datasets.
|
|
||||||
Physics of Fluids, 26(11), 111701.
|
|
||||||
DOI:10.1063/1.4901016
|
|
||||||
|
|
||||||
Parallel classical Gram-Schmidt process (tag:Ka):
|
|
||||||
Katagiri, T. (2003).
|
|
||||||
Performance evaluation of parallel
|
|
||||||
Gram-Schmidt re-orthogonalization methods.
|
|
||||||
In: Palma J. M. L. M., Sousa A. A., Dongarra J., Hernández V. (eds)
|
|
||||||
High Performance Computing for Computational Science — VECPAR 2002.
|
|
||||||
Lecture Notes in Computer Science, vol 2565, p. 302-314.
|
|
||||||
Berlin, Heidelberg: Springer.
|
|
||||||
DOI:10.1007/3-540-36569-9_19
|
|
||||||
|
|
||||||
Parallel direct tall-skinny QR decomposition (tags:BGD, DGHL):
|
|
||||||
Benson, A. R., Gleich, D. F., & Demmel, J. (2013).
|
|
||||||
Direct QR factorizations for
|
|
||||||
tall-and-skinny matrices in MapReduce architectures.
|
|
||||||
2013 IEEE International Conference on Big Data.
|
|
||||||
DOI:10.1109/bigdata.2013.6691583
|
|
||||||
|
|
||||||
Demmel, J., Grigori, L., Hoemmen, M., & Langou, J. (2012).
|
|
||||||
Communication-optimal parallel
|
|
||||||
and sequential QR and LU factorizations.
|
|
||||||
SIAM Journal on Scientific Computing, 34(1), A206-A239.
|
|
||||||
DOI:10.1137/080731992
|
|
||||||
|
|
||||||
DMD properties:
|
|
||||||
Brunton S. L. (2018).
|
|
||||||
Dynamic mode decomposition overview.
|
|
||||||
Seattle, Washington: University of Washington.
|
|
||||||
youtu.be/sQvrK8AGCAo (Retrieved:24-04-20)
|
|
||||||
\endverbatim
|
|
||||||
|
|
||||||
Operands:
|
|
||||||
\table
|
|
||||||
Operand | Type | Location
|
|
||||||
input | {vol,surface}\<Type\>Field <!--
|
|
||||||
--> | $FOAM_CASE/\<time\>/\<inpField\>
|
|
||||||
output file | dat <!--
|
|
||||||
--> | $FOAM_CASE/postProcessing/\<FO\>/\<time\>/\<file\>(s)
|
|
||||||
output field | volScalarField(s) | $FOAM_CASE/\<time\>/\<outField\>(s)
|
|
||||||
\endtable
|
|
||||||
|
|
||||||
where \c \<Type\>=Scalar/Vector/SphericalTensor/SymmTensor/Tensor.
|
|
||||||
|
|
||||||
Output fields:
|
|
||||||
\verbatim
|
|
||||||
modeReal<modeIndex><field> | Real part of a mode field
|
|
||||||
modeImag<modeIndex><field> | Imaginary part of a mode field
|
|
||||||
\endverbatim
|
|
||||||
|
|
||||||
Output files:
|
|
||||||
\verbatim
|
|
||||||
uSTDMD.dat | Unfiltered STDMD output
|
|
||||||
STDMD.dat | Filtered STDMD output
|
|
||||||
\endverbatim
|
|
||||||
|
|
||||||
wherein for each mode, the following quantities are output into files:
|
|
||||||
\verbatim
|
|
||||||
Frequency
|
|
||||||
Magnitude
|
|
||||||
Amplitude (real part)
|
|
||||||
Amplitude (imaginary part)
|
|
||||||
Eigenvalue (real part)
|
|
||||||
Eigenvalue (imaginary part)
|
|
||||||
\endverbatim
|
|
||||||
|
|
||||||
Note
|
|
||||||
Operations on boundary fields, e.g. \c wallShearStress, are currently not
|
|
||||||
available.
|
|
||||||
|
|
||||||
Usage
|
|
||||||
Minimal example by using \c system/controlDict.functions:
|
|
||||||
\verbatim
|
|
||||||
STDMD1
|
|
||||||
{
|
|
||||||
// Mandatory entries (unmodifiable)
|
|
||||||
type STDMD;
|
|
||||||
libs (fieldFunctionObjects);
|
|
||||||
field <inpField>;
|
|
||||||
|
|
||||||
// Conditional mandatory entries (unmodifiable)
|
|
||||||
// either of the below
|
|
||||||
stdmdInterval 5.5;
|
|
||||||
executeInterval 10;
|
|
||||||
|
|
||||||
// Optional entries (unmodifiable)
|
|
||||||
modeSorter kiewat;
|
|
||||||
nModes 50;
|
|
||||||
maxRank 50;
|
|
||||||
nGramSchmidt 5;
|
|
||||||
fMin 0;
|
|
||||||
fMax 1000000000;
|
|
||||||
|
|
||||||
// Optional entries (run-time modifiable, yet not recommended)
|
|
||||||
testEigen false;
|
|
||||||
dumpEigen false;
|
|
||||||
minBasis 0.00000001;
|
|
||||||
minEVal 0.00000001;
|
|
||||||
absTol 0.001;
|
|
||||||
relTol 0.0001;
|
|
||||||
sortLimiter 500;
|
|
||||||
|
|
||||||
// Optional (inherited) entries
|
|
||||||
...
|
|
||||||
}
|
|
||||||
\endverbatim
|
|
||||||
|
|
||||||
where the entries mean:
|
|
||||||
\table
|
|
||||||
Property | Description | Type | Req'd | Dflt
|
|
||||||
type | Type name: STDMD | word | yes | -
|
|
||||||
libs | Library name: fieldFunctionObjects | word | yes | -
|
|
||||||
field | Name of the operand field | word | yes | -
|
|
||||||
stdmdInterval | STDMD time-step size [s] | scalar| conditional | <!--
|
|
||||||
--> executeInterval*(current time-step of the simulation)
|
|
||||||
modeSorter | Mode-sorting algorithm variant | word | no | firstSnap
|
|
||||||
nModes | Number of output modes in input freq range | label | no | GREAT
|
|
||||||
maxRank | Max columns in accumulated matrices | label | no | GREAT
|
|
||||||
nGramSchmidt | Number of Gram-Schmidt iterations | label | no | 5
|
|
||||||
fMin | Min (non-negative) output frequency | label | no | 0
|
|
||||||
fMax | Max output frequency | label | no | GREAT
|
|
||||||
testEigen | Flag to verify eigendecompositions | bool | no | false
|
|
||||||
dumpEigen | Flag to log operands of eigendecomps | bool | no | false
|
|
||||||
minBasis | Orthogonal basis expansion threshold | scalar| no | 1e-8
|
|
||||||
minEVal | Min EVal for below EVals are omitted | scalar| no | 1e-8
|
|
||||||
absTol | Min abs tol in eigendecomposition tests | scalar| no | 1e-4
|
|
||||||
relTol | Relative tol in eigendecomposition tests | scalar| no | 1e-6
|
|
||||||
sortLimiter | Maximum allowable magnitude for <!--
|
|
||||||
--> mag(eigenvalue)*(number of STDMD steps) to be used in <!--
|
|
||||||
--> modeSorter={kiewat,kouZhang} to avoid overflow errors <!--
|
|
||||||
--> | scalar | no | 500.0
|
|
||||||
\endtable
|
|
||||||
|
|
||||||
Options for the \c modeSorter entry:
|
|
||||||
\verbatim
|
|
||||||
kiewat | Modified weighted amplitude scaling method
|
|
||||||
kouZhang | Weighted amplitude scaling method
|
|
||||||
firstSnap | Method of first snapshot amplitude magnitude
|
|
||||||
\endverbatim
|
|
||||||
|
|
||||||
The inherited entries are elaborated in:
|
|
||||||
- \link functionObject.H \endlink
|
|
||||||
- \link writeFile.H \endlink
|
|
||||||
|
|
||||||
Usage by \c postProcess utility is not available.
|
|
||||||
|
|
||||||
Note
|
|
||||||
- To specify the STDMD time-step size (not necessarily equal to the
|
|
||||||
time step of the simulation), entries of either \c stdmdInterval or
|
|
||||||
\c executeInterval must be available (highest to lowest precedence). While
|
|
||||||
\c stdmdInterval allows users to directly specify the STDMD time-step size
|
|
||||||
in seconds, in absence of \c stdmdInterval, for convenience,
|
|
||||||
\c executeInterval allows users to compute the STDMD time-step internally
|
|
||||||
by multiplying itself with the current time-step size of the simulation.
|
|
||||||
- Limitation: Restart is currently not available since intermediate writing
|
|
||||||
of STDMD matrices are not supported.
|
|
||||||
- Limitation: Non-physical input (e.g. full-zero fields) may upset STDMD.
|
|
||||||
- Warning: DMD is an active research area at the time of writing; therefore,
|
|
||||||
there would be cases whereat oddities might be encountered.
|
|
||||||
- Warning: This STDMD release is the \b beta release; therefore,
|
|
||||||
small-to-medium changes in input/output interfaces and internal structures
|
|
||||||
should be expected in the next versions.
|
|
||||||
- Warning: In \c modeSorter algorithms of \c kiewat and \c kouZhang, there
|
|
||||||
exists a function of \f$power(x,y)\f$ where \c x is the magnitude of an
|
|
||||||
eigenvalue, and \c y is the number of STDMD snapshots. This function poses
|
|
||||||
a risk of overflow errors since, for example, if \c x ends up above 1.5 with
|
|
||||||
500 snapshots or more, this function automatically throws the floating point
|
|
||||||
error meaning overflow. Therefore, the domain-range of this function is
|
|
||||||
heuristically constrained by the optional entry \c sortLimiter which skips
|
|
||||||
the evaluation of this function for a given
|
|
||||||
mag(eigenvalue)*(no. of STDMD steps), i.e. x*y, whose magnitude is larger
|
|
||||||
than \c sortLimiter.
|
|
||||||
|
|
||||||
See also
|
|
||||||
- Foam::functionObjects::fvMeshFunctionObject
|
|
||||||
- Foam::functionObjects::writeFile
|
|
||||||
- ExtendedCodeGuide::functionObjects::field::STDMD
|
|
||||||
|
|
||||||
SourceFiles
|
|
||||||
STDMD.C
|
|
||||||
STDMDTemplates.C
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef functionObjects_STDMD_H
|
|
||||||
#define functionObjects_STDMD_H
|
|
||||||
|
|
||||||
#include "fvMeshFunctionObject.H"
|
|
||||||
#include "writeFile.H"
|
|
||||||
#include "EigenMatrix.H"
|
|
||||||
#include "QRMatrix.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
namespace functionObjects
|
|
||||||
{
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
Class STDMD Declaration
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
class STDMD
|
|
||||||
:
|
|
||||||
public fvMeshFunctionObject,
|
|
||||||
public writeFile
|
|
||||||
{
|
|
||||||
|
|
||||||
typedef SquareMatrix<scalar> SMatrix;
|
|
||||||
typedef SquareMatrix<complex> SCMatrix;
|
|
||||||
typedef RectangularMatrix<scalar> RMatrix;
|
|
||||||
typedef RectangularMatrix<complex> RCMatrix;
|
|
||||||
|
|
||||||
|
|
||||||
// Private Enumerations
|
|
||||||
|
|
||||||
//- Options for the mode-sorting algorithm
|
|
||||||
enum modeSorterType
|
|
||||||
{
|
|
||||||
KIEWAT, //!< "Modified weighted amplitude scaling method"
|
|
||||||
KOU_ZHANG, //!< "Weighted amplitude scaling method"
|
|
||||||
FIRST_SNAPSHOT //!< "Method of first snapshot amplitude magnitude"
|
|
||||||
};
|
|
||||||
|
|
||||||
//- Names for modeSorterType
|
|
||||||
static const Enum<modeSorterType> modeSorterTypeNames;
|
|
||||||
|
|
||||||
|
|
||||||
// Private Data
|
|
||||||
|
|
||||||
//- Mode-sorting algorithm (default=modeSorterType::FIRST_SNAPSHOT)
|
|
||||||
const enum modeSorterType modeSorter_;
|
|
||||||
|
|
||||||
//- Name of the operand volume or surface field
|
|
||||||
const word fieldName_;
|
|
||||||
|
|
||||||
//- Flag: First execution-step initialisation
|
|
||||||
bool initialised_;
|
|
||||||
|
|
||||||
//- Flag: Verify eigendecompositions by using theoretical relations
|
|
||||||
bool testEigen_;
|
|
||||||
|
|
||||||
//- Flag: Write operands of eigendecompositions to log
|
|
||||||
// To activate it, testEigen=true
|
|
||||||
bool dumpEigen_;
|
|
||||||
|
|
||||||
//- Number of output modes within input frequency range
|
|
||||||
//- starting from the most energetic mode
|
|
||||||
const label nModes_;
|
|
||||||
|
|
||||||
//- Maximum allowable matrix column for Qz_ and Gz_
|
|
||||||
// Qz_ is assumed to always have full-rank, thus Qz_.n() = rank
|
|
||||||
const label maxRank_;
|
|
||||||
|
|
||||||
//- Number of maximum iterations of the classical Gram-Schmidt procedure
|
|
||||||
const label nGramSchmidt_;
|
|
||||||
|
|
||||||
//- Min frequency: Output only entries corresponding to freqs >= fMin
|
|
||||||
const label fMin_;
|
|
||||||
|
|
||||||
//- Max frequency: Output only entries corresponding to freqs <= fMax
|
|
||||||
const label fMax_;
|
|
||||||
|
|
||||||
//- Number of base components of input field, e.g. 3 for vector
|
|
||||||
label nComps_;
|
|
||||||
|
|
||||||
//- Number of elements in a snapshot
|
|
||||||
// A snapshot is an input dataset to be processed per execution-step
|
|
||||||
label nSnap_;
|
|
||||||
|
|
||||||
//- Current execution-step index of STDMD,
|
|
||||||
//- not necessarily that of the simulation
|
|
||||||
label currIndex_;
|
|
||||||
|
|
||||||
//- Maximum allowable magnitude for mag(eigenvalue)*(number of
|
|
||||||
//- STDMD steps) to be used in modeSorter={kiewat,kouZhang} to avoid
|
|
||||||
//- overflow errors
|
|
||||||
scalar sortLimiter_;
|
|
||||||
|
|
||||||
//- Min absolute tolerance being used in eigendecomposition tests
|
|
||||||
scalar absTol_;
|
|
||||||
|
|
||||||
//- Relative tolerance being used in eigendecomposition tests
|
|
||||||
scalar relTol_;
|
|
||||||
|
|
||||||
//- Min value to execute orthogonal basis expansion of Qz_ and Gz_
|
|
||||||
scalar minBasis_;
|
|
||||||
|
|
||||||
//- STDMD time-step size that equals to
|
|
||||||
//- (executeInterval of STDMD)*(deltaT of simulation) [s]
|
|
||||||
scalar dt_;
|
|
||||||
|
|
||||||
//- Min EVal magnitude threshold below where EVals are omitted
|
|
||||||
scalar minMagEVal_;
|
|
||||||
|
|
||||||
//- L2-norm of column vector z_
|
|
||||||
scalar zNorm_;
|
|
||||||
|
|
||||||
//- L2-norm of column vector ez_
|
|
||||||
scalar ezNorm_;
|
|
||||||
|
|
||||||
//- Augmented snapshot matrix (effectively a column vector) (K:Eq. 60)
|
|
||||||
// Upper half z_ = current-time snapshot slot
|
|
||||||
// Lower half z_ = previous-time snapshot slot
|
|
||||||
RMatrix z_;
|
|
||||||
|
|
||||||
//- Working copy of the augmented snapshot matrix z_
|
|
||||||
//- being used in the classical Gram-Schmidt process
|
|
||||||
RMatrix ez_;
|
|
||||||
|
|
||||||
//- First-processed snapshot required by the mode-sorting
|
|
||||||
//- algorithms at the final output computations (K:p. 43)
|
|
||||||
RMatrix X1_;
|
|
||||||
|
|
||||||
//- Accumulated-in-time unitary similarity matrix produced by the
|
|
||||||
//- orthonormal decomposition of the augmented snapshot matrix z_
|
|
||||||
// (K:Eq. 60)
|
|
||||||
RMatrix Qz_;
|
|
||||||
|
|
||||||
//- Accumulated-in-time (squared) upper triangular matrix produced by
|
|
||||||
//- the orthonormal decomposition of the augmented snapshot matrix z_
|
|
||||||
// (K:Eq. 64)
|
|
||||||
SMatrix Gz_;
|
|
||||||
|
|
||||||
//- Upper half of Qz_
|
|
||||||
RMatrix QzUH_;
|
|
||||||
|
|
||||||
//- Lower half of Qz_
|
|
||||||
RMatrix QzLH_;
|
|
||||||
|
|
||||||
//- Moore-Penrose pseudo-inverse of R produced by
|
|
||||||
//- the QR decomposition of the last time-step QzUH_
|
|
||||||
RMatrix RxInv_;
|
|
||||||
|
|
||||||
//- Projected STDMD operator (K:Eq. 78)
|
|
||||||
SMatrix Ap_;
|
|
||||||
|
|
||||||
//- Output eigenvectors
|
|
||||||
RCMatrix oEVecs_;
|
|
||||||
|
|
||||||
//- Output eigenvalues
|
|
||||||
List<complex> oEVals_;
|
|
||||||
|
|
||||||
//- Output amplitudes
|
|
||||||
List<complex> oAmps_;
|
|
||||||
|
|
||||||
//- Output (non-negative) frequencies
|
|
||||||
List<scalar> oFreqs_;
|
|
||||||
|
|
||||||
//- Indices of oFreqs_ where freqs are
|
|
||||||
//- non-negative and within [fMin_, fMax_]
|
|
||||||
DynamicList<label> iFreqs_;
|
|
||||||
|
|
||||||
//- Output (descending) magnitudes of (complex) amplitudes
|
|
||||||
List<scalar> oMags_;
|
|
||||||
|
|
||||||
//- Indices of oMags_
|
|
||||||
List<label> iMags_;
|
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
|
||||||
|
|
||||||
// Process
|
|
||||||
|
|
||||||
//- Move previous-time snapshot into previous-time slot in z_
|
|
||||||
//- and copy new current-time snapshot into current-time slot in z_
|
|
||||||
template<class GeoFieldType>
|
|
||||||
bool getSnapshot();
|
|
||||||
|
|
||||||
//- Get the input field type to be processed by snapshot()
|
|
||||||
template<class Type>
|
|
||||||
bool getSnapshotType();
|
|
||||||
|
|
||||||
//- Get the number of base components of input field
|
|
||||||
template<class GeoFieldType>
|
|
||||||
bool getComps();
|
|
||||||
|
|
||||||
//- Return (parallel) L2-norm of a given column vector
|
|
||||||
scalar parnorm(const RMatrix& colVector) const;
|
|
||||||
|
|
||||||
//- Move the current-time snapshot into the previous-time snapshot in z_
|
|
||||||
//- and copy the new field into the current-time snapshot
|
|
||||||
void snapshot();
|
|
||||||
|
|
||||||
//- Initialise all working matrices at the first execution-step
|
|
||||||
void init();
|
|
||||||
|
|
||||||
//- Initialise Qz_, Gz_ (both require the first two snapshots) and X1_
|
|
||||||
void initBasis();
|
|
||||||
|
|
||||||
//- Execute (parallel) classical Gram-Schmidt
|
|
||||||
//- process to orthonormalise ez_ (Ka:Fig. 5)
|
|
||||||
void GramSchmidt();
|
|
||||||
|
|
||||||
//- Expand orthonormal bases Qz_ and Gz_ by stacking a column
|
|
||||||
//- (ez_/ezNorm_) to Qz_, and a row (Zero) and column (Zero)
|
|
||||||
//- to Gz_ if (minBasis_ < ezNorm_/zNorm_)
|
|
||||||
void expandBasis();
|
|
||||||
|
|
||||||
//- Update Gz_ before the potential orthonormal basis compression
|
|
||||||
void updateGz();
|
|
||||||
|
|
||||||
//- Compress orthonormal basis for Qz_ and Gz_ if (maxRank_ < Qz_.n())
|
|
||||||
void compressBasis();
|
|
||||||
|
|
||||||
|
|
||||||
// Postprocess
|
|
||||||
|
|
||||||
//- Return a new List containing elems of List at indices
|
|
||||||
template<class Type>
|
|
||||||
void filterIndexed
|
|
||||||
(
|
|
||||||
List<Type>& lst,
|
|
||||||
const UList<label>& indices
|
|
||||||
);
|
|
||||||
|
|
||||||
//- Return a new Matrix containing columns of Matrix at indices
|
|
||||||
template<class MatrixType>
|
|
||||||
void filterIndexed
|
|
||||||
(
|
|
||||||
MatrixType& lst,
|
|
||||||
const UList<label>& indices
|
|
||||||
);
|
|
||||||
|
|
||||||
//- Compute global Ap (K:Eq. 78)
|
|
||||||
void calcAp();
|
|
||||||
|
|
||||||
//- Compute eigenvalues and eigenvectors
|
|
||||||
void calcEigen();
|
|
||||||
|
|
||||||
//- Weak-type floating-point comparison
|
|
||||||
// bit.ly/2Trdbgs (Eq. 2), and PEP-485
|
|
||||||
bool close
|
|
||||||
(
|
|
||||||
const scalar s1,
|
|
||||||
const scalar s2,
|
|
||||||
const scalar absTol = 0, //<! comparisons near zero
|
|
||||||
const scalar relTol = 1e-8 //<! e.g. vals the same within 8 decimals
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Test real/complex eigenvalues by using
|
|
||||||
//- the theoretical relation: (sum(eigenvalues) - trace(A) ~ 0)
|
|
||||||
void testEigenvalues
|
|
||||||
(
|
|
||||||
const SquareMatrix<scalar>& A,
|
|
||||||
const DiagonalMatrix<scalar>& EValsRe
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Test real eigenvectors by using the theoretical relation:
|
|
||||||
//- ((A & EVec - EVal*EVec).norm() ~ 0)
|
|
||||||
void testEigenvectors
|
|
||||||
(
|
|
||||||
const SquareMatrix<scalar>& A,
|
|
||||||
const DiagonalMatrix<scalar>& EValsRe,
|
|
||||||
const SquareMatrix<scalar>& EVecs
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Test complex eigenvectors by using the theoretical relation:
|
|
||||||
//- ((A & EVec - EVal*EVec).norm() ~ 0)
|
|
||||||
void testEigenvectors
|
|
||||||
(
|
|
||||||
const SquareMatrix<scalar>& A,
|
|
||||||
const List<complex>& EVals,
|
|
||||||
const RectangularMatrix<complex>& EVecs
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Remove any eigenvalues whose magnitude is smaller than
|
|
||||||
//- minMagEVal_ while keeping the order of elements the same
|
|
||||||
void filterEVals();
|
|
||||||
|
|
||||||
//- Compute and filter frequencies (K:Eq. 81)
|
|
||||||
void calcFreqs();
|
|
||||||
|
|
||||||
//- Compute frequency indices
|
|
||||||
// Locate indices where oFreqs_ are
|
|
||||||
// in [fMin_, fMax_], and store them in iFreqs_ indices
|
|
||||||
void calcFreqI();
|
|
||||||
|
|
||||||
//- Compute amplitudes
|
|
||||||
void calcAmps();
|
|
||||||
|
|
||||||
//- Compute magnitudes
|
|
||||||
// Includes advanced sorting methods using
|
|
||||||
// the chosen weighted amplitude scaling method
|
|
||||||
void calcMags();
|
|
||||||
|
|
||||||
//- Compute the ordered magnitude indices
|
|
||||||
void calcMagI();
|
|
||||||
|
|
||||||
//- Compute modes
|
|
||||||
void calcModes();
|
|
||||||
|
|
||||||
//- Eigenvalue weighted amplitude scaling (KZ:Eq. 33)
|
|
||||||
//- Modified eigenvalue weighted amplitude scaling (K)
|
|
||||||
scalar sorter
|
|
||||||
(
|
|
||||||
const List<scalar>& weight,
|
|
||||||
const complex& amplitude,
|
|
||||||
const complex& eval,
|
|
||||||
const scalar modeNorm
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Output file header information
|
|
||||||
virtual void writeFileHeader(Ostream& os) const;
|
|
||||||
|
|
||||||
//- Filter objects according to iFreqs_ and iMags_
|
|
||||||
void filterOutput();
|
|
||||||
|
|
||||||
//- Write unfiltered/filtered data
|
|
||||||
void writeOutput(OFstream& os) const;
|
|
||||||
|
|
||||||
//- Compute STDMD output
|
|
||||||
void calcOutput();
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
//- Runtime type information
|
|
||||||
TypeName("STDMD");
|
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
|
|
||||||
//- No default construct
|
|
||||||
STDMD() = delete;
|
|
||||||
|
|
||||||
//- Construct from Time and dictionary
|
|
||||||
STDMD
|
|
||||||
(
|
|
||||||
const word& name,
|
|
||||||
const Time& runTime,
|
|
||||||
const dictionary& dict
|
|
||||||
);
|
|
||||||
|
|
||||||
//- No copy construct
|
|
||||||
STDMD(const STDMD&) = delete;
|
|
||||||
|
|
||||||
//- No copy assignment
|
|
||||||
void operator=(const STDMD&) = delete;
|
|
||||||
|
|
||||||
|
|
||||||
//- Destructor
|
|
||||||
virtual ~STDMD() = default;
|
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
|
||||||
|
|
||||||
//- Read STDMD settings
|
|
||||||
virtual bool read(const dictionary&);
|
|
||||||
|
|
||||||
//- Execute STDMD
|
|
||||||
virtual bool execute();
|
|
||||||
|
|
||||||
//- Write STDMD output
|
|
||||||
virtual bool write();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace functionObjects
|
|
||||||
} // End namespace Foam
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
#ifdef NoRepository
|
|
||||||
#include "STDMDTemplates.C"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -36,7 +36,7 @@ boundaryField
|
|||||||
type symmetry;
|
type symmetry;
|
||||||
}
|
}
|
||||||
|
|
||||||
"left|right"
|
"(left|right)"
|
||||||
{
|
{
|
||||||
type empty;
|
type empty;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,7 +36,7 @@ boundaryField
|
|||||||
type symmetry;
|
type symmetry;
|
||||||
}
|
}
|
||||||
|
|
||||||
"left|right"
|
"(left|right)"
|
||||||
{
|
{
|
||||||
type empty;
|
type empty;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,15 +13,24 @@ runParallel renumberMesh -overwrite
|
|||||||
|
|
||||||
cp -f system/decomposeParDict system/coarseMesh
|
cp -f system/decomposeParDict system/coarseMesh
|
||||||
|
|
||||||
runApplication -s coarseMesh decomposePar -region coarseMesh
|
runApplication -s coarseMesh \
|
||||||
|
decomposePar -region coarseMesh
|
||||||
|
|
||||||
runParallel -s coarseMesh renumberMesh -overwrite -region coarseMesh
|
runParallel -s coarseMesh \
|
||||||
|
renumberMesh -overwrite -region coarseMesh
|
||||||
|
|
||||||
runParallel $(getApplication)
|
runParallel $(getApplication)
|
||||||
|
|
||||||
runParallel -s main redistributePar -reconstruct -latestTime
|
runParallel -s main \
|
||||||
|
redistributePar -reconstruct -overwrite
|
||||||
|
|
||||||
runParallel -s coarseMesh redistributePar -reconstruct \
|
runParallel -s coarseMesh \
|
||||||
-region coarseMesh -time '50,100,200'
|
redistributePar -reconstruct -region coarseMesh -time '50,100' -overwrite
|
||||||
|
|
||||||
|
if notTest "$@"
|
||||||
|
then
|
||||||
|
runParallel -s postProcess \
|
||||||
|
$(getApplication) -postProcess -fields '(U p)' -time '10:'
|
||||||
|
fi
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|||||||
@ -10,7 +10,6 @@ FoamFile
|
|||||||
version 2.0;
|
version 2.0;
|
||||||
format ascii;
|
format ascii;
|
||||||
class dictionary;
|
class dictionary;
|
||||||
location "constant";
|
|
||||||
object transportProperties;
|
object transportProperties;
|
||||||
}
|
}
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|||||||
@ -10,7 +10,6 @@ FoamFile
|
|||||||
version 2.0;
|
version 2.0;
|
||||||
format ascii;
|
format ascii;
|
||||||
class dictionary;
|
class dictionary;
|
||||||
location "constant";
|
|
||||||
object turbulenceProperties;
|
object turbulenceProperties;
|
||||||
}
|
}
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|||||||
@ -0,0 +1,49 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd01
|
||||||
|
{
|
||||||
|
// Mandatory entries (unmodifiable)
|
||||||
|
type DMD;
|
||||||
|
libs (fieldFunctionObjects);
|
||||||
|
DMDModel STDMD;
|
||||||
|
field U;
|
||||||
|
|
||||||
|
// Optional entries (unmodifiable)
|
||||||
|
/* patch <patchName>; */
|
||||||
|
|
||||||
|
// Conditional mandatory entries (runtime modifiable)
|
||||||
|
|
||||||
|
// Option-1
|
||||||
|
/* interval 5.5; */
|
||||||
|
|
||||||
|
// Option-2
|
||||||
|
/* executeInterval 10; */
|
||||||
|
|
||||||
|
// Optional entries (runtime modifiable)
|
||||||
|
/* modeSorter firstSnapshot; */
|
||||||
|
/* nGramSchmidt 5; */
|
||||||
|
/* maxRank 50; */
|
||||||
|
/* nModes 50; */
|
||||||
|
/* fMin 0; */
|
||||||
|
/* fMax 1000000000; */
|
||||||
|
|
||||||
|
// Optional entries (runtime modifiable, yet not recommended)
|
||||||
|
/* minBasis 0.00000001; */
|
||||||
|
/* minEVal 0.00000001; */
|
||||||
|
/* sortLimiter 500.0; */
|
||||||
|
|
||||||
|
|
||||||
|
// Optional (inherited) entries
|
||||||
|
region region0;
|
||||||
|
enabled true;
|
||||||
|
log true;
|
||||||
|
timeStart 10;
|
||||||
|
timeEnd 1000;
|
||||||
|
executeControl timeStep;
|
||||||
|
executeInterval 10;
|
||||||
|
writeControl onEnd;
|
||||||
|
writeInterval 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd02
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
region coarseMesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd03
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
patch cylinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd04
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
patch outlet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd05
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
maxRank 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd06
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
maxRank 5;
|
||||||
|
region coarseMesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd07
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
patch outlet;
|
||||||
|
maxRank 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd08
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd09
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field p;
|
||||||
|
region coarseMesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd10
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field p;
|
||||||
|
patch cylinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd11
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field p;
|
||||||
|
patch outlet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd12
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field p;
|
||||||
|
maxRank 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd13
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field p;
|
||||||
|
region coarseMesh;
|
||||||
|
maxRank 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd14
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field p;
|
||||||
|
patch outlet;
|
||||||
|
maxRank 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd15
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
modeSorter kiewat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd16
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
modeSorter kiewat;
|
||||||
|
region coarseMesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd17
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
patch cylinder;
|
||||||
|
modeSorter kiewat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd18
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
patch outlet;
|
||||||
|
modeSorter kiewat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd19
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
modeSorter kiewat;
|
||||||
|
maxRank 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd20
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
modeSorter kiewat;
|
||||||
|
maxRank 5;
|
||||||
|
region coarseMesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd21
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
patch outlet;
|
||||||
|
modeSorter kiewat;
|
||||||
|
maxRank 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd22
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field p;
|
||||||
|
modeSorter kiewat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd23
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field p;
|
||||||
|
modeSorter kiewat;
|
||||||
|
region coarseMesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd24
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field p;
|
||||||
|
patch cylinder;
|
||||||
|
modeSorter kiewat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd25
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field p;
|
||||||
|
patch outlet;
|
||||||
|
modeSorter kiewat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd26
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field p;
|
||||||
|
maxRank 10;
|
||||||
|
modeSorter kiewat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd27
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field p;
|
||||||
|
region coarseMesh;
|
||||||
|
maxRank 5;
|
||||||
|
modeSorter kiewat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd28
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field p;
|
||||||
|
patch outlet;
|
||||||
|
maxRank 2;
|
||||||
|
modeSorter kiewat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd29
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field UMean;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd30
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field UMean;
|
||||||
|
region coarseMesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd31
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field UMean;
|
||||||
|
patch cylinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd32
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field UMean;
|
||||||
|
patch outlet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd33
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field UMean;
|
||||||
|
maxRank 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd34
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field UMean;
|
||||||
|
maxRank 5;
|
||||||
|
region coarseMesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd35
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field UMean;
|
||||||
|
patch outlet;
|
||||||
|
maxRank 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd36
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field pMean;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd37
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field pMean;
|
||||||
|
region coarseMesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd38
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field pMean;
|
||||||
|
patch cylinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd39
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field pMean;
|
||||||
|
patch outlet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd40
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field pMean;
|
||||||
|
maxRank 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd41
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field pMean;
|
||||||
|
maxRank 5;
|
||||||
|
region coarseMesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd42
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field pMean;
|
||||||
|
patch outlet;
|
||||||
|
maxRank 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd43
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field pMean;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd44
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field pMean;
|
||||||
|
region coarseMesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd45
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field UPrime2Mean;
|
||||||
|
patch cylinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd46
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field UPrime2Mean;
|
||||||
|
patch outlet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd47
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field UPrime2Mean;
|
||||||
|
maxRank 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd48
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field UPrime2Mean;
|
||||||
|
maxRank 5;
|
||||||
|
region coarseMesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd49
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field UPrime2Mean;
|
||||||
|
patch outlet;
|
||||||
|
maxRank 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd50
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field UMean_movingAverageWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd51
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field UMean_movingAverageWindow;
|
||||||
|
region coarseMesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd52
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field UMean_movingAverageWindow;
|
||||||
|
patch cylinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd53
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field UMean_movingAverageWindow;
|
||||||
|
patch outlet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd54
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field UMean_movingAverageWindow;
|
||||||
|
maxRank 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd55
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field UMean_movingAverageWindow;
|
||||||
|
maxRank 5;
|
||||||
|
region coarseMesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd56
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field UMean_movingAverageWindow;
|
||||||
|
patch outlet;
|
||||||
|
maxRank 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd57
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field yPlus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd58
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field yPlus;
|
||||||
|
patch cylinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd59
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field yPlus;
|
||||||
|
patch outlet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd60
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field yPlus;
|
||||||
|
maxRank 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
stdmd61
|
||||||
|
{
|
||||||
|
${stdmd01}
|
||||||
|
|
||||||
|
field yPlus;
|
||||||
|
patch cylinder;
|
||||||
|
maxRank 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -44,10 +44,6 @@ blocks
|
|||||||
hex (0 1 2 3 4 5 6 7) ($nx $ny $nz) simpleGrading (1 1 1)
|
hex (0 1 2 3 4 5 6 7) ($nx $ny $nz) simpleGrading (1 1 1)
|
||||||
);
|
);
|
||||||
|
|
||||||
edges
|
|
||||||
(
|
|
||||||
);
|
|
||||||
|
|
||||||
boundary
|
boundary
|
||||||
(
|
(
|
||||||
allPatches
|
allPatches
|
||||||
@ -66,8 +62,5 @@ boundary
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
mergePatchPairs
|
|
||||||
(
|
|
||||||
);
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|||||||
@ -23,6 +23,18 @@ x3 #eval{ 10.0*$R };
|
|||||||
xOutlet #eval{ 18.6667*$R };
|
xOutlet #eval{ 18.6667*$R };
|
||||||
xInlet #eval{ -10.125*$R };
|
xInlet #eval{ -10.125*$R };
|
||||||
|
|
||||||
|
RsinPi8 #eval{ $R*sin(0.125*pi()) };
|
||||||
|
RsinPi8n #eval{ -$RsinPi8 };
|
||||||
|
RcosPi8 #eval{ $R*cos(0.125*pi()) };
|
||||||
|
RcosPi8n #eval{ -$RcosPi8 };
|
||||||
|
RsinPi4 #eval{ $R*sin(0.25*pi()) };
|
||||||
|
|
||||||
|
x2sinPi8 #eval{ $x2*sin(0.125*pi()) };
|
||||||
|
x2sinPi8n #eval{ -$x2sinPi8 };
|
||||||
|
x2cosPi8 #eval{ $x2*cos(0.125*pi()) };
|
||||||
|
x2cosPi8n #eval{ -$x2cosPi8 };
|
||||||
|
x2sinPi4 #eval{ $x2*sin(0.25*pi()) };
|
||||||
|
|
||||||
z0 -0.0075;
|
z0 -0.0075;
|
||||||
z1 0.0075;
|
z1 0.0075;
|
||||||
nz 1;
|
nz 1;
|
||||||
@ -37,18 +49,15 @@ vertices #codeStream
|
|||||||
|
|
||||||
code
|
code
|
||||||
#{
|
#{
|
||||||
// sin(45), cos(45)
|
|
||||||
const scalar sqrt05 = sqrt(0.5);
|
|
||||||
|
|
||||||
pointField points(19);
|
pointField points(19);
|
||||||
points[0] = point($R, 0, $z0);
|
points[0] = point($R, 0, $z0);
|
||||||
points[1] = point($x2, 0, $z0);
|
points[1] = point($x2, 0, $z0);
|
||||||
points[2] = point($x3, 0, $z0);
|
points[2] = point($x3, 0, $z0);
|
||||||
points[3] = point($x3, $x2*sqrt05, $z0);
|
points[3] = point($x3, $x2sinPi4, $z0);
|
||||||
points[4] = point($x2*sqrt05, $x2*sqrt05, $z0);
|
points[4] = point($x2sinPi4, $x2sinPi4, $z0);
|
||||||
points[5] = point($R*sqrt05, $R*sqrt05, $z0);
|
points[5] = point($RsinPi4, $RsinPi4, $z0);
|
||||||
points[6] = point($x3, $x3, $z0);
|
points[6] = point($x3, $x3, $z0);
|
||||||
points[7] = point($x2*sqrt05, $x3, $z0);
|
points[7] = point($x2sinPi4, $x3, $z0);
|
||||||
|
|
||||||
// Mirror +x points to -x side
|
// Mirror +x points to -x side
|
||||||
points[11] = point(-points[0].x(), points[0].y(), points[0].z());
|
points[11] = point(-points[0].x(), points[0].y(), points[0].z());
|
||||||
@ -67,7 +76,7 @@ vertices #codeStream
|
|||||||
|
|
||||||
// Mirror -z points to +z side
|
// Mirror -z points to +z side
|
||||||
label sz = points.size();
|
label sz = points.size();
|
||||||
points.resize(2*sz);
|
points.setSize(2*sz);
|
||||||
for (label i = 0; i < sz; ++i)
|
for (label i = 0; i < sz; ++i)
|
||||||
{
|
{
|
||||||
const point& pt = points[i];
|
const point& pt = points[i];
|
||||||
@ -77,7 +86,7 @@ vertices #codeStream
|
|||||||
// Add an inner cylinder
|
// Add an inner cylinder
|
||||||
sz = points.size();
|
sz = points.size();
|
||||||
label nAdd = 6;
|
label nAdd = 6;
|
||||||
points.resize(sz + nAdd);
|
points.setSize(sz + nAdd);
|
||||||
|
|
||||||
// Points within the inner cylinder
|
// Points within the inner cylinder
|
||||||
points[sz] = point(0, 0, $z0);
|
points[sz] = point(0, 0, $z0);
|
||||||
@ -93,7 +102,7 @@ vertices #codeStream
|
|||||||
|
|
||||||
// Mirror -z points to +z side
|
// Mirror -z points to +z side
|
||||||
sz = points.size();
|
sz = points.size();
|
||||||
points.resize(sz + nAdd);
|
points.setSize(sz + nAdd);
|
||||||
for (label i = 0; i < nAdd; ++i)
|
for (label i = 0; i < nAdd; ++i)
|
||||||
{
|
{
|
||||||
const point& pt = points[i+sz-nAdd];
|
const point& pt = points[i+sz-nAdd];
|
||||||
@ -103,21 +112,21 @@ vertices #codeStream
|
|||||||
// Add downstream and upstream blocks
|
// Add downstream and upstream blocks
|
||||||
sz = points.size();
|
sz = points.size();
|
||||||
nAdd = 6;
|
nAdd = 6;
|
||||||
points.resize(sz + nAdd);
|
points.setSize(sz + nAdd);
|
||||||
|
|
||||||
// Points on outlet
|
// Points on outlet
|
||||||
points[sz] = point($xOutlet, 0, $z0);
|
points[sz] = point($xOutlet, 0, $z0);
|
||||||
points[sz + 1] = point($xOutlet, $x3, $z0);
|
points[sz + 1] = point($xOutlet, $x3, $z0);
|
||||||
points[sz + 4] = point($xOutlet, $x2*sqrt05, $z0);
|
points[sz + 4] = point($xOutlet, $x2sinPi4, $z0);
|
||||||
|
|
||||||
// Points on inlet
|
// Points on inlet
|
||||||
points[sz + 2] = point($xInlet, 0, $z0);
|
points[sz + 2] = point($xInlet, 0, $z0);
|
||||||
points[sz + 3] = point($xInlet, $x3, $z0);
|
points[sz + 3] = point($xInlet, $x3, $z0);
|
||||||
points[sz + 5] = point($xInlet, $x2*sqrt05, $z0);
|
points[sz + 5] = point($xInlet, $x2sinPi4, $z0);
|
||||||
|
|
||||||
// Mirror -z points to +z side
|
// Mirror -z points to +z side
|
||||||
sz = points.size();
|
sz = points.size();
|
||||||
points.resize(sz + nAdd);
|
points.setSize(sz + nAdd);
|
||||||
for (label i = 0; i < nAdd; ++i)
|
for (label i = 0; i < nAdd; ++i)
|
||||||
{
|
{
|
||||||
const point& pt = points[i + sz - nAdd];
|
const point& pt = points[i + sz - nAdd];
|
||||||
@ -149,22 +158,22 @@ blocks
|
|||||||
|
|
||||||
edges
|
edges
|
||||||
(
|
(
|
||||||
arc 0 5 origin (0 0 $z0)
|
arc 0 5 ($RcosPi8 $RsinPi8 $z0)
|
||||||
arc 5 10 origin (0 0 $z0)
|
arc 5 10 ($RsinPi8 $RcosPi8 $z0)
|
||||||
arc 1 4 origin (0 0 $z0)
|
arc 1 4 ($x2cosPi8 $x2sinPi8 $z0)
|
||||||
arc 4 9 origin (0 0 $z0)
|
arc 4 9 ($x2sinPi8 $x2cosPi8 $z0)
|
||||||
arc 19 24 origin (0 0 $z1)
|
arc 19 24 ($RcosPi8 $RsinPi8 $z1)
|
||||||
arc 24 29 origin (0 0 $z1)
|
arc 24 29 ($RsinPi8 $RcosPi8 $z1)
|
||||||
arc 20 23 origin (0 0 $z1)
|
arc 20 23 ($x2cosPi8 $x2sinPi8 $z1)
|
||||||
arc 23 28 origin (0 0 $z1)
|
arc 23 28 ($x2sinPi8 $x2cosPi8 $z1)
|
||||||
arc 11 16 origin (0 0 $z0)
|
arc 11 16 ($RcosPi8n $RsinPi8 $z0)
|
||||||
arc 16 10 origin (0 0 $z0)
|
arc 16 10 ($RsinPi8n $RcosPi8 $z0)
|
||||||
arc 12 15 origin (0 0 $z0)
|
arc 12 15 ($x2cosPi8n $x2sinPi8 $z0)
|
||||||
arc 15 9 origin (0 0 $z0)
|
arc 15 9 ($x2sinPi8n $x2cosPi8 $z0)
|
||||||
arc 30 35 origin (0 0 $z1)
|
arc 30 35 ($RcosPi8n $RsinPi8 $z1)
|
||||||
arc 35 29 origin (0 0 $z1)
|
arc 35 29 ($RsinPi8n $RcosPi8 $z1)
|
||||||
arc 31 34 origin (0 0 $z1)
|
arc 31 34 ($x2cosPi8n $x2sinPi8 $z1)
|
||||||
arc 34 28 origin (0 0 $z1)
|
arc 34 28 ($x2sinPi8n $x2cosPi8 $z1)
|
||||||
);
|
);
|
||||||
|
|
||||||
boundary
|
boundary
|
||||||
@ -261,8 +270,5 @@ boundary
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
mergePatchPairs
|
|
||||||
();
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|||||||
@ -10,7 +10,6 @@ FoamFile
|
|||||||
version 2.0;
|
version 2.0;
|
||||||
format ascii;
|
format ascii;
|
||||||
class dictionary;
|
class dictionary;
|
||||||
location "system";
|
|
||||||
object fvSchemes;
|
object fvSchemes;
|
||||||
}
|
}
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|||||||
@ -10,7 +10,6 @@ FoamFile
|
|||||||
version 2.0;
|
version 2.0;
|
||||||
format ascii;
|
format ascii;
|
||||||
class dictionary;
|
class dictionary;
|
||||||
location "system";
|
|
||||||
object fvSolution;
|
object fvSolution;
|
||||||
}
|
}
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|||||||
@ -10,7 +10,6 @@ FoamFile
|
|||||||
version 2.0;
|
version 2.0;
|
||||||
format ascii;
|
format ascii;
|
||||||
class dictionary;
|
class dictionary;
|
||||||
location "system";
|
|
||||||
object controlDict;
|
object controlDict;
|
||||||
}
|
}
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
@ -23,13 +22,13 @@ startTime 0;
|
|||||||
|
|
||||||
stopAt endTime;
|
stopAt endTime;
|
||||||
|
|
||||||
endTime 200;
|
endTime 100;
|
||||||
|
|
||||||
deltaT 0.05;
|
deltaT 0.05;
|
||||||
|
|
||||||
writeControl runTime;
|
writeControl runTime;
|
||||||
|
|
||||||
writeInterval 50;
|
writeInterval 0.5;
|
||||||
|
|
||||||
purgeWrite 0;
|
purgeWrite 0;
|
||||||
|
|
||||||
@ -46,6 +45,45 @@ runTimeModifiable false;
|
|||||||
|
|
||||||
functions
|
functions
|
||||||
{
|
{
|
||||||
|
fieldAverage1
|
||||||
|
{
|
||||||
|
type fieldAverage;
|
||||||
|
libs (fieldFunctionObjects);
|
||||||
|
|
||||||
|
fields
|
||||||
|
(
|
||||||
|
U
|
||||||
|
{
|
||||||
|
mean on;
|
||||||
|
prime2Mean off;
|
||||||
|
base time;
|
||||||
|
windowType exact;
|
||||||
|
window 0.25;
|
||||||
|
windowName movingAverageWindow;
|
||||||
|
allowRestart no;
|
||||||
|
}
|
||||||
|
|
||||||
|
U
|
||||||
|
{
|
||||||
|
mean on;
|
||||||
|
prime2Mean on;
|
||||||
|
base time;
|
||||||
|
}
|
||||||
|
|
||||||
|
p
|
||||||
|
{
|
||||||
|
mean on;
|
||||||
|
prime2Mean on;
|
||||||
|
base time;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
timeStart 10;
|
||||||
|
executeControl timeStep;
|
||||||
|
executeInterval 1;
|
||||||
|
writeControl onEnd;
|
||||||
|
}
|
||||||
|
|
||||||
mapFields1
|
mapFields1
|
||||||
{
|
{
|
||||||
type mapFields;
|
type mapFields;
|
||||||
@ -55,7 +93,11 @@ functions
|
|||||||
consistent no;
|
consistent no;
|
||||||
patchMap ();
|
patchMap ();
|
||||||
cuttingPatches ();
|
cuttingPatches ();
|
||||||
fields ( U p );
|
fields
|
||||||
|
(
|
||||||
|
U
|
||||||
|
p
|
||||||
|
);
|
||||||
|
|
||||||
timeStart 10;
|
timeStart 10;
|
||||||
timeEnd 2000;
|
timeEnd 2000;
|
||||||
@ -67,162 +109,98 @@ functions
|
|||||||
writeInterval 50;
|
writeInterval 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
STDMD1U
|
mapFields2
|
||||||
{
|
{
|
||||||
// Mandatory entries
|
${mapFields1}
|
||||||
type STDMD;
|
fields
|
||||||
|
(
|
||||||
|
UMean
|
||||||
|
pMean
|
||||||
|
UPrime2Mean
|
||||||
|
pPrime2Mean
|
||||||
|
UMean_movingAverageWindow
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
yPlus1
|
||||||
|
{
|
||||||
|
type yPlus;
|
||||||
libs (fieldFunctionObjects);
|
libs (fieldFunctionObjects);
|
||||||
field U;
|
|
||||||
|
|
||||||
// Optional entries
|
|
||||||
modeSorter firstSnap;
|
|
||||||
|
|
||||||
// Optional (inherited) entries
|
|
||||||
region coarseMesh; // mapFields must be executed before.
|
|
||||||
timeStart 10;
|
timeStart 10;
|
||||||
executeControl timeStep;
|
executeControl timeStep;
|
||||||
executeInterval 10;
|
executeInterval 1;
|
||||||
writeControl onEnd;
|
writeControl writeTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
STDMD1p
|
#include "DMDs/stdmd01" // field=U
|
||||||
{
|
#include "DMDs/stdmd02" // field=U, region=coarseMesh
|
||||||
// Mandatory entries
|
#include "DMDs/stdmd03" // field=U, patch=cylinder
|
||||||
type STDMD;
|
#include "DMDs/stdmd04" // field=U, patch=outlet
|
||||||
libs (fieldFunctionObjects);
|
#include "DMDs/stdmd05" // field=U, maxRank=10
|
||||||
field p;
|
#include "DMDs/stdmd06" // field=U, region=coarseMesh, maxRank=5
|
||||||
|
#include "DMDs/stdmd07" // field=U, patch=outlet, maxRank=2
|
||||||
|
|
||||||
// Optional entries
|
#include "DMDs/stdmd08" // field=p
|
||||||
modeSorter firstSnap;
|
#include "DMDs/stdmd09" // field=p, region=coarseMesh
|
||||||
|
#include "DMDs/stdmd10" // field=p, patch=cylinder
|
||||||
|
#include "DMDs/stdmd11" // field=p, patch=outlet
|
||||||
|
#include "DMDs/stdmd12" // field=p, maxRank=10
|
||||||
|
#include "DMDs/stdmd13" // field=p, region=coarseMesh, maxRank=5
|
||||||
|
#include "DMDs/stdmd14" // field=p, patch=outlet, maxRank=2
|
||||||
|
|
||||||
// Optional (inherited) entries
|
#include "DMDs/stdmd15" // field=U, modeSorter=kiewat
|
||||||
region coarseMesh;
|
#include "DMDs/stdmd16" // field=U, region=coarseMesh, modeSorter=kiewat
|
||||||
timeStart 10;
|
#include "DMDs/stdmd17" // field=U, patch=cylinder, modeSorter=kiewat
|
||||||
executeControl timeStep;
|
#include "DMDs/stdmd18" // field=U, patch=outlet, modeSorter=kiewat
|
||||||
executeInterval 10;
|
#include "DMDs/stdmd19" // field=U, maxRank=10, modeSorter=kiewat
|
||||||
writeControl onEnd;
|
#include "DMDs/stdmd20" // field=U, region=coarseMesh, maxRank=5, modeSorter=kiewat
|
||||||
}
|
#include "DMDs/stdmd21" // field=U, patch=outlet, maxRank=2, modeSorter=kiewat
|
||||||
|
|
||||||
STDMD2U
|
#include "DMDs/stdmd22" // field=p, modeSorter=kiewat
|
||||||
{
|
#include "DMDs/stdmd23" // field=p, region=coarseMesh, modeSorter=kiewat
|
||||||
// Mandatory entries
|
#include "DMDs/stdmd24" // field=p, patch=cylinder, modeSorter=kiewat
|
||||||
type STDMD;
|
#include "DMDs/stdmd25" // field=p, patch=outlet, modeSorter=kiewat
|
||||||
libs (fieldFunctionObjects);
|
#include "DMDs/stdmd26" // field=p, maxRank=10, modeSorter=kiewat
|
||||||
field U;
|
#include "DMDs/stdmd27" // field=p, region=coarseMesh, maxRank=5, modeSorter=kiewat
|
||||||
|
#include "DMDs/stdmd28" // field=p, patch=outlet, maxRank=2, modeSorter=kiewat
|
||||||
|
|
||||||
// Optional entries
|
#include "DMDs/stdmd29" // field=UMean
|
||||||
modeSorter firstSnap;
|
// #include "DMDs/stdmd30" // field=UMean, region=coarseMesh
|
||||||
nModes 2;
|
#include "DMDs/stdmd31" // field=UMean, patch=cylinder
|
||||||
maxRank 2;
|
#include "DMDs/stdmd32" // field=UMean, patch=outlet
|
||||||
nGramSchmidt 5;
|
#include "DMDs/stdmd33" // field=UMean, maxRank=10
|
||||||
fMin 0;
|
// #include "DMDs/stdmd34" // field=UMean, region=coarseMesh, maxRank=5
|
||||||
fMax 1000000000;
|
#include "DMDs/stdmd35" // field=UMean, patch=outlet, maxRank=2
|
||||||
testEigen true;
|
|
||||||
dumpEigen true;
|
|
||||||
minBasis 0.00000001;
|
|
||||||
minEVal 0.00000001;
|
|
||||||
absTol 0.001;
|
|
||||||
relTol 0.0001;
|
|
||||||
|
|
||||||
// Optional (inherited) entries
|
#include "DMDs/stdmd36" // field=pMean
|
||||||
timeStart 50;
|
// #include "DMDs/stdmd37" // field=pMean, region=coarseMesh
|
||||||
timeEnd 2000;
|
#include "DMDs/stdmd38" // field=pMean, patch=cylinder
|
||||||
executeControl timeStep;
|
#include "DMDs/stdmd39" // field=pMean, patch=outlet
|
||||||
executeInterval 10;
|
#include "DMDs/stdmd40" // field=pMean, maxRank=10
|
||||||
writeControl onEnd;
|
// #include "DMDs/stdmd41" // field=pMean, region=coarseMesh, maxRank=5
|
||||||
}
|
#include "DMDs/stdmd42" // field=pMean, patch=outlet, maxRank=2
|
||||||
|
|
||||||
STDMD3U
|
#include "DMDs/stdmd43" // field=UPrime2Mean
|
||||||
{
|
// #include "DMDs/stdmd44" // field=UPrime2Mean, region=coarseMesh
|
||||||
// Mandatory entries
|
#include "DMDs/stdmd45" // field=UPrime2Mean, patch=cylinder
|
||||||
type STDMD;
|
#include "DMDs/stdmd46" // field=UPrime2Mean, patch=outlet
|
||||||
libs (fieldFunctionObjects);
|
#include "DMDs/stdmd47" // field=UPrime2Mean, maxRank=10
|
||||||
field U;
|
// #include "DMDs/stdmd48" // field=UPrime2Mean, region=coarseMesh, maxRank=5
|
||||||
|
#include "DMDs/stdmd49" // field=UPrime2Mean, patch=outlet, maxRank=2
|
||||||
|
|
||||||
// Optional entries
|
#include "DMDs/stdmd50" // field=UMean_movingAverageWindow
|
||||||
modeSorter firstSnap;
|
// #include "DMDs/stdmd51" // field=UMean_movingAverageWindow, region=coarseMesh
|
||||||
|
#include "DMDs/stdmd52" // field=UMean_movingAverageWindow, patch=cylinder
|
||||||
|
#include "DMDs/stdmd53" // field=UMean_movingAverageWindow, patch=outlet
|
||||||
|
#include "DMDs/stdmd54" // field=UMean_movingAverageWindow, maxRank=10
|
||||||
|
// #include "DMDs/stdmd55" // field=UMean_movingAverageWindow, region=coarseMesh, maxRank=5
|
||||||
|
#include "DMDs/stdmd56" // field=UMean_movingAverageWindow, patch=outlet, maxRank=2
|
||||||
|
|
||||||
// Optional (inherited) entries
|
#include "DMDs/stdmd57" // field=yPlus
|
||||||
region coarseMesh;
|
#include "DMDs/stdmd58" // field=yPlus, patch=cylinder
|
||||||
timeStart 10;
|
#include "DMDs/stdmd59" // field=yPlus, patch=outlet
|
||||||
timeEnd 150;
|
#include "DMDs/stdmd60" // field=yPlus, maxRank=10
|
||||||
executeControl timeStep;
|
#include "DMDs/stdmd61" // field=yPlus, patch=cylinder, maxRank=2
|
||||||
executeInterval 10;
|
|
||||||
writeControl runTime;
|
|
||||||
writeInterval 50;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMD4U
|
|
||||||
{
|
|
||||||
// Mandatory entries
|
|
||||||
type STDMD;
|
|
||||||
libs (fieldFunctionObjects);
|
|
||||||
field U;
|
|
||||||
|
|
||||||
// Optional entries
|
|
||||||
modeSorter kiewat;
|
|
||||||
|
|
||||||
// Optional (inherited) entries
|
|
||||||
region coarseMesh;
|
|
||||||
timeStart 10;
|
|
||||||
executeControl timeStep;
|
|
||||||
executeInterval 10;
|
|
||||||
writeControl onEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMD4p
|
|
||||||
{
|
|
||||||
// Mandatory entries
|
|
||||||
type STDMD;
|
|
||||||
libs (fieldFunctionObjects);
|
|
||||||
field p;
|
|
||||||
|
|
||||||
// Optional entries
|
|
||||||
modeSorter kiewat;
|
|
||||||
|
|
||||||
// Optional (inherited) entries
|
|
||||||
region coarseMesh;
|
|
||||||
timeStart 10;
|
|
||||||
executeControl timeStep;
|
|
||||||
executeInterval 10;
|
|
||||||
writeControl onEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMD5U
|
|
||||||
{
|
|
||||||
// Mandatory entries
|
|
||||||
type STDMD;
|
|
||||||
libs (fieldFunctionObjects);
|
|
||||||
field U;
|
|
||||||
|
|
||||||
// Optional entries
|
|
||||||
modeSorter kouZhang;
|
|
||||||
|
|
||||||
// Optional (inherited) entries
|
|
||||||
region coarseMesh;
|
|
||||||
timeStart 10;
|
|
||||||
executeControl timeStep;
|
|
||||||
executeInterval 10;
|
|
||||||
writeControl onEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMD5p
|
|
||||||
{
|
|
||||||
// Mandatory entries
|
|
||||||
type STDMD;
|
|
||||||
libs (fieldFunctionObjects);
|
|
||||||
field p;
|
|
||||||
|
|
||||||
// Optional entries
|
|
||||||
modeSorter kouZhang;
|
|
||||||
|
|
||||||
// Optional (inherited) entries
|
|
||||||
region coarseMesh;
|
|
||||||
timeStart 10;
|
|
||||||
executeControl timeStep;
|
|
||||||
executeInterval 10;
|
|
||||||
writeControl onEnd;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -10,18 +10,17 @@ FoamFile
|
|||||||
version 2.0;
|
version 2.0;
|
||||||
format ascii;
|
format ascii;
|
||||||
class dictionary;
|
class dictionary;
|
||||||
location "system";
|
|
||||||
object decomposeParDict;
|
object decomposeParDict;
|
||||||
}
|
}
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
numberOfSubdomains 8;
|
numberOfSubdomains 12;
|
||||||
|
|
||||||
method hierarchical;
|
method hierarchical;
|
||||||
|
|
||||||
coeffs
|
coeffs
|
||||||
{
|
{
|
||||||
n (8 1 1);
|
n (4 3 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,6 @@ FoamFile
|
|||||||
version 2.0;
|
version 2.0;
|
||||||
format ascii;
|
format ascii;
|
||||||
class dictionary;
|
class dictionary;
|
||||||
location "system";
|
|
||||||
object fvSchemes;
|
object fvSchemes;
|
||||||
}
|
}
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
@ -28,6 +27,7 @@ gradSchemes
|
|||||||
divSchemes
|
divSchemes
|
||||||
{
|
{
|
||||||
default Gauss linear;
|
default Gauss linear;
|
||||||
|
|
||||||
div((nuEff*dev(T(grad(U))))) Gauss linear;
|
div((nuEff*dev(T(grad(U))))) Gauss linear;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,6 @@ FoamFile
|
|||||||
version 2.0;
|
version 2.0;
|
||||||
format ascii;
|
format ascii;
|
||||||
class dictionary;
|
class dictionary;
|
||||||
location "system";
|
|
||||||
object fvSolution;
|
object fvSolution;
|
||||||
}
|
}
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|||||||
@ -24,4 +24,5 @@ pointAndNormalDict
|
|||||||
|
|
||||||
planeTolerance 1e-3;
|
planeTolerance 1e-3;
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|||||||
@ -22,7 +22,7 @@ geometry
|
|||||||
{
|
{
|
||||||
cylinder
|
cylinder
|
||||||
{
|
{
|
||||||
type cylinder;
|
type searchableCylinder;
|
||||||
point1 (0 0 -0.00375);
|
point1 (0 0 -0.00375);
|
||||||
point2 (0 0 0.00375);
|
point2 (0 0 0.00375);
|
||||||
radius 0.06;
|
radius 0.06;
|
||||||
|
|||||||
@ -43,7 +43,7 @@ atmAmbientTurbSource1
|
|||||||
atmAmbientTurbSourceCoeffs
|
atmAmbientTurbSourceCoeffs
|
||||||
{
|
{
|
||||||
selectionMode all;
|
selectionMode all;
|
||||||
kAmb 0.001;
|
kAmb 1.0e-04;
|
||||||
epsilonAmb 7.208e-08;
|
epsilonAmb 7.208e-08;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user