Loading...
Searching...
No Matches
hyperReduction.templates.H
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 GN3U 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#ifndef hyperReduction_templates_H
32#define hyperReduction_templates_H
33
34#include "hyperReduction.H"
35
36// TODO increase modularity to avoid heavy compiling costs
37
38// Template function constructor
39template <typename... SnapshotsLists>
41 label n_nodes,
42 Eigen::VectorXi initialSeeds,
43 word problemName,
44 SnapshotsLists &&...snapshotsLists)
45 : vectorial_dim{compute_vectorial_dim(snapshotsLists...)},
46 n_modes{n_modes},
47 n_nodes{n_nodes},
48 initialSeeds{initialSeeds},
49 problemName{problemName},
50 snapshotsListTuple{std::forward_as_tuple(snapshotsLists...)}
51{
52 Info << "Init HyperReduction class with vectorial dim: " << vectorial_dim << endl;
54 folderProblem = "ITHACAoutput/" + problemName;
55 mkDir(folderProblem);
56
57 // TODO check snapshotsLists is not empty
58 // TODO check that the first snapshotsList is not empty (includes above)
59
60 // TODO initialize vectorial_dim only from SnapshotsLists type
61 // vectorial_dim = std::apply(compute_vectorial_dim<SnapshotsLists&&...>, snapshotsListTuple);
62
63 // Get fields' names
64 std::apply([this](auto& ...snapList){(..., stackNames(snapList));}, snapshotsListTuple);
65
66 // Get fields' dimensions
67 std::apply([this](auto& ...snapList){(..., stackDimensions(snapList));}, snapshotsListTuple);
68
69 sumFieldsDim = 0;
70 std::apply([this](auto& ...snapList){(..., sumDimensions(this->sumFieldsDim, snapList));}, snapshotsListTuple);
71
72 Info << "Fields names: ";
73 for (unsigned int ith_field = 0; ith_field < fieldNames.size(); ith_field++)
74 {
75 Info << fieldNames[ith_field] << " (dim=" << fieldDims[ith_field] << "); ";
76 }
77 Info << endl;
78
79 n_snapshots = std::get<0>(snapshotsListTuple).size();
80 Info << "The number of snapshots is: " << n_snapshots << endl;
81 n_cells = std::get<0>(snapshotsListTuple)[0].size();
82 Info << "The number of cells is: " << n_cells << endl;
83 Info << "Initial seeds length: " << initialSeeds.rows() << endl;
84
85 // get boundaries info
86 n_boundary_patches = std::get<0>(snapshotsListTuple)[0].boundaryField().size();
87
90 for (unsigned int ith_boundary_patch = 0; ith_boundary_patch < n_boundary_patches; ith_boundary_patch++)
91 {
92 n_boundary_cells_list[ith_boundary_patch] = std::get<0>(snapshotsListTuple)[0].boundaryField()[ith_boundary_patch].size();
94 }
95 Info << "Number of boundary cells: " << n_boundary_cells << endl;
96}
97
98
99// Template function constructor
100template <typename... SnapshotsLists>
102 label n_nodes,
103 unsigned int vectorialDim,
104 label n_cells,
105 Eigen::VectorXi initialSeeds,
106 word problemName)
107 : n_modes{n_modes},
108 n_nodes{n_nodes},
109 vectorial_dim{vectorialDim},
110 n_cells{n_cells},
111 initialSeeds{initialSeeds},
112 problemName{problemName}
113{
114 Info << "Init HyperReduction class with vectorial dim: " << vectorial_dim << endl;
117 mkDir(folderProblem);
118
119 Info << "Initial seeds length: " << initialSeeds.rows() << endl;
120
121}
122
123template <typename... SnapshotsLists>
125 SnapshotsListTuple& snapshotsListTuple, Eigen::MatrixXd& modesSVD, Eigen::VectorXd& fieldWeights, bool saveModesFlag)
126{
127 // TODO move inside ITHACAPOD
129 word folderSVD = "ITHACAoutput/" + problemName + "/ModesSVD/";
130 if (!ITHACAutilities::check_folder(folderSVD))
131 {
132 mkDir(folderSVD);
133 // Initialize stacked snapshotsMatrix and normalizing weights
134 Eigen::MatrixXd snapMatrix;
135 getSnapMatrix(snapMatrix, fieldWeights);
136
137 word dimensionReductionMethod = para->ITHACAdict->lookupOrDefault<word>("DimensionReductionMethod", "SVD");
138
139 Eigen::MatrixXd eigenVectoreig;
140
141 if (dimensionReductionMethod == "RSVD")
142 {
143 Info << "####### Performing RSVD for " << problemName << " #######" << endl;
144
145 unsigned int r_modeSVD = para->ITHACAdict->lookupOrDefault<unsigned int>("RSVDdim", snapMatrix.cols());
146 RedSVD::RedSVD svd(fieldWeights.array().cwiseInverse().matrix().asDiagonal()*snapMatrix, r_modeSVD);
147
148 Info << "####### End of RSVD for " << problemName << " #######" <<
149 endl;
150
151 eigenValueseig = svd.singularValues().real();
152 eigenVectoreig = svd.matrixU().real();
153 }
154 else
155 {
156 Info << "####### Performing SVD for " << problemName << " #######" << endl;
157
158 Eigen::JacobiSVD<Eigen::MatrixXd> svd(fieldWeights.array().cwiseInverse().matrix().asDiagonal()*snapMatrix, Eigen::ComputeThinU | Eigen::ComputeThinV);
159
160 Info << "####### End of SVD for " << problemName << " #######" <<
161 endl;
162
163 eigenValueseig = svd.singularValues().real();
164 eigenVectoreig = svd.matrixU().real();
165 }
166
167 modesSVD = eigenVectoreig;
168
169 // TODO correct boundary conditions
170
171 cnpy::save(eigenValueseig, "ITHACAoutput/" + problemName + "/ModesSVD/eigenvalues.npy");
172
173 eigenValueseig = eigenValueseig / eigenValueseig.sum();
174 Eigen::VectorXd cumEigenValues(eigenValueseig);
175
176 for (label j = 1; j < cumEigenValues.size(); ++j)
177 {
178 cumEigenValues(j) += cumEigenValues(j - 1);
179 }
180
181 Eigen::saveMarketVector(eigenValueseig,
182 "ITHACAoutput/" + problemName + "/ModesSVD/Eigenvalues_" + problemName, para->precision,
183 para->outytpe);
184 Eigen::saveMarketVector(cumEigenValues,
185 "ITHACAoutput/" + problemName + "/ModesSVD/CumEigenvalues_" + problemName, para->precision,
186 para->outytpe);
187 cnpy::save(modesSVD, "ITHACAoutput/" + problemName + "/ModesSVD/modes.npy");
188 cnpy::save(fieldWeights, "ITHACAoutput/" + problemName + "/ModesSVD/normalizingWeights.npy");
189
190
191 if (saveModesFlag)
192 {
193 unsigned int rowIndex{0};
194 for (unsigned int modeIndex = 0; modeIndex < modesSVD.cols(); modeIndex++)
195 {
196 std::apply([this, &modesSVD, &rowIndex, &modeIndex, &folderSVD](auto& ...snapList){(..., saveModes(snapList, modesSVD, rowIndex, modeIndex, folderSVD));}, snapshotsListTuple);
197 rowIndex = 0;
198 }
199 }
200 }
201 else
202 {
203 Info << "Reading the existing modes" << endl;
204 cnpy::load(modesSVD, folderSVD + "/modes.npy");
205 cnpy::load(fieldWeights, folderSVD + "/normalizingWeights.npy");
206 }
207}
208
209template <typename... SnapshotsLists>
211 SnapshotsListTuple& snapshotsListTuple, Eigen::MatrixXd& modesSVD, Eigen::VectorXd& fieldWeights, Eigen::MatrixXd& modesSVDBoundary, Eigen::VectorXd& fieldWeightsBoundary, bool saveModesFlag)
212{
213 // TODO move inside ITHACAPOD
215 word folderSVD = "ITHACAoutput/" + problemName + "/ModesSVD/";
216 if (!ITHACAutilities::check_folder(folderSVD))
217 {
218 mkDir(folderSVD);
219 // Initialize stacked snapshotsMatrix and normalizing weights
220 Eigen::MatrixXd snapMatrix;
221 List<Eigen::MatrixXd> snapMatrixBoundary;
222 List<Eigen::VectorXd> fieldWeightsBoundaryList;
223 getSnapMatrix(snapMatrix, fieldWeights, snapMatrixBoundary, fieldWeightsBoundaryList);
224
225 for (unsigned int id = 0; id < n_boundary_patches; id++)
226 {
227 snapMatrix.conservativeResize(snapMatrix.rows()+snapMatrixBoundary[id].rows(), snapMatrix.cols());
228 snapMatrix.bottomRows(snapMatrixBoundary[id].rows()) = snapMatrixBoundary[id];
229
230 fieldWeightsBoundary.conservativeResize(fieldWeightsBoundary.rows()+snapMatrixBoundary[id].rows());
231 fieldWeightsBoundary.tail(fieldWeightsBoundaryList[id].rows()) = fieldWeightsBoundaryList[id];
232 }
233
234 cnpy::save(fieldWeights, "ITHACAoutput/" + problemName + "/ModesSVD/normalizingWeights.npy");
235 cnpy::save(fieldWeightsBoundary, "ITHACAoutput/" + problemName + "/ModesSVD/normalizingWeightsBoundary.npy");
236
237 fieldWeights.conservativeResize(fieldWeights.rows()+fieldWeightsBoundary.rows());
238 fieldWeights.tail(fieldWeightsBoundary.rows()) = fieldWeightsBoundary;
239
240 word dimensionReductionMethod = para->ITHACAdict->lookupOrDefault<word>("DimensionReductionMethod", "SVD");
241
242 Eigen::MatrixXd eigenVectoreig;
244 if (dimensionReductionMethod == "RSVD")
245 {
246 Info << "####### Performing RSVD for " << problemName << " #######" << endl;
247
248 unsigned int r_modeSVD = para->ITHACAdict->lookupOrDefault<unsigned int>("RSVDdim", snapMatrix.cols());
249
250 RedSVD::RedSVD svd(fieldWeights.array().cwiseInverse().matrix().asDiagonal()*snapMatrix, r_modeSVD);
252 Info << "####### End of RSVD for " << problemName << " #######" << endl;
253
254 eigenValueseig = svd.singularValues().real();
255 eigenVectoreig = svd.matrixU().real();
256 }
257 else
258 {
259 Info << "####### Performing SVD for " << problemName << " #######" << endl;
260
261 Eigen::JacobiSVD<Eigen::MatrixXd> svd(fieldWeights.array().cwiseInverse().matrix().asDiagonal()*snapMatrix, Eigen::ComputeThinU | Eigen::ComputeThinV);
262
263 Info << "####### End of SVD for " << problemName << " #######" <<
264 endl;
265
266 eigenValueseig = svd.singularValues().real();
267 eigenVectoreig = svd.matrixU().real();
269
270 modesSVD = eigenVectoreig.bottomRows(vectorial_dim*n_cells);
271 modesSVDBoundary = eigenVectoreig.topRows(n_boundary_cells);
272 fieldWeights.conservativeResize(fieldWeights.rows()-fieldWeightsBoundary.rows());
273
274 cnpy::save(eigenValueseig, "ITHACAoutput/" + problemName + "/ModesSVD/eigenvalues.npy");
275
276 eigenValueseig = eigenValueseig / eigenValueseig.sum();
277 Eigen::VectorXd cumEigenValues(eigenValueseig);
278
279 for (label j = 1; j < cumEigenValues.size(); ++j)
280 {
281 cumEigenValues(j) += cumEigenValues(j - 1);
282 }
283
284 Eigen::saveMarketVector(eigenValueseig,
285 "ITHACAoutput/" + problemName + "/ModesSVD/Eigenvalues_" + problemName, para->precision,
286 para->outytpe);
287 Eigen::saveMarketVector(cumEigenValues,
288 "ITHACAoutput/" + problemName + "/ModesSVD/CumEigenvalues_" + problemName, para->precision,
289 para->outytpe);
290 cnpy::save(modesSVD, "ITHACAoutput/" + problemName + "/ModesSVD/modes.npy");
291 cnpy::save(modesSVDBoundary, "ITHACAoutput/" + problemName + "/ModesSVD/modesBoundary.npy");
292
293 if (saveModesFlag)
294 {
295 unsigned int rowIndex{0};
296 unsigned int rowIndexBoundary{0};
297 for (unsigned int modeIndex = 0; modeIndex < modesSVD.cols(); modeIndex++)
298 {
299 std::apply([this, &modesSVD, &modesSVDBoundary, &rowIndex, &modeIndex, &rowIndexBoundary, &folderSVD](auto& ...snapList){(..., saveModes(snapList, modesSVD, modesSVDBoundary, rowIndex, rowIndexBoundary, modeIndex, folderSVD));}, snapshotsListTuple);
300 rowIndex = 0;
301 }
302 }
303 }
304 else
305 {
306 Info << "Reading the existing modes" << endl;
307 cnpy::load(modesSVD, folderSVD + "/modes.npy");
308 cnpy::load(modesSVDBoundary, "ITHACAoutput/" + problemName + "/ModesSVD/modesBoundary.npy");
309 cnpy::load(fieldWeights, folderSVD + "/normalizingWeights.npy");
310 cnpy::load(fieldWeightsBoundary, "ITHACAoutput/" + problemName + "/ModesSVD/normalizingWeightsBoundary.npy");
311 }
312}
313
314template <typename... SnapshotsLists>
315void HyperReduction<SnapshotsLists...>::getSnapMatrix(Eigen::MatrixXd& snapMatrix, Eigen::VectorXd& fieldWeights)
316{
317 std::apply([this, &fieldWeights, &snapMatrix](auto& ...snapList){(..., stackSnapshots(snapList, snapMatrix, fieldWeights));}, snapshotsListTuple);
318}
319
320template <typename... SnapshotsLists>
321void HyperReduction<SnapshotsLists...>::getSnapMatrix(Eigen::MatrixXd& snapMatrix, Eigen::VectorXd& fieldWeights, List<Eigen::MatrixXd>& snapMatrixBoundary, List<Eigen::VectorXd>& fieldWeightsBoundary)
322{
323 fieldWeightsBoundary.resize(n_boundary_patches);
324 snapMatrixBoundary.resize(n_boundary_patches);
325
326 std::apply([this, &fieldWeights, &snapMatrix, &fieldWeightsBoundary, &snapMatrixBoundary](auto& ...snapList){
327 (..., stackSnapshots(snapList, snapMatrix, fieldWeights));
328 (..., stackSnapshotsBoundary(snapList, snapMatrixBoundary, fieldWeightsBoundary));},
329 snapshotsListTuple);
330}
331
332template <typename... SnapshotsLists>
333template <typename SnapshotsList>
334void HyperReduction<SnapshotsLists...>::saveModes(SnapshotsList sList, Eigen::MatrixXd& snapshotsMatrix, unsigned int &rowIndex, unsigned int &modeIndex, word folder)
335{
336 unsigned int field_dim = get_field_dim<typename SnapshotsList::value_type>();
337 auto fieldName = sList[0].name();
338 unsigned int fieldSize = field_dim*sList[0].size();
339 Eigen::VectorXd fieldBlock = snapshotsMatrix.block(rowIndex, modeIndex, fieldSize, 1);
340 auto fieldOut = Foam2Eigen::Eigen2field(sList[0], fieldBlock , true);
341 rowIndex +=fieldSize;
342 ITHACAstream::exportSolution(fieldOut, name(modeIndex), folder);
343}
344
345template <typename... SnapshotsLists>
346template <typename SnapshotsList>
347void HyperReduction<SnapshotsLists...>::saveModes(SnapshotsList sList, Eigen::MatrixXd& snapshotsMatrix, Eigen::MatrixXd& snapshotsMatrixBoundary, unsigned int &rowIndex, unsigned int& rowIndexBoundary, unsigned int &modeIndex, word folder)
348{
349 unsigned int field_dim = get_field_dim<typename SnapshotsList::value_type>();
350 auto fieldName = sList[0].name();
351 unsigned int fieldSize = field_dim*sList[0].size();
352
353 Eigen::VectorXd fieldBlock = snapshotsMatrix.block(rowIndex, modeIndex, fieldSize, 1);
354
355 List<Eigen::VectorXd> fieldBlockBoundary;
356 fieldBlockBoundary.resize(n_boundary_patches);
357 for (unsigned int id = 0; id < n_boundary_patches; id++)
358 {
359 unsigned int bfieldDim = field_dim*int(n_boundary_cells_list[id]);
360 fieldBlockBoundary[id] = snapshotsMatrixBoundary.block(rowIndexBoundary, modeIndex, bfieldDim, 1);
361 rowIndexBoundary+=bfieldDim;
362 }
363
364 auto fieldOut = Foam2Eigen::Eigen2field(sList[0], fieldBlock, fieldBlockBoundary);
365 rowIndex +=fieldSize;
366
367 ITHACAstream::exportSolution(fieldOut, name(modeIndex), folder);
368}
369
370template <typename... SnapshotsLists>
371void HyperReduction<SnapshotsLists...>::offlineGappyDEIM(Eigen::MatrixXd& snapshotsModes, Eigen::VectorXd& weights, word folderMethodName)
372{
373 folderMethod = folderMethodName;
374 Info << "FolderMethod : " << folderMethod << endl;
375 mkDir(folderMethod);
376
377 normalizingWeights = weights;
378
379 nodePoints = autoPtr<IOList<label>>(new IOList<label>(
380 IOobject("nodePoints", para->runTime.time().constant(), "../" + folderMethod,
381 para->mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE)));
382
383 auto greedyMetric = para->ITHACAdict->lookupOrDefault<word>("GreedyMetric", "L2");
384
385 bool offlineStage = !nodePoints().headerOk();
386
387 if (offlineStage)
388 {
389 assert(n_modes > 0);
390 assert(n_nodes >= n_modes);
391
392 Eigen::VectorXd mp_not_mask = Eigen::VectorXd::Constant(n_cells * vectorial_dim, 1);
393 std::set<label> nodePointsSet;
394
395 // set initialSeeds
396 if (initialSeeds.rows() > 0)
397 {
398 initSeeds(mp_not_mask, nodePointsSet);
399 }
400
401 int na = n_nodes - initialSeeds.rows();
402 if (na > 0)
403 {
404 Eigen::SparseMatrix<double> reshapeMat;
405 initReshapeMat(reshapeMat);
406
407 if (greedyMetric=="L2")
408 {
409 Info << "####### Begin Greedy-L2 GappyDEIM #######" << endl;
410 Info << "####### Modes=" << n_modes
411 << ", nodePoints=" << n_nodes << " #######"
412 << endl;
413
414 int nb = 0;
415 int nit = std::min(n_modes, na);
416 int ncimin = std::floor(n_modes / nit);
417 int naimin = std::floor(na / n_modes);
418 Eigen::MatrixXd A;
419 Eigen::VectorXd b;
420 Eigen::VectorXd c;
421 Eigen::VectorXd r;
422 label ind_max, c1;
423 double max;
424
425 for (int i = 1; i <= nit; i++)
426 {
427 int nci = ncimin;
428 // add the remaining modes in the quotient n_modes / nite
429 if (i <= n_modes % nit)
430 {
431 nci = ncimin + 1;
432 }
433 int nai = naimin;
434 // add the remaining nodePoints in the quotient na / n_modes
435 if (i <= na % n_modes)
436 {
437 nai = naimin + 1;
438 }
439
440 Eigen::MatrixXd V;
441
442 // select basis
443 if (i == 1)
444 {
445 V = snapshotsModes.leftCols(nci);
446 }
447 else
448 {
449 for (int q = 1; q <= nci; q++)
451 A = P.transpose() * basisMatrix;
452 b = P.transpose() * snapshotsModes.col(nb + q - 1);
453 c = A.fullPivLu().solve(b);
454 r = snapshotsModes.col(nb + q - 1) - basisMatrix * c;
455 V.conservativeResize(snapshotsModes.rows(), q);
456 V.col(q - 1) = r;
458 }
459
460 for (int j = 1; j <= nai; j++)
461 {
462 if (P.cols() > 0)
463 {
464 max = (reshapeMat*(mp_not_mask.asDiagonal() * V)
465 .rowwise()
466 .lpNorm<2>().array().square().matrix())
467 .maxCoeff(&ind_max, &c1);
468 }
469 else
470 {
471 max = (reshapeMat*V.rowwise().lpNorm<2>().array().square().matrix()).maxCoeff(&ind_max, &c1);
472 }
473
474 updateNodes(P, ind_max, mp_not_mask);
475 }
476
477 nb += nci;
478 basisMatrix = snapshotsModes.leftCols(nb);
479 }
480 Info << "####### End of greedy GappyDEIM #######\n";
481 }
482 else if (greedyMetric=="SOPT")
483 {
484 Info << "####### Begin SOPT GappyDEIM #######" << endl;
485 Info << "####### Modes=" << n_modes
486 << ", nodePoints=" << n_nodes << " #######"
487 << endl;
488
489 label ind_max, c1;
490 double max;
491 Eigen::MatrixXd V = snapshotsModes.leftCols(n_modes);
492
493 for (unsigned int ith_node = 0; ith_node < na; ith_node++)
494 {
495 if (P.cols() > 0)
496 {
497 // TODO make efficient
498 Eigen::MatrixXd tmp = P.transpose()*V;
499 Eigen::MatrixXd R = mp_not_mask.asDiagonal() * V;
500 Eigen::MatrixXd inv = (tmp.transpose()*tmp).fullPivLu().inverse();
501 Eigen::VectorXd num = 1 + (reshapeMat*((R * inv).array()*R.array()).rowwise().sum().matrix()).array();
502 Eigen::VectorXd norma = (tmp.array().square()).colwise().sum();
503 Eigen::MatrixXd adding = reshapeMat*R.array().square().matrix();
504 adding.rowwise() += norma.transpose();
505 Eigen::VectorXd denom = (adding.array().pow(1./V.cols()).matrix()).rowwise().prod();
506
507 max = ((mp_not_mask.head(n_cells).asDiagonal()*num).array()/denom.array()).maxCoeff(&ind_max, &c1);
508 }
509 else
510 {
511 max = (reshapeMat*V.rowwise().lpNorm<2>().array().square().matrix()).maxCoeff(&ind_max, &c1);
512 }
513
514 updateNodes(P, ind_max, mp_not_mask);
515 }
516 basisMatrix = V;
517 Info << "####### End of SOPT GappyDEIM #######\n";
518 }
519 else if (greedyMetric=="SOPTE")
520 {
521 Info << "####### Begin SOPT-exact GappyDEIM #######" << endl;
522 Info << "####### Modes=" << n_modes
523 << ", nodePoints=" << n_nodes << " #######"
524 << endl;
525
526 label ind_max, c1;
527 double max;
528 Eigen::MatrixXd A;
529 Eigen::VectorXd b;
530 Eigen::VectorXd c;
531 Eigen::VectorXd r;
532 Eigen::MatrixXd V = snapshotsModes.col(0);
533
534 max = (reshapeMat* (mp_not_mask.asDiagonal()*snapshotsModes.leftCols(n_modes)).rowwise().lpNorm<2>().array().square().matrix()).maxCoeff(&ind_max, &c1);
535 updateNodes(P, ind_max, mp_not_mask);
536
537 for (unsigned int ith_node = 1; ith_node < na; ith_node++)
538 {
539 if (ith_node<n_modes)
540 {
541 A = P.transpose() * V;
542 b = P.transpose() * snapshotsModes.col(ith_node);
543 c = A.fullPivLu().solve(b);
544 r = snapshotsModes.col(ith_node) - V * c;
545 V.conservativeResize(snapshotsModes.rows(), ith_node + 1);
546 V.col(ith_node) = snapshotsModes.col(ith_node);
547
548 max = (reshapeMat*r.rowwise().lpNorm<2>().array().square().matrix()).maxCoeff(&ind_max, &c1);
549 }
550 else
551 {
552 // TODO optimize
553 Eigen::MatrixXd tmp = P.transpose()*snapshotsModes.leftCols(n_modes);
554 Info << "SOPT: " << s_optimality(tmp) << endl;
555 tmp.conservativeResize(tmp.rows()+vectorial_dim, tmp.cols());
556
557 Eigen::MatrixXd masked = mp_not_mask.asDiagonal()*snapshotsModes.leftCols(n_modes);
558
559 Eigen::VectorXd results(n_cells);
560
561 for (unsigned int ith_cell = 0; ith_cell < n_cells; ith_cell++)
562 {
563 for (unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
564 {
565 tmp.row(tmp.rows()-vectorial_dim+ith_field) = masked.row(ith_cell + ith_field*n_cells);
566 }
567 results(ith_cell) = s_optimality(tmp);
568 }
569 max = results.maxCoeff(&ind_max, &c1);
570 }
571
572 updateNodes(P, ind_max, mp_not_mask);
573 }
574 basisMatrix = snapshotsModes.leftCols(n_modes);
575 Info << "####### End of SOPTE GappyDEIM #######\n";
576 }
577 }
578 else
579 {
580 basisMatrix = snapshotsModes.leftCols(n_modes);
581 Info << "####### InitialSeeds equal to n_nodes #######\n";
582 }
583
584 evaluatePinv(P, basisMatrix, normalizingWeights);
585 renormalizedBasisMatrix = normalizingWeights.asDiagonal()*basisMatrix;
586
587 MatrixOnline = renormalizedBasisMatrix * pinvPU;
588
589 P.makeCompressed();
590 cnpy::save(basisMatrix, folderMethod +"/basisMatrix.npy");
591 cnpy::save(P, folderMethod +"/projectionMatrix.npz");
592 cnpy::save(normalizingWeights, folderMethod + "/normalizingWeights.npy");
593 cnpy::save(nodes, folderMethod + "/mp.npy");
594 cnpy::save(pinvPU, folderMethod + "/pinvPU.npy");
595 cnpy::save(MatrixOnline, folderMethod + "/MatrixOnline.npy");
596 nodePoints().write();
597
598 Info << "Projection Matrix shape: " << P.rows() << " " << P.cols() << endl;
599 Info << "Basis Matrix shape: " << basisMatrix.rows() << " " << basisMatrix.cols() << endl;
600 Info << "Pseudo Inverse Matrix shape: " << pinvPU.rows() << " " << pinvPU.cols() << endl;
601 }
602 else
603 {
604 Info << "Read GappyDEIM\n";
605 cnpy::load(basisMatrix, folderMethod +"/basisMatrix.npy");
606 cnpy::load(MatrixOnline, folderMethod +"/MatrixOnline.npy");
607 cnpy::load(normalizingWeights, folderMethod + "/normalizingWeights.npy");
608 cnpy::load(P, folderMethod +"/projectionMatrix.npz");
609 cnpy::load(nodes, folderMethod + "/mp.npy");
610 cnpy::load(pinvPU, folderMethod + "/pinvPU.npy");
611
612 renormalizedBasisMatrix = normalizingWeights.asDiagonal()*basisMatrix;
613
614 Info << "Projection Matrix shape: " << P.rows() << " " << P.cols() << endl;
615 Info << "Basis Matrix shape: " << basisMatrix.rows() << " " << basisMatrix.cols() << endl;
616 Info << "Pseudo Inverse Matrix shape: " << pinvPU.rows() << " " << pinvPU.cols() << endl;
617 }
618}
619
620template <typename... SnapshotsLists>
621void HyperReduction<SnapshotsLists...>::offlineECP(Eigen::MatrixXd& snapshotsModes, Eigen::VectorXd& weights, word folderMethodName)
622{
623 folderMethod = folderMethodName;
624 Info << "FolderMethod : " << folderMethod << endl;
625 mkDir(folderMethod);
626
627 n_nodes = n_modes + 1;
628
629 normalizingWeights = weights;
630
631 Info << "####### Begin ECP #######" << endl;
632 Info << "####### Modes=" << n_modes
633 << ", nodePoints=" << n_nodes << " #######"
634 << endl;
635
636 nodePoints = autoPtr<IOList<label>>(new IOList<label>(
637 IOobject("nodePoints", para->runTime.time().constant(), "../" + folderMethod,
638 para->mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE)));
639
640 bool offlineStage = !nodePoints().headerOk();
641
642 if (offlineStage)
643 {
644 assert(n_modes > 0);
645 assert(n_nodes >= n_modes);
646
647 // matrices for quadratureWeights evaluation
648 Eigen::MatrixXd J;//shape: (vectorial_dim * (n_modes + 1), nodePoints->size())
649 Eigen::MatrixXd Jwhole(vectorial_dim * (n_modes + 1), n_cells);
650 Eigen::VectorXd q(vectorial_dim * (n_modes + 1));
651
652 // matrices for greedy selection of the nodes
653 Eigen::MatrixXd A(vectorial_dim*n_modes, n_cells);
654 Eigen::VectorXd b = Eigen::VectorXd::Constant(vectorial_dim*n_modes, 1);
655
656 Eigen::VectorXd volumes = ITHACAutilities::getMassMatrixFV(std::get<0>(snapshotsListTuple)[0]);
657 double volume = volumes.array().sum();
658 for (unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
659 {
660 Eigen::MatrixXd block = snapshotsModes.block(ith_field*n_cells, 0, n_cells, n_modes).transpose();
661
662 q.segment(ith_field*(n_modes+1), n_modes) = block.rowwise().sum();
663 q(ith_field*(n_modes+1)+n_modes) = volume;
664
665 Jwhole.middleRows(ith_field*(n_modes+1), n_modes) = block;
666 Jwhole.row(ith_field*(n_modes+1)+n_modes) = Eigen::VectorXd::Constant(n_cells, 1);
667
668 Eigen::VectorXd mean = block.rowwise().mean();
669 block.colwise() -= mean;
670 Eigen::VectorXd Anorm = block.colwise().lpNorm<2>();
671 if (Anorm.minCoeff()> 0)
672 {
673 block.array().rowwise() /= Anorm.transpose().array();
674 }
675
676 A.middleRows(ith_field*n_modes, n_modes) = block;
677 }
678 Eigen::VectorXd mp_not_mask = Eigen::VectorXd::Constant(n_cells * vectorial_dim, 1);
679 std::set<label> nodePointsSet;
680
681 // set initialSeeds
682 if (initialSeeds.rows() > 0)
683 {
684 initialSeeds(mp_not_mask, nodePointsSet);
685 computeLS(J, Jwhole, b, q);
686 }
687
688 int na = n_nodes - initialSeeds.rows();
689 Eigen::SparseMatrix<double> reshapeMat;
690 initReshapeMat(reshapeMat);
691
692 if (na > 0)
693 {
694 label ind_max, r1;
695 double max;
696
697 for (unsigned int ith_node = 0; ith_node < na; ith_node++)
698 {
699 max = ((b.transpose()*A*mp_not_mask.head(n_cells).asDiagonal()).colwise().sum()).maxCoeff(&r1, &ind_max);
700
701 updateNodes(P, ind_max, mp_not_mask);
702 computeLS(J, Jwhole, b, q);
703 }
704 }
705
706 Info << "####### End ECP #######" << endl;
707
708 basisMatrix = snapshotsModes.leftCols(n_modes);
709 evaluateWPU(P, basisMatrix, normalizingWeights, quadratureWeights);
710
711 cnpy::save(basisMatrix, folderMethod +"/basisMatrix.npy");
712 cnpy::save(quadratureWeights, folderMethod +"/quadratureWeights.npy");
713 cnpy::save(normalizingWeights, folderMethod +"/normalizingWeights.npy");
714 cnpy::save(nodes, folderMethod + "/mp.npy");
715 cnpy::save(wPU, folderMethod + "/wPU.npy");
716 nodePoints().write();
717 }
718 else
719 {
720 Info << "Read ECP\n";
721 cnpy::load(basisMatrix, folderMethod +"/basisMatrix.npy");
722 cnpy::load(quadratureWeights, folderMethod +"/quadratureWeights.npy");
723 cnpy::load(normalizingWeights, folderMethod +"/normalizingWeights.npy");
724 cnpy::load(nodes, folderMethod + "/mp.npy");
725 cnpy::load(wPU, folderMethod + "/wPU.npy");
726 }
727}
728
729template<typename... SnapshotsLists>
730void HyperReduction<SnapshotsLists...>::initSeeds(Eigen::VectorXd mp_not_mask, std::set<label> nodePointsSet)
731{
732 P.resize(n_cells * vectorial_dim, initialSeeds.rows() * vectorial_dim);
733 P.reserve(Eigen::VectorXi::Constant(initialSeeds.rows() * vectorial_dim /*n_cols*/, 1 /*n_non_zero_elements*/));
734
735 unsigned int trueSeeds{0};
736 for (int i = 0; i < initialSeeds.rows(); i++)
737 {
738 unsigned int index = initialSeeds(i) % n_cells;
739 // check that there are not repeated nodes in initialSeeds
740 if (nodePointsSet.find(index) == nodePointsSet.end()){
741 nodePointsSet.insert(index);
742 nodePoints->append(index);
743
744 for (unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
745 {
746 P.insert(index+ith_field*n_cells, vectorial_dim*trueSeeds+ith_field) = 1;
747 mp_not_mask(index + ith_field * n_cells) = 0;
748 }
749 trueSeeds++;
750 }
751 }
752
753 P.conservativeResize(P.rows(), nodePoints->size()*vectorial_dim);
754 P.makeCompressed();
755 M_Assert(nodePoints->size()<=n_nodes, "Size of 'initialSeeds' is greater than 'n_nodes'");
756}
757
758template <typename... SnapshotsLists>
759void HyperReduction<SnapshotsLists...>::updateNodes(Eigen::SparseMatrix<double>& P, label& ind, Eigen::VectorXd& mp_not_mask)
760{
761 nodePoints->append(ind);
762
763 nodes.conservativeResize(nodes.rows()+1);
764 nodes(nodes.rows()-1) = ind;
765
766 unsigned int last_col{0};
767
768 if (P.rows()==0)
769 {
770 P.resize(n_cells*vectorial_dim, vectorial_dim);
771 }
772 else
773 {
774 last_col = P.cols();
775 P.resize(P.rows(), P.cols() + vectorial_dim);
776 }
777 int step = P.cols() / vectorial_dim - 1;
778
779 for (int ith_node=0; ith_node <= step; ith_node++)
780 {
781 for (unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
782 {
783 P.insert(nodes[ith_node]+ith_field*n_cells,ith_node+ith_field*(step+1))=1;
784 }
785 }
786
787 for (unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
788 {
789 mp_not_mask(ind + ith_field * n_cells) = 0;
790 }
791}
792
793template<typename... SnapshotsLists>
794void HyperReduction<SnapshotsLists...>::computeLS(Eigen::MatrixXd& J, Eigen::MatrixXd& Jwhole, Eigen::VectorXd& b, Eigen::VectorXd& q)
795{
796 // TODO fix with only positive weights (NNLS)
797 J.resize(vectorial_dim * (n_modes + 1), nodePoints->size());
798 J = Jwhole(Eigen::indexing::all, nodes);
799
800 quadratureWeights.resize(nodePoints->size()*vectorial_dim);
801 for (unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
802 {
803 quadratureWeights.segment(ith_field*nodePoints->size(), nodePoints->size()) = J.middleRows(ith_field*(n_modes+1), n_modes+1).colPivHouseholderQr().solve(q.segment(ith_field*(n_modes+1), n_modes+1));
804 b.segment(ith_field*n_modes, n_modes) = q.segment(ith_field*(n_modes+1), n_modes)-J.middleRows(ith_field*(n_modes+1), n_modes)*quadratureWeights.segment(ith_field*nodePoints->size(), nodePoints->size());
805 }
806 b = b/b.lpNorm<2>();
807}
808
809template<typename... SnapshotsLists>
810void HyperReduction<SnapshotsLists...>::initReshapeMat(Eigen::SparseMatrix<double> &reshapeMat)
811{
812 reshapeMat.resize(n_cells, n_cells*vectorial_dim);
813 reshapeMat.reserve(Eigen::VectorXi::Constant(n_cells * vectorial_dim /*n_cols*/, 1 /*n_non_zero_elements*/));
814
815 for (unsigned int i = 0; i < n_cells; i++)
816 {
817 for (unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
818 {
819 reshapeMat.insert(i, i+n_cells*ith_field) = 1;
820 }
821 }
822 reshapeMat.makeCompressed();
823}
824
825template <typename... SnapshotsLists>
826template <typename SnapshotsList>
827void HyperReduction<SnapshotsLists...>::stackSnapshots(SnapshotsList sList, Eigen::MatrixXd& snapshotsMatrix, Eigen::VectorXd& fieldWeights)
828{
829 unsigned int field_dim = get_field_dim<typename SnapshotsList::value_type>();
830
831 Eigen::MatrixXd tmpSnapshots = Foam2Eigen::PtrList2Eigen(sList);
832 // get volumes
833 Eigen::VectorXd V = ITHACAutilities::getMassMatrixFV(sList[0]);
834
835
836 double maxVal = std::sqrt(tmpSnapshots.colwise().lpNorm<2>().maxCoeff());
837
838 fieldWeights.conservativeResize(fieldWeights.rows()+field_dim*n_cells);
839 fieldWeights.tail(n_cells * field_dim) = V.array().sqrt().cwiseInverse()*maxVal;
840
841 snapshotsMatrix.conservativeResize(snapshotsMatrix.rows() + n_cells * field_dim, n_snapshots);
842 snapshotsMatrix.bottomRows(n_cells * field_dim) = tmpSnapshots;
843}
844
845template <typename... SnapshotsLists>
846template <typename SnapshotsList>
847void HyperReduction<SnapshotsLists...>::stackSnapshotsBoundary(SnapshotsList sList, List<Eigen::MatrixXd>& snapshotsMatrixBoundary, List<Eigen::VectorXd>& fieldWeightsBoundary)
848{
849 unsigned int field_dim = get_field_dim<typename SnapshotsList::value_type>();
850
851 List<Eigen::MatrixXd> tmpBoundarySnapshots = Foam2Eigen::PtrList2EigenBC(sList);
852
853 List<double> maxVal;
854 maxVal.resize(n_boundary_patches);
855
856 for (label id = 0; id < n_boundary_patches; id++)
857 {
858 maxVal[id] = std::sqrt(tmpBoundarySnapshots[id].colwise().lpNorm<2>().maxCoeff());
859
860 // get surface areas
861 Eigen::VectorXd S = Foam2Eigen::field2Eigen(sList[0].mesh().magSf().boundaryField()[id]);
862 S = S.replicate(field_dim, 1);
863
864 unsigned int bSize = field_dim*int(n_boundary_cells_list[id]);
865 fieldWeightsBoundary[id].conservativeResize(fieldWeightsBoundary[id].rows()+bSize);
866 fieldWeightsBoundary[id].tail(bSize) = S.array().pow(3/4)*maxVal[id];
867
868 snapshotsMatrixBoundary[id].conservativeResize(snapshotsMatrixBoundary[id].rows() + bSize, n_snapshots);
869 snapshotsMatrixBoundary[id].bottomRows(bSize) = tmpBoundarySnapshots[id];
870 }
871}
872
873template<typename... SnapshotsLists>
874void HyperReduction<SnapshotsLists...>::evaluatePinv(Eigen::SparseMatrix<double> &Projector, Eigen::MatrixXd &Modes, Eigen::VectorXd &fieldWeights) {
875 assert(Projector.cols() > 0);
876 Eigen::MatrixXd restricted = Projector.transpose() * Modes;
877 Info << "S-Optimalty: " << s_optimality(restricted) << endl;
878 pinvPU = ITHACAutilities::invertMatrix(restricted, para->ITHACAdict->lookupOrDefault<word>("InversionMethod", "completeOrthogonalDecomposition"));
879 pinvPU = pinvPU*(Projector.transpose() * fieldWeights.array().cwiseInverse().matrix()).asDiagonal();
880}
881
882template<typename... SnapshotsLists>
883void HyperReduction<SnapshotsLists...>::evaluateWPU(Eigen::SparseMatrix<double> &Projector, Eigen::MatrixXd &Modes, Eigen::VectorXd &fieldWeights, Eigen::VectorXd& quadratureWeights) {
884 assert(Projector.cols() > 0);
885
886 Eigen::VectorXd quadratureWeightsOrderedAsProjector(quadratureWeights.rows());
887 unsigned int n_weightsPerField = quadratureWeights.rows()/vectorial_dim;
888 unsigned int reorderIndex{0};
889
890 for (unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
891 {
892 for (unsigned int ith_weight = 0; ith_weight < n_weightsPerField; ith_weight++)
893 {
894 quadratureWeightsOrderedAsProjector(reorderIndex) = quadratureWeights(ith_weight + ith_field * n_weightsPerField);
895 reorderIndex++;
896 }
897 }
898 wPU = quadratureWeightsOrderedAsProjector.transpose()*(Projector.transpose() * fieldWeights.array().cwiseInverse().matrix()).asDiagonal();
899}
900
901template<typename... SnapshotsLists>
903
904 Info << "####### Extract submesh #######\n";
906
907 totalNodePoints = autoPtr<IOList<labelList>>(new IOList<labelList>(IOobject(
908 "totalNodePoints", para->runTime.time().constant(), "../" + folderMethod,
909 para->mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE)));
910
911 uniqueNodePoints = autoPtr<IOList<label>>(new IOList<label>(IOobject(
912 "uniqueNodePoints", para->runTime.time().constant(), "../" + folderMethod,
913 para->mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE)));
914
915 volScalarField Indici
916 (
917 IOobject
918 (
919 problemName + "_indices",
920 mesh.time().timeName(),
921 mesh,
922 IOobject::NO_READ,
923 IOobject::NO_WRITE
924 ),
925 mesh,
926 dimensionedScalar(problemName + "_indices",
927 dimensionSet(0, 0, 0, 0, 0, 0, 0), 0.0));
928
929 submesh = autoPtr<fvMeshSubset>(new fvMeshSubset(mesh));
930 bool offlineStage = !totalNodePoints().headerOk();
931
932 if (offlineStage) {
933 List<label> indices;
934 for (label i = 0; i < nodePoints().size(); i++) {
935 indices = ITHACAutilities::getIndices(mesh, nodePoints()[i], layers);
936 totalNodePoints().append(indices);
937 }
938
939 labelList a = ListListOps::combine<labelList>(totalNodePoints(),
940 accessOp<labelList>());
941
942 inplaceUniqueSort(a);
943 uniqueNodePoints() = a;
944
945 scalar zerodot25 = 0.25;
946 ITHACAutilities::assignIF(Indici, zerodot25,
947 uniqueNodePoints().List<label>::clone()());
948 ITHACAutilities::assignONE(Indici, nodePoints());
949
950 totalNodePoints().write();
951 uniqueNodePoints().write();
952 ITHACAstream::exportSolution(Indici, "1", folderMethod);
953 }
954
955 submesh->setCellSubset(uniqueNodePoints());
956 submesh->subMesh().fvSchemes::readOpt() = mesh.fvSchemes::readOpt();
957 submesh->subMesh().fvSolution::readOpt() = mesh.fvSolution::readOpt();
958 submesh->subMesh().fvSchemes::read();
959 submesh->subMesh().fvSolution::read();
960 std::cout.clear();
961
962 localNodePoints = global2local(nodePoints(), submesh());
963
964 n_cellsSubfields = submesh().cellMap().size();
965 Info << "####### End extract submesh size = " << n_cellsSubfields <<" #######\n";
966
967 createMasks(offlineStage);
968 Info << "####### End create masks #######\n";
969}
970
971template<typename... SnapshotsLists>
973{
974 if (offlineStage)
975 {
976 field2submesh.resize(submesh().cellMap().size() * vectorial_dim, n_cells*vectorial_dim);
977 field2submesh.reserve(Eigen::VectorXi::Constant(n_cells*vectorial_dim, 1));
978
979 for (unsigned int ith_subCell{0} ; ith_subCell <submesh().cellMap().size(); ith_subCell++)
980 {
981 for (unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
982 {
983 field2submesh.insert(ith_subCell+ith_field*submesh().cellMap().size(), submesh().cellMap()[ith_subCell]+n_cells*ith_field) = 1;
984 }
985 }
986 field2submesh.makeCompressed();
987
988 submesh2nodes.resize(nodePoints().size() * vectorial_dim, submesh().cellMap().size()*vectorial_dim);
989 submesh2nodes.reserve(Eigen::VectorXi::Constant(submesh().cellMap().size()*vectorial_dim, 1));
990 submesh2nodesMask.resize(nodePoints().size() * vectorial_dim);
991
992 int index_col = 0;
993 for (unsigned int ith_node{0} ; ith_node <nodePoints().size(); ith_node++) {
994 for (unsigned int ith_subCell{0} ; ith_subCell <submesh().cellMap().size(); ith_subCell++) {
995 if (nodePoints()[ith_node] == submesh().cellMap()[ith_subCell]) {
996 for (unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
997 {
998 submesh2nodes.insert(ith_node + nodePoints().size()*ith_field, index_col + ith_field*submesh().cellMap().size()) = 1;
999 submesh2nodesMask(ith_node + nodePoints().size()*ith_field) = index_col + ith_field*submesh().cellMap().size();
1000 }
1001 break;
1002 } else {
1003 index_col++;
1004 }
1005 }
1006 index_col = 0;
1007 }
1008 submesh2nodes.makeCompressed();
1009
1010 cnpy::save(field2submesh, folderMethod +"/field2submesh.npz");
1011 cnpy::save(submesh2nodes, folderMethod +"/submesh2nodes.npz");
1012 cnpy::save(submesh2nodesMask, folderMethod +"/submesh2nodesMask.npy");
1013 }
1014 else
1015 {
1016 cnpy::load(field2submesh, folderMethod +"/field2submesh.npz");
1017 cnpy::load(submesh2nodes, folderMethod +"/submesh2nodes.npz");
1018 cnpy::load(submesh2nodesMask, folderMethod +"/submesh2nodesMask.npy");
1019 }
1020}
1021
1022template<typename... SnapshotsLists>
1023List<label> HyperReduction<SnapshotsLists...>::global2local(List<label> &points, fvMeshSubset &submesh) {
1024 List<label> localPoints;
1025
1026 for (label i = 0; i < points.size(); i++) {
1027 for (label j = 0; j < submesh.cellMap().size(); j++) {
1028 if (submesh.cellMap()[j] == points[i]) {
1029 localPoints.append(j);
1030 break;
1031 }
1032 }
1033 }
1034
1035 return localPoints;
1036}
1037
1038#endif
Foam::fvMesh & mesh
Definition createMesh.H:47
#define M_Assert(Expr, Msg)
static GeometricField< scalar, PatchField, GeoMesh > Eigen2field(GeometricField< scalar, PatchField, GeoMesh > &field, Eigen::VectorXd &eigen_vector, bool correctBC=true)
Convert a vector in Eigen format into an OpenFOAM scalar GeometricField.
Definition Foam2Eigen.C:506
static Eigen::VectorXd field2Eigen(GeometricField< tensor, PatchField, GeoMesh > &field)
Convert a vector OpenFOAM field into an Eigen Vector.
Definition Foam2Eigen.C:40
static List< Eigen::MatrixXd > PtrList2EigenBC(PtrList< GeometricField< scalar, PatchField, GeoMesh > > &fields, label Nfields=-1)
Convert an OpenFOAM scalar field to a List of Eigen Vectors, one for each boundary.
Definition Foam2Eigen.C:257
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:638
void stackSnapshotsBoundary(SnapshotsList sList, List< Eigen::MatrixXd > &snapshotsMatrixBoundary, List< Eigen::VectorXd > &fieldWeightsBoundary)
TODO.
SnapshotsListTuple snapshotsListTuple
The snapshots matrix containing the nonlinear function or operator.
void evaluateWPU(Eigen::SparseMatrix< double > &Projector, Eigen::MatrixXd &Modes, Eigen::VectorXd &fieldWeights, Eigen::VectorXd &quadratureWeights)
Compute the pseudo-inverse of the matrix M restricted with the projector P.
void stackNames(SnapshotsList sList)
TODO.
List< word > fieldNames
Names of the fields.
void generateSubmesh(label layers, const fvMesh &mesh)
Compute the submesh common to all fields in SnapshotsLists.
List< label > n_boundary_cells_list
void offlineGappyDEIM(Eigen::MatrixXd &snapshotsModes, Eigen::VectorXd &normalizingWeights)
Methods implemented: 'GappyDEIM' from "DEIM, Chaturantabut, Saifon, and Danny C. Sorensen....
void updateNodes(Eigen::SparseMatrix< double > &P, label &ind_max, Eigen::VectorXd &mp_not_mask)
TODO.
unsigned int sumFieldsDim
void evaluatePinv(Eigen::SparseMatrix< double > &Projector, Eigen::MatrixXd &Modes, Eigen::VectorXd &fieldWeights)
Compute the pseudo-inverse of the matrix M restricted with the projector P.
void sumDimensions(double sum, SnapshotsList sList)
TODO.
List< label > global2local(List< label > &points, fvMeshSubset &submesh)
Get local indices in the submesh from indices in the global ones.
void stackDimensions(SnapshotsList sList)
TODO.
void getSnapMatrix(Eigen::MatrixXd &snapMatrix, Eigen::VectorXd &fieldWeights)
TODO.
Eigen::VectorXi initialSeeds
void offlineECP(Eigen::MatrixXd &snapshotsModes, Eigen::VectorXd &normalizingWeights)
Methods implemented: 'ECP' from "ECP, Hernandez, Joaquin Alberto, Manuel Alejandro Caicedo,...
word problemName
The name of the non-linear function e.g. HR_method/residual.
HyperReduction(label n_modes, label n_nodes, Eigen::VectorXi initialSeeds, word problemName, SnapshotsLists &&...snapshotsLists)
Construct HyperReduction class, interpolation-based.
ITHACAparameters * para
std::tuple< std::decay_t< SnapshotsLists >... > SnapshotsListTuple
unsigned int vectorial_dim
label n_cells
Int Number of Cells;.
void initReshapeMat(Eigen::SparseMatrix< double > &reshapeMat)
TODO.
void initSeeds(Eigen::VectorXd mp_not_mask, std::set< label > nodePointsSet)
TODO.
void getModesSVD(SnapshotsListTuple &SnapshotsListTuple, Eigen::MatrixXd &modesSVD, Eigen::VectorXd &fieldWeights, bool saveModesFlag=false)
TODO.
label n_snapshots
The length of the snapshots lists.
List< unsigned int > fieldDims
Dimensions of the fields.
void saveModes(SnapshotsList sList, Eigen::MatrixXd &snapshotsMatrix, unsigned int &rowIndex, unsigned int &modeIndex, word folder)
TODO.
word folderProblem
Folder for the HR problem.
void stackSnapshots(SnapshotsList sList, Eigen::MatrixXd &snapshotsMatrix, Eigen::VectorXd &fieldWeights)
TODO.
void createMasks(bool offlineStage=true)
TODO.
void computeLS(Eigen::MatrixXd &J, Eigen::MatrixXd &JWhole, Eigen::VectorXd &b, Eigen::VectorXd &q)
TODO.
Class for the definition of some general parameters, the parameters must be defined from the file ITH...
Time & runTime
runTime defined locally
label precision
precision of the output Market Matrix objects (i.e. reduced matrices, eigenvalues,...
IOdictionary * ITHACAdict
Dictionary for input objects from file.
fvMesh & mesh
Mesh object defined locally.
static ITHACAparameters * getInstance()
Gets an instance of ITHACAparameters, to be used if the instance is already existing.
std::_Ios_Fmtflags outytpe
type of output format can be fixed or scientific
Implementation of a container class derived from PtrList.
Definition Modes.H:69
volScalarField & A
T max(Eigen::SparseMatrix< T > &mat, label &ind_row, label &ind_col)
Find the maximum of a sparse Matrix (Useful for DEIM)
bool saveMarketVector(const VectorType &vec, const std::string &filename, label prec, std::_Ios_Fmtflags outytpe=std::ios_base::scientific)
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 assignIF(GeometricField< Type, fvPatchField, volMesh > &s, Type value)
Assign internal field.
List< label > getIndices(const fvMesh &mesh, int index, int layers)
Gets the indices of the cells around a certain cell.
Eigen::MatrixXd invertMatrix(Eigen::MatrixXd &matrixToInvert, const word inversionMethod)
Invert a matrix given the method name in the ITHACAdict.
void assignONE(volScalarField &s, List< label > &L)
Assign one to volScalarField.
Eigen::VectorXd getMassMatrixFV(GeometricField< Type, PatchField, GeoMesh > &snapshot)
Gets a vector containing the volumes of each cell of the mesh.
bool check_folder(word folder)
Checks if a folder exists.
void save(const Eigen::Matrix< T, -1, dim > &mat, const std::string fname)
Eigen::Matrix< T, -1, dim > load(Eigen::Matrix< T, -1, dim > &mat, const std::string fname, std::string order="rowMajor")
Info<< endl;Info<< "*********************************************************"<< endl;Info<< "Performing test for the parameterized BC inverse solver"<< endl;Info<< endl;word outputFolder="./ITHACAoutput/parameterizedBCtest_RBFparameter/";volScalarField gTrueField=example_paramBC.list2Field(example_paramBC.gTrue);ITHACAstream::exportSolution(gTrueField, "1", outputFolder, "gTrue");Eigen::VectorXd rbfWidth=EigenFunctions::ExpSpaced(0.001, 100, rbfWidthTest_size);ITHACAstream::exportMatrix(rbfWidth, "rbfShapeParameters", "eigen", outputFolder);Eigen::VectorXd residualNorms;residualNorms.resize(rbfWidthTest_size);Eigen::VectorXd heatFluxL2norm(rbfWidthTest_size);Eigen::VectorXd heatFluxLinfNorm=heatFluxL2norm;Eigen::VectorXd condNumber=heatFluxL2norm;Eigen::MatrixXd singVal;for(int i=0;i< rbfWidthTest_size;i++){ Info<< "*********************************************************"<< endl;Info<< "RBF parameter "<< rbfWidth(i)<< endl;Info<< "Test "<< i+1<< endl;Info<< endl;example_paramBC.set_gParametrized("rbf", rbfWidth(i));example_paramBC.parameterizedBCoffline(1);example_paramBC.parameterizedBC("fullPivLU");volScalarField gParametrizedField=example_paramBC.list2Field(example_paramBC.g);ITHACAstream::exportSolution(gParametrizedField, std::to_string(i+1), outputFolder, "gParametrized");volScalarField &T(example_paramBC._T());ITHACAstream::exportSolution(T, std::to_string(i+1), outputFolder, "T");residualNorms(i)=Foam::sqrt(example_paramBC.residual.squaredNorm());Eigen::MatrixXd A=example_paramBC.Theta.transpose() *example_paramBC.Theta;Eigen::JacobiSVD< Eigen::MatrixXd > svd(A, Eigen::ComputeThinU|Eigen::ComputeThinV)
label i
Definition pEqn.H:46
volScalarField S(IOobject("S", runTime.timeName(), mesh, IOobject::NO_READ, IOobject::AUTO_WRITE), T.mesh(), dimensionedScalar("zero", dimensionSet(0, 0, -1, 1, 0, 0, 0), 0))