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 -------------------------------------------------------------------------------
10 License
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 
34 namespace Foam
35 {
36 namespace functionObjects
37 {
38  defineTypeNameAndDebug(DMD, 0);
39  addToRunTimeSelectionTable(functionObject, DMD, dictionary);
40 }
41 }
42 
43 
44 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
45 
46 void 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 
68 Foam::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 
90 void 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 :
140  fvMeshFunctionObject(name, runTime, dict),
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
156  if (runTime.isAdjustTimeStep())
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  }
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 // ************************************************************************* //
List< ReturnType > get(const UPtrList< T > &list, const AccessOp &aop)
List of values generated by applying the access operation to each list item.
dictionary dict
defineTypeNameAndDebug(ObukhovLength, 0)
DMD(const word &name, const Time &runTime, const dictionary &dict)
Construct from Time and dictionary.
Definition: DMD.C:127
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
constexpr char tab
The tab &#39;\t&#39; character(0x09)
Definition: Ostream.H:49
::Foam::direction nComponents(const expressions::valueTypeCode) noexcept
The number of components associated with given valueTypeCode.
Definition: exprTraits.C:40
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
Macros for easy insertion into run-time selection tables.
const word & name() const noexcept
Return the name of this functionObject.
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:799
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
A class for handling words, derived from Foam::string.
Definition: word.H:63
virtual const word & type() const =0
Runtime type information.
A List of wordRe with additional matching capabilities.
Definition: wordRes.H:53
virtual bool read(const dictionary &dict)
Read DMD settings.
Definition: DMD.C:170
virtual bool end()
Write DMD results.
Definition: DMD.C:219
bool topoChanging() const noexcept
Is mesh topology changing.
Definition: polyMesh.H:749
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:201
addToRunTimeSelectionTable(functionObject, ObukhovLength, dictionary)
virtual bool execute()
Execute DMD.
Definition: DMD.C:183
virtual bool write()
Write DMD results.
Definition: DMD.C:208
#define WarningInFunction
Report a warning using Foam::Warning.
#define Log
Definition: PDRblock.C:28
messageStream Info
Information stream (stdout output on master, null elsewhere)
virtual bool read(const dictionary &dict)
Read optional controls.
Abstract base class for DMD models to handle DMD characteristics for the DMD function object...
Definition: DMDModel.H:62
List< label > labelList
A List of labels.
Definition: List.H:62
bool found
const fvMesh & mesh_
Reference to the fvMesh.
Namespace for OpenFOAM.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127