Loading...
Searching...
No Matches
SteadyNSTurbIntrusive.C
1/*---------------------------------------------------------------------------*\
2 ██╗████████╗██╗ ██╗ █████╗ ██████╗ █████╗ ███████╗██╗ ██╗
3 ██║╚══██╔══╝██║ ██║██╔══██╗██╔════╝██╔══██╗ ██╔════╝██║ ██║
4 ██║ ██║ ███████║███████║██║ ███████║█████╗█████╗ ██║ ██║
5 ██║ ██║ ██╔══██║██╔══██║██║ ██╔══██║╚════╝██╔══╝ ╚██╗ ██╔╝
6 ██║ ██║ ██║ ██║██║ ██║╚██████╗██║ ██║ ██║ ╚████╔╝
7 ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝ ╚═╝ ╚═══╝
8
9 * In real Time Highly Advanced Computational Applications for Finite Volumes
10 * Copyright (C) 2017 by the ITHACA-FV authors
11-------------------------------------------------------------------------------
12
13License
14 This file is part of ITHACA-FV
15
16 ITHACA-FV is free software: you can redistribute it and/or modify
17 it under the terms of the GNU Lesser General Public License as published by
18 the Free Software Foundation, either version 3 of the License, or
19 (at your option) any later version.
20
21 ITHACA-FV is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU Lesser General Public License for more details.
25
26 You should have received a copy of the GNU Lesser General Public License
27 along with ITHACA-FV. If not, see <http://www.gnu.org/licenses/>.
28
29\*---------------------------------------------------------------------------*/
30
31#include "steadyNS.H"
33#include "viscosityModel.H"
34
35// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * * //
36
37// Constructor
38SteadyNSTurbIntrusive::SteadyNSTurbIntrusive() {}
39
40SteadyNSTurbIntrusive::SteadyNSTurbIntrusive(int argc, char* argv[])
41{
42 _args = autoPtr<argList>
43 (
44 new argList(argc, argv)
45 );
46
47 if (!_args->checkRootCase())
48 {
49 Foam::FatalError.exit();
50 }
51
52 argList& args = _args();
53#include "createTime.H"
54#include "createMesh.H"
55 _simple = autoPtr<simpleControl>
56 (
57 new simpleControl
58 (
59 mesh
60 )
61 );
62 simpleControl& simple = _simple();
63#include "createFields.H"
64#include "createFvOptions.H"
65 //
66#pragma GCC diagnostic push
67#pragma GCC diagnostic ignored "-Wunused-variable"
68#include "initContinuityErrs.H"
69#pragma GCC diagnostic pop
70 //
71 turbulence->validate();
72 ITHACAdict = new IOdictionary
73 (
74 IOobject
75 (
76 "ITHACAdict",
77 runTime.system(),
78 mesh,
79 IOobject::MUST_READ,
80 IOobject::NO_WRITE
81 )
82 );
83 tolerance = ITHACAdict->lookupOrDefault<scalar>("tolerance", 1e-5);
84 maxIter = ITHACAdict->lookupOrDefault<scalar>("maxIter", 1000);
85 bcMethod = ITHACAdict->lookupOrDefault<word>("bcMethod", "lift");
86 M_Assert(bcMethod == "lift" || bcMethod == "penalty",
87 "The BC method must be set to lift or penalty in ITHACAdict");
88 para = ITHACAparameters::getInstance(mesh, runTime);
92}
93
94
95// * * * * * * * * * * * * * * Full Order Methods * * * * * * * * * * * * * * //
96
97// Method to performa a truthSolve
98void SteadyNSTurbIntrusive::truthSolve(List<scalar> mu_now)
99{
100 Time& runTime = _runTime();
101 fvMesh& mesh = _mesh();
102 volScalarField& p = _p();
103 volVectorField& U = _U();
104 surfaceScalarField& phi = _phi();
105 fv::options& fvOptions = _fvOptions();
106 simpleControl& simple = _simple();
107 IOMRFZoneList& MRF = _MRF();
108 singlePhaseTransportModel& laminarTransport = _laminarTransport();
109#include "NLsolveSteadyNSTurbIntrusive.H"
110 ITHACAstream::exportSolution(U, name(counter), "./ITHACAoutput/Offline/");
111 ITHACAstream::exportSolution(p, name(counter), "./ITHACAoutput/Offline/");
112 volScalarField _nut(turbulence->nut());
113 ITHACAstream::exportSolution(_nut, name(counter), "./ITHACAoutput/Offline/");
114 Ufield.append(U.clone());
115 Pfield.append(p.clone());
116 nutFields.append(_nut.clone());
117 counter++;
118 writeMu(mu_now);
119 // --- Fill in the mu_samples with parameters (mu) to be used for the PODI sample points
120 mu_samples.conservativeResize(mu_samples.rows() + 1, mu_now.size());
121
122 for (label i = 0; i < mu_now.size(); i++)
123 {
124 mu_samples(mu_samples.rows() - 1, i) = mu_now[i];
125 }
126
127 // Resize to Unitary if not initialized by user (i.e. non-parametric problem)
128 if (mu.cols() == 0)
129 {
130 mu.resize(1, 1);
131 }
132
133 if (mu_samples.rows() == mu.cols())
134 {
135 ITHACAstream::exportMatrix(mu_samples, "mu_samples", "eigen",
136 "./ITHACAoutput/Offline");
137 }
138}
139
140Eigen::Tensor<double, 3> SteadyNSTurbIntrusive::turbulenceTensor1(label nModes)
141{
142 Eigen::Tensor<double, 3> ct1Tensor;
143 ct1Tensor.resize(nModes, nModes, nModes);
144
145 for (label i = 0; i < nModes; i++)
146 {
147 for (label j = 0; j < nModes; j++)
148 {
149 for (label k = 0; k < nModes; k++)
150 {
151 ct1Tensor(i, j, k) = fvc::domainIntegrate(Umodes[i] & fvc::laplacian(
152 nutModes[j], Umodes[k])).value();
153 }
154 }
155 }
156
157 if (Pstream::parRun())
158 {
159 reduce(ct1Tensor, sumOp<Eigen::Tensor<double, 3 >> ());
160 }
161
162 // Export the tensor
163 ITHACAstream::SaveDenseTensor(ct1Tensor, "./ITHACAoutput/Matrices/",
164 "ct1_" + name(nModes) + "_t");
165 return ct1Tensor;
166}
167
168Eigen::Tensor<double, 3> SteadyNSTurbIntrusive::turbulenceTensor2(label nModes)
169{
170 Eigen::Tensor<double, 3> ct2Tensor;
171 ct2Tensor.resize(nModes, nModes, nModes);
172
173 for (label i = 0; i < nModes; i++)
174 {
175 for (label j = 0; j < nModes; j++)
176 {
177 for (label k = 0; k < nModes; k++)
178 {
179 ct2Tensor(i, j, k) = fvc::domainIntegrate(Umodes[i] & (fvc::div(
180 nutModes[j] * dev((fvc::grad(Umodes[k]))().T())))).value();
181 }
182 }
183 }
184
185 if (Pstream::parRun())
186 {
187 reduce(ct2Tensor, sumOp<Eigen::Tensor<double, 3 >> ());
188 }
189
190 // Export the tensor
191 ITHACAstream::SaveDenseTensor(ct2Tensor, "./ITHACAoutput/Matrices/",
192 "ct2_" + name(nModes) + "_t");
193 return ct2Tensor;
194}
195
196Eigen::MatrixXd SteadyNSTurbIntrusive::btTurbulence(label nModes)
197{
198 Eigen::MatrixXd btMatrix(nModes, nModes);
199 btMatrix = btMatrix * 0;
200
201 // Project everything
202 for (label i = 0; i < nModes; i++)
203 {
204 for (label j = 0; j < nModes; j++)
205 {
206 btMatrix(i, j) = fvc::domainIntegrate(Umodes[i] & (fvc::div(dev((T(
207 fvc::grad(
208 Umodes[j]))))))).value();
209 }
210 }
211
212 // Export the matrix
213 ITHACAstream::SaveDenseMatrix(btMatrix, "./ITHACAoutput/Matrices/",
214 "bt_" + name(nModes) + "_t");
215 return btMatrix;
216}
217
218void SteadyNSTurbIntrusive::project(fileName folder, label nModes)
219{
220 nModesOnline = nModes;
221
222 if (ITHACAutilities::check_folder("./ITHACAoutput/Matrices/"))
223 {
224 word bStr = "b_" + name(nModes);
225
226 if (ITHACAutilities::check_file("./ITHACAoutput/Matrices/" + bStr))
227 {
228 ITHACAstream::ReadDenseMatrix(bMatrix, "./ITHACAoutput/Matrices/", bStr);
229 }
230 else
231 {
232 bMatrix = diffusiveTerm(nModes);
233 }
234
235 word btStr = "bt_" + name(nModes);
236
237 if (ITHACAutilities::check_file("./ITHACAoutput/Matrices/" + btStr))
238 {
239 ITHACAstream::ReadDenseMatrix(btMatrix, "./ITHACAoutput/Matrices/", btStr);
240 }
241 else
242 {
243 btMatrix = btTurbulence(nModes);
244 }
245
246 word kStr = "k_" + name(nModes);
247
248 if (ITHACAutilities::check_file("./ITHACAoutput/Matrices/" + kStr))
249 {
250 ITHACAstream::ReadDenseMatrix(kMatrix, "./ITHACAoutput/Matrices/", kStr);
251 }
252 else
253 {
255 }
256
257 word cStr = "c_" + name(nModes) + "_t";
258
259 if (ITHACAutilities::check_file("./ITHACAoutput/Matrices/" + cStr))
260 {
261 ITHACAstream::ReadDenseTensor(convTensor, "./ITHACAoutput/Matrices/", cStr);
262 }
263 else
264 {
265 convTensor = convectiveTerm(nModes);
266 }
267
268 word ct1Str = "ct1_" + name(nModes) + "_t";
269
270 if (ITHACAutilities::check_file("./ITHACAoutput/Matrices/" + ct1Str))
271 {
272 ITHACAstream::ReadDenseTensor(ct1Tensor, "./ITHACAoutput/Matrices/", ct1Str);
273 }
274 else
275 {
277 }
278
279 word ct2Str = "ct2_" + name(nModes) + "_t";
280
281 if (ITHACAutilities::check_file("./ITHACAoutput/Matrices/" + ct2Str))
282 {
283 ITHACAstream::ReadDenseTensor(ct2Tensor, "./ITHACAoutput/Matrices/", ct2Str);
284 }
285 else
286 {
288 }
289
290 if (bcMethod == "penalty")
291 {
292 bcVelVec = bcVelocityVec(nModes);
293 bcVelMat = bcVelocityMat(nModes);
294 }
295 }
296 else
297 {
298 bMatrix = diffusiveTerm(nModes);
299 convTensor = convectiveTerm(nModes);
301 btMatrix = btTurbulence(nModes);
304
305 if (bcMethod == "penalty")
306 {
307 bcVelVec = bcVelocityVec(nModes);
308 bcVelMat = bcVelocityMat(nModes);
309 }
310 }
311
312 // Export the matrices
313 if (para->exportPython)
314 {
315 ITHACAstream::exportMatrix(bMatrix, "b", "python", "./ITHACAoutput/Matrices/");
316 ITHACAstream::exportMatrix(kMatrix, "k", "python", "./ITHACAoutput/Matrices/");
317 ITHACAstream::exportMatrix(btMatrix, "bt", "python",
318 "./ITHACAoutput/Matrices/");
320 "./ITHACAoutput/Matrices/");
321 ITHACAstream::exportTensor(ct1Tensor, "ct1", "python",
322 "./ITHACAoutput/Matrices/");
323 ITHACAstream::exportTensor(ct2Tensor, "ct2", "python",
324 "./ITHACAoutput/Matrices/");
325 }
326
327 if (para->exportMatlab)
328 {
329 ITHACAstream::exportMatrix(bMatrix, "b", "matlab", "./ITHACAoutput/Matrices/");
330 ITHACAstream::exportMatrix(kMatrix, "k", "matlab", "./ITHACAoutput/Matrices/");
331 ITHACAstream::exportMatrix(btMatrix, "bt", "matlab",
332 "./ITHACAoutput/Matrices/");
334 "./ITHACAoutput/Matrices/");
335 ITHACAstream::exportTensor(ct1Tensor, "ct1", "matlab",
336 "./ITHACAoutput/Matrices/");
337 ITHACAstream::exportTensor(ct2Tensor, "ct2", "matlab",
338 "./ITHACAoutput/Matrices/");
339 }
340
341 if (para->exportTxt)
342 {
343 ITHACAstream::exportMatrix(bMatrix, "b", "eigen", "./ITHACAoutput/Matrices/");
344 ITHACAstream::exportMatrix(kMatrix, "k", "eigen", "./ITHACAoutput/Matrices/");
345 ITHACAstream::exportMatrix(btMatrix, "bt", "eigen", "./ITHACAoutput/Matrices/");
347 "./ITHACAoutput/Matrices/c");
348 ITHACAstream::exportTensor(ct1Tensor, "ct1_", "eigen",
349 "./ITHACAoutput/Matrices/ct1");
350 ITHACAstream::exportTensor(ct2Tensor, "ct2_", "eigen",
351 "./ITHACAoutput/Matrices/ct2");
352 }
353
355 cTotalTensor.resize(nModes, nModes, nModes);
357}
358
359Eigen::MatrixXd SteadyNSTurbIntrusive::diffusiveTerm(label nModes)
360{
361 Eigen::MatrixXd bMatrix;
362 bMatrix.resize(nModes, nModes);
363
364 // Project everything
365 for (label i = 0; i < nModes; i++)
366 {
367 for (label j = 0; j < nModes; j++)
368 {
369 bMatrix(i, j) = fvc::domainIntegrate(Umodes[i] & fvc::laplacian(
370 dimensionedScalar("1", dimless, 1), Umodes[j])).value();
371 }
372 }
373
374 if (Pstream::parRun())
375 {
376 reduce(bMatrix, sumOp<Eigen::MatrixXd>());
377 }
378
379 ITHACAstream::SaveDenseMatrix(bMatrix, "./ITHACAoutput/Matrices/",
380 "b_" + name(nModes));
381 return bMatrix;
382}
383
384Eigen::Tensor<double, 3> SteadyNSTurbIntrusive::convectiveTerm(label nModes)
385{
386 Eigen::Tensor<double, 3> convTensor;
387 convTensor.resize(nModes, nModes, nModes);
388
389 for (label i = 0; i < nModes; i++)
390 {
391 for (label j = 0; j < nModes; j++)
392 {
393 for (label k = 0; k < nModes; k++)
394 {
395 convTensor(i, j, k) = fvc::domainIntegrate(Umodes[i] & fvc::div(
396 linearInterpolate(Umodes[j]) & Umodes[j].mesh().Sf(),
397 Umodes[k])).value();
398 }
399 }
400 }
401
402 if (Pstream::parRun())
403 {
404 reduce(convTensor, sumOp<Eigen::Tensor<double, 3 >> ());
405 }
406
407 // Export the tensor
408 ITHACAstream::SaveDenseTensor(convTensor, "./ITHACAoutput/Matrices/",
409 "c_" + name(nModes) + "_t");
410 return convTensor;
411}
412
414{
415 Eigen::MatrixXd kMatrix(nModes, nModes);
416
417 // Project everything
418 for (label i = 0; i < nModes; i++)
419 {
420 for (label j = 0; j < nModes; j++)
421 {
422 kMatrix(i, j) = fvc::domainIntegrate(Umodes[i] & fvc::grad(
423 Pmodes[j])).value();
424 }
425 }
426
427 if (Pstream::parRun())
428 {
429 reduce(kMatrix, sumOp<Eigen::MatrixXd>());
430 }
431
432 ITHACAstream::SaveDenseMatrix(kMatrix, "./ITHACAoutput/Matrices/",
433 "k_" + name(nModes));
434 return kMatrix;
435}
436
437List< Eigen::MatrixXd > SteadyNSTurbIntrusive::bcVelocityVec(label nModes)
438{
439 List < Eigen::MatrixXd > bcVelVec(inletIndex.rows());
440
441 for (label j = 0; j < inletIndex.rows(); j++)
442 {
443 bcVelVec[j].resize(nModes, 1);
444 }
445
446 for (label k = 0; k < inletIndex.rows(); k++)
447 {
448 label BCind = inletIndex(k, 0);
449 label BCcomp = inletIndex(k, 1);
450
451 for (label i = 0; i < nModes; i++)
452 {
453 bcVelVec[k](i, 0) = gSum(Umodes[i].boundaryField()[BCind].component(
454 BCcomp));
455 }
456 }
457
458 ITHACAstream::exportMatrix(bcVelVec, "bcVelVec", "eigen",
459 "./ITHACAoutput/Matrices/bcVelVec");
460 return bcVelVec;
461}
462
463List< Eigen::MatrixXd > SteadyNSTurbIntrusive::bcVelocityMat(label nModes)
464{
465 label BCUsize = inletIndex.rows();
466 List < Eigen::MatrixXd > bcVelMat(BCUsize);
467
468 for (label j = 0; j < inletIndex.rows(); j++)
469 {
470 bcVelMat[j].resize(nModes, nModes);
471 }
472
473 for (label k = 0; k < inletIndex.rows(); k++)
474 {
475 label BCind = inletIndex(k, 0);
476 label BCcomp = inletIndex(k, 1);
477
478 for (label i = 0; i < nModes; i++)
479 {
480 for (label j = 0; j < nModes; j++)
481 {
482 bcVelMat[k](i, j) = gSum(Umodes[i].boundaryField()[BCind].component(
483 BCcomp) *
484 Umodes[j].boundaryField()[BCind].component(BCcomp));
485 }
486 }
487 }
488
489 ITHACAstream::exportMatrix(bcVelMat, "bcVelMat", "eigen",
490 "./ITHACAoutput/Matrices/bcVelMat");
491 return bcVelMat;
492}
Header file of the SteadyNSTurbIntrusive class.
static ITHACAparameters * getInstance()
Gets an instance of ITHACAparameters, to be used if the instance is already existing.
Eigen::MatrixXd diffusiveTerm(label nModes)
Diffusive Term.
Eigen::MatrixXd bTotalMatrix
Total B Matrix.
PtrList< volScalarField > nutModes
List of POD modes for eddy viscosity.
Eigen::MatrixXd btTurbulence(label nModes)
bt added matrix for the turbulence treatement
Eigen::Tensor< double, 3 > turbulenceTensor2(label nModes)
Method to compute one of the turbulence eddy viscosity tensors.
Eigen::Tensor< double, 3 > convTensor
Convective tensor.
PtrList< volScalarField > nutFields
List of snapshots for the solution for eddy viscosity.
List< Eigen::MatrixXd > bcVelocityVec(label nModes)
Boundary integral modes on boundary used by the penaly method.
Eigen::Tensor< double, 3 > cTotalTensor
Total Turbulent tensor.
Eigen::Tensor< double, 3 > convectiveTerm(label nModes)
The method for computing the convective term tensor.
autoPtr< volScalarField > _nut
Eddy viscosity field.
Eigen::MatrixXd kMatrix
Pressure Gradient matrix.
Eigen::MatrixXd btMatrix
Turbulent viscosity matrix.
List< Eigen::MatrixXd > bcVelocityMat(label nModes)
Boundary integral modes on boundary used by the penaly method.
Eigen::Tensor< double, 3 > turbulenceTensor1(label nModes)
Method to compute one of the turbulence eddy viscosity tensors.
Eigen::MatrixXd pressureGradientTerm(label nModes)
The method for computing the pressure gradient term with number of modes of pressure being equal to t...
label nModesOnline
Number of modes used in the online stage.
Eigen::MatrixXd bMatrix
Diffusive matrix.
Eigen::Tensor< double, 3 > ct2Tensor
Turbulent viscosity tensor.
Eigen::Tensor< double, 3 > ct1Tensor
Turbulent viscosity tensor.
void project()
General projection operation.
void writeMu(List< scalar > mu_now)
Write out a list of scalar corresponding to the parameters used in the truthSolve.
Eigen::MatrixXd mu_samples
Matrix of parameters to be used for PODI, where each row corresponds to a sample point....
label counter
Counter used for the output of the full order solutions.
bool offline
Boolean variable, it is 1 if the Offline phase has already been computed, else 0.
IOdictionary * ITHACAdict
dictionary to store input output infos
Eigen::MatrixXd mu
Row matrix of parameters.
autoPtr< argList > _args
argList
Eigen::MatrixXi inletIndex
Matrix that contains informations about the inlet boundaries.
bool podex
Boolean variable, it is 1 if the POD has already been computed, else 0.
void truthSolve()
Perform a TruthSolve.
List< Eigen::MatrixXd > bcVelVec
Boundary term for penalty method - vector.
Definition steadyNS.H:227
scalar maxIter
Number of maximum iterations to be done for the computation of the truth solution.
Definition steadyNS.H:128
bool supex
Boolean variable to check the existence of the supremizer modes.
Definition steadyNS.H:265
autoPtr< surfaceScalarField > _phi
Flux.
Definition steadyNS.H:302
autoPtr< simpleControl > _simple
simpleControl
Definition steadyNS.H:293
PtrList< volScalarField > Pfield
List of pointers used to form the pressure snapshots matrix.
Definition steadyNS.H:86
autoPtr< fv::options > _fvOptions
fvOptions
Definition steadyNS.H:296
autoPtr< Time > _runTime
Time.
Definition steadyNS.H:299
volVectorModes Umodes
List of pointers used to form the velocity modes.
Definition steadyNS.H:101
PtrList< volVectorField > Ufield
List of pointers used to form the velocity snapshots matrix.
Definition steadyNS.H:89
scalar tolerance
Tolerance for the residual of the stationary problems, there is the same tolerance for velocity and p...
Definition steadyNS.H:125
autoPtr< fvMesh > _mesh
Mesh.
Definition steadyNS.H:290
autoPtr< singlePhaseTransportModel > _laminarTransport
Laminar transport (used by turbulence model).
Definition steadyNS.H:311
autoPtr< IOMRFZoneList > _MRF
MRF variable.
Definition steadyNS.H:314
autoPtr< incompressible::turbulenceModel > turbulence
Turbulence model.
Definition steadyNS.H:308
List< Eigen::MatrixXd > bcVelMat
Boundary term for penalty method - matrix.
Definition steadyNS.H:230
autoPtr< volVectorField > _U
Velocity field.
Definition steadyNS.H:272
volScalarModes Pmodes
List of pointers used to form the pressure modes.
Definition steadyNS.H:98
word bcMethod
Boundary Method.
Definition steadyNS.H:326
autoPtr< volScalarField > _p
Pressure field.
Definition steadyNS.H:269
void ReadDenseMatrix(MatrixType &Matrix, word folder, word MatrixName)
Read a dense matrix from a binary format file.
void exportSolution(GeometricField< Type, PatchField, GeoMesh > &s, fileName subfolder, fileName folder, word fieldName)
Export a field to file in a certain folder and subfolder.
void exportMatrix(Eigen::Matrix< T, -1, dim > &matrix, word Name, word type, word folder)
Export the reduced matrices in numpy (type=python), matlab (type=matlab) and txt (type=eigen) format ...
void SaveDenseMatrix(MatrixType &Matrix, word folder, word MatrixName)
Save a dense matrix to a binary format file.
void ReadDenseTensor(TensorType &Tensor, word folder, word MatrixName)
Read a dense tensor from file.
void exportTensor(Eigen::Tensor< T, 3 > tensor, word Name, word type, word folder)
Export the reduced tensor in numpy (tipo=python), matlab (tipo=matlab) and txt (tipo=eigen) format.
void SaveDenseTensor(TensorType &Tensor, word folder, word MatrixName)
Save a dense tensor to file.
bool check_pod()
Check if the POD data folder "./ITHACAoutput/POD" exists.
bool check_off()
Check if the offline data folder "./ITHACAoutput/Offline" exists.
bool check_folder(word folder)
Checks if a folder exists.
bool check_file(std::string fileName)
Function that returns true if a file exists.
bool check_sup()
Check if the supremizer folder exists.
Header file of the steadyNS class.