Loading...
Searching...
No Matches
ITHACAcoeffsMass.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-------------------------------------------------------------------------------
12License
13 This file is part of ITHACA-FV
14 ITHACA-FV is free software: you can redistribute it and/or modify
15 it under the terms of the GNU Lesser General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18 ITHACA-FV is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU Lesser General Public License for more details.
22 You should have received a copy of the GNU Lesser General Public License
23 along with ITHACA-FV. If not, see <http://www.gnu.org/licenses/>.
24\*---------------------------------------------------------------------------*/
25#include "ITHACAcoeffsMass.H"
26
27namespace ITHACAutilities
28{
29
30template<class Type, template<class> class PatchField, class GeoMesh>
31PtrList<GeometricField<Type, PatchField, GeoMesh>> reconstructFromCoeff(
32 PtrList<GeometricField<Type, PatchField, GeoMesh>>& modes,
33 Eigen::MatrixXd& coeff_matrix, label Nmodes)
34{
35 PtrList<GeometricField<Type, PatchField, GeoMesh>> rec_field;
36 rec_field.resize(0);
37
38 for (label k = 0; k < coeff_matrix.cols(); k++)
39 {
40 for (label i = 0; i < Nmodes; i++)
41 if ( i == 0)
42 {
43 rec_field.append(modes[i]*coeff_matrix(i, k));
44 }
45 else
46 {
47 rec_field[k] += modes[i] * coeff_matrix(i, k);
48 }
49 }
50
51 return rec_field;
52}
53
54template PtrList<GeometricField<scalar, fvPatchField, volMesh>>
56 PtrList<GeometricField<scalar, fvPatchField, volMesh>>& modes,
57 Eigen::MatrixXd& coeff_matrix, label Nmodes);
58template PtrList<GeometricField<vector, fvPatchField, volMesh>>
60 PtrList<GeometricField<vector, fvPatchField, volMesh>>& modes,
61 Eigen::MatrixXd& coeff_matrix, label Nmodes);
62template PtrList<GeometricField<tensor, fvPatchField, volMesh>>
64 PtrList<GeometricField<tensor, fvPatchField, volMesh>>& modes,
65 Eigen::MatrixXd& coeff_matrix, label Nmodes);
66
67template<class Type, template<class> class PatchField, class GeoMesh>
68Eigen::MatrixXd getMassMatrix(
69 PtrList<GeometricField<Type, PatchField, GeoMesh>>& modes, label Nmodes,
70 bool consider_volumes)
71{
72 label Msize;
73
74 if (Nmodes == 0)
75 {
76 Msize = modes.size();
77 }
78 else
79 {
80 Msize = Nmodes;
81 }
82
83 M_Assert(modes.size() >= Msize,
84 "The Number of requested modes is larger then the available quantity.");
85 Eigen::MatrixXd F = Foam2Eigen::PtrList2Eigen(modes);
86 Eigen::MatrixXd M = Eigen::MatrixXd::Zero(Msize,Msize);
87
88 if (consider_volumes)
89 {
90 Eigen::VectorXd V = getMassMatrixFV(modes[0]);
91 // If V is too big then we need a for loop to avoid RAM overload
92 if (V.size() > 1e6)
93 {
94 for (int i=0; i<V.size(); i++)
95 {
96 M += V(i) * F.transpose().topRows(Msize).col(i) * F.leftCols(Msize).row(i);
97 }
98 }
99 else
100 {
101 M = F.transpose().topRows(Msize) * V.asDiagonal() * F.leftCols(Msize);
102 }
103 }
104 else
105 {
106 M = F.transpose().topRows(Msize) * F.leftCols(Msize);
107 }
108
109 if (Pstream::parRun())
110 {
111 reduce(M, sumOp<Eigen::MatrixXd>());
112 }
113
114 return M;
115}
116
117template Eigen::MatrixXd getMassMatrix(
118 PtrList<GeometricField<scalar, fvPatchField, volMesh>>& modes, label Nmodes,
119 bool consider_volumes);
120
121template Eigen::MatrixXd getMassMatrix(
122 PtrList<GeometricField<scalar, fvsPatchField, surfaceMesh>>& modes,
123 label Nmodes,
124 bool consider_volumes = false);
125
126template Eigen::MatrixXd getMassMatrix(
127 PtrList<GeometricField<vector, fvPatchField, volMesh>>& modes, label Nmodes,
128 bool consider_volumes);
129
130template Eigen::MatrixXd getMassMatrix(
131 PtrList<GeometricField<tensor, fvPatchField, volMesh>>& modes, label Nmodes,
132 bool consider_volumes);
133
134template<class Type, template<class> class PatchField, class GeoMesh>
135Eigen::MatrixXd getMassMatrix(
136 PtrList<GeometricField<Type, PatchField, GeoMesh>>& modes,
137 PtrList<GeometricField<Type, PatchField, GeoMesh>>& modes2, label Nmodes,
138 bool consider_volumes)
139{
140 label Msize,Msize2;
141 if (Nmodes == 0)
142 {
143 Msize = modes.size();
144 Msize2 = modes2.size();
145 }
146 else
147 {
148 Msize = Nmodes;
149 Msize2 = Nmodes;
150 }
151 M_Assert(modes.size() >= Msize,
152 "The Number of requested modes is larger then the available quantity.");
153 M_Assert(modes2.size() >= Msize2,
154 "The Number of requested modes is larger then the available quantity.");
155
156 Eigen::MatrixXd F = Foam2Eigen::PtrList2Eigen(modes);
157 Eigen::MatrixXd F2 = Foam2Eigen::PtrList2Eigen(modes2);
158 Eigen::MatrixXd M = Eigen::MatrixXd::Zero(Msize,Msize2);
159
160 if (consider_volumes)
161 {
162 Eigen::VectorXd V = getMassMatrixFV(modes[0]);
163 // If V is too big then we need a for loop to avoid RAM overload
164 if (V.size() > 1e6)
165 {
166 for (int i=0; i<V.size(); i++)
167 {
168 M += V(i) * F.transpose().topRows(Msize).col(i) * F2.leftCols(Msize2).row(i);
169 }
170 }
171 else
172 {
173 // Classical M computation
174 M = F.transpose().topRows(Msize) * V.asDiagonal() * F2.leftCols(Msize2);
175 }
176 }
177 else
178 {
179 M = F.transpose().topRows(Msize) * F2.leftCols(Msize2);
180 }
181
182 if (Pstream::parRun())
183 {
184 reduce(M, sumOp<Eigen::MatrixXd>());
185 }
186
187 return M;
188}
189
190template Eigen::MatrixXd getMassMatrix(
191 PtrList<GeometricField<scalar, fvPatchField, volMesh>>& modes,
192 PtrList<GeometricField<scalar, fvPatchField, volMesh>>& modes2, label Nmodes,
193 bool consider_volumes);
194
195template Eigen::MatrixXd getMassMatrix(
196 PtrList<GeometricField<scalar, fvsPatchField, surfaceMesh>>& modes,
197 PtrList<GeometricField<scalar, fvsPatchField, surfaceMesh>>& modes2,
198 label Nmodes,
199 bool consider_volumes = false);
200
201template Eigen::MatrixXd getMassMatrix(
202 PtrList<GeometricField<vector, fvPatchField, volMesh>>& modes,
203 PtrList<GeometricField<vector, fvPatchField, volMesh>>& modes2, label Nmodes,
204 bool consider_volumes);
205
206template Eigen::MatrixXd getMassMatrix(
207 PtrList<GeometricField<tensor, fvPatchField, volMesh>>& modes,
208 PtrList<GeometricField<tensor, fvPatchField, volMesh>>& modes2, label Nmodes,
209 bool consider_volumes);
210
211
212template<class Type, template<class> class PatchField, class GeoMesh>
213Eigen::MatrixXd getMassMatrix(PtrList<GeometricField<Type, PatchField, GeoMesh>>& modes,
214 PtrList<GeometricField<Type, PatchField, GeoMesh>>& modes2,
215 Eigen::VectorXd weights,
216 label Nmodes,
217 bool consider_volumes)
218{
219 label Msize,Msize2;
220 if (Nmodes == 0)
221 {
222 Msize = modes.size();
223 Msize2 = modes2.size();
224 }
225 else
226 {
227 Msize = Nmodes;
228 Msize2 = Nmodes;
229 }
230 M_Assert(modes.size() >= Msize,
231 "The Number of requested modes is larger then the available quantity.");
232 M_Assert(modes2.size() >= Msize2,
233 "The Number of requested modes is larger then the available quantity.");
234
235 Eigen::MatrixXd F = Foam2Eigen::PtrList2Eigen(modes);
236 Eigen::MatrixXd F2 = Foam2Eigen::PtrList2Eigen(modes2);
237 Eigen::MatrixXd M = Eigen::MatrixXd::Zero(Msize,Msize2);
238
239 if (consider_volumes)
240 {
241 Eigen::VectorXd V = getMassMatrixFV(modes[0]);
242 // If V is too big then we need a for loop to avoid RAM overload
243 if (V.size() > 1e6)
244 {
245 for (int i=0; i<V.size(); i++)
246 {
247 M += (V(i) * weights(i)) * F.transpose().topRows(Msize).col(i) * F2.leftCols(Msize2).row(i);
248 }
249 }
250 else
251 {
252 // Classical M computation
253 M = F.transpose().topRows(Msize) * ( V * weights ).asDiagonal() * F2.leftCols(Msize2);
254 }
255 }
256 else
257 {
258 M = F.transpose().topRows(Msize) * weights.asDiagonal() * F2.leftCols(Msize2);
259 }
260
261 if (Pstream::parRun())
262 {
263 reduce(M, sumOp<Eigen::MatrixXd>());
264 }
265
266 return M;
267}
268
269template Eigen::MatrixXd getMassMatrix(
270 PtrList<GeometricField<scalar, fvPatchField, volMesh>>& modes,
271 PtrList<GeometricField<scalar, fvPatchField, volMesh>>& modes2,
272 Eigen::VectorXd weights,
273 label Nmodes = 0,
274 bool consider_volumes);
275
276template Eigen::MatrixXd getMassMatrix(
277 PtrList<GeometricField<scalar, fvsPatchField, surfaceMesh>>& modes,
278 PtrList<GeometricField<scalar, fvsPatchField, surfaceMesh>>& modes2,
279 Eigen::VectorXd weights,
280 label Nmodes = 0,
281 bool consider_volumes);
282
283template Eigen::MatrixXd getMassMatrix(
284 PtrList<GeometricField<vector, fvPatchField, volMesh>>& modes,
285 PtrList<GeometricField<vector, fvPatchField, volMesh>>& modes2,
286 Eigen::VectorXd weights,
287 label Nmodes = 0,
288 bool consider_volumes);
289
290template Eigen::MatrixXd getMassMatrix(
291 PtrList<GeometricField<tensor, fvPatchField, volMesh>>& modes,
292 PtrList<GeometricField<tensor, fvPatchField, volMesh>>& modes2,
293 Eigen::VectorXd weights,
294 label Nmodes = 0,
295 bool consider_volumes);
296
297
298template<class Type, template<class> class PatchField, class GeoMesh>
299Eigen::VectorXd getMassMatrixFV(
300 GeometricField<Type, PatchField, GeoMesh>& snapshot)
301{
302 Eigen::MatrixXd snapEigen = Foam2Eigen::field2Eigen(snapshot);
303 label dim = std::nearbyint(snapEigen.rows() / (snapshot.mesh().V()).size());
304 Eigen::VectorXd volumes = Foam2Eigen::field2Eigen(snapshot.mesh().V());
305 Eigen::VectorXd vol3 = volumes.replicate(dim, 1);
306 return vol3;
307}
308
309template Eigen::VectorXd getMassMatrixFV(
310 GeometricField<scalar, fvPatchField, volMesh>& snapshot);
311template Eigen::VectorXd getMassMatrixFV(
312 GeometricField<vector, fvPatchField, volMesh>& snapshot);
313template Eigen::VectorXd getMassMatrixFV(
314 GeometricField<tensor, fvPatchField, volMesh>& snapshot);
315
316template<class Type, template<class> class PatchField, class GeoMesh>
317Eigen::VectorXd getCoeffs(GeometricField<Type, PatchField, GeoMesh>&
318 snapshot,
319 PtrList<GeometricField<Type, PatchField, GeoMesh>>& modes, label Nmodes,
320 bool consider_volumes)
321{
322 label Msize;
323
324 if (Nmodes == 0)
325 {
326 Msize = modes.size();
327 }
328 else
329 {
330 Msize = Nmodes;
331 }
332
333 M_Assert(modes.size() >= Msize,
334 "The Number of requested modes is larger then the available quantity.");
335 Eigen::MatrixXd F = Foam2Eigen::PtrList2Eigen(modes);
336 Eigen::MatrixXd M_matrix = getMassMatrix(modes, Nmodes, consider_volumes);
337 Eigen::MatrixXd snapEigen = Foam2Eigen::field2Eigen(snapshot);
338 Eigen::VectorXd a(Msize);
339 Eigen::VectorXd b(Msize);
340
341 if (consider_volumes)
342 {
343 Eigen::VectorXd V = getMassMatrixFV(modes[0]);
344 b = F.transpose().topRows(Msize) * V.asDiagonal() * snapEigen;
345 }
346 else
347 {
348 b = F.transpose().topRows(Msize) * snapEigen;
349 }
350
351 if (Pstream::parRun())
352 {
353 reduce(b, sumOp<Eigen::VectorXd>());
354 }
355
356 a = M_matrix.fullPivLu().solve(b);
357 return a;
358}
359
360template Eigen::VectorXd getCoeffs(
361 GeometricField<scalar, fvPatchField, volMesh>&
362 snapshot, PtrList<GeometricField<scalar, fvPatchField, volMesh>>& modes,
363 label Nmodes,
364 bool consider_volumes);
365
366template Eigen::VectorXd getCoeffs(
367 GeometricField<scalar, fvsPatchField, surfaceMesh>&
368 snapshot, PtrList<GeometricField<scalar, fvsPatchField, surfaceMesh>>& modes,
369 label Nmodes,
370 bool consider_volumes = false);
371
372template Eigen::VectorXd getCoeffs(
373 GeometricField<vector, fvPatchField, volMesh>&
374 snapshot, PtrList<GeometricField<vector, fvPatchField, volMesh>>& modes,
375 label Nmodes,
376 bool consider_volumes);
377
378template<class Type, template<class> class PatchField, class GeoMesh>
379Eigen::MatrixXd getCoeffs(PtrList<GeometricField<Type, PatchField, GeoMesh>>&
380 snapshots,
381 PtrList<GeometricField<Type, PatchField, GeoMesh>>& modes, label Nmodes,
382 bool consider_volumes)
383{
384 label Msize;
385
386 if (Nmodes == 0)
387 {
388 Msize = modes.size();
389 }
390 else
391 {
392 Msize = Nmodes;
393 }
394
395 M_Assert(modes.size() >= Msize,
396 "The Number of requested modes is larger then the available quantity.");
397 Eigen::MatrixXd coeff(Msize, snapshots.size());
398
399 for (auto i = 0; i < snapshots.size(); i++)
400 {
401 coeff.col(i) = getCoeffs(snapshots[i], modes, Nmodes, consider_volumes);
402 }
403
404 return coeff;
405}
406
407template Eigen::MatrixXd getCoeffs(
408 PtrList<GeometricField<scalar, fvPatchField, volMesh>>&
409 snapshot, PtrList<GeometricField<scalar, fvPatchField, volMesh>>& modes,
410 label Nmodes,
411 bool consider_volumes);
412
413template Eigen::MatrixXd getCoeffs(
414 PtrList<GeometricField<vector, fvPatchField, volMesh>>&
415 snapshot, PtrList<GeometricField<vector, fvPatchField, volMesh>>& modes,
416 label Nmodes,
417 bool consider_volumes);
418
419template Eigen::MatrixXd getCoeffs(
420 PtrList<GeometricField<scalar, fvsPatchField, surfaceMesh>>&
421 snapshot, PtrList<GeometricField<scalar, fvsPatchField, surfaceMesh>>& modes,
422 label Nmodes,
423 bool consider_volumes);
424
425Eigen::MatrixXd parTimeCombMat(List<Eigen::VectorXd>
426 acquiredSnapshotsTimes,
427 Eigen::MatrixXd parameters)
428{
429 label parsNum = parameters.cols();
430 label parsSamplesNum = parameters.rows();
431 M_Assert(parsSamplesNum == acquiredSnapshotsTimes.size(),
432 "The list of time instants does not have the same number of vectors as the number of parameters samples");
433 Eigen::MatrixXd comb;
434 label totalSnapshotsNum = 0;
435
436 for (label k = 0; k < acquiredSnapshotsTimes.size(); k++)
437 {
438 totalSnapshotsNum += acquiredSnapshotsTimes[k].size();
439 }
440
441 comb.resize(totalSnapshotsNum, parsNum + 1);
442 label i = 0;
443
444 for (label j = 0; j < acquiredSnapshotsTimes.size(); j++)
445 {
446 for (label k = 0; k < acquiredSnapshotsTimes[j].size(); k++)
447 {
448 comb(i, parsNum) = (acquiredSnapshotsTimes[j])(k, 0);
449 comb.block(i, 0, 1, parsNum) = parameters.row(j);
450 i = i + 1;
451 }
452 }
453
454 return comb;
455}
456
457}
#define M_Assert(Expr, Msg)
Header file of the ITHACAcoeffsMass file.
static Eigen::VectorXd field2Eigen(GeometricField< tensor, PatchField, GeoMesh > &field)
Convert a vector OpenFOAM field into an Eigen Vector.
Definition Foam2Eigen.C:40
static Eigen::MatrixXd PtrList2Eigen(PtrList< GeometricField< Type, PatchField, GeoMesh > > &fields, label Nfields=-1)
Convert a PtrList of snapshots to Eigen matrix (only internal field)
Definition Foam2Eigen.C:649
Namespace to implement some useful assign operation of OF fields.
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.
PtrList< GeometricField< Type, PatchField, GeoMesh > > reconstructFromCoeff(PtrList< GeometricField< Type, PatchField, GeoMesh > > &modes, Eigen::MatrixXd &coeff_matrix, label Nmodes)
Exact reconstruction using a certain number of modes for a list of fields and the projection coeffici...
Eigen::VectorXd getMassMatrixFV(GeometricField< Type, PatchField, GeoMesh > &snapshot)
Gets a vector containing the volumes of each cell of the mesh.
Eigen::MatrixXd parTimeCombMat(List< Eigen::VectorXd > acquiredSnapshotsTimes, Eigen::MatrixXd parameters)
A method to compute the time-parameter combined matrix whose any single element corresponds to a uniq...
Eigen::MatrixXd getMassMatrix(PtrList< GeometricField< Type, PatchField, GeoMesh > > &modes, label Nmodes, bool consider_volumes)
Gets the mass matrix using the eigen routine.
label i
Definition pEqn.H:46