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...)},
50 snapshotsListTuple{std::forward_as_tuple(snapshotsLists...)}
51{
52 Info << "Init HyperReduction class with vectorial dim: " << vectorial_dim <<
53 endl;
55 folderProblem = "ITHACAoutput/" + problemName;
56 mkDir(folderProblem);
57 // TODO check snapshotsLists is not empty
58 // TODO check that the first snapshotsList is not empty (includes above)
59 // TODO initialize vectorial_dim only from SnapshotsLists type
60 // vectorial_dim = std::apply(compute_vectorial_dim<SnapshotsLists&&...>, snapshotsListTuple);
61 // Get fields' names
62 std::apply([this](auto & ...snapList)
63 {
64 (..., stackNames(snapList));
66
67 // Get fields' dimensions
68 std::apply([this](auto & ...snapList)
69 {
70 (..., stackDimensions(snapList));
72
73 sumFieldsDim = 0;
74 std::apply([this](auto & ...snapList)
75 {
76 (..., sumDimensions(this->sumFieldsDim, snapList));
79 Info << "Fields names: ";
80
81 for (unsigned int ith_field = 0; ith_field < fieldNames.size(); ith_field++)
82 {
83 Info << fieldNames[ith_field] << " (dim=" << fieldDims[ith_field] << "); ";
84 }
85
86 Info << endl;
87 n_snapshots = std::get<0>(snapshotsListTuple).size();
88 Info << "The number of snapshots is: " << n_snapshots << endl;
89 n_cells = std::get<0>(snapshotsListTuple)[0].size();
90 Info << "The number of cells is: " << n_cells << endl;
91 Info << "Initial seeds length: " << initialSeeds.rows() << endl;
92 // get boundaries info
93 n_boundary_patches = std::get<0>(snapshotsListTuple)[0].boundaryField().size();
96
97 for (unsigned int ith_boundary_patch = 0;
98 ith_boundary_patch < n_boundary_patches; ith_boundary_patch++)
99 {
100 n_boundary_cells_list[ith_boundary_patch] = std::get<0>
101 (snapshotsListTuple)[0].boundaryField()[ith_boundary_patch].size();
103 }
104
105 Info << "Number of boundary cells: " << n_boundary_cells << endl;
106}
107
108
109// Template function constructor
110template <typename... SnapshotsLists>
112 label n_nodes,
113 unsigned int vectorialDim,
114 label n_cells,
115 Eigen::VectorXi initialSeeds,
116 word problemName)
117 : n_modes{n_modes},
119 vectorial_dim{vectorialDim},
123{
124 Info << "Init HyperReduction class with vectorial dim: " << vectorial_dim <<
125 endl;
128 mkDir(folderProblem);
129 Info << "Initial seeds length: " << initialSeeds.rows() << endl;
130}
131
132template <typename... SnapshotsLists>
134 SnapshotsListTuple& snapshotsListTuple, Eigen::MatrixXd& modesSVD,
135 Eigen::VectorXd& fieldWeights, bool saveModesFlag)
136{
137 // TODO move inside ITHACAPOD
139 word folderSVD = "ITHACAoutput/" + problemName + "/ModesSVD/";
140
141 if (!ITHACAutilities::check_folder(folderSVD))
142 {
143 mkDir(folderSVD);
144 // Initialize stacked snapshotsMatrix and normalizing weights
145 Eigen::MatrixXd snapMatrix;
146 getSnapMatrix(snapMatrix, fieldWeights);
147 word dimensionReductionMethod =
148 para->ITHACAdict->lookupOrDefault<word>("DimensionReductionMethod", "SVD");
149 Eigen::MatrixXd eigenVectoreig;
150
151 if (dimensionReductionMethod == "RSVD")
152 {
153 Info << "####### Performing RSVD for " << problemName << " #######" << endl;
154 unsigned int r_modeSVD =
155 para->ITHACAdict->lookupOrDefault<unsigned int>("RSVDdim", snapMatrix.cols());
156 RedSVD::RedSVD svd(fieldWeights.array().cwiseInverse().matrix().asDiagonal() *
157 snapMatrix, r_modeSVD);
158 Info << "####### End of RSVD for " << problemName << " #######" <<
159 endl;
160 eigenValueseig = svd.singularValues().real();
161 eigenVectoreig = svd.matrixU().real();
162 }
163 else
164 {
165 Info << "####### Performing SVD for " << problemName << " #######" << endl;
166 Eigen::JacobiSVD<Eigen::MatrixXd> svd(
167 fieldWeights.array().cwiseInverse().matrix().asDiagonal() * snapMatrix,
168 Eigen::ComputeThinU | Eigen::ComputeThinV);
169 Info << "####### End of SVD for " << problemName << " #######" <<
170 endl;
171 eigenValueseig = svd.singularValues().real();
172 eigenVectoreig = svd.matrixU().real();
173 }
174
175 modesSVD = eigenVectoreig;
176 // TODO correct boundary conditions
178 "ITHACAoutput/" + problemName + "/ModesSVD/eigenvalues.npy");
180 Eigen::VectorXd cumEigenValues(eigenValueseig);
181
182 for (label j = 1; j < cumEigenValues.size(); ++j)
183 {
184 cumEigenValues(j) += cumEigenValues(j - 1);
185 }
186
188 "ITHACAoutput/" + problemName + "/ModesSVD/Eigenvalues_" + problemName,
189 para->precision,
190 para->outytpe);
191 Eigen::saveMarketVector(cumEigenValues,
192 "ITHACAoutput/" + problemName + "/ModesSVD/CumEigenvalues_" + problemName,
193 para->precision,
194 para->outytpe);
195 cnpy::save(modesSVD, "ITHACAoutput/" + problemName + "/ModesSVD/modes.npy");
196 cnpy::save(fieldWeights,
197 "ITHACAoutput/" + problemName + "/ModesSVD/normalizingWeights.npy");
198
199 if (saveModesFlag)
200 {
201 unsigned int rowIndex{0};
202
203 for (unsigned int modeIndex = 0; modeIndex < modesSVD.cols(); modeIndex++)
204 {
205 std::apply([this, & modesSVD, & rowIndex, & modeIndex,
206 & folderSVD](auto & ...snapList)
207 {
208 (..., saveModes(snapList, modesSVD, rowIndex, modeIndex, folderSVD));
210
211 rowIndex = 0;
212 }
213 }
214 }
215 else
216 {
217 Info << "Reading the existing modes" << endl;
218 cnpy::load(modesSVD, folderSVD + "/modes.npy");
219 cnpy::load(fieldWeights, folderSVD + "/normalizingWeights.npy");
220 }
221}
222
223template <typename... SnapshotsLists>
225 SnapshotsListTuple& snapshotsListTuple, Eigen::MatrixXd& modesSVD,
226 Eigen::VectorXd& fieldWeights, Eigen::MatrixXd& modesSVDBoundary,
227 Eigen::VectorXd& fieldWeightsBoundary, bool saveModesFlag)
228{
229 // TODO move inside ITHACAPOD
231 word folderSVD = "ITHACAoutput/" + problemName + "/ModesSVD/";
233 if (!ITHACAutilities::check_folder(folderSVD))
234 {
235 mkDir(folderSVD);
236 // Initialize stacked snapshotsMatrix and normalizing weights
237 Eigen::MatrixXd snapMatrix;
238 List<Eigen::MatrixXd> snapMatrixBoundary;
239 List<Eigen::VectorXd> fieldWeightsBoundaryList;
240 getSnapMatrix(snapMatrix, fieldWeights, snapMatrixBoundary,
241 fieldWeightsBoundaryList);
242
243 for (unsigned int id = 0; id < n_boundary_patches; id++)
244 {
245 snapMatrix.conservativeResize(snapMatrix.rows() + snapMatrixBoundary[id].rows(),
246 snapMatrix.cols());
247 snapMatrix.bottomRows(snapMatrixBoundary[id].rows()) = snapMatrixBoundary[id];
248 fieldWeightsBoundary.conservativeResize(fieldWeightsBoundary.rows() +
249 snapMatrixBoundary[id].rows());
250 fieldWeightsBoundary.tail(fieldWeightsBoundaryList[id].rows()) =
251 fieldWeightsBoundaryList[id];
253
254 cnpy::save(fieldWeights,
255 "ITHACAoutput/" + problemName + "/ModesSVD/normalizingWeights.npy");
256 cnpy::save(fieldWeightsBoundary,
257 "ITHACAoutput/" + problemName + "/ModesSVD/normalizingWeightsBoundary.npy");
258 fieldWeights.conservativeResize(fieldWeights.rows() +
259 fieldWeightsBoundary.rows());
260 fieldWeights.tail(fieldWeightsBoundary.rows()) = fieldWeightsBoundary;
261 word dimensionReductionMethod =
262 para->ITHACAdict->lookupOrDefault<word>("DimensionReductionMethod", "SVD");
263 Eigen::MatrixXd eigenVectoreig;
264
265 if (dimensionReductionMethod == "RSVD")
266 {
267 Info << "####### Performing RSVD for " << problemName << " #######" << endl;
268 unsigned int r_modeSVD =
269 para->ITHACAdict->lookupOrDefault<unsigned int>("RSVDdim", snapMatrix.cols());
270 RedSVD::RedSVD svd(fieldWeights.array().cwiseInverse().matrix().asDiagonal() *
271 snapMatrix, r_modeSVD);
272 Info << "####### End of RSVD for " << problemName << " #######" << endl;
273 eigenValueseig = svd.singularValues().real();
274 eigenVectoreig = svd.matrixU().real();
275 }
276 else
277 {
278 Info << "####### Performing SVD for " << problemName << " #######" << endl;
279 Eigen::JacobiSVD<Eigen::MatrixXd> svd(
280 fieldWeights.array().cwiseInverse().matrix().asDiagonal() * snapMatrix,
281 Eigen::ComputeThinU | Eigen::ComputeThinV);
282 Info << "####### End of SVD for " << problemName << " #######" <<
283 endl;
284 eigenValueseig = svd.singularValues().real();
285 eigenVectoreig = svd.matrixU().real();
286 }
287
288 modesSVD = eigenVectoreig.bottomRows(vectorial_dim * n_cells);
289 modesSVDBoundary = eigenVectoreig.topRows(n_boundary_cells);
290 fieldWeights.conservativeResize(fieldWeights.rows() -
291 fieldWeightsBoundary.rows());
292 cnpy::save(eigenValueseig,
293 "ITHACAoutput/" + problemName + "/ModesSVD/eigenvalues.npy");
295 Eigen::VectorXd cumEigenValues(eigenValueseig);
296
297 for (label j = 1; j < cumEigenValues.size(); ++j)
298 {
299 cumEigenValues(j) += cumEigenValues(j - 1);
300 }
301
302 Eigen::saveMarketVector(eigenValueseig,
303 "ITHACAoutput/" + problemName + "/ModesSVD/Eigenvalues_" + problemName,
304 para->precision,
305 para->outytpe);
306 Eigen::saveMarketVector(cumEigenValues,
307 "ITHACAoutput/" + problemName + "/ModesSVD/CumEigenvalues_" + problemName,
308 para->precision,
309 para->outytpe);
310 cnpy::save(modesSVD, "ITHACAoutput/" + problemName + "/ModesSVD/modes.npy");
311 cnpy::save(modesSVDBoundary,
312 "ITHACAoutput/" + problemName + "/ModesSVD/modesBoundary.npy");
313
314 if (saveModesFlag)
315 {
316 unsigned int rowIndex{0};
317 unsigned int rowIndexBoundary{0};
318
319 for (unsigned int modeIndex = 0; modeIndex < modesSVD.cols(); modeIndex++)
320 {
321 std::apply([this, & modesSVD, & modesSVDBoundary, & rowIndex, & modeIndex,
322 & rowIndexBoundary, & folderSVD](auto & ...snapList)
323 {
324 (..., saveModes(snapList, modesSVD, modesSVDBoundary, rowIndex,
325 rowIndexBoundary, modeIndex, folderSVD));
327
328 rowIndex = 0;
329 }
330 }
331 }
332 else
333 {
334 Info << "Reading the existing modes" << endl;
335 cnpy::load(modesSVD, folderSVD + "/modes.npy");
336 cnpy::load(modesSVDBoundary,
337 "ITHACAoutput/" + problemName + "/ModesSVD/modesBoundary.npy");
338 cnpy::load(fieldWeights, folderSVD + "/normalizingWeights.npy");
339 cnpy::load(fieldWeightsBoundary,
340 "ITHACAoutput/" + problemName + "/ModesSVD/normalizingWeightsBoundary.npy");
341 }
342}
343
344template <typename... SnapshotsLists>
346 snapMatrix, Eigen::VectorXd& fieldWeights)
347{
348 std::apply([this, & fieldWeights, & snapMatrix](auto & ...snapList)
349 {
350 (..., stackSnapshots(snapList, snapMatrix, fieldWeights));
352}
353
354template <typename... SnapshotsLists>
356 snapMatrix, Eigen::VectorXd& fieldWeights,
357 List<Eigen::MatrixXd>& snapMatrixBoundary,
358 List<Eigen::VectorXd>& fieldWeightsBoundary)
359{
360 fieldWeightsBoundary.resize(n_boundary_patches);
361 snapMatrixBoundary.resize(n_boundary_patches);
362 std::apply([this, & fieldWeights, & snapMatrix, & fieldWeightsBoundary,
363 & snapMatrixBoundary](auto & ...snapList)
364 {
365 (..., stackSnapshots(snapList, snapMatrix, fieldWeights));
366 (..., stackSnapshotsBoundary(snapList, snapMatrixBoundary,
367 fieldWeightsBoundary));
368 },
371}
372
373template <typename... SnapshotsLists>
374template <typename SnapshotsList>
376 Eigen::MatrixXd& snapshotsMatrix, unsigned int& rowIndex,
377 unsigned int& modeIndex, word folder)
378{
380 auto fieldName = sList[0].name();
381 unsigned int fieldSize = field_dim * sList[0].size();
382 Eigen::VectorXd fieldBlock = snapshotsMatrix.block(rowIndex, modeIndex,
383 fieldSize, 1);
384 auto fieldOut = Foam2Eigen::Eigen2field(sList[0], fieldBlock, true);
385 rowIndex += fieldSize;
386 ITHACAstream::exportSolution(fieldOut, name(modeIndex), folder);
387}
388
389template <typename... SnapshotsLists>
390template <typename SnapshotsList>
392 Eigen::MatrixXd& snapshotsMatrix, Eigen::MatrixXd& snapshotsMatrixBoundary,
393 unsigned int& rowIndex, unsigned int& rowIndexBoundary,
394 unsigned int& modeIndex, word folder)
395{
396 unsigned int field_dim = get_field_dim<typename SnapshotsList::value_type>();
397 auto fieldName = sList[0].name();
398 unsigned int fieldSize = field_dim * sList[0].size();
399 Eigen::VectorXd fieldBlock = snapshotsMatrix.block(rowIndex, modeIndex,
400 fieldSize, 1);
401 List<Eigen::VectorXd> fieldBlockBoundary;
402 fieldBlockBoundary.resize(n_boundary_patches);
403
404 for (unsigned int id = 0; id < n_boundary_patches; id++)
405 {
406 unsigned int bfieldDim = field_dim * int(n_boundary_cells_list[id]);
407 fieldBlockBoundary[id] = snapshotsMatrixBoundary.block(rowIndexBoundary,
408 modeIndex, bfieldDim, 1);
409 rowIndexBoundary += bfieldDim;
410 }
411
412 auto fieldOut = Foam2Eigen::Eigen2field(sList[0], fieldBlock,
413 fieldBlockBoundary);
414 rowIndex += fieldSize;
415 ITHACAstream::exportSolution(fieldOut, name(modeIndex), folder);
416}
417
418template <typename... SnapshotsLists>
420 Eigen::MatrixXd& snapshotsModes, Eigen::VectorXd& weights,
421 word folderMethodName)
422{
423 folderMethod = folderMethodName;
424 Info << "FolderMethod : " << folderMethod << endl;
425 mkDir(folderMethod);
426 normalizingWeights = weights;
427 nodePoints = autoPtr<IOList<label >> (new IOList<label>(
428 IOobject("nodePoints", para->runTime.time().constant(), "../" + folderMethod,
429 para->mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE)));
430 auto greedyMetric = para->ITHACAdict->lookupOrDefault<word>("GreedyMetric",
431 "L2");
432 bool offlineStage = !nodePoints().headerOk();
433
434 if (offlineStage)
435 {
436 assert(n_modes > 0);
437 assert(n_nodes >= n_modes);
438 Eigen::VectorXd mp_not_mask = Eigen::VectorXd::Constant(n_cells * vectorial_dim,
439 1);
440 std::set<label> nodePointsSet;
441
442 // set initialSeeds
443 if (initialSeeds.rows() > 0)
444 {
445 initSeeds(mp_not_mask, nodePointsSet);
446 }
447
448 int na = n_nodes - initialSeeds.rows();
449
450 if (na > 0)
451 {
452 Eigen::SparseMatrix<double> reshapeMat;
453 initReshapeMat(reshapeMat);
454
455 if (greedyMetric == "L2")
456 {
457 Info << "####### Begin Greedy-L2 GappyDEIM #######" << endl;
458 Info << "####### Modes=" << n_modes
459 << ", nodePoints=" << n_nodes << " #######"
460 << endl;
461 int nb = 0;
462 int nit = std::min(n_modes, na);
463 int ncimin = std::floor(n_modes / nit);
464 int naimin = std::floor(na / n_modes);
465 Eigen::MatrixXd A;
466 Eigen::VectorXd b;
467 Eigen::VectorXd c;
468 Eigen::VectorXd r;
469 label ind_max, c1;
470 double max;
471
472 for (int i = 1; i <= nit; i++)
473 {
474 int nci = ncimin;
475
476 // add the remaining modes in the quotient n_modes / nite
477 if (i <= n_modes % nit)
478 {
479 nci = ncimin + 1;
480 }
481
482 int nai = naimin;
483
484 // add the remaining nodePoints in the quotient na / n_modes
485 if (i <= na % n_modes)
486 {
487 nai = naimin + 1;
488 }
489
490 Eigen::MatrixXd V;
492 // select basis
493 if (i == 1)
494 {
495 V = snapshotsModes.leftCols(nci);
496 }
497 else
499 for (int q = 1; q <= nci; q++)
500 {
501 A = P.transpose() * basisMatrix;
502 b = P.transpose() * snapshotsModes.col(nb + q - 1);
503 c = A.fullPivLu().solve(b);
504 r = snapshotsModes.col(nb + q - 1) - basisMatrix * c;
505 V.conservativeResize(snapshotsModes.rows(), q);
506 V.col(q - 1) = r;
507 }
508 }
509
510 for (int j = 1; j <= nai; j++)
511 {
512 if (P.cols() > 0)
513 {
514 max = (reshapeMat * (mp_not_mask.asDiagonal() * V)
515 .rowwise()
516 .lpNorm<2>().array().square().matrix())
517 .maxCoeff(& ind_max, & c1);
518 }
519 else
520 {
521 max = (reshapeMat * V.rowwise().lpNorm<2>().array().square().matrix()).maxCoeff(
522 & ind_max, & c1);
523 }
524
525 updateNodes(P, ind_max, mp_not_mask);
526 }
527
528 nb += nci;
529 basisMatrix = snapshotsModes.leftCols(nb);
530 }
531
532 Info << "####### End of greedy GappyDEIM #######\n";
533 }
534 else if (greedyMetric == "SOPT")
535 {
536 Info << "####### Begin SOPT GappyDEIM #######" << endl;
537 Info << "####### Modes=" << n_modes
538 << ", nodePoints=" << n_nodes << " #######"
539 << endl;
540 label ind_max, c1;
541 double max;
542 Eigen::MatrixXd V = snapshotsModes.leftCols(n_modes);
543
544 for (unsigned int ith_node = 0; ith_node < na; ith_node++)
545 {
546 if (P.cols() > 0)
547 {
548 // TODO make efficient
549 Eigen::MatrixXd tmp = P.transpose() * V;
550 Eigen::MatrixXd R = mp_not_mask.asDiagonal() * V;
551 Eigen::MatrixXd inv = (tmp.transpose() * tmp).fullPivLu().inverse();
552 Eigen::VectorXd num = 1 + (reshapeMat * ((R * inv).array() *
553 R.array()).rowwise().sum().matrix()).array();
554 Eigen::VectorXd norma = (tmp.array().square()).colwise().sum();
555 Eigen::MatrixXd adding = reshapeMat * R.array().square().matrix();
556 adding.rowwise() += norma.transpose();
557 Eigen::VectorXd denom = (adding.array().pow(1. /
558 V.cols()).matrix()).rowwise().prod();
559 max = ((mp_not_mask.head(n_cells).asDiagonal() * num).array() /
560 denom.array()).maxCoeff(& ind_max, & c1);
561 }
562 else
563 {
564 max = (reshapeMat * V.rowwise().lpNorm<2>().array().square().matrix()).maxCoeff(
565 & ind_max, & c1);
566 }
567
568 updateNodes(P, ind_max, mp_not_mask);
569 }
570
571 basisMatrix = V;
572 Info << "####### End of SOPT GappyDEIM #######\n";
573 }
574 else if (greedyMetric == "SOPTE")
575 {
576 Info << "####### Begin SOPT-exact GappyDEIM #######" << endl;
577 Info << "####### Modes=" << n_modes
578 << ", nodePoints=" << n_nodes << " #######"
579 << endl;
580 label ind_max, c1;
581 double max;
582 Eigen::MatrixXd A;
583 Eigen::VectorXd b;
584 Eigen::VectorXd c;
585 Eigen::VectorXd r;
586 Eigen::MatrixXd V = snapshotsModes.col(0);
587 max = (reshapeMat * (mp_not_mask.asDiagonal() * snapshotsModes.leftCols(
588 n_modes)).rowwise().lpNorm<2>().array().square().matrix()).maxCoeff(& ind_max,
589 & c1);
590 updateNodes(P, ind_max, mp_not_mask);
591
592 for (unsigned int ith_node = 1; ith_node < na; ith_node++)
593 {
594 if (ith_node < n_modes)
595 {
596 A = P.transpose() * V;
597 b = P.transpose() * snapshotsModes.col(ith_node);
598 c = A.fullPivLu().solve(b);
599 r = snapshotsModes.col(ith_node) - V * c;
600 V.conservativeResize(snapshotsModes.rows(), ith_node + 1);
601 V.col(ith_node) = snapshotsModes.col(ith_node);
602 max = (reshapeMat * r.rowwise().lpNorm<2>().array().square().matrix()).maxCoeff(
603 & ind_max, & c1);
604 }
605 else
606 {
607 // TODO optimize
608 Eigen::MatrixXd tmp = P.transpose() * snapshotsModes.leftCols(n_modes);
609 Info << "SOPT: " << s_optimality(tmp) << endl;
610 tmp.conservativeResize(tmp.rows() + vectorial_dim, tmp.cols());
611 Eigen::MatrixXd masked = mp_not_mask.asDiagonal() * snapshotsModes.leftCols(
612 n_modes);
613 Eigen::VectorXd results(n_cells);
614
615 for (unsigned int ith_cell = 0; ith_cell < n_cells; ith_cell++)
616 {
617 for (unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
618 {
619 tmp.row(tmp.rows() - vectorial_dim + ith_field) = masked.row(
620 ith_cell + ith_field * n_cells);
621 }
622
623 results(ith_cell) = s_optimality(tmp);
624 }
625
626 max = results.maxCoeff(& ind_max, & c1);
627 }
628
629 updateNodes(P, ind_max, mp_not_mask);
630 }
631
632 basisMatrix = snapshotsModes.leftCols(n_modes);
633 Info << "####### End of SOPTE GappyDEIM #######\n";
634 }
635 }
636 else
637 {
638 basisMatrix = snapshotsModes.leftCols(n_modes);
639 Info << "####### InitialSeeds equal to n_nodes #######\n";
640 }
641
642 evaluatePinv(P, basisMatrix, normalizingWeights);
643 renormalizedBasisMatrix = normalizingWeights.asDiagonal() * basisMatrix;
644 MatrixOnline = renormalizedBasisMatrix * pinvPU;
645 P.makeCompressed();
646 cnpy::save(basisMatrix, folderMethod + "/basisMatrix.npy");
647 cnpy::save(P, folderMethod + "/projectionMatrix.npz");
648 cnpy::save(normalizingWeights, folderMethod + "/normalizingWeights.npy");
649 cnpy::save(nodes, folderMethod + "/mp.npy");
650 cnpy::save(pinvPU, folderMethod + "/pinvPU.npy");
651 cnpy::save(MatrixOnline, folderMethod + "/MatrixOnline.npy");
652 nodePoints().write();
653 Info << "Projection Matrix shape: " << P.rows() << " " << P.cols() << endl;
654 Info << "Basis Matrix shape: " << basisMatrix.rows() << " " <<
655 basisMatrix.cols() << endl;
656 Info << "Pseudo Inverse Matrix shape: " << pinvPU.rows() << " " << pinvPU.cols()
657 << endl;
658 }
659 else
660 {
661 Info << "Read GappyDEIM\n";
662 cnpy::load(basisMatrix, folderMethod + "/basisMatrix.npy");
663 cnpy::load(MatrixOnline, folderMethod + "/MatrixOnline.npy");
664 cnpy::load(normalizingWeights, folderMethod + "/normalizingWeights.npy");
665 cnpy::load(P, folderMethod + "/projectionMatrix.npz");
666 cnpy::load(nodes, folderMethod + "/mp.npy");
667 cnpy::load(pinvPU, folderMethod + "/pinvPU.npy");
668 renormalizedBasisMatrix = normalizingWeights.asDiagonal() * basisMatrix;
669 Info << "Projection Matrix shape: " << P.rows() << " " << P.cols() << endl;
670 Info << "Basis Matrix shape: " << basisMatrix.rows() << " " <<
671 basisMatrix.cols() << endl;
672 Info << "Pseudo Inverse Matrix shape: " << pinvPU.rows() << " " << pinvPU.cols()
673 << endl;
674 }
675}
676
677template <typename... SnapshotsLists>
679 snapshotsModes, Eigen::VectorXd& weights, word folderMethodName)
680{
681 folderMethod = folderMethodName;
682 Info << "FolderMethod : " << folderMethod << endl;
683 mkDir(folderMethod);
684 n_nodes = n_modes + 1;
685 normalizingWeights = weights;
686 Info << "####### Begin ECP #######" << endl;
687 Info << "####### Modes=" << n_modes
688 << ", nodePoints=" << n_nodes << " #######"
689 << endl;
690 nodePoints = autoPtr<IOList<label >> (new IOList<label>(
691 IOobject("nodePoints", para->runTime.time().constant(), "../" + folderMethod,
692 para->mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE)));
693 bool offlineStage = !nodePoints().headerOk();
694
695 if (offlineStage)
696 {
697 assert(n_modes > 0);
698 assert(n_nodes >= n_modes);
699 // matrices for quadratureWeights evaluation
700 Eigen::MatrixXd J;//shape: (vectorial_dim * (n_modes + 1), nodePoints->size())
701 Eigen::MatrixXd Jwhole(vectorial_dim * (n_modes + 1), n_cells);
702 Eigen::VectorXd q(vectorial_dim * (n_modes + 1));
703 // matrices for greedy selection of the nodes
704 Eigen::MatrixXd A(vectorial_dim * n_modes, n_cells);
705 Eigen::VectorXd b = Eigen::VectorXd::Constant(vectorial_dim * n_modes, 1);
706 Eigen::VectorXd volumes = ITHACAutilities::getMassMatrixFV(std::get<0>
707 (snapshotsListTuple)[0]);
708 double volume = volumes.array().sum();
709
710 for (unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
711 {
712 Eigen::MatrixXd block = snapshotsModes.block(ith_field * n_cells, 0, n_cells,
713 n_modes).transpose();
714 q.segment(ith_field * (n_modes + 1), n_modes) = block.rowwise().sum();
715 q(ith_field * (n_modes + 1) + n_modes) = volume;
716 Jwhole.middleRows(ith_field * (n_modes + 1), n_modes) = block;
717 Jwhole.row(ith_field * (n_modes + 1) + n_modes) = Eigen::VectorXd::Constant(
718 n_cells, 1);
719 Eigen::VectorXd mean = block.rowwise().mean();
720 block.colwise() -= mean;
721 Eigen::VectorXd Anorm = block.colwise().lpNorm<2>();
722
723 if (Anorm.minCoeff() > 0)
724 {
725 block.array().rowwise() /= Anorm.transpose().array();
726 }
727
728 A.middleRows(ith_field * n_modes, n_modes) = block;
729 }
730
731 Eigen::VectorXd mp_not_mask = Eigen::VectorXd::Constant(n_cells * vectorial_dim,
732 1);
733 std::set<label> nodePointsSet;
734
735 // set initialSeeds
736 if (initialSeeds.rows() > 0)
737 {
738 initialSeeds(mp_not_mask, nodePointsSet);
739 computeLS(J, Jwhole, b, q);
740 }
741
742 int na = n_nodes - initialSeeds.rows();
743 Eigen::SparseMatrix<double> reshapeMat;
744 initReshapeMat(reshapeMat);
745
746 if (na > 0)
747 {
748 label ind_max, r1;
749 double max;
750
751 for (unsigned int ith_node = 0; ith_node < na; ith_node++)
752 {
753 max = ((b.transpose() * A * mp_not_mask.head(
754 n_cells).asDiagonal()).colwise().sum()).maxCoeff(& r1, & ind_max);
755 updateNodes(P, ind_max, mp_not_mask);
756 computeLS(J, Jwhole, b, q);
757 }
758 }
759
760 Info << "####### End ECP #######" << endl;
761 basisMatrix = snapshotsModes.leftCols(n_modes);
763 cnpy::save(basisMatrix, folderMethod + "/basisMatrix.npy");
764 cnpy::save(quadratureWeights, folderMethod + "/quadratureWeights.npy");
765 cnpy::save(normalizingWeights, folderMethod + "/normalizingWeights.npy");
766 cnpy::save(nodes, folderMethod + "/mp.npy");
767 cnpy::save(wPU, folderMethod + "/wPU.npy");
768 nodePoints().write();
769 }
770 else
771 {
772 Info << "Read ECP\n";
773 cnpy::load(basisMatrix, folderMethod + "/basisMatrix.npy");
774 cnpy::load(quadratureWeights, folderMethod + "/quadratureWeights.npy");
775 cnpy::load(normalizingWeights, folderMethod + "/normalizingWeights.npy");
776 cnpy::load(nodes, folderMethod + "/mp.npy");
777 cnpy::load(wPU, folderMethod + "/wPU.npy");
778 }
779}
780
781template<typename... SnapshotsLists>
782void HyperReduction<SnapshotsLists...>::initSeeds(Eigen::VectorXd mp_not_mask,
783 std::set<label> nodePointsSet)
784{
786 P.reserve(Eigen::VectorXi::Constant(initialSeeds.rows() *
787 vectorial_dim /*n_cols*/, 1 /*n_non_zero_elements*/));
788 unsigned int trueSeeds{0};
789
790 for (int i = 0; i < initialSeeds.rows(); i++)
791 {
792 unsigned int index = initialSeeds(i) % n_cells;
793
794 // check that there are not repeated nodes in initialSeeds
795 if (nodePointsSet.find(index) == nodePointsSet.end())
796 {
797 nodePointsSet.insert(index);
798 nodePoints->append(index);
799
800 for (unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
801 {
802 P.insert(index + ith_field * n_cells,
803 vectorial_dim * trueSeeds + ith_field) = 1;
804 mp_not_mask(index + ith_field * n_cells) = 0;
805 }
806
807 trueSeeds++;
808 }
809 }
810
811 P.conservativeResize(P.rows(), nodePoints->size() * vectorial_dim);
812 P.makeCompressed();
813 M_Assert(nodePoints->size() <= n_nodes,
814 "Size of 'initialSeeds' is greater than 'n_nodes'");
815}
816
817template <typename... SnapshotsLists>
819 & P, label& ind, Eigen::VectorXd& mp_not_mask)
820{
821 nodePoints->append(ind);
822 nodes.conservativeResize(nodes.rows() + 1);
823 nodes(nodes.rows() - 1) = ind;
824 unsigned int last_col{0};
825
826 if (P.rows() == 0)
827 {
829 }
830 else
831 {
832 last_col = P.cols();
833 P.resize(P.rows(), P.cols() + vectorial_dim);
834 }
835
836 int step = P.cols() / vectorial_dim - 1;
837
838 for (int ith_node = 0; ith_node <= step; ith_node++)
839 {
840 for (unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
841 {
842 P.insert(nodes[ith_node] + ith_field * n_cells,
843 ith_node + ith_field * (step + 1)) = 1;
844 }
845 }
846
847 for (unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
848 {
849 mp_not_mask(ind + ith_field * n_cells) = 0;
850 }
851}
852
853template<typename... SnapshotsLists>
855 Eigen::MatrixXd& Jwhole, Eigen::VectorXd& b, Eigen::VectorXd& q)
856{
857 // TODO fix with only positive weights (NNLS)
858 J.resize(vectorial_dim * (n_modes + 1), nodePoints->size());
859 J = Jwhole(Eigen::indexing::all, nodes);
861
862 for (unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
863 {
864 quadratureWeights.segment(ith_field * nodePoints->size(),
865 nodePoints->size()) = J.middleRows(ith_field * (n_modes + 1),
866 n_modes + 1).colPivHouseholderQr().solve(q.segment(ith_field * (n_modes + 1),
867 n_modes + 1));
868 b.segment(ith_field * n_modes, n_modes) = q.segment(ith_field * (n_modes + 1),
869 n_modes) - J.middleRows(ith_field * (n_modes + 1),
870 n_modes) * quadratureWeights.segment(ith_field * nodePoints->size(),
871 nodePoints->size());
872 }
873
874 b = b / b.lpNorm<2>();
875}
876
877template<typename... SnapshotsLists>
879 Eigen::SparseMatrix<double>& reshapeMat)
880{
881 reshapeMat.resize(n_cells, n_cells * vectorial_dim);
882 reshapeMat.reserve(Eigen::VectorXi::Constant(n_cells * vectorial_dim /*n_cols*/,
883 1 /*n_non_zero_elements*/));
884
885 for (unsigned int i = 0; i < n_cells; i++)
886 {
887 for (unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
888 {
889 reshapeMat.insert(i, i + n_cells * ith_field) = 1;
890 }
891 }
892
893 reshapeMat.makeCompressed();
894}
895
896template <typename... SnapshotsLists>
897template <typename SnapshotsList>
899 Eigen::MatrixXd& snapshotsMatrix, Eigen::VectorXd& fieldWeights)
900{
901 unsigned int field_dim = get_field_dim<typename SnapshotsList::value_type>();
902 Eigen::MatrixXd tmpSnapshots = Foam2Eigen::PtrList2Eigen(sList);
903 // get volumes
904 Eigen::VectorXd V = ITHACAutilities::getMassMatrixFV(sList[0]);
905 double maxVal = std::sqrt(tmpSnapshots.colwise().lpNorm<2>().maxCoeff());
906 fieldWeights.conservativeResize(fieldWeights.rows() + field_dim * n_cells);
907 fieldWeights.tail(n_cells * field_dim) = V.array().sqrt().cwiseInverse() *
908 maxVal;
909 snapshotsMatrix.conservativeResize(snapshotsMatrix.rows() + n_cells * field_dim,
911 snapshotsMatrix.bottomRows(n_cells * field_dim) = tmpSnapshots;
912}
913
914template <typename... SnapshotsLists>
915template <typename SnapshotsList>
917 SnapshotsList sList, List<Eigen::MatrixXd>& snapshotsMatrixBoundary,
918 List<Eigen::VectorXd>& fieldWeightsBoundary)
919{
920 unsigned int field_dim = get_field_dim<typename SnapshotsList::value_type>();
921 List<Eigen::MatrixXd> tmpBoundarySnapshots = Foam2Eigen::PtrList2EigenBC(sList);
922 List<double> maxVal;
923 maxVal.resize(n_boundary_patches);
924
925 for (label id = 0; id < n_boundary_patches; id++)
926 {
927 maxVal[id] = std::sqrt(
928 tmpBoundarySnapshots[id].colwise().lpNorm<2>().maxCoeff());
929 // get surface areas
930 Eigen::VectorXd S = Foam2Eigen::field2Eigen(
931 sList[0].mesh().magSf().boundaryField()[id]);
932 S = S.replicate(field_dim, 1);
933 unsigned int bSize = field_dim * int(n_boundary_cells_list[id]);
934 fieldWeightsBoundary[id].conservativeResize(fieldWeightsBoundary[id].rows() +
935 bSize);
936 fieldWeightsBoundary[id].tail(bSize) = S.array().pow(3 / 4) * maxVal[id];
937 snapshotsMatrixBoundary[id].conservativeResize(
938 snapshotsMatrixBoundary[id].rows() + bSize, n_snapshots);
939 snapshotsMatrixBoundary[id].bottomRows(bSize) = tmpBoundarySnapshots[id];
940 }
941}
942
943template<typename... SnapshotsLists>
945 & Projector, Eigen::MatrixXd& Modes, Eigen::VectorXd& fieldWeights)
946{
947 assert(Projector.cols() > 0);
948 Eigen::MatrixXd restricted = Projector.transpose() * Modes;
949 Info << "S-Optimalty: " << s_optimality(restricted) << endl;
951 para->ITHACAdict->lookupOrDefault<word>("InversionMethod",
952 "completeOrthogonalDecomposition"));
953 pinvPU = pinvPU * (Projector.transpose() *
954 fieldWeights.array().cwiseInverse().matrix()).asDiagonal();
955}
956
957template<typename... SnapshotsLists>
959 & Projector, Eigen::MatrixXd& Modes, Eigen::VectorXd& fieldWeights,
960 Eigen::VectorXd& quadratureWeights)
961{
962 assert(Projector.cols() > 0);
963 Eigen::VectorXd quadratureWeightsOrderedAsProjector(quadratureWeights.rows());
964 unsigned int n_weightsPerField = quadratureWeights.rows() / vectorial_dim;
965 unsigned int reorderIndex{0};
966
967 for (unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
968 {
969 for (unsigned int ith_weight = 0; ith_weight < n_weightsPerField; ith_weight++)
970 {
971 quadratureWeightsOrderedAsProjector(reorderIndex) = quadratureWeights(
972 ith_weight + ith_field * n_weightsPerField);
973 reorderIndex++;
974 }
975 }
976
977 wPU = quadratureWeightsOrderedAsProjector.transpose() *
978 (Projector.transpose() *
979 fieldWeights.array().cwiseInverse().matrix()).asDiagonal();
980}
981
982template<typename... SnapshotsLists>
984 const fvMesh& mesh)
985{
986 Info << "####### Extract submesh #######\n";
988 totalNodePoints = autoPtr<IOList<labelList >> (new IOList<labelList>(IOobject(
989 "totalNodePoints", para->runTime.time().constant(), "../" + folderMethod,
990 para->mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE)));
991 uniqueNodePoints = autoPtr<IOList<label >> (new IOList<label>(IOobject(
992 "uniqueNodePoints", para->runTime.time().constant(), "../" + folderMethod,
993 para->mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE)));
994 volScalarField Indici
995 (
996 IOobject
997 (
998 problemName + "_indices",
999 mesh.time().timeName(),
1000 mesh,
1001 IOobject::NO_READ,
1002 IOobject::NO_WRITE
1003 ),
1004 mesh,
1005 dimensionedScalar(problemName + "_indices",
1006 dimensionSet(0, 0, 0, 0, 0, 0, 0), 0.0));
1007 submesh = autoPtr<fvMeshSubset>(new fvMeshSubset(mesh));
1008 bool offlineStage = !totalNodePoints().headerOk();
1009
1010 if (offlineStage)
1011 {
1012 List<label> indices;
1013
1014 for (label i = 0; i < nodePoints().size(); i++)
1015 {
1016 indices = ITHACAutilities::getIndices(mesh, nodePoints()[i], layers);
1017 totalNodePoints().append(indices);
1018 }
1019
1020 labelList a = ListListOps::combine<labelList>(totalNodePoints(),
1021 accessOp<labelList>());
1022 inplaceUniqueSort(a);
1023 uniqueNodePoints() = a;
1024 scalar zerodot25 = 0.25;
1025 ITHACAutilities::assignIF(Indici, zerodot25,
1026 uniqueNodePoints().List<label>::clone()());
1028 totalNodePoints().write();
1029 uniqueNodePoints().write();
1031 }
1032 submesh->setCellSubset(uniqueNodePoints());
1033 submesh->subMesh().fvSchemes::readOpt() = mesh.fvSchemes::readOpt();
1034 submesh->subMesh().fvSolution::readOpt() = mesh.fvSolution::readOpt();
1035 submesh->subMesh().fvSchemes::read();
1036 submesh->subMesh().fvSolution::read();
1037 std::cout.clear();
1039 n_cellsSubfields = submesh().cellMap().size();
1040 Info << "####### End extract submesh size = " << n_cellsSubfields <<
1041 " #######\n";
1042 createMasks(offlineStage);
1043 Info << "####### End create masks #######\n";
1044}
1045
1046template<typename... SnapshotsLists>
1048{
1049 if (offlineStage)
1050 {
1051 field2submesh.resize(submesh().cellMap().size() * vectorial_dim,
1053 field2submesh.reserve(Eigen::VectorXi::Constant(n_cells * vectorial_dim, 1));
1054
1055 for (unsigned int ith_subCell{0} ; ith_subCell < submesh().cellMap().size();
1056 ith_subCell++)
1057 {
1058 for (unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
1059 {
1060 field2submesh.insert(ith_subCell + ith_field * submesh().cellMap().size(),
1061 submesh().cellMap()[ith_subCell] + n_cells * ith_field) = 1;
1062 }
1063 }
1064
1065 field2submesh.makeCompressed();
1066 submesh2nodes.resize(nodePoints().size() * vectorial_dim,
1067 submesh().cellMap().size() * vectorial_dim);
1068 submesh2nodes.reserve(Eigen::VectorXi::Constant(submesh().cellMap().size() *
1069 vectorial_dim, 1));
1070 submesh2nodesMask.resize(nodePoints().size() * vectorial_dim);
1071 int index_col = 0;
1072
1073 for (unsigned int ith_node{0} ; ith_node < nodePoints().size(); ith_node++)
1074 {
1075 for (unsigned int ith_subCell{0} ; ith_subCell < submesh().cellMap().size();
1076 ith_subCell++)
1077 {
1078 if (nodePoints()[ith_node] == submesh().cellMap()[ith_subCell])
1079 {
1080 for (unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
1081 {
1082 submesh2nodes.insert(ith_node + nodePoints().size() * ith_field,
1083 index_col + ith_field * submesh().cellMap().size()) = 1;
1084 submesh2nodesMask(ith_node + nodePoints().size() * ith_field) = index_col +
1085 ith_field * submesh().cellMap().size();
1086 }
1087
1088 break;
1089 }
1090 else
1091 {
1092 index_col++;
1093 }
1094 }
1095
1096 index_col = 0;
1097 }
1098
1099 submesh2nodes.makeCompressed();
1100 cnpy::save(field2submesh, folderMethod + "/field2submesh.npz");
1101 cnpy::save(submesh2nodes, folderMethod + "/submesh2nodes.npz");
1102 cnpy::save(submesh2nodesMask, folderMethod + "/submesh2nodesMask.npy");
1103 }
1104 else
1105 {
1106 cnpy::load(field2submesh, folderMethod + "/field2submesh.npz");
1107 cnpy::load(submesh2nodes, folderMethod + "/submesh2nodes.npz");
1108 cnpy::load(submesh2nodesMask, folderMethod + "/submesh2nodesMask.npy");
1109 }
1110}
1111
1112template<typename... SnapshotsLists>
1114 List<label>& points, fvMeshSubset& submesh)
1115{
1116 List<label> localPoints;
1117
1118 for (label i = 0; i < points.size(); i++)
1119 {
1120 for (label j = 0; j < submesh.cellMap().size(); j++)
1121 {
1122 if (submesh.cellMap()[j] == points[i])
1123 {
1124 localPoints.append(j);
1125 break;
1126 }
1127 }
1128 }
1129
1130 return localPoints;
1131}
1132
1133#endif
Foam::fvMesh & mesh
Definition createMesh.H:47
#define M_Assert(Expr, Msg)
ITHACAparameters * para
Definition NLsolve.H:40
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:514
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:270
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:646
Eigen::VectorXi submesh2nodesMask
void stackSnapshotsBoundary(SnapshotsList sList, List< Eigen::MatrixXd > &snapshotsMatrixBoundary, List< Eigen::VectorXd > &fieldWeightsBoundary)
SnapshotsListTuple snapshotsListTuple
The snapshots matrix containing the nonlinear function or operator.
label n_modes
The maximum number of modes to be considered.
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.
label n_nodes
The maximum number of modes to be considered.
word folderMethod
Folder for the selected HR method.
void stackNames(SnapshotsList sList)
TODO.
void generateSubmesh(label layers, const fvMesh &mesh)
Compute the submesh common to all fields in SnapshotsLists.
Eigen::VectorXi nodes
autoPtr< fvMeshSubset > submesh
Submesh of the HyperReduction method.
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.
Eigen::VectorXd quadratureWeights
Quadrature weights. Ordered in the same order of matrix P.
autoPtr< IOList< labelList > > totalNodePoints
List of label lists of the nodes and corresponding surrounding nodes.
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.
Eigen::SparseMatrix< double > submesh2nodes
void stackDimensions(SnapshotsList sList)
TODO.
constexpr unsigned int compute_vectorial_dim(LastList x)
TODO.
void getSnapMatrix(Eigen::MatrixXd &snapMatrix, Eigen::VectorXd &fieldWeights)
TODO.
Eigen::VectorXi initialSeeds
Eigen::MatrixXd pinvPU
List< label > localNodePoints
Indices of the local node points in the subMesh.
Eigen::VectorXd normalizingWeights
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
Eigen::VectorXd eigenValueseig
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.
autoPtr< IOList< label > > nodePoints
Nodes in the case of the a nonlinear function.
static double s_optimality(Eigen::MatrixXd &A)
TODO.
void getModesSVD(SnapshotsListTuple &SnapshotsListTuple, Eigen::MatrixXd &modesSVD, Eigen::VectorXd &fieldWeights, bool saveModesFlag=false)
TODO.
label n_snapshots
The length of the snapshots lists.
autoPtr< IOList< label > > uniqueNodePoints
List of the unique indices of the nodes that define the submesh.
Eigen::SparseMatrix< double > field2submesh
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.
label n_cellsSubfields
Int Number of Cells in submeshes;.
void createMasks(bool offlineStage=true)
TODO.
void computeLS(Eigen::MatrixXd &J, Eigen::MatrixXd &JWhole, Eigen::VectorXd &b, Eigen::VectorXd &q)
TODO.
Eigen::MatrixXd wPU
Class for the definition of some general parameters, the parameters must be defined from the file ITH...
static ITHACAparameters * getInstance(fvMesh &mesh, Time &localTime)
Gets an instance of ITHACAparameters, to be used if the instance is not existing.
static ITHACAparameters * getInstance()
Gets an instance of ITHACAparameters, to be used if the instance is already existing.
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)
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))