Loading...
Searching...
No Matches
ReducedUnsteadyNSExplicit.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) 2020 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 initialization
44
46 FOMproblem)
47 :
48 problem(&FOMproblem)
49{
50 N_BC = problem->inletIndex.rows();
51 Nphi_u = problem->B_matrix.rows();
52 Nphi_p = problem->K_matrix.cols();
53}
54
55// * * * * * * * * * * * * * Solve Functions * * * * * * * * * * * //
56
58 label startSnap)
59{
60 if (problem->fluxMethod == "inconsistent")
61 {
62 // Create and resize the solution vectors
63 Eigen::VectorXd a_o = Eigen::VectorXd::Zero(Nphi_u);
64 Eigen::VectorXd a_n = a_o;
65 Eigen::MatrixXd b = Eigen::VectorXd::Zero(Nphi_p);
66 Eigen::MatrixXd x = Eigen::VectorXd::Zero(Nphi_p);
67 Eigen::VectorXd presidual = Eigen::VectorXd::Zero(Nphi_p);
68 Eigen::VectorXd RHS = Eigen::VectorXd::Zero(Nphi_p);
69 // Counting variable
70 int counter = 0;
71 // Set the initial time
72 time = tstart;
73
74 // Determine number of time steps
75 while (time < finalTime - 0.5 * dt)
76 {
77 time = time + dt;
78 counter ++;
79 }
80
81 // Set the initial time
82 time = tstart;
83 // Initial conditions / guesses
88 // Set size of online solution
89 online_solution.resize(counter + 1);
90 // Create vector to store temporal solution and save initial condition as first solution
91 Eigen::MatrixXd tmp_sol(Nphi_u + Nphi_p + 1, 1);
92 tmp_sol(0) = time;
93 tmp_sol.col(0).segment(1, Nphi_u) = a_o;
94 tmp_sol.col(0).tail(b.rows()) = b;
95 online_solution[0] = tmp_sol;
96
97 for (label i = 1; i < online_solution.size(); i++)
98 {
99 time = time + dt;
100 std::cout << " ################## time = " << time <<
101 " ##################" << std::endl;
102 // Pressure Poisson Equation
103 // Diffusion Term
104 Eigen::VectorXd M1 = problem->BP_matrix * a_o * nu ;
105 // Convection Term
106 Eigen::MatrixXd cf(1, 1);
107 // Divergence term
108 Eigen::MatrixXd M2 = problem->P_matrix * a_o;
109
110 for (label l = 0; l < Nphi_p; l++)
111 {
112 cf = a_o.transpose() * Eigen::SliceFromTensor(problem->Cf_tensor, 0,
113 l) * a_o;
114 RHS(l) = (1 / dt) * M2(l, 0) - cf(0, 0) + M1(l, 0);
115 }
116
117 // Boundary Term (divergence + diffusion + convection)
118 List<Eigen::MatrixXd> RedLinSysP = problem->LinSysDiv;
119 RedLinSysP[1] = RHS;
120
121 for (label i = 0; i < N_BC; i++)
122 {
123 RedLinSysP[1] += vel(i, 0) * ((1 / dt) * problem->LinSysDiv[i + 1] +
124 nu * problem->LinSysDiff[i + 1] +
125 vel(i, 0) * problem->LinSysConv[i + 1]);
126 }
127
128 b = reducedProblem::solveLinearSys(RedLinSysP, x, presidual);
129 // Momentum Equation
130 // Convective term
131 Eigen::MatrixXd cc(1, 1);
132 // Diffusion Term
133 Eigen::VectorXd M5 = problem->B_matrix * a_o * nu ;
134 // Pressure Gradient Term
135 Eigen::VectorXd M3 = problem->K_matrix * b;
136 // Boundary Term Diffusion + Convection
137 Eigen::MatrixXd boundaryTerm = Eigen::MatrixXd::Zero(Nphi_u, N_BC);
138
139 for (label l = 0; l < N_BC; l++)
140 {
141 boundaryTerm.col(l) = (vel(l, 0) * (problem->RD_matrix[l] * nu +
142 vel(l, 0) * problem->RC_matrix[l]));
143 }
144
145 for (label l = 0; l < Nphi_u; l++)
146 {
147 cc = a_o.transpose() * Eigen::SliceFromTensor(problem->C_tensor, 0,
148 l) * a_o;
149 a_n(l) = a_o(l) + (M5(l) - cc(0, 0) - M3(l)) * dt;
150
151 for (label j = 0; j < N_BC; j++)
152 {
153 a_n(l) += boundaryTerm(l, j) * dt;
154 }
155 }
156
157 tmp_sol(0) = time;
158 tmp_sol.col(0).segment(1, Nphi_u) = a_n;
159 tmp_sol.col(0).tail(b.rows()) = b;
160 online_solution[i] = tmp_sol;
161 a_o = a_n;
162 }
163 }
164 else if (problem->fluxMethod == "consistent")
165 {
166 // Create and resize the solution vectors
167 Eigen::VectorXd a_o = Eigen::VectorXd::Zero(Nphi_u);
168 Eigen::VectorXd a_n = a_o;
169 Eigen::MatrixXd b = Eigen::VectorXd::Zero(Nphi_p);
170 Eigen::VectorXd c_o = Eigen::VectorXd::Zero(Nphi_u);
171 Eigen::VectorXd c_n = Eigen::VectorXd::Zero(Nphi_u);
172 Eigen::MatrixXd x = Eigen::VectorXd::Zero(Nphi_p);
173 Eigen::VectorXd presidual = Eigen::VectorXd::Zero(Nphi_p);
174 Eigen::VectorXd RHS = Eigen::VectorXd::Zero(Nphi_p);
175 // Counting variable
176 int counter = 0;
177 // Set the initial time
178 time = tstart;
179
180 // Determine number of time steps
181 while (time < finalTime - 0.5 * dt)
182 {
183 time = time + dt;
184 counter ++;
185 }
186
187 // Set the initial time
188 time = tstart;
189 // Initial conditions / guesses
191 problem->Umodes);
193 problem->Pmodes);
195 problem->Phimodes, 0, false);
196 // Set size of online solution
197 online_solution.resize(counter + 1);
198 // Create vector to store temporal solution and save initial condition as first solution
199 Eigen::MatrixXd tmp_sol(Nphi_u + Nphi_p + Nphi_u + 1, 1);
200 tmp_sol(0) = time;
201 tmp_sol.col(0).segment(1, Nphi_u) = a_o;
202 tmp_sol.col(0).segment(Nphi_u + 1, Nphi_p) = b;
203 tmp_sol.col(0).tail(Nphi_u) = c_o;
204 online_solution[0] = tmp_sol;
205
206 for (label i = 1; i < online_solution.size(); i++)
207 {
208 time = time + dt;
209 std::cout << " ################## time = " << time <<
210 " ##################" << std::endl;
211 Eigen::VectorXd presidual = Eigen::VectorXd::Zero(Nphi_p);
212 // Pressure Poisson Equation
213 // Diffusion Term
214 Eigen::VectorXd M1 = problem->BP_matrix * a_o * nu ;
215 // Convection Term
216 Eigen::MatrixXd cf(1, 1);
217 // Divergence term
218 Eigen::MatrixXd M2 = problem->P_matrix * a_o;
219
220 for (label l = 0; l < Nphi_p; l++)
221 {
222 cf = c_o.transpose() * Eigen::SliceFromTensor(problem->Cf_tensor, 0,
223 l) * a_o;
224 RHS(l) = (1 / dt) * M2(l, 0) - cf(0, 0) + M1(l, 0);
225 }
226
227 // Boundary Term (divergence + diffusion + convection)
228 List<Eigen::MatrixXd> RedLinSysP = problem->LinSysDiv;
229 RedLinSysP[1] = RHS;
230
231 for (label l = 0; l < N_BC; l++)
232 {
233 RedLinSysP[1] += vel(l, 0) * ((1 / dt) * problem->LinSysDiv[l + 1] +
234 nu * problem->LinSysDiff[l + 1] +
235 vel(l, 0) * problem->LinSysConv[l + 1]);
236 }
237
238 b = reducedProblem::solveLinearSys(RedLinSysP, x, presidual);
239 // Momentum Equation
240 // Convective term
241 Eigen::MatrixXd cc(1, 1);
242 // Diffusion Term
243 Eigen::VectorXd M5 = problem->B_matrix * a_o * nu ;
244 // Pressure Gradient Term
245 Eigen::VectorXd M3 = problem->K_matrix * b;
246 // Boundary Term Diffusion + Convection
247 Eigen::MatrixXd boundaryTerm = Eigen::MatrixXd::Zero(Nphi_u, N_BC);
248
249 for (label l = 0; l < N_BC; l++)
250 {
251 boundaryTerm.col(l) = (vel(l, 0) * (problem->RD_matrix[l] * nu +
252 vel(l, 0) * problem->RC_matrix[l]));
253 }
254
255 for (label k = 0; k < Nphi_u; k++)
256 {
257 cc = c_o.transpose() * Eigen::SliceFromTensor(problem->C_tensor, 0,
258 k) * a_o;
259 a_n(k) = a_o(k) + (M5(k) - cc(0, 0) - M3(k)) * dt;
260
261 for (label l = 0; l < N_BC; l++)
262 {
263 a_n(k) += boundaryTerm(k, l) * dt;
264 }
265 }
266
267 // Flux Equation
268 // Mass Term
269 Eigen::MatrixXd M6 = problem->I_matrix * a_o;
270 // Diffusion Term
271 Eigen::MatrixXd M7 = problem->DF_matrix * a_o * nu;
272 // Pressure Gradient Term
273 Eigen::MatrixXd M8 = problem->KF_matrix * b.col(0);
274 // Convective Term
275 Eigen::MatrixXd M9 = Eigen::VectorXd::Zero(Nphi_u);
276
277 for (label k = 0; k < Nphi_u; k++)
278 {
280 k) * a_o * c_o(k);
281 }
282
283 // Boundary Term Diffusion + Convection
284 Eigen::VectorXd boundaryTermFlux = Eigen::VectorXd::Zero(Nphi_u);
285
286 for (label l = 0; l < N_BC; l++)
287 {
288 boundaryTermFlux += (vel(l, 0) * (problem->SD_matrix[l] * nu +
289 vel(l, 0) * problem->SC_matrix[l]));
290 }
291
292 c_n = problem->W_matrix.colPivHouseholderQr().solve(M6 - M9 + dt * (-M8 + M7
293 + boundaryTermFlux));
294 tmp_sol(0) = time;
295 tmp_sol.col(0).segment(1, Nphi_u) = a_n;
296 tmp_sol.col(0).segment(Nphi_u + 1, Nphi_p) = b;
297 tmp_sol.col(0).tail(Nphi_u) = c_n;
298 online_solution[i] = tmp_sol;
299 a_o = a_n;
300 c_o = c_n;
301 }
302 }
303 else
304 {
305 std::cout <<
306 "Only the inconsistent flux method and consistent flux method are implemented."
307 << std::endl;
308 exit(0);
309 }
310}
311
312
313void ReducedUnsteadyNSExplicit::reconstruct(bool exportFields, fileName folder)
314{
315 if (exportFields)
316 {
317 mkDir(folder);
319 }
320
321 int counter = 0;
322 int nextwrite = 0;
323 List < Eigen::MatrixXd> CoeffU;
324 List < Eigen::MatrixXd> CoeffP;
325 List <double> tValues;
326 CoeffU.resize(0);
327 CoeffP.resize(0);
328 tValues.resize(0);
329 int exportEveryIndex = round(exportEvery / storeEvery);
330
331 for (label i = 0; i < online_solution.size(); i++)
332 {
333 if (counter == nextwrite)
334 {
335 Eigen::MatrixXd currentUCoeff;
336 Eigen::MatrixXd currentPCoeff;
337 currentUCoeff = online_solution[i].block(1, 0, Nphi_u, 1);
338 currentPCoeff = online_solution[i].block(1 + Nphi_u, 0, Nphi_p, 1);
339 CoeffU.append(currentUCoeff);
340 CoeffP.append(currentPCoeff);
341 nextwrite += exportEveryIndex;
342 double timeNow = online_solution[i](0, 0);
343 tValues.append(timeNow);
344 }
345
346 counter++;
347 }
348
349 volVectorField uRec("uRec", problem->Umodes[0]);
350 volScalarField pRec("pRec", problem->Pmodes[0]);
351 uRecFields = problem->Umodes.reconstruct(uRec, CoeffU, "uRec");
352 pRecFields = problem->Pmodes.reconstruct(pRec, CoeffP, "pRec");
353
354 if (exportFields)
355 {
357 "uRec");
359 "pRec");
360 }
361}
362
363
364//************************************************************************* //
scalar presidual
Header file of the ReducedUnsteadyNSExplicit class.
GeometricField< Type, PatchField, GeoMesh > reconstruct(GeometricField< Type, PatchField, GeoMesh > &inputField, Eigen::MatrixXd Coeff, word Name)
Function to reconstruct the solution starting from the coefficients, in this case the field is passed...
Definition Modes.C:275
void reconstruct(bool exportFields=false, fileName folder="./online_rec")
Method to reconstruct the solutions from an online solve with a supremizer stabilisation technique.
UnsteadyNSExplicit * problem
Pointer to the FOM problem.
Implementation of a parametrized full order unsteady NS problem and preparation of the the reduced ...
virtual void solveOnline()
Virtual Method to perform and online Solve.
static Eigen::MatrixXd solveLinearSys(List< Eigen::MatrixXd > LinSys, Eigen::MatrixXd x, Eigen::VectorXd &residual, const Eigen::MatrixXd &bc=Eigen::MatrixXd::Zero(0, 0), const std::string solverType="fullPivLu")
Linear system solver for the online problem.
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.
PtrList< volScalarField > pRecFields
Reconstructed pressure fields list.
PtrList< volVectorField > uRecFields
Recontructed velocity fields list.
int N_BC
Number of parametrized boundary conditions.
int Nphi_u
Number of velocity modes.
double exportEvery
A variable for exporting the fields.
scalar finalTime
Scalar to store the final time if the online simulation.
scalar tstart
Scalar to store the initial time if the online simulation.
scalar time
Scalar to store the current time.
double dt
Scalar to store the time increment.
double storeEvery
A variable for storing the reduced coefficients.
Eigen::MatrixXi inletIndex
Matrix that contains informations about the inlet boundaries.
Eigen::Tensor< double, 3 > C_tensor
Diffusion term.
Definition steadyNS.H:167
PtrList< volScalarField > Pfield
List of pointers used to form the pressure snapshots matrix.
Definition steadyNS.H:86
Eigen::MatrixXd W_matrix
Mass Matrix New Time Step - Consistent Flux Method.
Definition steadyNS.H:197
Eigen::MatrixXd I_matrix
Mass Matrix Old Time Step - Consistent Flux Method.
Definition steadyNS.H:200
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
List< Eigen::MatrixXd > LinSysDiff
Projection Peqn onto Pressure modes - Diffusion term.
Definition steadyNS.H:248
List< Eigen::MatrixXd > LinSysDiv
Projection Peqn onto Pressure modes - Divergence term.
Definition steadyNS.H:245
PtrList< surfaceScalarField > Phifield
List of pointers used to form the flux snapshots matrix.
Definition steadyNS.H:95
word fluxMethod
Flux Method.
Definition steadyNS.H:320
Eigen::MatrixXd B_matrix
Diffusion term.
Definition steadyNS.H:157
List< Eigen::MatrixXd > RD_matrix
Boundary term for diffusion term.
Definition steadyNS.H:227
List< Eigen::MatrixXd > SD_matrix
Boundary term for diffusion term - Consistent Flux Method.
Definition steadyNS.H:233
Eigen::MatrixXd KF_matrix
Pressure Gradient Term - Consistent Flux Method.
Definition steadyNS.H:206
Eigen::MatrixXd K_matrix
Gradient of pressure matrix.
Definition steadyNS.H:163
List< Eigen::MatrixXd > LinSysConv
Projection Peqn onto Pressure modes - Convection term.
Definition steadyNS.H:251
List< Eigen::MatrixXd > SC_matrix
Boundary term for convection term - Consistent Flux Method.
Definition steadyNS.H:236
Eigen::MatrixXd DF_matrix
Diffusion Term - Consistent Flux Method.
Definition steadyNS.H:203
Eigen::MatrixXd P_matrix
Div of velocity.
Definition steadyNS.H:170
List< Eigen::MatrixXd > RC_matrix
Boundary vector for convection term.
Definition steadyNS.H:230
Eigen::MatrixXd BP_matrix
Diffusion term for flux method PPE.
Definition steadyNS.H:224
Eigen::Tensor< double, 3 > Cf_tensor
Convection term for flux method.
Definition steadyNS.H:239
surfaceScalarModes Phimodes
List of pointers used to form the flux modes.
Definition steadyNS.H:107
Eigen::Tensor< double, 3 > Ci_tensor
Convection term - Consistent Flux Method.
Definition steadyNS.H:242
volScalarModes Pmodes
List of pointers used to form the pressure modes.
Definition steadyNS.H:98
Matrix< VectorType, Dynamic, Dynamic > SliceFromTensor(Eigen::Tensor< VectorType, 3 > &tensor, label dim, label index1)
void exportFields(PtrList< GeometricField< Type, PatchField, GeoMesh > > &field, word folder, word fieldname)
Function to export a scalar of vector field.
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.
void createSymLink(word folder)
Creates symbolic links to 0, system and constant.
label i
Definition pEqn.H:46