677 Eigen::VectorXd& weights, word folderMethodName)
683 normalizingWeights = weights;
685 label n_subspaces = listSnapshotsModes.size();
686 List<label> n_subspaceModes(0);
687 label n_totalModes = 0;
688 for (
int ith_subspace = 0; ith_subspace < n_subspaces; ith_subspace++)
690 n_subspaceModes.append(listSnapshotsModes[ith_subspace].cols());
691 n_totalModes += listSnapshotsModes[ith_subspace].cols();
693 quadratureWeightsSubspaces.resize(n_subspaces);
695 Info <<
"####### Begin ECP #######" << endl;
696 Info <<
"####### Modes=" << n_subspaceModes
697 <<
", nodePoints=" <<
n_nodes <<
" #######"
699 nodePoints = autoPtr<IOList<label >> (
new IOList<label>(
700 IOobject(
"nodePoints", para->runTime.time().constant(),
"../" +
folderMethod,
701 para->mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE)));
707 bool normalizedArgmaxForCubaturePointsSelection = 1;
708 bool cellVolumesInCubatureWeights = 0;
709 bool predictVolume = 0;
712 assert(n_totalModes > 0);
717 List<Eigen::MatrixXd> Jwhole(n_subspaces);
718 List<Eigen::VectorXd> q(n_subspaces);
720 Eigen::MatrixXd A(vectorial_dim * n_totalModes,
n_cells);
721 Eigen::VectorXd b = Eigen::VectorXd::Constant(vectorial_dim * n_totalModes, 1);
722 Eigen::VectorXd cellVolumes =
volumes;
723 double volume = cellVolumes.array().sum();
724 label n_modesPrevious = 0;
726 for (
int ith_subspace = 0; ith_subspace < n_subspaces; ith_subspace++)
728 label n_modesCurrent = n_subspaceModes[ith_subspace];
729 label n_modesCurrent_modif = n_modesCurrent + predictVolume;
730 q[ith_subspace] = Eigen::VectorXd::Zero(vectorial_dim * n_modesCurrent_modif);
731 Jwhole[ith_subspace] = Eigen::MatrixXd::Zero(vectorial_dim * n_modesCurrent_modif,
n_cells);
733 for (
unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
735 Eigen::MatrixXd block = listSnapshotsModes[ith_subspace](Eigen::seq(ith_field,
736 Eigen::indexing::last, vectorial_dim), Eigen::indexing::all).transpose();
740 Eigen::MatrixXd volumeAwareMean = (block.rowwise().sum()/volume) * cellVolumes.transpose();
741 block -= volumeAwareMean;
743 q[ith_subspace](ith_field * n_modesCurrent_modif + n_modesCurrent) = volume;
744 Jwhole[ith_subspace].row(ith_field * n_modesCurrent_modif + n_modesCurrent) = cellVolumes;
747 q[ith_subspace].segment(ith_field * n_modesCurrent_modif, n_modesCurrent) = block.rowwise().sum();
748 Jwhole[ith_subspace].middleRows(ith_field * n_modesCurrent_modif, n_modesCurrent) = block;
750 if (cellVolumesInCubatureWeights)
752 Jwhole[ith_subspace].middleRows(ith_field * n_modesCurrent_modif, n_modesCurrent_modif)
753 .array().rowwise() /= cellVolumes.transpose().array().sqrt();
756 if (normalizedArgmaxForCubaturePointsSelection)
758 Eigen::VectorXd mean = block.rowwise().mean();
759 block.colwise() -= mean;
760 Eigen::VectorXd Anorm = block.colwise().lpNorm<2>();
762 if (Anorm.minCoeff() > 0)
764 block.array().rowwise() /= Anorm.transpose().array();
767 A.middleRows(n_modesPrevious + ith_field* n_modesCurrent, n_modesCurrent) = block;
771 A.middleRows(n_modesPrevious + ith_field * n_modesCurrent, n_modesCurrent) =
772 Jwhole[ith_subspace].middleRows(ith_field * n_modesCurrent_modif, n_modesCurrent);
775 n_modesPrevious += vectorial_dim * n_modesCurrent;
778 Eigen::VectorXd mp_not_mask = Eigen::VectorXd::Constant(
n_cells * vectorial_dim,
780 std::set<label> nodePointsSet;
783 if (initialSeeds.rows() > 0)
787 for (
int ith_subspace = 0; ith_subspace < n_subspaces; ith_subspace++)
789 label n_modesCurrent = n_subspaceModes[ith_subspace];
790 label n_modesCurrent_modif = n_modesCurrent + predictVolume;
791 quadratureWeightsSubspaces[ith_subspace].resize(vectorial_dim *
nodePoints->size());
793 for (
unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
795 Eigen::VectorXd b_tmp(n_modesCurrent);
796 Eigen::MatrixXd J_partial = Jwhole[ith_subspace].middleRows(ith_field * n_modesCurrent_modif, n_modesCurrent_modif);
797 Eigen::VectorXd q_partial = q[ith_subspace].segment(ith_field * n_modesCurrent_modif, n_modesCurrent_modif);
798 computeLS(J, J_partial, b_tmp, q_partial, NNLS);
799 b.segment(n_modesPrevious,n_modesCurrent) = b_tmp;
800 quadratureWeightsSubspaces[ith_subspace].segment(ith_field *
nodePoints->size(),
802 n_modesPrevious += n_modesCurrent;
807 int na =
n_nodes - initialSeeds.rows();
808 Eigen::SparseMatrix<double> reshapeMat;
818 max = ((b.transpose() * A * mp_not_mask(Eigen::seq(0, Eigen::indexing::last, vectorial_dim))
819 .asDiagonal()).colwise().sum()).maxCoeff(& r1, & ind_max);
822 for (
int ith_subspace = 0; ith_subspace < n_subspaces; ith_subspace++)
824 label n_modesCurrent = n_subspaceModes[ith_subspace];
825 label n_modesCurrent_modif = n_modesCurrent + predictVolume;
826 quadratureWeightsSubspaces[ith_subspace].resize(vectorial_dim *
nodePoints->size());
828 for (
unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
830 Eigen::VectorXd b_tmp(n_modesCurrent);
831 Eigen::MatrixXd J_partial = Jwhole[ith_subspace].middleRows(ith_field * n_modesCurrent_modif, n_modesCurrent_modif);
832 Eigen::VectorXd q_partial = q[ith_subspace].segment(ith_field * n_modesCurrent_modif, n_modesCurrent_modif);
834 computeLS(J, J_partial, b_tmp, q_partial, NNLS);
835 b.segment(n_modesPrevious,n_modesCurrent) = b_tmp;
836 quadratureWeightsSubspaces[ith_subspace].segment(ith_field *
nodePoints->size(),
838 n_modesPrevious += n_modesCurrent;
843 Eigen::VectorXd maxQuadWeights = Eigen::VectorXd::Zero(
nodePoints->size());
844 for (
int ith_subspace = 0; ith_subspace < n_subspaces; ith_subspace++)
846 for (
unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
848 maxQuadWeights = maxQuadWeights.cwiseMax(quadratureWeightsSubspaces[ith_subspace]
857 if (cellVolumesInCubatureWeights)
861 for (
int ith_subspace = 0; ith_subspace < n_subspaces; ith_subspace++)
863 for (
unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
865 quadratureWeightsSubspaces[ith_subspace](ith_field *
nodePoints->size() + i) /=
872 Info <<
"####### End ECP #######" << endl;
873 if (n_subspaces == 1)
884 Eigen::MatrixXd quadratureWeightsMerged(
n_nodes, n_subspaces);
885 for (
int ith_subspace = 0; ith_subspace < n_subspaces; ith_subspace++)
888 quadratureWeightsSubspaces[ith_subspace], vectorial_dim);
889 cnpy::save(quadratureWeightsSubspaces[ith_subspace],
folderMethod +
"/quadratureWeights_subspace" +
890 std::to_string(ith_subspace+1) +
".npy");
891 quadratureWeightsMerged.col(ith_subspace) = quadratureWeightsSubspaces[ith_subspace];
893 cnpy::save(quadratureWeightsMerged,
folderMethod +
"/quadratureWeights.npy");
895 cnpy::save(normalizingWeights,
folderMethod +
"/normalizingWeights.npy");
903 Info <<
"Read ECP\n";
904 if (n_subspaces == 1)
912 for (
int ith_subspace = 0; ith_subspace < n_subspaces; ith_subspace++)
914 cnpy::load(quadratureWeightsSubspaces[ith_subspace],
folderMethod +
"/quadratureWeights_subspace" +
915 std::to_string(ith_subspace+1) +
".npy");
918 cnpy::load(normalizingWeights,
folderMethod +
"/normalizingWeights.npy");
1230 field2submesh.resize(
submesh().cellMap().size() * vectorial_dim,
1232 field2submesh.reserve(Eigen::VectorXi::Constant(
n_cells * vectorial_dim, 1));
1234 for (
int ith_subCell{0} ; ith_subCell <
submesh().cellMap().size();
1237 for (
unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
1239 field2submesh.insert(ith_subCell + ith_field *
submesh().cellMap().size(),
1244 field2submesh.makeCompressed();
1245 submesh2nodes.resize(
nodePoints().size() * vectorial_dim,
1246 submesh().cellMap().size() * vectorial_dim);
1247 submesh2nodes.reserve(Eigen::VectorXi::Constant(
submesh().cellMap().size() *
1249 submesh2nodesMask.resize(
nodePoints().size() * vectorial_dim);
1252 for (
int ith_node{0} ; ith_node <
nodePoints().size(); ith_node++)
1254 for (
int ith_subCell{0} ; ith_subCell <
submesh().cellMap().size();
1259 for (
unsigned int ith_field = 0; ith_field < vectorial_dim; ith_field++)
1261 submesh2nodes.insert(ith_node +
nodePoints().size() * ith_field,
1262 index_col + ith_field *
submesh().cellMap().size()) = 1;
1263 submesh2nodesMask(ith_node +
nodePoints().size() * ith_field) = index_col +
1264 ith_field *
submesh().cellMap().size();
1278 submesh2nodes.makeCompressed();
1279 cnpy::save(field2submesh,
folderMethod +
"/field2submesh.npz");
1280 cnpy::save(submesh2nodes,
folderMethod +
"/submesh2nodes.npz");
1281 cnpy::save(submesh2nodesMask,
folderMethod +
"/submesh2nodesMask.npy");
1285 cnpy::load(field2submesh,
folderMethod +
"/field2submesh.npz");
1286 cnpy::load(submesh2nodes,
folderMethod +
"/submesh2nodes.npz");
1287 cnpy::load(submesh2nodesMask,
folderMethod +
"/submesh2nodesMask.npy");