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
84 a_o = ITHACAutilities::getCoeffs(problem->Ufield[0],
85 problem->Umodes);
87 problem->Pmodes);
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
190 a_o = ITHACAutilities::getCoeffs(problem->Ufield[0],
191 problem->Umodes);
192 b = ITHACAutilities::getCoeffs(problem->Pfield[0],
193 problem->Pmodes);
194 c_o = ITHACAutilities::getCoeffs(problem->Phifield[0],
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 {
279 M9 += dt * Eigen::SliceFromTensor(problem->Ci_tensor, 0,
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
Definition NLsolve.H:38
Header file of the ReducedUnsteadyNSExplicit class.
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.
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