Loading...
Searching...
No Matches
ReducedUnsteadyNSTTurb.C
Go to the documentation of this file.
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
33
34
36
37
38// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * * //
39
40// Constructor
44
46
47//problem(&FOMproblem)
48{
49 problem = & FOMproblem;
50 N_BC = problem->inletIndex.rows();
51 N_BC_t = problem->inletIndexT.rows();
52 Nphi_u = problem->B_matrix.rows();
53 Nphi_p = problem->K_matrix.cols();
54 Nphi_t = problem->Y_matrix.rows();
55 Nphi_nut = problem->CT2_matrix[0].rows();
56
57 // Create locally the velocity modes
58 for (int k = 0; k < problem->liftfield.size(); k++)
59 {
60 Umodes.append((problem->liftfield[k]).clone());
61 }
62
63 for (int k = 0; k < problem->NUmodes; k++)
64 {
65 Umodes.append((problem->Umodes[k]).clone());
66 }
67
68 for (int k = 0; k < problem->NSUPmodes; k++)
69 {
70 Umodes.append((problem->supmodes[k]).clone());
71 }
72
73 // Create locally the pressure modes
74 for (int k = 0; k < problem->NPmodes; k++)
75 {
76 Pmodes.append((problem->Pmodes[k]).clone());
77 }
78
79 for (int k = 0; k < problem->liftfieldT.size(); k++)
80 {
81 Tmodes.append((problem->liftfieldT[k]).clone());
82 }
83
84 // Create locally the temperature modes
85 for (int k = 0; k < problem->NTmodes; k++)
86 {
87 Tmodes.append((problem->Tmodes[k]).clone());
88 }
89
90 // Store locally the snapshots for projections
91 for (int k = 0; k < problem->Ufield.size(); k++)
92 {
93 Usnapshots.append((problem->Ufield[k]).clone());
94 Psnapshots.append((problem->Pfield[k]).clone());
95 }
96
97 for (int k = 0; k < problem->Tfield.size(); k++)
98 {
99 Tsnapshots.append((problem->Tfield[k]).clone());
100 }
101
103 FOMproblem);
105}
106
107// * * * * * * * * * * * * * * * Operators supremizer * * * * * * * * * * * * * //
108
109// Operator to evaluate the residual for the supremizer approach
110int newton_unsteadyNSTTurb_sup::operator()(const Eigen::VectorXd& x,
111 Eigen::VectorXd& fvec) const
112{
113 Eigen::VectorXd a_dot(Nphi_u);
114 Eigen::VectorXd a_tmp(Nphi_u);
115 Eigen::VectorXd b_tmp(Nphi_p);
116 a_tmp = x.head(Nphi_u);
117 b_tmp = x.tail(Nphi_p);
118 a_dot = (x.head(Nphi_u) - y_old.head(Nphi_u)) / dt;
119 // Convective term
120 Eigen::MatrixXd cc(1, 1);
121 // Mom Term
122 Eigen::VectorXd M1 = problem ->B_total_matrix * a_tmp * nu;
123 // Gradient of pressure
124 Eigen::VectorXd M2 = problem->K_matrix * b_tmp;
125 // Mass Term
126 Eigen::VectorXd M5 = problem->M_matrix * a_dot;
127 // Pressure Term
128 Eigen::VectorXd M3 = problem->P_matrix * a_tmp;
129
130 //std::cerr << "I am here 5" << std::endl;
131 for (int i = 0; i < Nphi_u; i++)
132 {
133 cc = a_tmp.transpose() * problem->C_matrix[i] * a_tmp - nu_c.transpose() *
134 problem->C_total_matrix[i] * a_tmp;
135 fvec(i) = - M5(i) + M1(i) - cc(0, 0) - M2(i);
136 //Info << "Non-turb part is " << a_tmp.transpose() * C_matrix[i] * a_tmp << endl; //Info << "Turb part is " << nu_c.transpose() * C_total_matrix[i] * a_tmp << endl
137 }
138
139 for (int j = 0; j < Nphi_p; j++)
140 {
141 int k = j + Nphi_u;
142 fvec(k) = M3(j);
143 }
144
145 for (int j = 0; j < N_BC; j++)
146 {
147 fvec(j) = x(j) - BC(j);
148 }
149
150 return 0;
151}
152
153// Operator to evaluate the Jacobian for the supremizer approach
154int newton_unsteadyNSTTurb_sup::df(const Eigen::VectorXd& x,
155 Eigen::MatrixXd& fjac) const
156{
157 Eigen::NumericalDiff<newton_unsteadyNSTTurb_sup> numDiff(* this);
158 numDiff.df(x, fjac);
159 return 0;
160}
161
162
163int newton_unsteadyNSTTurb_sup_t::operator()(const Eigen::VectorXd& t,
164 Eigen::VectorXd& fvect) const
165{
166 // Eigen::VectorXd a_tmp(Nphi_u);
167 Eigen::VectorXd c_dot(Nphi_t);
168 Eigen::VectorXd c_tmp(Nphi_t);
169 c_tmp = t.head(Nphi_t);
170 c_dot = (t.head(Nphi_t) - z_old.head(Nphi_t)) / dt;
171 // Convective term temperature
172 Eigen::MatrixXd qq(1, 1);
173 Eigen::MatrixXd st(1, 1);
174 // diffusive term temperature
175 Eigen::VectorXd M6 = problem->Y_matrix * c_tmp * nu / Pr;
176 // Mass Term Temperature
177 Eigen::VectorXd M8 = problem->MT_matrix * c_dot;
178
179 for (int i = 0; i < Nphi_t; i++)
180 {
181 qq = a_tmp.transpose() * problem->Q_matrix[i] * c_tmp;
182 st = nu_c.transpose() * problem->S_matrix[i] * c_tmp;
183 fvect(i) = -M8(i) + M6(i) - qq(0, 0) + st(0, 0) / Prt;
184 }
185
186 for (int j = 0; j < N_BC_t; j++)
187 {
188 fvect(j) = t(j) - BC_t(j);
189 }
190
191 return 0;
192}
193
194int newton_unsteadyNSTTurb_sup_t::df(const Eigen::VectorXd& t,
195 Eigen::MatrixXd& fjact) const
196{
197 Eigen::NumericalDiff<newton_unsteadyNSTTurb_sup_t> numDiff(* this);
198 numDiff.df(t, fjact);
199 return 0;
200}
201
202
203// * * * * * * * * * * * * * * * Solve Functions * * * * * * * * * * * * * //
205 Eigen::MatrixXd& temp_now, int startSnap)
206{
207 // Create and resize the solution vector
208 y.resize(Nphi_u + Nphi_p, 1);
209 y.setZero();
210 z.resize(Nphi_t, 1);
211 z.setZero();
212 volScalarField T_IC("T_IC", problem->Tfield[0]);
213
214 for (int j = 0; j < T_IC.boundaryField().size(); j++)
215 {
216 for (int i = 0; i < N_BC_t; i++)
217 {
218 if (j == problem->inletIndexT(i, 0))
219 {
220 T_IC.boundaryFieldRef()[problem->inletIndexT(i, 0)][j] = temp_now(i, 0);
221 }
222 else
223 {
224 }
225 }
226 }
227
231
232 // Change initial condition for the lifting function
233 for (int j = 0; j < N_BC; j++)
234 {
235 y(j) = vel_now(j, 0);
236 }
237
238 for (int j = 0; j < N_BC_t; j++)
239 {
240 z(j) = temp_now(j, 0);
241 }
242
243 // Set some properties of the newton object
245 newton_object_sup.y_old = y;
251 newton_object_sup_t.z_old = z;
252 newton_object_sup.BC.resize(N_BC);
253 newton_object_sup_t.BC_t.resize(N_BC_t);
254
255 for (int j = 0; j < N_BC; j++)
256 {
257 newton_object_sup.BC(j) = vel_now(j, 0);
258 }
259
260 for (int j = 0; j < N_BC_t; j++)
261 {
262 newton_object_sup_t.BC_t(j) = temp_now(j, 0);
263 }
264
265 // Set number of online solutions
266 int Ntsteps = static_cast<int>((finalTime - tstart) / dt);
267 online_solution.resize(Ntsteps);
268 online_solutiont.resize(Ntsteps);
269 // Set the initial time
270 time = tstart;
271 // Counting variable
272 int counter = 0;
273 // Create vector to store temporal solution and save initial condition as first solution
274 Eigen::MatrixXd tmp_sol(Nphi_u + Nphi_p + 1, 1);
275 tmp_sol(0) = time;
276 tmp_sol.col(0).tail(y.rows()) = y;
277 online_solution[counter] = tmp_sol;
278 Eigen::MatrixXd tmp_solt(Nphi_t + 1, 1);
279 tmp_solt(0) = time;
280 tmp_solt.col(0).tail(z.rows()) = z;
281 online_solutiont[counter] = tmp_solt;
282 counter ++;
283 Eigen::HybridNonLinearSolver<newton_unsteadyNSTTurb_sup> hnls(
285 Eigen::HybridNonLinearSolver<newton_unsteadyNSTTurb_sup_t> hnlst(
287 // Set output colors for fancy output
291
292 // Start the time loop
293 while (time < finalTime)
294 {
295 time = time + dt;
296 std::vector<double> tv;
297 tv.resize(1 + vel_now.size());
298 tv[0] = time;
299
300 for (int i = 1; i < tv.size(); i++)
301 {
302 tv[i] = vel_now(i - 1);
303 }
304
305 for (int i = 0; i < Nphi_nut; i++)
306 {
307 newton_object_sup.nu_c(i) = problem->rbfsplines[i]->eval(tv);
308 }
309
310 volScalarField nut_rec("nut_rec", problem->nuTmodes[0] * 0);
311
312 for (int j = 0; j < Nphi_nut; j++)
313 {
314 nut_rec += problem->nuTmodes[j] * newton_object_sup.nu_c(j);
315 }
316
317 nutREC.append((nut_rec).clone());
319 Eigen::VectorXd res(y);
320 Eigen::VectorXd rest(z);
321 res.setZero();
322 rest.setZero();
323 hnls.solve(y);
324
325 for (int j = 0; j < N_BC; j++)
326 {
327 y(j) = vel_now(j, 0);
328 }
329
330 newton_object_sup_t.a_tmp = y.head(Nphi_u);
331 hnlst.solve(z);
332
333 for (int j = 0; j < N_BC_t; j++)
334 {
335 z(j) = temp_now(j, 0);
336 }
337
338 newton_object_sup.operator()(y, res);
339 newton_object_sup.y_old = y;
340 newton_object_sup_t.operator()(z, rest);
341 newton_object_sup_t.z_old = z;
342 std::cout << "################## Online solve N° " << count_online_solve <<
343 " ##################" << std::endl;
344 Info << "Time = " << time << endl;
345 std::cout << "Solving for the parameter: " << vel_now << std::endl;
346
347 if (res.norm() < 1e-5)
348 {
349 std::cout << green << "|F(x)| = " << res.norm() << " - Minimun reached in " <<
350 hnls.iter << " iterations " << def << std::endl << std::endl;
351 }
352 else
353 {
354 std::cout << red << "|F(x)| = " << res.norm() << " - Minimun reached in " <<
355 hnls.iter << " iterations " << def << std::endl << std::endl;
356 }
357
359 tmp_sol(0) = time;
360 tmp_sol.col(0).tail(y.rows()) = y;
361
362 if (counter >= online_solution.size())
363 {
364 online_solution.append(tmp_sol);
365 }
366 else
367 {
368 online_solution[counter] = tmp_sol;
369 }
370
371 tmp_solt(0) = time;
372 tmp_solt.col(0).tail(z.rows()) = z;
373
374 if (counter >= online_solutiont.size())
375 {
376 online_solutiont.append(tmp_solt);
377 }
378 else
379 {
380 online_solutiont[counter] = tmp_solt;
381 }
382
383 counter ++;
384 }
385
386 // Save the solution
387 ITHACAstream::exportMatrix(online_solution, "red_coeff", "python",
388 "./ITHACAoutput/red_coeff");
389 ITHACAstream::exportMatrix(online_solution, "red_coeff", "matlab",
390 "./ITHACAoutput/red_coeff");
391 ITHACAstream::exportMatrix(online_solutiont, "red_coeff", "python",
392 "./ITHACAoutput/red_coeff_t");
393 ITHACAstream::exportMatrix(online_solutiont, "red_coeff", "matlab",
394 "./ITHACAoutput/red_coeff_t");
395 ITHACAstream::exportFields(nutREC, "nutfield", "./ITHACAoutput/nutfield/");
397}
398
399// * * * * * * * * * * * * * * * Solve Functions * * * * * * * * * * * * * //
400
401void ReducedUnsteadyNSTTurb::reconstructSup(fileName folder, int printevery)
402{
403 mkDir(folder);
404 system("ln -s ../../constant " + folder + "/constant");
405 system("ln -s ../../0 " + folder + "/0");
406 system("ln -s ../../system " + folder + "/system");
407 int counter = 0;
408 int nextwrite = 0;
409 int counter2 = 1;
410
411 for (int i = 0; i < online_solution.size(); i++)
412 {
413 if (counter == nextwrite)
414 {
415 volVectorField U_rec("U_rec", Umodes[0] * 0);
416
417 for (int j = 0; j < Nphi_u; j++)
418 {
419 U_rec += Umodes[j] * online_solution[i](j + 1, 0);
420 }
421
422 ITHACAstream::exportSolution(U_rec, name(counter2), folder);
423 volScalarField P_rec("P_rec", Pmodes[0] * 0);
424
425 for (int j = 0; j < Nphi_p; j++)
426 {
427 P_rec += Pmodes[j] * online_solution[i](j + Nphi_u + 1, 0);
428 }
429
430 ITHACAstream::exportSolution(P_rec, name(counter2), folder);
431 ITHACAstream::exportSolution(nutREC[nextwrite], name(counter2), folder);
432 nextwrite += printevery;
433 counter2 ++;
434 UREC.append((U_rec).clone());
435 PREC.append((P_rec).clone());
436 }
437
438 counter++;
439 }
440}
441
442void ReducedUnsteadyNSTTurb::reconstructSupt(fileName folder, int printevery)
443{
444 mkDir(folder);
445 system("ln -s ../../constant " + folder + "/constant");
446 system("ln -s ../../0 " + folder + "/0");
447 system("ln -s ../../system " + folder + "/system");
448 int counter = 0;
449 int nextwrite = 0;
450 int counter2 = 1;
451
452 for (int i = 0; i < online_solutiont.size(); i++)
453 {
454 if (counter == nextwrite)
455 {
456 volScalarField T_rec("T_rec", Tmodes[0] * 0);
457
458 for (int j = 0; j < Nphi_t; j++)
459 {
460 T_rec += Tmodes[j] * online_solutiont[i](j + 1, 0);
461 }
462
463 ITHACAstream::exportSolution(T_rec, name(counter2), folder);
464 nextwrite += printevery;
465 counter2 ++;
466 TREC.append((T_rec).clone());
467 }
468
469 counter++;
470 }
471}
472
473// ************************************************************************* //
Header file of the reducedUnsteadyNSTTurb class.
Class to change color to the output stream.
Definition colormod.H:24
ReducedUnsteadyNSTTurb()
Construct Null.
void solveOnlineSup(Eigen::MatrixXd &vel_now, Eigen::MatrixXd &temp_now, int startSnap=0)
Method to perform an online solve using a supremizer stabilisation method.
double time
Scalar to store the current time.
newton_unsteadyNSTTurb_sup_t newton_object_sup_t
Functor object to call the non linear solver sup. approach for temperature field.
double dt
Scalar to store the time increment.
newton_unsteadyNSTTurb_sup newton_object_sup
Functor object to call the non linear solver sup. approach.
scalar Prt
Scalar to store the turbulent Prandtl number.
int Nphi_nut
Number of nut field modes.
UnsteadyNSTTurb * problem
Pointer to the FOM problem.
void reconstructSup(fileName folder="./ITHACAOutput/online_rec", int printevery=1)
Method to reconstruct a solution for velocity and pressure from an online solve with a supremizer sta...
PtrList< volScalarField > nutREC
Reconstructed eddy viscosity field.
double finalTime
Scalar to store the final time if the online simulation.
void reconstructSupt(fileName folder="./ITHACAOutput/online_rec", int printevery=1)
Method to reconstruct a solution for temperature from an online solve with a supremizer stabilisation...
scalar Pr
Scalar to store the Prandtl number.
double tstart
Scalar to store the final time if the online simulation.
Implementation of a parametrized full order unsteady NST problem weakly coupled with the energy equa...
PtrList< volScalarField > PREC
Reconstructed pressure field.
Eigen::VectorXd y
Vector to store the solution during the Newton procedure.
PtrList< volScalarField > Pmodes
List of pointers to store the modes for pressure.
List< Eigen::MatrixXd > online_solution
List of Eigen matrices to store the online solution.
int Nphi_p
Number of pressure modes.
scalar nu
Reduced viscosity in case of parametrized viscosity.
int count_online_solve
Counter to count the online solutions.
Eigen::MatrixXd vel_now
Online inlet velocity vector.
PtrList< volScalarField > Psnapshots
List of pointers to store the snapshots for pressure.
PtrList< volVectorField > Usnapshots
List of pointers to store the snapshots for velocity.
PtrList< volVectorField > Umodes
List of pointers to store the modes for velocity.
int N_BC
Number of parametrized boundary conditions.
PtrList< volVectorField > UREC
Recontructed velocity field.
int Nphi_u
Number of velocity modes.
PtrList< volScalarField > TREC
Reconstructed temperature field.
int N_BC_t
Number of parametrized boundary conditions related to temperature field.
PtrList< volScalarField > Tmodes
List of pointers to store the modes for temperature.
PtrList< volScalarField > T_rec
Reconstructed temperature field.
List< Eigen::MatrixXd > online_solutiont
List of Eigen matrices to store the online solution for temperature equation.
int Nphi_t
Number of temperature modes.
Eigen::VectorXd z
Vector to store the temperature solution during the Newton procedure.
PtrList< volScalarField > Tsnapshots
List of pointers to store the snapshots for temperature.
@ FG_GREEN
Definition colormod.H:14
@ FG_DEFAULT
Definition colormod.H:16
@ FG_RED
Definition colormod.H:13
void exportFields(PtrList< GeometricField< Type, PatchField, GeoMesh > > &field, word folder, word fieldname)
Function to export a scalar of vector field.
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 ...
Eigen::VectorXd getCoeffs(GeometricField< Type, PatchField, GeoMesh > &snapshot, PtrList< GeometricField< Type, PatchField, GeoMesh > > &modes, label Nmodes, bool consider_volumes)
Projects a snapshot on a basis function and gets the coefficients of the projection.
label i
Definition pEqn.H:46
int operator()(const Eigen::VectorXd &x, Eigen::VectorXd &fvec) const
int df(const Eigen::VectorXd &x, Eigen::MatrixXd &fjac) const
int df(const Eigen::VectorXd &x, Eigen::MatrixXd &fjac) const
int operator()(const Eigen::VectorXd &x, Eigen::VectorXd &fvec) const