Loading...
Searching...
No Matches
ReducedSteadyNSTurb.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 "ReducedSteadyNSTurb.H"
32
33// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * * //
34
35// Constructor
39
41 :
42 problem(& fomProblem)
43{
44 N_BC = problem->inletIndex.rows();
45 Nphi_u = problem->B_matrix.rows();
46 Nphi_p = problem->K_matrix.cols();
47 nphiNut = problem->cTotalTensor.dimension(1);
48
49 for (int k = 0; k < problem->liftfield.size(); k++)
50 {
51 Umodes.append((problem->liftfield[k]).clone());
52 }
53
54 for (int k = 0; k < problem->NUmodes; k++)
55 {
56 Umodes.append((problem->Umodes[k]).clone());
57 }
58
59 for (int k = 0; k < problem->NSUPmodes; k++)
60 {
61 Umodes.append((problem->supmodes[k]).clone());
62 }
63
65 fomProblem);
67 fomProblem);
68}
69
70int newtonSteadyNSTurbSUP::operator()(const Eigen::VectorXd& x,
71 Eigen::VectorXd& fvec) const
72{
73 Eigen::VectorXd aTmp(Nphi_u);
74 Eigen::VectorXd bTmp(Nphi_p);
75 aTmp = x.head(Nphi_u);
76 bTmp = x.tail(Nphi_p);
77 // Convective term
78 Eigen::MatrixXd cc(1, 1);
79 // Mom Term
80 Eigen::VectorXd m1 = problem->bTotalMatrix * aTmp * nu;
81 // Gradient of pressure
82 Eigen::VectorXd m2 = problem->K_matrix * bTmp;
83 // Pressure Term
84 Eigen::VectorXd m3 = problem->P_matrix * aTmp;
85 // Penalty term
86 Eigen::MatrixXd penaltyU = Eigen::MatrixXd::Zero(Nphi_u, N_BC);
87
88 // Term for penalty method
89 if (problem->bcMethod == "penalty")
90 {
91 for (int l = 0; l < N_BC; l++)
92 {
93 penaltyU.col(l) = bc(l) * problem->bcVelVec[l] - problem->bcVelMat[l] *
94 aTmp;
95 }
96 }
97
98 for (int i = 0; i < Nphi_u; i++)
99 {
100 cc = aTmp.transpose() * Eigen::SliceFromTensor(problem->C_tensor, 0,
101 i) * aTmp - gNut.transpose() *
102 Eigen::SliceFromTensor(problem->cTotalTensor, 0, i) * aTmp;
103 fvec(i) = m1(i) - cc(0, 0) - m2(i);
104
105 if (problem->bcMethod == "penalty")
106 {
107 fvec(i) += ((penaltyU * tauU)(i, 0));
108 }
109 }
110
111 for (int j = 0; j < Nphi_p; j++)
112 {
113 int k = j + Nphi_u;
114 fvec(k) = m3(j);
115 }
116
117 if (problem->bcMethod == "lift")
118 {
119 for (int j = 0; j < N_BC; j++)
120 {
121 fvec(j) = x(j) - bc(j);
122 }
123 }
124
125 return 0;
126}
127
128int newtonSteadyNSTurbPPE::operator()(const Eigen::VectorXd& x,
129 Eigen::VectorXd& fvec) const
130{
131 Eigen::VectorXd aTmp(Nphi_u);
132 Eigen::VectorXd bTmp(Nphi_p);
133 aTmp = x.head(Nphi_u);
134 bTmp = x.tail(Nphi_p);
135 // Convective term
136 Eigen::MatrixXd cc(1, 1);
137 Eigen::MatrixXd gg(1, 1);
138 Eigen::MatrixXd bb(1, 1);
139 // Mom Term
140 Eigen::VectorXd m1 = problem->bTotalMatrix * aTmp * nu;
141 // Gradient of pressure
142 Eigen::VectorXd m2 = problem->K_matrix * bTmp;
143 // Pressure Term
144 Eigen::VectorXd m3 = problem->D_matrix * bTmp;
145 // BC PPE
146 Eigen::VectorXd m7 = problem->BC3_matrix * aTmp * nu;
147 // Penalty term
148 Eigen::MatrixXd penaltyU = Eigen::MatrixXd::Zero(Nphi_u, N_BC);
149
150 // Term for penalty method
151 if (problem->bcMethod == "penalty")
152 {
153 for (int l = 0; l < N_BC; l++)
154 {
155 penaltyU.col(l) = bc(l) * problem->bcVelVec[l] - problem->bcVelMat[l] *
156 aTmp;
157 }
158 }
159
160 for (int i = 0; i < Nphi_u; i++)
161 {
162 cc = aTmp.transpose() * Eigen::SliceFromTensor(problem->C_tensor, 0,
163 i) * aTmp - gNut.transpose() *
164 Eigen::SliceFromTensor(problem->cTotalTensor, 0, i) * aTmp;
165 fvec(i) = m1(i) - cc(0, 0) - m2(i);
166
167 if (problem->bcMethod == "penalty")
168 {
169 fvec(i) += ((penaltyU * tauU)(i, 0));
170 }
171 }
172
173 for (int j = 0; j < Nphi_p; j++)
174 {
175 int k = j + Nphi_u;
176 gg = aTmp.transpose() * Eigen::SliceFromTensor(problem->gTensor, 0,
177 j) * aTmp;
178 //fvec(k) = m3(j, 0) - gg(0, 0) - m6(j, 0) + bb(0, 0);
179 fvec(k) = m3(j, 0) + gg(0, 0) - m7(j, 0);
180 }
181
182 if (problem->bcMethod == "lift")
183 {
184 for (int j = 0; j < N_BC; j++)
185 {
186 fvec(j) = x(j) - bc(j);
187 }
188 }
189
190 return 0;
191}
192
193
194int newtonSteadyNSTurbSUP::df(const Eigen::VectorXd& x,
195 Eigen::MatrixXd& fjac) const
196{
197 Eigen::NumericalDiff<newtonSteadyNSTurbSUP> numDiff(* this);
198 numDiff.df(x, fjac);
199 return 0;
200}
201
202int newtonSteadyNSTurbPPE::df(const Eigen::VectorXd& x,
203 Eigen::MatrixXd& fjac) const
204{
205 Eigen::NumericalDiff<newtonSteadyNSTurbPPE> numDiff(* this);
206 numDiff.df(x, fjac);
207 return 0;
208}
209
210// * * * * * * * * * * * * * * * Solve Functions * * * * * * * * * * * * * //
211
212void ReducedSteadyNSTurb::solveOnlineSUP(Eigen::MatrixXd vel)
213{
214 if (problem->bcMethod == "lift")
215 {
217 }
218 else if (problem->bcMethod == "penalty")
219 {
220 vel_now = vel;
221 }
222
223 y.resize(Nphi_u + Nphi_p, 1);
224 y.setZero();
225
226 // Change initial condition for the lifting function
227 if (problem->bcMethod == "lift")
228 {
229 for (int j = 0; j < N_BC; j++)
230 {
231 y(j) = vel_now(j, 0);
232 }
233 }
234
235 Color::Modifier red(Color::FG_RED);
236 Color::Modifier green(Color::FG_GREEN);
237 Color::Modifier def(Color::FG_DEFAULT);
238 Eigen::HybridNonLinearSolver<newtonSteadyNSTurbSUP> hnls(newtonObjectSUP);
239 newtonObjectSUP.bc.resize(N_BC);
240 newtonObjectSUP.tauU = tauU;
241
242 for (int j = 0; j < N_BC; j++)
243 {
244 newtonObjectSUP.bc(j) = vel_now(j, 0);
245 }
246
247 // Convert vel_now to vector for RBF interpolation
248 Eigen::VectorXd vel_vec = vel_now.col(0);
249 for (int i = 0; i < nphiNut; i++)
250 {
251 newtonObjectSUP.gNut(i) = problem->rbfSplines[i]->predict(vel_vec);
253 }
254
255 newtonObjectSUP.nu = nu;
256 hnls.solve(y);
257 Eigen::VectorXd res(y);
258 newtonObjectSUP.operator()(y, res);
259 Info << "################## Online solve N° " << count_online_solve <<
260 " ##################" << endl;
261 Info << "Solving for the parameter: " << vel_now << endl;
262
263 if (res.norm() < 1e-5)
264 {
265 Info << green << "|F(x)| = " << res.norm() << " - Minimun reached in " <<
266 hnls.iter << " iterations " << def << endl << endl;
267 }
268 else
269 {
270 Info << red << "|F(x)| = " << res.norm() << " - Minimun reached in " <<
271 hnls.iter << " iterations " << def << endl << endl;
272 }
273
275}
276
277void ReducedSteadyNSTurb::solveOnlinePPE(Eigen::MatrixXd vel)
278{
279 if (problem->bcMethod == "lift")
280 {
282 }
283 else if (problem->bcMethod == "penalty")
284 {
285 vel_now = vel;
286 }
287
288 y.resize(Nphi_u + Nphi_p, 1);
289 y.setZero();
290
291 // Change initial condition for the lifting function
292 if (problem->bcMethod == "lift")
293 {
294 for (int j = 0; j < N_BC; j++)
295 {
296 y(j) = vel_now(j, 0);
297 }
298 }
299
300 Color::Modifier red(Color::FG_RED);
301 Color::Modifier green(Color::FG_GREEN);
302 Color::Modifier def(Color::FG_DEFAULT);
303 Eigen::HybridNonLinearSolver<newtonSteadyNSTurbPPE> hnls(newtonObjectPPE);
304 newtonObjectPPE.bc.resize(N_BC);
305 newtonObjectPPE.tauU = tauU;
306
307 for (int j = 0; j < N_BC; j++)
308 {
309 newtonObjectPPE.bc(j) = vel_now(j, 0);
310 }
311
312 // Convert vel_now to vector for RBF interpolation
313 Eigen::VectorXd vel_vec = vel_now.col(0);
314 for (int i = 0; i < nphiNut; i++)
315 {
316 newtonObjectPPE.gNut(i) = problem->rbfSplines[i]->predict(vel_vec);
318 }
319
320 newtonObjectPPE.nu = nu;
321 hnls.solve(y);
322 Eigen::VectorXd res(y);
323 newtonObjectPPE.operator()(y, res);
324 Info << "################## Online solve N° " << count_online_solve <<
325 " ##################" << endl;
326 Info << "Solving for the parameter: " << vel_now << endl;
327
328 if (res.norm() < 1e-5)
329 {
330 Info << green << "|F(x)| = " << res.norm() << " - Minimun reached in " <<
331 hnls.iter << " iterations " << def << endl << endl;
332 }
333 else
334 {
335 Info << red << "|F(x)| = " << res.norm() << " - Minimun reached in " <<
336 hnls.iter << " iterations " << def << endl << endl;
337 }
338
340}
341
342void ReducedSteadyNSTurb::reconstruct(bool exportFields, fileName folder,
343 int printevery)
344{
345 if (exportFields)
346 {
347 mkDir(folder);
349 }
350
351 int counter = 0;
352 int nextWrite = 0;
353 List <Eigen::MatrixXd> CoeffU;
354 List <Eigen::MatrixXd> CoeffP;
355 List <Eigen::MatrixXd> CoeffNut;
356 CoeffU.resize(0);
357 CoeffP.resize(0);
358 CoeffNut.resize(0);
359
360 for (int i = 0; i < online_solution.size(); i++)
361 {
362 if (counter == nextWrite)
363 {
364 Eigen::MatrixXd currentUCoeff;
365 Eigen::MatrixXd currentPCoeff;
366 Eigen::MatrixXd currentNutCoeff;
367 currentUCoeff = online_solution[i].block(1, 0, Nphi_u, 1);
368 currentPCoeff = online_solution[i].bottomRows(Nphi_p);
369 currentNutCoeff = rbfCoeffMat.block(0, i, nphiNut, 1);
370 CoeffU.append(currentUCoeff);
371 CoeffP.append(currentPCoeff);
372 CoeffNut.append(currentNutCoeff);
373 nextWrite += printevery;
374 }
375
376 counter++;
377 }
378
379 volVectorField uRec("uRec", Umodes[0]);
380 volScalarField pRec("pRec", problem->Pmodes[0]);
381 volScalarField nutRec("nutRec", problem->nutModes[0]);
382 uRecFields = problem->L_U_SUPmodes.reconstruct(uRec, CoeffU, "uRec");
383 pRecFields = problem->Pmodes.reconstruct(pRec, CoeffP, "pRec");
384 nutRecFields = problem->nutModes.reconstruct(nutRec, CoeffNut, "nutRec");
385
386 if (exportFields)
387 {
389 "uRec");
391 "pRec");
393 "nutRec");
394 }
395}
396
397Eigen::MatrixXd ReducedSteadyNSTurb::setOnlineVelocity(Eigen::MatrixXd vel)
398{
399 assert(problem->inletIndex.rows() == vel.rows()
400 && "Imposed boundary conditions dimensions do not match given values matrix dimensions");
401 Eigen::MatrixXd vel_scal;
402 vel_scal.resize(vel.rows(), vel.cols());
403
404 for (int k = 0; k < problem->inletIndex.rows(); k++)
405 {
406 int p = problem->inletIndex(k, 0);
407 int l = problem->inletIndex(k, 1);
408 scalar area = gSum(problem->liftfield[0].mesh().magSf().boundaryField()[p]);
409 scalar u_lf = gSum(problem->liftfield[k].mesh().magSf().boundaryField()[p] *
410 problem->liftfield[k].boundaryField()[p]).component(l) / area;
411 vel_scal(k, 0) = vel(k, 0) / u_lf;
412 }
413
414 return vel_scal;
415}
416
417// ************************************************************************* //
418
Header file of the ReducedSteadyNSTurb class.
Class to change color to the output stream.
Definition colormod.H:24
PtrList< volScalarField > nutRecFields
Reconstructed eddy viscosity fields list.
newtonSteadyNSTurbSUP newtonObjectSUP
Newton Object to solve the nonlinear problem sup approach.
newtonSteadyNSTurbPPE newtonObjectPPE
Newton Object to solve the nonlinear problem PPE approach.
void solveOnlinePPE(Eigen::MatrixXd velNow)
Method to perform an online solve using a PPE stabilisation method.
ReducedSteadyNSTurb()
Construct Null.
int nphiNut
Number of viscosity modes.
Eigen::MatrixXd rbfCoeffMat
The matrix of the eddy viscosity RBF interoplated coefficients.
void solveOnlineSUP(Eigen::MatrixXd velNow)
Method to perform an online solve using a supremizer stabilisation method.
SteadyNSTurb * problem
Pointer to the FOM problem.
void reconstruct(bool exportFields=false, fileName folder="./ITHACAoutput/online_rec", int printevery=1)
Method to reconstruct the solutions from an online solve.
Eigen::VectorXd rbfCoeff
Vector of eddy viscosity RBF interoplated coefficients.
Eigen::MatrixXd setOnlineVelocity(Eigen::MatrixXd vel)
Sets the online velocity.
Implementation of a parametrized full order steady turbulent Navier Stokes problem and preparation ...
Eigen::MatrixXd bTotalMatrix
Total B Matrix.
Eigen::VectorXd y
Vector to store the solution during the Newton procedure.
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.
Eigen::MatrixXd tauU
Penalty Factor.
PtrList< volScalarField > pRecFields
Reconstructed pressure fields list.
int count_online_solve
Counter to count the online solutions.
Eigen::MatrixXd vel_now
Online inlet velocity vector.
PtrList< volVectorField > Umodes
List of pointers to store the modes for velocity.
PtrList< volVectorField > uRecFields
Recontructed velocity fields list.
int N_BC
Number of parametrized boundary conditions.
int Nphi_u
Number of velocity modes.
List< Eigen::MatrixXd > bcVelVec
Boundary term for penalty method - vector.
Definition steadyNS.H:227
Eigen::MatrixXd K_matrix
Gradient of pressure matrix.
Definition steadyNS.H:166
List< Eigen::MatrixXd > bcVelMat
Boundary term for penalty method - matrix.
Definition steadyNS.H:230
Eigen::MatrixXd P_matrix
Div of velocity.
Definition steadyNS.H:173
word bcMethod
Boundary Method.
Definition steadyNS.H:326
void exportFields(PtrList< GeometricField< Type, PatchField, GeoMesh > > &field, word folder, word fieldname)
Function to export a scalar of vector field.
void createSymLink(word folder)
Creates symbolic links to 0, system and constant.
Structure to implement a newton object for a stationary NS problem.