31#ifndef hyperReduction_templates_H
32#define hyperReduction_templates_H
39template <
typename... SnapshotsLists>
42 Eigen::VectorXi initialSeeds,
44 SnapshotsLists &&...snapshotsLists)
45 : vectorial_dim{compute_vectorial_dim(snapshotsLists...)},
48 initialSeeds{initialSeeds},
49 problemName{problemName},
50 snapshotsListTuple{std::forward_as_tuple(snapshotsLists...)}
52 Info <<
"Init HyperReduction class with vectorial dim: " <<
vectorial_dim << endl;
72 Info <<
"Fields names: ";
73 for (
unsigned int ith_field = 0; ith_field <
fieldNames.size(); ith_field++)
80 Info <<
"The number of snapshots is: " <<
n_snapshots << endl;
82 Info <<
"The number of cells is: " <<
n_cells << endl;
83 Info <<
"Initial seeds length: " <<
initialSeeds.rows() << endl;
90 for (
unsigned int ith_boundary_patch = 0; ith_boundary_patch <
n_boundary_patches; ith_boundary_patch++)
100template <
typename... SnapshotsLists>
103 unsigned int vectorialDim,
105 Eigen::VectorXi initialSeeds,
109 vectorial_dim{vectorialDim},
111 initialSeeds{initialSeeds},
112 problemName{problemName}
114 Info <<
"Init HyperReduction class with vectorial dim: " <<
vectorial_dim << endl;
119 Info <<
"Initial seeds length: " <<
initialSeeds.rows() << endl;
123template <
typename... SnapshotsLists>
125 SnapshotsListTuple& snapshotsListTuple, Eigen::MatrixXd& modesSVD, Eigen::VectorXd& fieldWeights,
bool saveModesFlag)
129 word folderSVD =
"ITHACAoutput/" + problemName +
"/ModesSVD/";
134 Eigen::MatrixXd snapMatrix;
135 getSnapMatrix(snapMatrix, fieldWeights);
137 word dimensionReductionMethod = para->
ITHACAdict->lookupOrDefault<word>(
"DimensionReductionMethod",
"SVD");
139 Eigen::MatrixXd eigenVectoreig;
141 if (dimensionReductionMethod ==
"RSVD")
143 Info <<
"####### Performing RSVD for " << problemName <<
" #######" << endl;
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);
148 Info <<
"####### End of RSVD for " << problemName <<
" #######" <<
151 eigenValueseig =
svd.singularValues().real();
152 eigenVectoreig =
svd.matrixU().real();
156 Info <<
"####### Performing SVD for " << problemName <<
" #######" << endl;
158 Eigen::JacobiSVD<Eigen::MatrixXd>
svd(fieldWeights.array().cwiseInverse().matrix().asDiagonal()*snapMatrix, Eigen::ComputeThinU | Eigen::ComputeThinV);
160 Info <<
"####### End of SVD for " << problemName <<
" #######" <<
163 eigenValueseig =
svd.singularValues().real();
164 eigenVectoreig =
svd.matrixU().real();
167 modesSVD = eigenVectoreig;
171 cnpy::save(eigenValueseig,
"ITHACAoutput/" + problemName +
"/ModesSVD/eigenvalues.npy");
173 eigenValueseig = eigenValueseig / eigenValueseig.sum();
174 Eigen::VectorXd cumEigenValues(eigenValueseig);
176 for (label j = 1; j < cumEigenValues.size(); ++j)
178 cumEigenValues(j) += cumEigenValues(j - 1);
182 "ITHACAoutput/" + problemName +
"/ModesSVD/Eigenvalues_" + problemName, para->
precision,
185 "ITHACAoutput/" + problemName +
"/ModesSVD/CumEigenvalues_" + problemName, para->
precision,
187 cnpy::save(modesSVD,
"ITHACAoutput/" + problemName +
"/ModesSVD/modes.npy");
188 cnpy::save(fieldWeights,
"ITHACAoutput/" + problemName +
"/ModesSVD/normalizingWeights.npy");
193 unsigned int rowIndex{0};
194 for (
unsigned int modeIndex = 0; modeIndex < modesSVD.cols(); modeIndex++)
196 std::apply([
this, &modesSVD, &rowIndex, &modeIndex, &folderSVD](
auto& ...snapList){(..., saveModes(snapList, modesSVD, rowIndex, modeIndex, folderSVD));}, snapshotsListTuple);
203 Info <<
"Reading the existing modes" << endl;
204 cnpy::load(modesSVD, folderSVD +
"/modes.npy");
205 cnpy::load(fieldWeights, folderSVD +
"/normalizingWeights.npy");
209template <
typename... SnapshotsLists>
211 SnapshotsListTuple& snapshotsListTuple, Eigen::MatrixXd& modesSVD, Eigen::VectorXd& fieldWeights, Eigen::MatrixXd& modesSVDBoundary, Eigen::VectorXd& fieldWeightsBoundary,
bool saveModesFlag)
215 word folderSVD =
"ITHACAoutput/" + problemName +
"/ModesSVD/";
220 Eigen::MatrixXd snapMatrix;
221 List<Eigen::MatrixXd> snapMatrixBoundary;
222 List<Eigen::VectorXd> fieldWeightsBoundaryList;
223 getSnapMatrix(snapMatrix, fieldWeights, snapMatrixBoundary, fieldWeightsBoundaryList);
225 for (
unsigned int id = 0;
id < n_boundary_patches;
id++)
227 snapMatrix.conservativeResize(snapMatrix.rows()+snapMatrixBoundary[
id].rows(), snapMatrix.cols());
228 snapMatrix.bottomRows(snapMatrixBoundary[
id].rows()) = snapMatrixBoundary[id];
230 fieldWeightsBoundary.conservativeResize(fieldWeightsBoundary.rows()+snapMatrixBoundary[
id].rows());
231 fieldWeightsBoundary.tail(fieldWeightsBoundaryList[
id].rows()) = fieldWeightsBoundaryList[id];
234 cnpy::save(fieldWeights,
"ITHACAoutput/" + problemName +
"/ModesSVD/normalizingWeights.npy");
235 cnpy::save(fieldWeightsBoundary,
"ITHACAoutput/" + problemName +
"/ModesSVD/normalizingWeightsBoundary.npy");
237 fieldWeights.conservativeResize(fieldWeights.rows()+fieldWeightsBoundary.rows());
238 fieldWeights.tail(fieldWeightsBoundary.rows()) = fieldWeightsBoundary;
240 word dimensionReductionMethod = para->ITHACAdict->lookupOrDefault<word>(
"DimensionReductionMethod",
"SVD");
242 Eigen::MatrixXd eigenVectoreig;
244 if (dimensionReductionMethod ==
"RSVD")
246 Info <<
"####### Performing RSVD for " << problemName <<
" #######" << endl;
248 unsigned int r_modeSVD = para->ITHACAdict->lookupOrDefault<
unsigned int>(
"RSVDdim", snapMatrix.cols());
250 RedSVD::RedSVD
svd(fieldWeights.array().cwiseInverse().matrix().asDiagonal()*snapMatrix, r_modeSVD);
252 Info <<
"####### End of RSVD for " << problemName <<
" #######" << endl;
254 eigenValueseig =
svd.singularValues().real();
255 eigenVectoreig =
svd.matrixU().real();
259 Info <<
"####### Performing SVD for " << problemName <<
" #######" << endl;
261 Eigen::JacobiSVD<Eigen::MatrixXd>
svd(fieldWeights.array().cwiseInverse().matrix().asDiagonal()*snapMatrix, Eigen::ComputeThinU | Eigen::ComputeThinV);
263 Info <<
"####### End of SVD for " << problemName <<
" #######" <<
266 eigenValueseig =
svd.singularValues().real();
267 eigenVectoreig =
svd.matrixU().real();
270 modesSVD = eigenVectoreig.bottomRows(vectorial_dim*n_cells);
271 modesSVDBoundary = eigenVectoreig.topRows(n_boundary_cells);
272 fieldWeights.conservativeResize(fieldWeights.rows()-fieldWeightsBoundary.rows());
274 cnpy::save(eigenValueseig,
"ITHACAoutput/" + problemName +
"/ModesSVD/eigenvalues.npy");
276 eigenValueseig = eigenValueseig / eigenValueseig.sum();
277 Eigen::VectorXd cumEigenValues(eigenValueseig);
279 for (label j = 1; j < cumEigenValues.size(); ++j)
281 cumEigenValues(j) += cumEigenValues(j - 1);
285 "ITHACAoutput/" + problemName +
"/ModesSVD/Eigenvalues_" + problemName, para->precision,
288 "ITHACAoutput/" + problemName +
"/ModesSVD/CumEigenvalues_" + problemName, para->precision,
290 cnpy::save(modesSVD,
"ITHACAoutput/" + problemName +
"/ModesSVD/modes.npy");
291 cnpy::save(modesSVDBoundary,
"ITHACAoutput/" + problemName +
"/ModesSVD/modesBoundary.npy");
295 unsigned int rowIndex{0};
296 unsigned int rowIndexBoundary{0};
297 for (
unsigned int modeIndex = 0; modeIndex < modesSVD.cols(); modeIndex++)
299 std::apply([
this, &modesSVD, &modesSVDBoundary, &rowIndex, &modeIndex, &rowIndexBoundary, &folderSVD](
auto& ...snapList){(..., saveModes(snapList, modesSVD, modesSVDBoundary, rowIndex, rowIndexBoundary, modeIndex, folderSVD));}, snapshotsListTuple);
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");
314template <
typename... SnapshotsLists>
317 std::apply([
this, &fieldWeights, &snapMatrix](
auto& ...snapList){(..., stackSnapshots(snapList, snapMatrix, fieldWeights));}, snapshotsListTuple);
320template <
typename... SnapshotsLists>
323 fieldWeightsBoundary.resize(n_boundary_patches);
324 snapMatrixBoundary.resize(n_boundary_patches);
326 std::apply([
this, &fieldWeights, &snapMatrix, &fieldWeightsBoundary, &snapMatrixBoundary](
auto& ...snapList){
327 (..., stackSnapshots(snapList, snapMatrix, fieldWeights));
328 (..., stackSnapshotsBoundary(snapList, snapMatrixBoundary, fieldWeightsBoundary));},
332template <
typename... SnapshotsLists>
333template <
typename SnapshotsList>
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);
341 rowIndex +=fieldSize;
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)
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();
353 Eigen::VectorXd fieldBlock = snapshotsMatrix.block(rowIndex, modeIndex, fieldSize, 1);
355 List<Eigen::VectorXd> fieldBlockBoundary;
356 fieldBlockBoundary.resize(n_boundary_patches);
357 for (
unsigned int id = 0;
id < n_boundary_patches;
id++)
359 unsigned int bfieldDim = field_dim*int(n_boundary_cells_list[
id]);
360 fieldBlockBoundary[id] = snapshotsMatrixBoundary.block(rowIndexBoundary, modeIndex, bfieldDim, 1);
361 rowIndexBoundary+=bfieldDim;
365 rowIndex +=fieldSize;
370template <
typename... SnapshotsLists>
373 folderMethod = folderMethodName;
374 Info <<
"FolderMethod : " << folderMethod << endl;
377 normalizingWeights = weights;
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)));
383 auto greedyMetric = para->ITHACAdict->lookupOrDefault<word>(
"GreedyMetric",
"L2");
385 bool offlineStage = !nodePoints().headerOk();
390 assert(n_nodes >= n_modes);
392 Eigen::VectorXd mp_not_mask = Eigen::VectorXd::Constant(n_cells * vectorial_dim, 1);
393 std::set<label> nodePointsSet;
396 if (initialSeeds.rows() > 0)
398 initSeeds(mp_not_mask, nodePointsSet);
401 int na = n_nodes - initialSeeds.rows();
404 Eigen::SparseMatrix<double> reshapeMat;
405 initReshapeMat(reshapeMat);
407 if (greedyMetric==
"L2")
409 Info <<
"####### Begin Greedy-L2 GappyDEIM #######" << endl;
410 Info <<
"####### Modes=" << n_modes
411 <<
", nodePoints=" << n_nodes <<
" #######"
415 int nit = std::min(n_modes, na);
416 int ncimin = std::floor(n_modes / nit);
417 int naimin = std::floor(na / n_modes);
425 for (
int i = 1;
i <= nit;
i++)
429 if (
i <= n_modes % nit)
435 if (
i <= na % n_modes)
445 V = snapshotsModes.leftCols(nci);
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);
460 for (
int j = 1; j <= nai; j++)
464 max = (reshapeMat*(mp_not_mask.asDiagonal() * V)
466 .lpNorm<2>().array().square().matrix())
467 .maxCoeff(&ind_max, &c1);
471 max = (reshapeMat*V.rowwise().lpNorm<2>().array().square().matrix()).maxCoeff(&ind_max, &c1);
474 updateNodes(P, ind_max, mp_not_mask);
478 basisMatrix = snapshotsModes.leftCols(nb);
480 Info <<
"####### End of greedy GappyDEIM #######\n";
482 else if (greedyMetric==
"SOPT")
484 Info <<
"####### Begin SOPT GappyDEIM #######" << endl;
485 Info <<
"####### Modes=" << n_modes
486 <<
", nodePoints=" << n_nodes <<
" #######"
491 Eigen::MatrixXd V = snapshotsModes.leftCols(n_modes);
493 for (
unsigned int ith_node = 0; ith_node < na; ith_node++)
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();
507 max = ((mp_not_mask.head(n_cells).asDiagonal()*num).array()/denom.array()).maxCoeff(&ind_max, &c1);
511 max = (reshapeMat*V.rowwise().lpNorm<2>().array().square().matrix()).maxCoeff(&ind_max, &c1);
514 updateNodes(P, ind_max, mp_not_mask);
517 Info <<
"####### End of SOPT GappyDEIM #######\n";
519 else if (greedyMetric==
"SOPTE")
521 Info <<
"####### Begin SOPT-exact GappyDEIM #######" << endl;
522 Info <<
"####### Modes=" << n_modes
523 <<
", nodePoints=" << n_nodes <<
" #######"
532 Eigen::MatrixXd V = snapshotsModes.col(0);
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);
537 for (
unsigned int ith_node = 1; ith_node < na; ith_node++)
539 if (ith_node<n_modes)
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);
548 max = (reshapeMat*r.rowwise().lpNorm<2>().array().square().matrix()).maxCoeff(&ind_max, &c1);
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());
557 Eigen::MatrixXd masked = mp_not_mask.asDiagonal()*snapshotsModes.leftCols(n_modes);
559 Eigen::VectorXd results(n_cells);
561 for (
unsigned int ith_cell = 0; ith_cell < n_cells; ith_cell++)
563 for (
unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
565 tmp.row(tmp.rows()-vectorial_dim+ith_field) = masked.row(ith_cell + ith_field*n_cells);
567 results(ith_cell) = s_optimality(tmp);
569 max = results.maxCoeff(&ind_max, &c1);
572 updateNodes(P, ind_max, mp_not_mask);
574 basisMatrix = snapshotsModes.leftCols(n_modes);
575 Info <<
"####### End of SOPTE GappyDEIM #######\n";
580 basisMatrix = snapshotsModes.leftCols(n_modes);
581 Info <<
"####### InitialSeeds equal to n_nodes #######\n";
584 evaluatePinv(P, basisMatrix, normalizingWeights);
585 renormalizedBasisMatrix = normalizingWeights.asDiagonal()*basisMatrix;
587 MatrixOnline = renormalizedBasisMatrix * pinvPU;
590 cnpy::save(basisMatrix, folderMethod +
"/basisMatrix.npy");
591 cnpy::save(P, folderMethod +
"/projectionMatrix.npz");
592 cnpy::save(normalizingWeights, folderMethod +
"/normalizingWeights.npy");
594 cnpy::save(pinvPU, folderMethod +
"/pinvPU.npy");
595 cnpy::save(MatrixOnline, folderMethod +
"/MatrixOnline.npy");
596 nodePoints().write();
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;
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");
610 cnpy::load(pinvPU, folderMethod +
"/pinvPU.npy");
612 renormalizedBasisMatrix = normalizingWeights.asDiagonal()*basisMatrix;
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;
620template <
typename... SnapshotsLists>
623 folderMethod = folderMethodName;
624 Info <<
"FolderMethod : " << folderMethod << endl;
627 n_nodes = n_modes + 1;
629 normalizingWeights = weights;
631 Info <<
"####### Begin ECP #######" << endl;
632 Info <<
"####### Modes=" << n_modes
633 <<
", nodePoints=" << n_nodes <<
" #######"
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)));
640 bool offlineStage = !nodePoints().headerOk();
645 assert(n_nodes >= n_modes);
649 Eigen::MatrixXd Jwhole(vectorial_dim * (n_modes + 1), n_cells);
650 Eigen::VectorXd q(vectorial_dim * (n_modes + 1));
653 Eigen::MatrixXd
A(vectorial_dim*n_modes, n_cells);
654 Eigen::VectorXd b = Eigen::VectorXd::Constant(vectorial_dim*n_modes, 1);
657 double volume = volumes.array().sum();
658 for (
unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
660 Eigen::MatrixXd block = snapshotsModes.block(ith_field*n_cells, 0, n_cells, n_modes).transpose();
662 q.segment(ith_field*(n_modes+1), n_modes) = block.rowwise().sum();
663 q(ith_field*(n_modes+1)+n_modes) = volume;
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);
668 Eigen::VectorXd mean = block.rowwise().mean();
669 block.colwise() -= mean;
670 Eigen::VectorXd Anorm = block.colwise().lpNorm<2>();
671 if (Anorm.minCoeff()> 0)
673 block.array().rowwise() /= Anorm.transpose().array();
676 A.middleRows(ith_field*n_modes, n_modes) = block;
678 Eigen::VectorXd mp_not_mask = Eigen::VectorXd::Constant(n_cells * vectorial_dim, 1);
679 std::set<label> nodePointsSet;
682 if (initialSeeds.rows() > 0)
684 initialSeeds(mp_not_mask, nodePointsSet);
685 computeLS(J, Jwhole, b, q);
688 int na = n_nodes - initialSeeds.rows();
689 Eigen::SparseMatrix<double> reshapeMat;
690 initReshapeMat(reshapeMat);
697 for (
unsigned int ith_node = 0; ith_node < na; ith_node++)
699 max = ((b.transpose()*
A*mp_not_mask.head(n_cells).asDiagonal()).colwise().sum()).maxCoeff(&r1, &ind_max);
701 updateNodes(P, ind_max, mp_not_mask);
702 computeLS(J, Jwhole, b, q);
706 Info <<
"####### End ECP #######" << endl;
708 basisMatrix = snapshotsModes.leftCols(n_modes);
709 evaluateWPU(P, basisMatrix, normalizingWeights, quadratureWeights);
711 cnpy::save(basisMatrix, folderMethod +
"/basisMatrix.npy");
712 cnpy::save(quadratureWeights, folderMethod +
"/quadratureWeights.npy");
713 cnpy::save(normalizingWeights, folderMethod +
"/normalizingWeights.npy");
716 nodePoints().write();
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");
729template<
typename... SnapshotsLists>
732 P.resize(n_cells * vectorial_dim, initialSeeds.rows() * vectorial_dim);
733 P.reserve(Eigen::VectorXi::Constant(initialSeeds.rows() * vectorial_dim , 1 ));
735 unsigned int trueSeeds{0};
736 for (
int i = 0;
i < initialSeeds.rows();
i++)
738 unsigned int index = initialSeeds(
i) % n_cells;
740 if (nodePointsSet.find(index) == nodePointsSet.end()){
741 nodePointsSet.insert(index);
742 nodePoints->append(index);
744 for (
unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
746 P.insert(index+ith_field*n_cells, vectorial_dim*trueSeeds+ith_field) = 1;
747 mp_not_mask(index + ith_field * n_cells) = 0;
753 P.conservativeResize(P.rows(), nodePoints->size()*vectorial_dim);
755 M_Assert(nodePoints->size()<=n_nodes,
"Size of 'initialSeeds' is greater than 'n_nodes'");
758template <
typename... SnapshotsLists>
761 nodePoints->append(ind);
763 nodes.conservativeResize(nodes.rows()+1);
764 nodes(nodes.rows()-1) = ind;
766 unsigned int last_col{0};
770 P.resize(n_cells*vectorial_dim, vectorial_dim);
775 P.resize(P.rows(), P.cols() + vectorial_dim);
777 int step = P.cols() / vectorial_dim - 1;
779 for (
int ith_node=0; ith_node <= step; ith_node++)
781 for (
unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
783 P.insert(nodes[ith_node]+ith_field*n_cells,ith_node+ith_field*(step+1))=1;
787 for (
unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
789 mp_not_mask(ind + ith_field * n_cells) = 0;
793template<
typename... SnapshotsLists>
797 J.resize(vectorial_dim * (n_modes + 1), nodePoints->size());
798 J = Jwhole(Eigen::indexing::all, nodes);
800 quadratureWeights.resize(nodePoints->size()*vectorial_dim);
801 for (
unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
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());
809template<
typename... SnapshotsLists>
812 reshapeMat.resize(n_cells, n_cells*vectorial_dim);
813 reshapeMat.reserve(Eigen::VectorXi::Constant(n_cells * vectorial_dim , 1 ));
815 for (
unsigned int i = 0;
i < n_cells;
i++)
817 for (
unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
819 reshapeMat.insert(
i,
i+n_cells*ith_field) = 1;
822 reshapeMat.makeCompressed();
825template <
typename... SnapshotsLists>
826template <
typename SnapshotsList>
829 unsigned int field_dim = get_field_dim<typename SnapshotsList::value_type>();
836 double maxVal = std::sqrt(tmpSnapshots.colwise().lpNorm<2>().maxCoeff());
838 fieldWeights.conservativeResize(fieldWeights.rows()+field_dim*n_cells);
839 fieldWeights.tail(n_cells * field_dim) = V.array().sqrt().cwiseInverse()*maxVal;
841 snapshotsMatrix.conservativeResize(snapshotsMatrix.rows() + n_cells * field_dim, n_snapshots);
842 snapshotsMatrix.bottomRows(n_cells * field_dim) = tmpSnapshots;
845template <
typename... SnapshotsLists>
846template <
typename SnapshotsList>
849 unsigned int field_dim = get_field_dim<typename SnapshotsList::value_type>();
854 maxVal.resize(n_boundary_patches);
856 for (label
id = 0;
id < n_boundary_patches;
id++)
858 maxVal[id] = std::sqrt(tmpBoundarySnapshots[
id].colwise().lpNorm<2>().maxCoeff());
862 S =
S.replicate(field_dim, 1);
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];
868 snapshotsMatrixBoundary[id].conservativeResize(snapshotsMatrixBoundary[
id].rows() + bSize, n_snapshots);
869 snapshotsMatrixBoundary[id].bottomRows(bSize) = tmpBoundarySnapshots[id];
873template<
typename... SnapshotsLists>
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();
882template<
typename... SnapshotsLists>
884 assert(Projector.cols() > 0);
886 Eigen::VectorXd quadratureWeightsOrderedAsProjector(quadratureWeights.rows());
887 unsigned int n_weightsPerField = quadratureWeights.rows()/vectorial_dim;
888 unsigned int reorderIndex{0};
890 for (
unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
892 for (
unsigned int ith_weight = 0; ith_weight < n_weightsPerField; ith_weight++)
894 quadratureWeightsOrderedAsProjector(reorderIndex) = quadratureWeights(ith_weight + ith_field * n_weightsPerField);
898 wPU = quadratureWeightsOrderedAsProjector.transpose()*(Projector.transpose() * fieldWeights.array().cwiseInverse().matrix()).asDiagonal();
901template<
typename... SnapshotsLists>
904 Info <<
"####### Extract submesh #######\n";
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)));
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)));
915 volScalarField Indici
919 problemName +
"_indices",
920 mesh.time().timeName(),
926 dimensionedScalar(problemName +
"_indices",
927 dimensionSet(0, 0, 0, 0, 0, 0, 0), 0.0));
929 submesh = autoPtr<fvMeshSubset>(
new fvMeshSubset(
mesh));
930 bool offlineStage = !totalNodePoints().headerOk();
934 for (label
i = 0;
i < nodePoints().size();
i++) {
936 totalNodePoints().append(indices);
939 labelList a = ListListOps::combine<labelList>(totalNodePoints(),
940 accessOp<labelList>());
942 inplaceUniqueSort(a);
943 uniqueNodePoints() = a;
945 scalar zerodot25 = 0.25;
947 uniqueNodePoints().List<label>::clone()());
950 totalNodePoints().write();
951 uniqueNodePoints().write();
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();
962 localNodePoints = global2local(nodePoints(), submesh());
964 n_cellsSubfields = submesh().cellMap().size();
965 Info <<
"####### End extract submesh size = " << n_cellsSubfields <<
" #######\n";
967 createMasks(offlineStage);
968 Info <<
"####### End create masks #######\n";
971template<
typename... SnapshotsLists>
976 field2submesh.resize(submesh().cellMap().size() * vectorial_dim, n_cells*vectorial_dim);
977 field2submesh.reserve(Eigen::VectorXi::Constant(n_cells*vectorial_dim, 1));
979 for (
unsigned int ith_subCell{0} ; ith_subCell <submesh().cellMap().size(); ith_subCell++)
981 for (
unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
983 field2submesh.insert(ith_subCell+ith_field*submesh().cellMap().size(), submesh().cellMap()[ith_subCell]+n_cells*ith_field) = 1;
986 field2submesh.makeCompressed();
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);
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++)
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();
1008 submesh2nodes.makeCompressed();
1010 cnpy::save(field2submesh, folderMethod +
"/field2submesh.npz");
1011 cnpy::save(submesh2nodes, folderMethod +
"/submesh2nodes.npz");
1012 cnpy::save(submesh2nodesMask, folderMethod +
"/submesh2nodesMask.npy");
1016 cnpy::load(field2submesh, folderMethod +
"/field2submesh.npz");
1017 cnpy::load(submesh2nodes, folderMethod +
"/submesh2nodes.npz");
1018 cnpy::load(submesh2nodesMask, folderMethod +
"/submesh2nodesMask.npy");
1022template<
typename... SnapshotsLists>
1024 List<label> localPoints;
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);
#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.
static Eigen::VectorXd field2Eigen(GeometricField< tensor, PatchField, GeoMesh > &field)
Convert a vector OpenFOAM field into an Eigen Vector.
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.
static Eigen::MatrixXd PtrList2Eigen(PtrList< GeometricField< Type, PatchField, GeoMesh > > &fields, label Nfields=-1)
Convert a PtrList of snapshots to Eigen matrix (only internal field)
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.
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.
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)
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))