DMD.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2020-2021 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
11 This file is part of OpenFOAM.
12
13 OpenFOAM is free software: you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25
26\*---------------------------------------------------------------------------*/
27
28#include "DMD.H"
29#include "DMDModel.H"
31
32// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
33
34namespace Foam
35{
36namespace functionObjects
37{
40}
41}
42
43
44// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
45
46void Foam::functionObjects::DMD::snapshot()
47{
48 bool processed = false;
49 processed = processed || getSnapshot<scalar>();
50 processed = processed || getSnapshot<vector>();
51 processed = processed || getSnapshot<sphericalTensor>();
52 processed = processed || getSnapshot<symmTensor>();
53 processed = processed || getSnapshot<tensor>();
54
55 if (!processed)
56 {
58 << " functionObjects::" << type() << " " << name() << ":"
59 << " cannot find required input field during snapshot loading: "
60 << fieldName_ << nl
61 << " Do you execute required functionObjects"
62 << " before executing DMD, e.g. mapFields?"
63 << exit(FatalError);
64 }
65}
66
67
68Foam::label Foam::functionObjects::DMD::nComponents(const word& fieldName) const
69{
70 label nComps = 0;
71 bool processed = false;
72 processed = processed || nComponents<scalar>(fieldName, nComps);
73 processed = processed || nComponents<vector>(fieldName, nComps);
74 processed = processed || nComponents<sphericalTensor>(fieldName, nComps);
75 processed = processed || nComponents<symmTensor>(fieldName, nComps);
76 processed = processed || nComponents<tensor>(fieldName, nComps);
77
78 if (!processed)
79 {
81 << "Unknown type of input field during initialisation: "
82 << fieldName << nl
83 << exit(FatalError);
84 }
85
86 return nComps;
87}
88
89
90void Foam::functionObjects::DMD::initialise()
91{
92 const label nComps = nComponents(fieldName_);
93
94 if (patches_.empty())
95 {
96 nSnap_ = nComps*mesh_.nCells();
97 }
98 else
99 {
100 const labelList patchis
101 (
102 mesh_.boundaryMesh().patchSet(patches_).sortedToc()
103 );
104
105 for (const label patchi : patchis)
106 {
107 nSnap_ += nComps*(mesh_.C().boundaryField()[patchi]).size();
108 }
109 }
110
111 const label nSnapTotal = returnReduce(nSnap_, sumOp<label>());
112
113 if (nSnapTotal <= 0)
114 {
116 << "Zero-size input field = " << fieldName_
117 << exit(FatalError);
118 }
119
120 if (nSnap_ > 0)
121 {
122 z_ = RMatrix(2*nSnap_, 1, Zero);
123 }
124 else
125 {
126 z_ = RMatrix(1, 1, Zero);
127 }
128}
129
130
131// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
132
134(
135 const word& name,
136 const Time& runTime,
137 const dictionary& dict
138)
139:
141 DMDModelPtr_(DMDModel::New(mesh_, name, dict)),
142 z_(),
143 patches_
144 (
145 dict.getOrDefault<wordRes>
146 (
147 "patches",
148 dict.found("patch") ? wordRes(1,dict.get<word>("patch")) : wordRes()
149 )
150 ),
151 fieldName_(dict.get<word>("field")),
152 nSnap_(0),
153 step_(0)
154{
155 // Check if computation time-step is varying
157 {
159 << "DMD is available only for fixed time-step computations."
160 << endl;
161 }
162
163 // Check if mesh topology is changing
164 if (mesh_.topoChanging())
165 {
167 << "DMD is available only for non-changing mesh topology."
168 << exit(FatalError);
169 }
170
171 read(dict);
172}
173
174
175// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
176
178{
179 Info<< type() << " " << name() << ":" << endl;
180
181 if (fvMeshFunctionObject::read(dict) && DMDModelPtr_->read(dict))
182 {
183 return true;
184 }
185
186 return false;
187}
188
189
191{
192 Log << type() << " " << name() << " execute:" << endl;
193
194 snapshot();
195
196 if (step_ == 1)
197 {
198 DMDModelPtr_->initialise(z_);
199 }
200
201 if (step_ > 1)
202 {
203 DMDModelPtr_->update(z_);
204 }
205
206 ++step_;
207
208 Log << tab << "Execution index = " << step_ << " for field: " << fieldName_
209 << endl;
210
211 return true;
212}
213
214
216{
217 if (postProcess)
218 {
219 return true;
220 }
221
222 return end();
223}
224
225
227{
228 if (step_ == 0)
229 {
230 // Avoid double execution of write() when writeControl=onEnd
231 return true;
232 }
233
234 Log << type() << " " << name() << " write:" << endl;
235
236 if (step_ < 2)
237 {
239 << "DMD needs at least three snapshots to produce output" << nl
240 << " Only " << step_ + 1 << " snapshots are available" << nl
241 << " Skipping DMD output calculation and write"
242 << endl;
243
244 return false;
245 }
246
247 z_.clear();
248
249 DMDModelPtr_->fit();
250
251 mesh_.time().printExecutionTime(Info);
252
253 // Restart the incremental orthonormal basis update
254 step_ = 0;
255
256 return true;
257}
258
259
260// ************************************************************************* //
#define Log
Definition: PDRblock.C:35
bool found
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
Abstract base class for DMD models to handle DMD characteristics for the DMD function object.
Definition: DMDModel.H:68
virtual bool read()
Re-read model coefficients if they have changed.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:80
virtual bool isAdjustTimeStep() const
Return true if adjustTimeStep is true.
Definition: Time.C:991
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
Abstract base-class for Time/database function objects.
const word & name() const noexcept
Return the name of this functionObject.
virtual const word & type() const =0
Runtime type information.
Computes a dynamic mode decomposition model on a specified field.
Definition: DMD.H:257
virtual bool read(const dictionary &dict)
Read DMD settings.
Definition: DMD.C:177
virtual bool execute()
Execute DMD.
Definition: DMD.C:190
virtual bool write()
Write DMD results.
Definition: DMD.C:215
virtual bool end()
Write DMD results.
Definition: DMD.C:226
Specialization of Foam::functionObject for an Foam::fvMesh, providing a reference to the Foam::fvMesh...
const fvMesh & mesh_
Reference to the fvMesh.
static constexpr direction nComponents
Number of components in bool is 1.
Definition: bool.H:98
bool topoChanging() const noexcept
Is mesh topology changing.
Definition: polyMesh.H:548
A List of wordRe with additional matching capabilities.
Definition: wordRes.H:54
A class for handling words, derived from Foam::string.
Definition: word.H:68
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
engineTime & runTime
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
#define WarningInFunction
Report a warning using Foam::Warning.
Namespace for OpenFOAM.
List< label > labelList
A List of labels.
Definition: List.H:66
messageStream Info
Information stream (stdout output on master, null elsewhere)
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: MSwindows.C:598
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh > > &tdf1, const word &name, const dimensionSet &dimensions)
Global function forwards to reuseTmpDimensionedField::New.
error FatalError
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce (copy) and return value.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
constexpr char tab
The tab '\t' character(0x09)
Definition: Ostream.H:52
dictionary dict