25 #include "libmesh/sparse_matrix.h" 26 #include "libmesh/numeric_vector.h" 27 #include "libmesh/dense_matrix.h" 28 #include "libmesh/dense_vector.h" 29 #include "libmesh/dof_map.h" 30 #include "libmesh/libmesh_logging.h" 31 #include "libmesh/equation_systems.h" 32 #include "libmesh/parallel.h" 33 #include "libmesh/parallel_algebra.h" 34 #include "libmesh/fe.h" 35 #include "libmesh/quadrature.h" 36 #include "libmesh/utility.h" 37 #include "libmesh/fe_interface.h" 38 #include "libmesh/fe_compute_data.h" 39 #include "libmesh/getpot.h" 40 #include "libmesh/exodusII_io.h" 41 #include "libmesh/fem_context.h" 42 #include "libmesh/elem.h" 43 #include "libmesh/int_range.h" 46 #include "libmesh/rb_construction_base.h" 47 #include "libmesh/rb_eim_construction.h" 48 #include "libmesh/rb_eim_evaluation.h" 49 #include "libmesh/rb_parameters.h" 50 #include "libmesh/rb_parametrized_function.h" 70 template <
typename DataMap>
71 void add(DataMap & u,
const Number k,
const DataMap & v)
73 for (
auto & [key, vec_vec_u] : u)
75 const std::vector<std::vector<Number>> & vec_vec_v = libmesh_map_find(v, key);
77 libmesh_error_msg_if (vec_vec_u.size() != vec_vec_v.size(),
"Size mismatch");
81 libmesh_error_msg_if (vec_vec_u[i].size() != vec_vec_v[i].size(),
"Size mismatch");
84 vec_vec_u[i][j] += k*vec_vec_v[i][j];
92 for (
auto & [key, vec_u] : u)
94 const std::vector<Number> & vec_v = libmesh_map_find(v, key);
96 libmesh_error_msg_if (vec_u.size() != vec_v.size(),
"Size mismatch");
100 vec_u[i] += k*vec_v[i];
108 const std::string & name_in,
109 const unsigned int number_in)
111 best_fit_type_flag(PROJECTION_BEST_FIT),
113 _set_Nmax_from_n_snapshots(false),
114 _Nmax_from_n_snapshots_increment(0),
115 _rel_training_tolerance(1.e-4),
116 _abs_training_tolerance(1.e-12),
117 _max_abs_value_in_training_set(0.),
118 _max_abs_value_in_training_set_index(0)
159 libmesh_error_msg_if(!
_rb_eim_eval,
"Error: RBEIMEvaluation object hasn't been initialized yet");
165 libmesh_error_msg_if(!
_rb_eim_eval,
"Error: RBEIMEvaluation object hasn't been initialized yet");
171 if (best_fit_type_string ==
"projection")
175 else if (best_fit_type_string ==
"eim")
179 else if (best_fit_type_string ==
"pod")
184 libmesh_error_msg(
"Error: invalid best_fit_type in input file");
190 libMesh::out << std::endl <<
"RBEIMConstruction parameters:" << std::endl;
195 libMesh::out <<
"Overruling Nmax based on number of snapshots, with increment set to " 216 libMesh::out <<
"EIM best fit type: projection" << std::endl;
234 GetPot infile(parameters_filename);
236 std::string best_fit_type_string = infile(
"best_fit_type",
"projection");
239 const unsigned int n_training_samples = infile(
"n_training_samples",0);
240 const bool deterministic_training = infile(
"deterministic_training",
false);
241 unsigned int training_parameters_random_seed_in =
242 static_cast<unsigned int>(-1);
243 training_parameters_random_seed_in = infile(
"training_parameters_random_seed",
244 training_parameters_random_seed_in);
245 const bool quiet_mode_in = infile(
"quiet_mode",
quiet_mode);
246 const unsigned int Nmax_in = infile(
"Nmax",
_Nmax);
247 const Real rel_training_tolerance_in = infile(
"rel_training_tolerance",
249 const Real abs_training_tolerance_in = infile(
"abs_training_tolerance",
253 unsigned int n_continuous_parameters = infile.vector_variable_size(
"parameter_names");
256 for (
unsigned int i=0; i<n_continuous_parameters; i++)
259 std::string param_name = infile(
"parameter_names",
"NONE", i);
262 Real min_val = infile(param_name, 0., 0);
263 mu_min_in.
set_value(param_name, min_val);
267 Real max_val = infile(param_name, 0., 1);
268 mu_max_in.
set_value(param_name, max_val);
272 std::map<std::string, std::vector<Real>> discrete_parameter_values_in;
274 unsigned int n_discrete_parameters = infile.vector_variable_size(
"discrete_parameter_names");
275 for (
unsigned int i=0; i<n_discrete_parameters; i++)
277 std::string param_name = infile(
"discrete_parameter_names",
"NONE", i);
279 unsigned int n_vals_for_param = infile.vector_variable_size(param_name);
280 std::vector<Real> vals_for_param(n_vals_for_param);
281 for (
auto j :
make_range(vals_for_param.size()))
282 vals_for_param[j] = infile(param_name, 0., j);
284 discrete_parameter_values_in[param_name] = vals_for_param;
287 std::map<std::string,bool> log_scaling_in;
291 for (
const auto & pr : mu_min_in)
292 log_scaling_in[pr.first] =
false;
296 deterministic_training,
297 training_parameters_random_seed_in,
300 rel_training_tolerance_in,
301 abs_training_tolerance_in,
304 discrete_parameter_values_in,
309 bool deterministic_training_in,
310 int training_parameters_random_seed_in,
312 unsigned int Nmax_in,
313 Real rel_training_tolerance_in,
314 Real abs_training_tolerance_in,
317 const std::map<std::string, std::vector<Real>> & discrete_parameter_values_in,
318 const std::map<std::string,bool> & log_scaling_in,
319 std::map<std::string, std::vector<RBParameter>> * training_sample_list)
337 const std::string & lookup_table_param_name =
340 libmesh_error_msg_if(!discrete_parameter_values_in.count(lookup_table_param_name),
341 "Lookup table parameter should be discrete");
344 std::map<std::string, std::vector<Real>> discrete_parameter_values_final(
345 discrete_parameter_values_in);
347 std::vector<Real> & lookup_table_param_values =
348 libmesh_map_find(discrete_parameter_values_final, lookup_table_param_name);
352 std::iota(lookup_table_param_values.begin(), lookup_table_param_values.end(), 0);
357 n_training_samples_in = lookup_table_param_values.size();
368 bool updated_deterministic_training = deterministic_training_in;
378 updated_deterministic_training =
false;
383 n_training_samples_in,
385 updated_deterministic_training);
387 if (training_sample_list)
399 const std::string & lookup_table_param_name =
405 std::vector<RBParameter> lookup_table_training_samples(n_training_samples_in, {val});
406 for (
auto & vec : lookup_table_training_samples)
434 LOG_SCOPE(
"train_eim_approximation_with_greedy()",
"RBEIMConstruction");
450 "Error: We currently only support EIM training starting from an empty basis");
452 libMesh::out << std::endl <<
"---- Performing Greedy EIM basis enrichment ----" << std::endl;
456 Real greedy_error = -1.;
457 std::vector<RBParameters> greedy_param_list;
468 bool exit_on_next_iteration =
false;
473 bool bfs_equals_n_samples =
false;
480 <<
") equals number of training samples." << std::endl;
482 bfs_equals_n_samples =
true;
486 if (!exit_on_next_iteration)
490 libMesh::out <<
"Greedily selected parameter vector:" << std::endl;
494 libMesh::out <<
"Enriching the EIM approximation" << std::endl;
497 bool is_zero_bf = bfs_equals_n_samples || (greedy_error == 0.);
504 std::unique_ptr<EimPointData> eim_point_data;
512 !exit_on_next_iteration,
513 eim_point_data.get());
528 libMesh::out <<
"Computing EIM error on training set" << std::endl;
532 libMesh::out <<
"Maximum EIM error is " << greedy_error << std::endl << std::endl;
534 #ifdef LIBMESH_ENABLE_EXCEPTIONS 535 catch (
const std::exception & e)
539 if (exit_on_next_iteration)
541 std::cout <<
"Exception occurred when enriching basis for error indicator hence we skip the error indicator in this case" << std::endl;
549 if (exit_on_next_iteration)
551 libMesh::out <<
"Extra EIM iteration for error indicator is complete, hence exiting EIM training now" << std::endl;
557 bool exit_condition_satisfied =
false;
561 libMesh::out <<
"Maximum number of basis functions reached: Nmax = " 563 exit_condition_satisfied =
true;
568 if (!exit_condition_satisfied)
571 libMesh::out <<
"Relative error tolerance reached." << std::endl;
572 exit_condition_satisfied =
true;
575 if (!exit_condition_satisfied)
578 libMesh::out <<
"Absolute error tolerance reached." << std::endl;
579 exit_condition_satisfied =
true;
583 if (!exit_condition_satisfied)
585 bool do_exit =
false;
589 for (
auto & param : greedy_param_list)
592 libMesh::out <<
"Exiting greedy because the same parameters were selected twice" 599 exit_condition_satisfied =
true;
602 if (exit_condition_satisfied)
610 exit_on_next_iteration =
true;
611 libMesh::out <<
"EIM error indicator is active, hence we will run one extra EIM iteration before exiting" 633 LOG_SCOPE(
"apply_normalization_to_solution_snapshots()",
"RBEIMConstruction");
635 libMesh::out <<
"Normalizing solution snapshots" << std::endl;
641 for (
unsigned int i=0; i<n_snapshots; i++)
649 apply_comp_scaling)));
659 apply_comp_scaling)));
669 apply_comp_scaling)));
691 libMesh::out <<
"Maximum absolute value in the training set after normalization: " 697 LOG_SCOPE(
"train_eim_approximation_with_POD()",
"RBEIMConstruction");
710 if (updated_Nmax > 0)
711 _Nmax =
static_cast<unsigned int>(updated_Nmax);
725 "Error: We currently only support EIM training starting from an empty basis");
727 libMesh::out << std::endl <<
"---- Performing POD EIM basis enrichment ----" << std::endl;
734 std::cout <<
"Start computing correlation matrix" << std::endl;
737 for (
unsigned int i=0; i<n_snapshots; i++)
739 for (
unsigned int j=0; j<=i; j++)
765 correlation_matrix(i,j) = inner_prod;
773 if ( (i+1) % 10 == 0)
774 std::cout <<
"Finished row " << (i+1) <<
" of " << n_snapshots << std::endl;
776 std::cout <<
"Finished computing correlation matrix" << std::endl;
794 correlation_matrix.
svd(sigma, U, VT );
799 bool exit_on_next_iteration =
false;
808 bool j_equals_n_snapshots =
false;
811 bool exit_condition_satisfied =
false;
813 if ((j == 0) && (sigma(0) == 0.))
815 libMesh::out <<
"Terminating EIM POD with empty basis because first singular value is zero" << std::endl;
816 exit_condition_satisfied =
true;
819 else if (j >= n_snapshots)
821 libMesh::out <<
"Number of basis functions equals number of training samples." << std::endl;
822 exit_condition_satisfied =
true;
823 j_equals_n_snapshots =
true;
835 rel_err = std::sqrt(sigma(j)) / std::sqrt(sigma(0));
838 if (exit_on_next_iteration)
840 libMesh::out <<
"Extra EIM iteration for error indicator is complete, POD error norm for extra iteration: " << rel_err << std::endl;
845 <<
", POD error norm: " << rel_err << std::endl;
847 if (!exit_condition_satisfied)
850 libMesh::out <<
"Maximum number of basis functions (" << j <<
") reached." << std::endl;
851 exit_condition_satisfied =
true;
854 if (!exit_condition_satisfied)
857 libMesh::out <<
"Training tolerance reached." << std::endl;
858 exit_condition_satisfied =
true;
861 if (exit_condition_satisfied)
870 exit_on_next_iteration =
true;
871 libMesh::out <<
"EIM error indicator is active, hence we will run one extra EIM iteration before exiting" 878 bool is_zero_bf = j_equals_n_snapshots || (rel_err == 0.);
888 for (
unsigned int i=0; i<n_snapshots; ++i )
891 Real norm_v = std::sqrt(sigma(j));
902 std::unique_ptr<EimPointData> eim_point_data;
910 !exit_on_next_iteration,
911 eim_point_data.get());
913 if (is_linearly_dependent && !is_zero_bf)
924 !exit_on_next_iteration,
925 eim_point_data.get());
930 #ifdef LIBMESH_ENABLE_EXCEPTIONS 931 catch (
const std::exception & e)
935 if (exit_on_next_iteration)
937 std::cout <<
"Exception occurred when enriching basis for error indicator hence we skip the error indicator in this case" << std::endl;
954 for (
unsigned int i=0; i<n_snapshots; ++i )
957 Real norm_v = std::sqrt(sigma(j));
968 std::unique_ptr<EimPointData> eim_point_data;
976 !exit_on_next_iteration,
977 eim_point_data.get());
979 if (is_linearly_dependent && !is_zero_bf)
990 !exit_on_next_iteration,
991 eim_point_data.get());
996 #ifdef LIBMESH_ENABLE_EXCEPTIONS 997 catch (
const std::exception & e)
1001 if (exit_on_next_iteration)
1003 std::cout <<
"Exception occurred when enriching basis for error indicator hence we skip the error indicator in this case" << std::endl;
1020 for (
unsigned int i=0; i<n_snapshots; ++i )
1023 Real norm_v = std::sqrt(sigma(j));
1034 std::unique_ptr<EimPointData> eim_point_data;
1042 !exit_on_next_iteration,
1043 eim_point_data.get());
1045 if (is_linearly_dependent && !is_zero_bf)
1056 !exit_on_next_iteration,
1057 eim_point_data.get());
1062 #ifdef LIBMESH_ENABLE_EXCEPTIONS 1063 catch (
const std::exception & e)
1067 if (exit_on_next_iteration)
1069 std::cout <<
"Exception occurred when enriching basis for error indicator hence we skip the error indicator in this case" << std::endl;
1083 std::cout <<
"Zero basis function encountered, hence exiting." << std::endl;
1116 if (
mesh.elem_dimensions().count(
dim))
1180 LOG_SCOPE(
"store_eim_solutions_for_training_set()",
"RBEIMConstruction");
1185 eim_solutions.clear();
1202 for (
unsigned int j=0; j<RB_size; j++)
1225 for (
unsigned int j=0; j<RB_size; j++)
1246 for (
unsigned int j=0; j<RB_size; j++)
1264 "Invalid index: " << training_index);
1271 "Invalid index: " << training_index);
1278 "Invalid index: " << training_index);
1314 LOG_SCOPE(
"compute_max_eim_error()",
"RBEIMConstruction");
1319 return std::make_pair(0.,0);
1323 unsigned int max_err_index = 0;
1327 "Error: Training samples should be the same on all procs");
1344 for (
unsigned int i=0; i<RB_size; i++)
1356 RB_inner_product_matrix_N.
lu_solve(best_fit_rhs, best_fit_coeffs);
1361 if (best_fit_error > max_err)
1363 max_err_index = training_index;
1364 max_err = best_fit_error;
1376 for (
unsigned int i=0; i<RB_size; i++)
1388 RB_inner_product_matrix_N.
lu_solve(best_fit_rhs, best_fit_coeffs);
1393 if (best_fit_error > max_err)
1395 max_err_index = training_index;
1396 max_err = best_fit_error;
1408 for (
unsigned int i=0; i<RB_size; i++)
1420 RB_inner_product_matrix_N.
lu_solve(best_fit_rhs, best_fit_coeffs);
1425 if (best_fit_error > max_err)
1427 max_err_index = training_index;
1428 max_err = best_fit_error;
1457 if (best_fit_error > max_err)
1459 max_err_index = training_index;
1460 max_err = best_fit_error;
1469 if (best_fit_error > max_err)
1471 max_err_index = training_index;
1472 max_err = best_fit_error;
1481 if (best_fit_error > max_err)
1483 max_err_index = training_index;
1484 max_err = best_fit_error;
1491 libmesh_error_msg(
"EIM best fit type not recognized");
1494 return std::make_pair(max_err,max_err_index);
1499 LOG_SCOPE(
"initialize_parametrized_functions_in_training_set()",
"RBEIMConstruction");
1502 "Error: We must have serial_training_set==true in " 1503 "RBEIMConstruction::initialize_parametrized_functions_in_training_set");
1505 libMesh::out <<
"Initializing parametrized functions in training set..." << std::endl;
1527 std::vector<Real> max_abs_value_per_component_in_training_set(n_comps);
1534 libMesh::out <<
"Initializing parametrized function for training sample " 1549 std::vector<std::vector<Number>> comps_and_qps(n_comps);
1550 for (
unsigned int comp=0; comp<n_comps; comp++)
1552 comps_and_qps[comp].resize(xyz_vector.size());
1557 elem_side_pair.first,
1558 elem_side_pair.second,
1560 comps_and_qps[comp][qp] =
value;
1569 if (abs_value > max_abs_value_per_component_in_training_set[comp])
1570 max_abs_value_per_component_in_training_set[comp] = abs_value;
1578 libMesh::out <<
"Parametrized functions in training set initialized" << std::endl;
1580 unsigned int max_id = 0;
1583 libMesh::out <<
"Maximum absolute value in the training set: " 1588 comm().
max(max_abs_value_per_component_in_training_set);
1597 max_abs_value_per_component_in_training_set[i] == 0.)
1608 libMesh::out <<
"Initializing parametrized function for training sample " 1620 const auto & node_id = pr.first;
1622 std::vector<Number> comps(n_comps);
1623 for (
unsigned int comp=0; comp<n_comps; comp++)
1628 comps[comp] =
value;
1637 if (abs_value > max_abs_value_per_component_in_training_set[comp])
1638 max_abs_value_per_component_in_training_set[comp] = abs_value;
1645 libMesh::out <<
"Parametrized functions in training set initialized" << std::endl;
1647 unsigned int max_id = 0;
1650 libMesh::out <<
"Maximum absolute value in the training set: " 1655 comm().
max(max_abs_value_per_component_in_training_set);
1664 max_abs_value_per_component_in_training_set[i] == 0.)
1675 libMesh::out <<
"Initializing parametrized function for training sample " 1688 std::vector<std::vector<Number>> comps_and_qps(n_comps);
1689 for (
unsigned int comp=0; comp<n_comps; comp++)
1691 comps_and_qps[comp].resize(xyz_vector.size());
1696 comps_and_qps[comp][qp] =
value;
1705 if (abs_value > max_abs_value_per_component_in_training_set[comp])
1706 max_abs_value_per_component_in_training_set[comp] = abs_value;
1714 libMesh::out <<
"Parametrized functions in training set initialized" << std::endl;
1716 unsigned int max_id = 0;
1719 libMesh::out <<
"Maximum absolute value in the training set: " 1724 comm().
max(max_abs_value_per_component_in_training_set);
1733 max_abs_value_per_component_in_training_set[i] == 0.)
1747 LOG_SCOPE(
"initialize_qp_data()",
"RBEIMConstruction");
1751 libMesh::out <<
"Initializing quadrature point locations" << std::endl;
1755 libMesh::out <<
"Initializing quadrature point and perturbation locations" << std::endl;
1766 const std::set<boundary_id_type> & parametrized_function_boundary_ids =
1768 libmesh_error_msg_if (parametrized_function_boundary_ids.empty(),
1769 "Need to have non-empty boundary IDs to initialize side data");
1780 const auto & binfo =
mesh.get_boundary_info();
1781 std::vector<boundary_id_type> side_boundary_ids;
1783 for (
const auto & elem :
mesh.active_local_element_ptr_range())
1791 const std::vector<Real> & JxW = elem_fe->get_JxW();
1792 const std::vector<Point> & xyz = elem_fe->get_xyz();
1795 auto side_fe = context.
get_side_fe(0, elem->dim());
1796 const std::vector<Real> & JxW_side = side_fe->get_JxW();
1797 const std::vector< Point > & xyz_side = side_fe->get_xyz();
1799 for (context.
side = 0;
1806 binfo.boundary_ids(elem, context.
side, side_boundary_ids);
1808 bool has_side_boundary_id =
false;
1811 if(parametrized_function_boundary_ids.count(side_boundary_id))
1813 has_side_boundary_id =
true;
1814 matching_boundary_id = side_boundary_id;
1818 if(has_side_boundary_id)
1822 auto elem_side_pair = std::make_pair(elem_id, context.
side);
1836 std::vector<std::vector<Point>> xyz_perturb_vec_at_qps;
1838 for (
const Point & xyz_qp : xyz_side)
1840 std::vector<Point> xyz_perturb_vec;
1841 if (elem->dim() == 3)
1852 std::unique_ptr<const Elem> elem_side;
1853 elem->build_side_ptr(elem_side, context.
side);
1865 Point xi_eta_perturb = xi_eta;
1867 xi_eta_perturb(0) += fd_delta;
1868 Point xyz_perturb_0 =
1872 xi_eta_perturb(0) -= fd_delta;
1874 xi_eta_perturb(1) += fd_delta;
1875 Point xyz_perturb_1 =
1879 xi_eta_perturb(1) -= fd_delta;
1884 Point unit_0 = (xyz_perturb_0-xyz_qp).unit();
1885 Point unit_1 = (xyz_perturb_1-xyz_qp).unit();
1887 xyz_perturb_vec.emplace_back(xyz_qp + fd_delta*unit_0);
1888 xyz_perturb_vec.emplace_back(xyz_qp + fd_delta*unit_1);
1897 xyz_perturb_vec_at_qps.emplace_back(xyz_perturb_vec);
1907 if (elem->dim() == 2)
1908 for (
unsigned int shellface_index=0; shellface_index<2; shellface_index++)
1910 binfo.shellface_boundary_ids(elem, shellface_index, side_boundary_ids);
1912 bool has_side_boundary_id =
false;
1915 if(parametrized_function_boundary_ids.count(side_boundary_id))
1917 has_side_boundary_id =
true;
1918 matching_boundary_id = side_boundary_id;
1922 if(has_side_boundary_id)
1928 auto elem_side_pair = std::make_pair(elem_id, shellface_index);
1942 std::vector<std::vector<Point>> xyz_perturb_vec_at_qps;
1944 for (
const Point & xyz_qp : xyz)
1946 std::vector<Point> xyz_perturb_vec;
1960 Point xi_eta_perturb = xi_eta;
1962 xi_eta_perturb(0) += fd_delta;
1963 Point xyz_perturb_0 =
1967 xi_eta_perturb(0) -= fd_delta;
1969 xi_eta_perturb(1) += fd_delta;
1970 Point xyz_perturb_1 =
1974 xi_eta_perturb(1) -= fd_delta;
1979 Point unit_0 = (xyz_perturb_0-xyz_qp).unit();
1980 Point unit_1 = (xyz_perturb_1-xyz_qp).unit();
1982 xyz_perturb_vec.emplace_back(xyz_qp + fd_delta*unit_0);
1983 xyz_perturb_vec.emplace_back(xyz_qp + fd_delta*unit_1);
1986 xyz_perturb_vec_at_qps.emplace_back(xyz_perturb_vec);
1997 const std::set<boundary_id_type> & parametrized_function_boundary_ids =
1999 libmesh_error_msg_if (parametrized_function_boundary_ids.empty(),
2000 "Need to have non-empty boundary IDs to initialize node data");
2005 const auto & binfo =
mesh.get_boundary_info();
2011 std::set<dof_id_type> nodes_with_nodesets;
2012 for (
const auto & t : binfo.build_node_list())
2013 nodes_with_nodesets.insert(std::get<0>(t));
2016 std::vector<boundary_id_type> node_boundary_ids;
2020 const Node * node =
mesh.node_ptr(node_id);
2025 binfo.boundary_ids(node, node_boundary_ids);
2027 bool has_node_boundary_id =
false;
2032 has_node_boundary_id =
true;
2037 if(has_node_boundary_id)
2052 for (
const auto & elem :
mesh.active_local_element_ptr_range())
2055 const std::vector<Real> & JxW = elem_fe->get_JxW();
2056 const std::vector<Point> & xyz = elem_fe->get_xyz();
2071 std::vector<std::vector<Point>> xyz_perturb_vec_at_qps;
2073 for (
const Point & xyz_qp : xyz)
2075 std::vector<Point> xyz_perturb_vec;
2076 if (elem->dim() == 3)
2078 Point xyz_perturb = xyz_qp;
2080 xyz_perturb(0) += fd_delta;
2081 xyz_perturb_vec.emplace_back(xyz_perturb);
2082 xyz_perturb(0) -= fd_delta;
2084 xyz_perturb(1) += fd_delta;
2085 xyz_perturb_vec.emplace_back(xyz_perturb);
2086 xyz_perturb(1) -= fd_delta;
2088 xyz_perturb(2) += fd_delta;
2089 xyz_perturb_vec.emplace_back(xyz_perturb);
2090 xyz_perturb(2) -= fd_delta;
2092 else if (elem->dim() == 2)
2113 Point xi_eta_perturb = xi_eta;
2115 xi_eta_perturb(0) += fd_delta;
2116 Point xyz_perturb_0 =
2120 xi_eta_perturb(0) -= fd_delta;
2122 xi_eta_perturb(1) += fd_delta;
2123 Point xyz_perturb_1 =
2127 xi_eta_perturb(1) -= fd_delta;
2132 Point unit_0 = (xyz_perturb_0-xyz_qp).unit();
2133 Point unit_1 = (xyz_perturb_1-xyz_qp).unit();
2135 xyz_perturb_vec.emplace_back(xyz_qp + fd_delta*unit_0);
2136 xyz_perturb_vec.emplace_back(xyz_qp + fd_delta*unit_1);
2146 xyz_perturb_vec_at_qps.emplace_back(xyz_perturb_vec);
2158 LOG_SCOPE(
"inner_product()",
"RBEIMConstruction");
2162 for (
const auto & [elem_id, v_comp_and_qp] : v)
2164 const auto & w_comp_and_qp = libmesh_map_find(w, elem_id);
2167 for (
const auto & comp :
index_range(v_comp_and_qp))
2169 const std::vector<Number> & v_qp = v_comp_and_qp[comp];
2170 const std::vector<Number> & w_qp = w_comp_and_qp[comp];
2172 Real comp_scaling = 1.;
2173 if (apply_comp_scaling)
2181 val += JxW[qp] * comp_scaling * v_qp[qp] *
libmesh_conj(w_qp[qp]);
2192 LOG_SCOPE(
"side_inner_product()",
"RBEIMConstruction");
2196 for (
const auto & [elem_and_side, v_comp_and_qp] : v)
2198 const auto & w_comp_and_qp = libmesh_map_find(w, elem_and_side);
2201 for (
const auto & comp :
index_range(v_comp_and_qp))
2203 const std::vector<Number> & v_qp = v_comp_and_qp[comp];
2204 const std::vector<Number> & w_qp = w_comp_and_qp[comp];
2206 Real comp_scaling = 1.;
2207 if (apply_comp_scaling)
2215 val += JxW[qp] * comp_scaling * v_qp[qp] *
libmesh_conj(w_qp[qp]);
2226 LOG_SCOPE(
"node_inner_product()",
"RBEIMConstruction");
2230 for (
const auto & [node_id, v_comps] : v)
2232 const auto & w_comps = libmesh_map_find(w, node_id);
2239 Real comp_scaling = 1.;
2240 if (apply_comp_scaling)
2247 val += comp_scaling * v_comps[comp] *
libmesh_conj(w_comps[comp]);
2257 Real max_value = 0.;
2259 for (
const auto & pr : v)
2261 const auto & values = pr.second;
2264 const auto &
value = values[comp];
2266 Real comp_scaling = 1.;
2271 "Invalid vector index");
2275 max_value = std::max(max_value, std::abs(
value * comp_scaling));
2284 bool add_basis_function,
2287 LOG_SCOPE(
"enrich_eim_approximation()",
"RBEIMConstruction");
2310 bool add_basis_function,
2329 for (
unsigned int i=0; i<RB_size; i++)
2350 Number optimal_value = 0.;
2351 Point optimal_point;
2352 unsigned int optimal_comp = 0;
2354 unsigned int optimal_side_index = 0;
2357 unsigned int optimal_qp = 0;
2358 std::vector<Point> optimal_point_perturbs;
2359 std::vector<Real> optimal_point_phi_i_qp;
2362 Real largest_abs_value = -1.;
2368 for (
const auto & [elem_and_side, comp_and_qp] : local_pf)
2371 unsigned int side_index = elem_and_side.second;
2378 std::vector<std::vector<Real>> phi;
2387 side_fe->reinit(&elem_ref, side_index);
2389 phi = side_fe->get_phi();
2391 else if (side_type == 1)
2396 phi = elem_fe->get_phi();
2399 libmesh_error_msg (
"Unrecognized side_type: " << side_type);
2401 for (
const auto & comp :
index_range(comp_and_qp))
2403 const std::vector<Number> & qp_values = comp_and_qp[comp];
2410 bool update_optimal_point =
false;
2411 if (!eim_point_data)
2412 update_optimal_point = (abs_value > largest_abs_value);
2414 update_optimal_point = (elem_id == eim_point_data->
elem_id) &&
2415 (side_index == eim_point_data->
side_index) &&
2419 if (update_optimal_point)
2421 largest_abs_value = abs_value;
2422 optimal_value =
value;
2423 optimal_comp = comp;
2424 optimal_elem_id = elem_id;
2425 optimal_side_index = side_index;
2428 optimal_point_phi_i_qp.resize(phi.size());
2430 optimal_point_phi_i_qp[i] = phi[i][qp];
2432 const auto & point_list =
2435 libmesh_error_msg_if(qp >= point_list.size(),
"Error: Invalid qp");
2437 optimal_point = point_list[qp];
2444 const auto & perturb_list =
2447 libmesh_error_msg_if(qp >= perturb_list.size(),
"Error: Invalid qp");
2449 optimal_point_perturbs = perturb_list[qp];
2458 unsigned int proc_ID_index;
2459 this->
comm().
maxloc(largest_abs_value, proc_ID_index);
2466 this->
comm().
broadcast(optimal_subdomain_id, proc_ID_index);
2469 this->
comm().
broadcast(optimal_point_perturbs, proc_ID_index);
2470 this->
comm().
broadcast(optimal_point_phi_i_qp, proc_ID_index);
2474 if (add_basis_function)
2476 if (optimal_value == 0.)
2478 libMesh::out <<
"Encountered linearly dependent data in EIM enrichment, hence skip adding new basis function" << std::endl;
2494 optimal_subdomain_id,
2495 optimal_boundary_id,
2497 optimal_point_perturbs,
2498 optimal_point_phi_i_qp);
2505 bool add_basis_function,
2524 for (
unsigned int i=0; i<RB_size; i++)
2543 Number optimal_value = 0.;
2544 Point optimal_point;
2545 unsigned int optimal_comp = 0;
2550 Real largest_abs_value = -1.;
2552 for (
const auto & [node_id, values] : local_pf)
2559 bool update_optimal_point =
false;
2560 if (!eim_point_data)
2561 update_optimal_point = (abs_value > largest_abs_value);
2563 update_optimal_point = (node_id == eim_point_data->
node_id) &&
2566 if (update_optimal_point)
2568 largest_abs_value = abs_value;
2569 optimal_value =
value;
2570 optimal_comp = comp;
2571 optimal_node_id = node_id;
2582 unsigned int proc_ID_index;
2583 this->
comm().
maxloc(largest_abs_value, proc_ID_index);
2593 if (add_basis_function)
2595 if (optimal_value == 0.)
2597 libMesh::out <<
"Encountered linearly dependent data in EIM enrichment, hence skip adding new basis function" << std::endl;
2612 optimal_boundary_id);
2619 bool add_basis_function,
2638 for (
unsigned int i=0; i<RB_size; i++)
2658 Number optimal_value = 0.;
2659 Point optimal_point;
2660 unsigned int optimal_comp = 0;
2663 unsigned int optimal_qp = 0;
2664 std::vector<Point> optimal_point_perturbs;
2665 std::vector<Real> optimal_point_phi_i_qp;
2667 std::vector<Real> optimal_JxW_all_qp;
2668 std::vector<std::vector<Real>> optimal_phi_i_all_qp;
2670 Point optimal_dxyzdxi_elem_center;
2671 Point optimal_dxyzdeta_elem_center;
2674 Real largest_abs_value = -1.;
2687 for (
const auto & [elem_id, comp_and_qp] : local_pf)
2694 const std::vector<std::vector<Real>> & phi = elem_fe->get_phi();
2695 const auto & JxW = elem_fe->get_JxW();
2696 const auto & dxyzdxi = elem_fe->get_dxyzdxi();
2697 const auto & dxyzdeta = elem_fe->get_dxyzdeta();
2699 elem_fe->reinit(&elem_ref);
2701 for (
const auto & comp :
index_range(comp_and_qp))
2703 const std::vector<Number> & qp_values = comp_and_qp[comp];
2713 bool update_optimal_point =
false;
2714 if (!eim_point_data)
2715 update_optimal_point = (abs_value > largest_abs_value);
2717 update_optimal_point = (elem_id == eim_point_data->
elem_id) &&
2721 if (update_optimal_point)
2723 largest_abs_value = abs_value;
2724 optimal_value =
value;
2725 optimal_comp = comp;
2726 optimal_elem_id = elem_id;
2728 optimal_elem_type = elem_ref.
type();
2730 optimal_point_phi_i_qp.resize(phi.size());
2732 optimal_point_phi_i_qp[i] = phi[i][qp];
2734 const auto & point_list =
2737 libmesh_error_msg_if(qp >= point_list.size(),
"Error: Invalid qp");
2739 optimal_point = point_list[qp];
2745 const auto & perturb_list =
2748 libmesh_error_msg_if(qp >= perturb_list.size(),
"Error: Invalid qp");
2750 optimal_point_perturbs = perturb_list[qp];
2755 optimal_JxW_all_qp = JxW;
2756 optimal_phi_i_all_qp = phi;
2764 elem_fe->reinit (&elem_ref, &nodes);
2766 Point dxyzdxi_pt, dxyzdeta_pt;
2768 dxyzdxi_pt = dxyzdxi[0];
2770 dxyzdeta_pt = dxyzdeta[0];
2772 optimal_dxyzdxi_elem_center = dxyzdxi_pt;
2773 optimal_dxyzdeta_elem_center = dxyzdeta_pt;
2775 elem_fe->reinit(&elem_ref);
2784 unsigned int proc_ID_index;
2785 this->
comm().
maxloc(largest_abs_value, proc_ID_index);
2791 this->
comm().
broadcast(optimal_subdomain_id, proc_ID_index);
2793 this->
comm().
broadcast(optimal_point_perturbs, proc_ID_index);
2794 this->
comm().
broadcast(optimal_point_phi_i_qp, proc_ID_index);
2796 this->
comm().
broadcast(optimal_phi_i_all_qp, proc_ID_index);
2797 this->
comm().
broadcast(optimal_dxyzdxi_elem_center, proc_ID_index);
2798 this->
comm().
broadcast(optimal_dxyzdeta_elem_center, proc_ID_index);
2802 int optimal_elem_type_int =
static_cast<int>(optimal_elem_type);
2803 this->
comm().
broadcast(optimal_elem_type_int, proc_ID_index);
2804 optimal_elem_type =
static_cast<ElemType>(optimal_elem_type_int);
2809 int optimal_qrule_order_int =
static_cast<int>(optimal_qrule_order);
2810 this->
comm().
broadcast(optimal_qrule_order_int, proc_ID_index);
2811 optimal_qrule_order =
static_cast<Order>(optimal_qrule_order_int);
2816 if (add_basis_function)
2818 if (optimal_value == 0.)
2820 libMesh::out <<
"Encountered linearly dependent data in EIM enrichment, hence skip adding new basis function" << std::endl;
2835 optimal_subdomain_id,
2837 optimal_point_perturbs,
2838 optimal_point_phi_i_qp,
2841 optimal_phi_i_all_qp,
2842 optimal_qrule_order,
2843 optimal_dxyzdxi_elem_center,
2844 optimal_dxyzdeta_elem_center);
2852 LOG_SCOPE(
"update_eim_matrices()",
"RBEIMConstruction");
2857 libmesh_assert_msg(RB_size >= 1,
"Must have at least 1 basis function.");
2859 if (set_eim_error_indicator)
2870 for (
unsigned int j=0; j<RB_size; j++)
2880 extra_point_row(j) =
value;
2886 for (
unsigned int j=0; j<RB_size; j++)
2894 extra_point_row(j) =
value;
2900 for (
unsigned int j=0; j<RB_size; j++)
2909 extra_point_row(j) =
value;
2921 for (
unsigned int i=(RB_size-1); i<RB_size; i++)
2923 for (
unsigned int j=0; j<RB_size; j++)
2939 for (
unsigned int j=0; j<RB_size; j++)
2956 for (
unsigned int i=(RB_size-1); i<RB_size; i++)
2958 for (
unsigned int j=0; j<RB_size; j++)
2974 for (
unsigned int j=0; j<RB_size; j++)
2989 for (
unsigned int i=(RB_size-1); i<RB_size; i++)
2991 for (
unsigned int j=0; j<RB_size; j++)
3007 for (
unsigned int j=0; j<RB_size; j++)
3024 for (
auto & pr : local_pf)
3026 auto & values = pr.second;
3027 for (
auto &
value : values)
3028 value *= scaling_factor;
3039 std::default_random_engine gen;
3040 std::uniform_int_distribution<> dist{0,
static_cast<int>(n)};
3055 if (
comm().size() > 1)
3070 bool error_finding_new_element =
false;
3071 if (
comm().rank() == 0)
3076 std::set<dof_id_type> previous_elem_ids(vec_eval_input.
elem_ids.begin(), vec_eval_input.
elem_ids.end());
3092 std::set<dof_id_type> new_elem_ids;
3093 for (
const auto & v_pair : *v_ptr)
3094 if (previous_elem_ids.count(v_pair.first) == 0)
3095 new_elem_ids.insert(v_pair.first);
3101 error_finding_new_element = (new_elem_ids.empty());
3103 if (!error_finding_new_element)
3107 auto item = new_elem_ids.begin();
3108 std::advance(item, random_elem_idx);
3109 eim_point_data.
elem_id = *item;
3113 if (!error_finding_new_element)
3116 const auto & vars_and_qps = libmesh_map_find(*v_ptr,eim_point_data.
elem_id);
3121 const auto & qps = libmesh_map_find(*v_ptr,eim_point_data.
elem_id)[eim_point_data.
comp_index];
3128 libmesh_error_msg_if(error_finding_new_element,
"Could not find new element in get_random_point()");
3135 return eim_point_data;
3149 if (
comm().size() > 1)
3164 bool error_finding_new_element_and_side =
false;
3165 if (
comm().rank() == 0)
3169 std::pair<dof_id_type,unsigned int> elem_and_side;
3171 std::set<std::pair<dof_id_type,unsigned int>> previous_elem_and_side_ids;
3174 previous_elem_and_side_ids.insert(
3181 std::set<std::pair<dof_id_type,unsigned int>> new_elem_and_side_ids;
3182 for (
const auto & v_pair : *v_ptr)
3183 if (previous_elem_and_side_ids.count(v_pair.first) == 0)
3184 new_elem_and_side_ids.insert(v_pair.first);
3190 error_finding_new_element_and_side = (new_elem_and_side_ids.empty());
3192 if (!error_finding_new_element_and_side)
3196 auto item = new_elem_and_side_ids.begin();
3197 std::advance(item, random_elem_and_side_idx);
3198 elem_and_side = *item;
3199 eim_point_data.
elem_id = elem_and_side.first;
3200 eim_point_data.
side_index = elem_and_side.second;
3204 if (!error_finding_new_element_and_side)
3207 const auto & vars_and_qps = libmesh_map_find(*v_ptr,elem_and_side);
3212 const auto & qps = libmesh_map_find(*v_ptr,elem_and_side)[eim_point_data.
comp_index];
3219 libmesh_error_msg_if(error_finding_new_element_and_side,
"Could not find new (element,side) in get_random_point()");
3227 return eim_point_data;
3241 if (
comm().size() > 1)
3256 bool error_finding_new_node =
false;
3257 if (
comm().rank() == 0)
3262 std::set<dof_id_type> previous_node_ids(vec_eval_input.
node_ids.begin(), vec_eval_input.
node_ids.end());
3266 std::set<dof_id_type> new_node_ids;
3267 for (
const auto & v_pair : *v_ptr)
3268 if (previous_node_ids.count(v_pair.first) == 0)
3269 new_node_ids.insert(v_pair.first);
3275 error_finding_new_node = (new_node_ids.empty());
3277 if (!error_finding_new_node)
3281 auto item = new_node_ids.begin();
3282 std::advance(item, random_node_idx);
3283 eim_point_data.
node_id = *item;
3287 if (!error_finding_new_node)
3289 const auto & vars = libmesh_map_find(*v_ptr,eim_point_data.
node_id);
3295 libmesh_error_msg_if(error_finding_new_node,
"Could not find new node in get_random_point()");
3301 return eim_point_data;
virtual unsigned int get_n_components() const =0
Specify the number of components in this parametrized function.
ElemType
Defines an enum for geometric element types.
Real get_max_abs_value(const DataMap &v) const
Get the maximum absolute value from a vector stored in the format that we use for basis functions...
virtual void preevaluate_parametrized_function_on_mesh_sides(const RBParameters &mu, const std::map< std::pair< dof_id_type, unsigned int >, std::vector< Point >> &side_all_xyz, const std::map< std::pair< dof_id_type, unsigned int >, subdomain_id_type > &sbd_ids, const std::map< std::pair< dof_id_type, unsigned int >, boundary_id_type > &side_boundary_ids, const std::map< std::pair< dof_id_type, unsigned int >, unsigned int > &side_types, const std::map< std::pair< dof_id_type, unsigned int >, std::vector< std::vector< Point >> > &side_all_xyz_perturb, const System &sys)
Same as preevaluate_parametrized_function_on_mesh() except for mesh sides.
This is the EquationSystems class.
std::map< std::pair< dof_id_type, unsigned int >, std::vector< std::vector< Number > > > SideQpDataMap
Type of the data structure used to map from (elem id, side index) -> [n_vars][n_qp] data...
Order
defines an enum for polynomial orders.
bool quiet_mode
Flag to indicate whether we print out extra information during the Offline stage. ...
A Node is like a Point, but with more information.
Real get_max_abs_value_in_training_set() const
Get the maximum value (across all processors) from the parametrized functions in the training set...
std::unordered_map< dof_id_type, boundary_id_type > _local_node_boundary_ids
void get_side_fe(unsigned int var, FEGenericBase< OutputShape > *&fe) const
Accessor for edge/face (2D/3D) finite element object for variable var for the largest dimension in th...
virtual void pre_fe_reinit(const System &, const Elem *e)
Reinitializes local data vectors/matrices on the current geometric element.
boost::multiprecision::float128 real(const boost::multiprecision::float128 in)
const SideQpDataMap & get_side_basis_function(unsigned int i) const
Get a reference to the i^th side basis function.
void add_basis_function(const QpDataMap &bf)
Add bf to our EIM basis.
bool enrich_eim_approximation_on_nodes(const NodeDataMap &node_pf, bool add_basis_function, EimPointData *eim_point_data)
Implementation of enrich_eim_approximation() for the case of element nodes.
void set_interpolation_matrix_entry(unsigned int i, unsigned int j, Number value)
Set entry of the EIM interpolation matrix.
std::map< dof_id_type, std::vector< Number > > NodeDataMap
Type of the data structure used to map from (node id) -> [n_vars] data.
void initialize_eim_construction()
Perform initialization of this object to prepare for running train_eim_approximation().
bool _normalize_solution_snapshots
Set this boolean to true if we want to normalize solution snapshots used in training to have norm of ...
RBEIMEvaluation & get_rb_eim_evaluation()
Get a reference to the RBEvaluation object.
const std::set< unsigned int > & scale_components_in_enrichment() const
Get _scale_components_in_enrichment.
const std::set< boundary_id_type > & get_parametrized_function_boundary_ids() const
For RBParametrizedFunctions defined on element sides or nodes, we get/set the boundary IDs that this ...
void enable_set_Nmax_from_n_snapshots(int increment)
Call this method to set _set_Nmax_from_n_snapshots=true and _Nmax_from_n_snapshots_increment=incremen...
void rb_eim_solves(const std::vector< RBParameters > &mus, unsigned int N)
Perform rb_eim_solves at each mu in mus and store the results in _rb_eim_solutions.
Number get_eim_basis_function_value(unsigned int basis_function_index, dof_id_type elem_id, unsigned int comp, unsigned int qp) const
Same as above, except that we just return the value at the qp^th quadrature point.
static constexpr Real TOLERANCE
unsigned char get_elem_dim() const
const Elem & get_elem() const
Accessor for current Elem object.
virtual void reinit()
Reinitializes degrees of freedom and other required data on the current mesh.
static Point inverse_map(const unsigned int dim, const Elem *elem, const Point &p, const Real tolerance=TOLERANCE, const bool secure=true, const bool extra_checks=true)
virtual Real train_eim_approximation()
Generate the EIM approximation for the specified parametrized function using either POD or the Greedy...
std::vector< SideQpDataMap > _local_side_parametrized_functions_for_training
Same as _local_parametrized_functions_for_training except for side data.
Real get_parameter_min(const std::string ¶m_name) const
Get minimum allowable value of parameter param_name.
unsigned int get_n_basis_functions() const
Return the current number of EIM basis functions.
void add_node_basis_function(const NodeDataMap &node_bf)
Add node_bf to our EIM basis.
Number side_inner_product(const SideQpDataMap &v, const SideQpDataMap &w, bool apply_comp_scaling)
Same as inner_product() except for side data.
Real get_parameter_max(const std::string ¶m_name) const
Get maximum allowable value of parameter param_name.
std::map< std::pair< dof_id_type, unsigned int >, unsigned int > _local_side_quad_point_side_types
For side data, we also store "side type" info.
const RBParameters & get_parameters_max() const
Get an RBParameters object that specifies the maximum allowable value for each parameter.
std::unordered_map< dof_id_type, std::vector< Real > > _local_quad_point_JxW
This struct is used to encapsulate the arguments required to specify an EIM point that we may add to ...
This is the base class from which all geometric element types are derived.
virtual ~RBEIMConstruction()
void add_interpolation_data(Point p, unsigned int comp, dof_id_type elem_id, subdomain_id_type subdomain_id, unsigned int qp, const std::vector< Point > &perturbs, const std::vector< Real > &phi_i_qp, ElemType elem_type, const std::vector< Real > &JxW_all_qp, const std::vector< std::vector< Real >> &phi_i_all_qp, Order qrule_order, const Point &dxyz_dxi_elem_center, const Point &dxyz_deta_elem_center)
Add interpolation data associated with a new basis function.
void set_quiet_mode(bool quiet_mode_in)
Set the quiet_mode flag.
const std::vector< DenseVector< Number > > & get_rb_eim_solutions() const
Return the EIM solution coefficients from the most recent call to rb_eim_solves().
virtual void set_best_fit_type_flag(const std::string &best_fit_type_string)
Specify which type of "best fit" we use to guide the EIM greedy algorithm.
void reinit_eim_projection_matrix()
Zero the _eim_projection_matrix and resize it to be get_Nmax() x get_Nmax().
virtual void process_parameters_file(const std::string ¶meters_filename)
Read parameters in from file and set up this system accordingly.
Real _max_abs_value_in_training_set
Maximum value in _local_parametrized_functions_for_training across all processors.
const Parallel::Communicator & comm() const
bool is_quiet() const
Is the system in quiet mode?
RBEIMEvaluation * _rb_eim_eval
The RBEIMEvaluation object that we use to perform the EIM training.
const QpDataMap & get_parametrized_function_from_training_set(unsigned int training_index) const
Get a const reference to the specified parametrized function from the training set.
RBEIMConstruction(EquationSystems &es, const std::string &name, const unsigned int number)
Constructor.
unsigned int get_interpolation_points_side_index(unsigned int index) const
virtual void clear() override
Clear this object.
void decrement_vector(QpDataMap &v, const DenseVector< Number > &coeffs)
Subtract coeffs[i]*basis_function[i] from v.
EimPointData get_random_point(const QpDataMap &v)
Helper function that identifies a random EIM point from v.
void set_training_parameter_values(const std::string ¶m_name, const std::vector< RBParameter > &values)
Overwrite the local training samples for param_name using values.
const NodeDataMap & get_node_basis_function(unsigned int i) const
Get a reference to the i^th node basis function.
The libMesh namespace provides an interface to certain functionality in the library.
unsigned int get_interpolation_points_comp(unsigned int index) const
const std::vector< DenseVector< Number > > & get_eim_solutions_for_training_set() const
Return a const reference to the EIM solutions for the parameters in the training set.
void set_abs_training_tolerance(Real new_training_tolerance)
Get/set the absolute tolerance for the basis training.
void update_eim_matrices(bool set_eim_error_indicator)
Update the matrices used in training the EIM approximation.
virtual Real train_eim_approximation_with_greedy()
Generate the EIM approximation for the specified parametrized function using the Greedy Algorithm...
const MeshBase & get_mesh() const
Number node_inner_product(const NodeDataMap &v, const NodeDataMap &w, bool apply_comp_scaling)
Same as inner_product() except for node data.
virtual void set_Nmax(unsigned int Nmax)
void iota(ForwardIter first, ForwardIter last, T value)
Utility::iota was created back when std::iota was just an SGI STL extension.
virtual void preevaluate_parametrized_function_on_mesh(const RBParameters &mu, const std::unordered_map< dof_id_type, std::vector< Point >> &all_xyz, const std::unordered_map< dof_id_type, subdomain_id_type > &sbd_ids, const std::unordered_map< dof_id_type, std::vector< std::vector< Point >> > &all_xyz_perturb, const System &sys)
Store the result of vectorized_evaluate.
void add_side_basis_function(const SideQpDataMap &side_bf)
Add side_bf to our EIM basis.
virtual Number lookup_preevaluated_value_on_mesh(unsigned int comp, dof_id_type elem_id, unsigned int qp) const
Look up the preevaluate values of the parametrized function for component comp, element elem_id...
static Number get_parametrized_function_value(const Parallel::Communicator &comm, const QpDataMap &pf, dof_id_type elem_id, unsigned int comp, unsigned int qp)
Same as above, except that we just return the value at the qp^th quadrature point.
This is the MeshBase class.
virtual void print_info()
Print out info that describes the current setup of this RBConstruction.
void side_decrement_vector(SideQpDataMap &v, const DenseVector< Number > &coeffs)
Same as decrement_vector() except for Side data.
std::map< std::pair< dof_id_type, unsigned int >, subdomain_id_type > _local_side_quad_point_subdomain_ids
virtual void elem_fe_reinit(const std::vector< Point > *const pts=nullptr)
Reinitializes interior FE objects on the current geometric element.
virtual void load_training_set(const std::map< std::string, std::vector< RBParameter >> &new_training_set)
Overwrite the training parameters with new_training_set.
Real get_node_max_abs_value(const NodeDataMap &v) const
Get the maximum absolute value from a vector stored in the format that we use for basis functions...
const std::unordered_map< dof_id_type, std::vector< Real > > & get_local_quad_point_JxW()
Get the interior and side quadrature weights.
virtual void initialize_training_parameters(const RBParameters &mu_min, const RBParameters &mu_max, const unsigned int n_global_training_samples, const std::map< std::string, bool > &log_param_scale, const bool deterministic=true)
Initialize the parameter ranges and indicate whether deterministic or random training parameters shou...
Real get_rel_training_tolerance()
void set_training_random_seed(int seed)
Set the seed that is used to randomly generate training parameters.
Real get_abs_training_tolerance()
unsigned int n_parameters() const
Get the number of parameters that have been added.
bool is_lookup_table
Boolean to indicate if this parametrized function is defined based on a lookup table or not...
std::string lookup_table_param_name
If this is a lookup table, then lookup_table_param_name specifies the parameter that is used to index...
const QpDataMap & get_basis_function(unsigned int i) const
Get a reference to the i^th basis function.
std::vector< QpDataMap > _local_parametrized_functions_for_training
The parametrized functions that are used for training.
static const boundary_id_type invalid_id
Number used for internal use.
Real _abs_training_tolerance
const RBParameters & get_parameters_min() const
Get an RBParameters object that specifies the minimum allowable value for each parameter.
virtual T el(const unsigned int i, const unsigned int j) const override final
const System & get_system() const
Accessor for associated system.
std::vector< NodeDataMap > _local_node_parametrized_functions_for_training
Same as _local_parametrized_functions_for_training except for node data.
void resize_data_structures(const unsigned int Nmax)
Resize the data structures for storing data associated with this object.
void svd(DenseVector< Real > &sigma)
Compute the singular value decomposition of the matrix.
const boundary_id_type node_boundary_id
unsigned int _Nmax
Maximum number of EIM basis functions we are willing to use.
Manages consistently variables, degrees of freedom, and coefficient vectors.
std::map< dof_id_type, std::vector< std::vector< Number > > > QpDataMap
Type of the data structure used to map from (elem id) -> [n_vars][n_qp] data.
Number get_eim_basis_function_side_value(unsigned int basis_function_index, dof_id_type elem_id, unsigned int side_index, unsigned int comp, unsigned int qp) const
Same as get_eim_basis_function_value() except for side data.
std::map< std::pair< dof_id_type, unsigned int >, std::vector< Real > > _local_side_quad_point_JxW
virtual Number lookup_preevaluated_side_value_on_mesh(unsigned int comp, dof_id_type elem_id, unsigned int side_index, unsigned int qp) const
Look up the preevaluated values of the parametrized function for component comp, element elem_id...
virtual void init_context(FEMContext &)
Pre-request FE data needed for calculations.
numeric_index_type get_local_n_training_samples() const
Get the total number of training samples local to this processor.
void store_eim_solutions_for_training_set()
Get the EIM solution vector at all parametrized functions in the training set.
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
void add_side_interpolation_data(Point p, unsigned int comp, dof_id_type elem_id, unsigned int side_index, subdomain_id_type subdomain_id, boundary_id_type boundary_id, unsigned int qp, const std::vector< Point > &perturbs, const std::vector< Real > &phi_i_qp)
Add interpolation data associated with a new basis function.
This class provides all data required for a physics package (e.g.
bool on_mesh_nodes() const
const Elem * reference_elem() const
void add_node_interpolation_data(Point p, unsigned int comp, dof_id_type node_id, boundary_id_type boundary_id)
Add interpolation data associated with a new basis function.
void node_decrement_vector(NodeDataMap &v, const DenseVector< Number > &coeffs)
Same as decrement_vector() except for node data.
const RBParameters & get_parameters() const
Get the current parameters.
void print_parameters() const
Print the current parameters.
unsigned int _max_abs_value_in_training_set_index
The training sample index at which we found _max_abs_value_in_training_set.
bool requires_all_elem_qp_data
Boolean to indicate whether this parametrized function requires data from all qps on the current elem...
void get_principal_submatrix(unsigned int sub_m, unsigned int sub_n, DenseMatrix< T > &dest) const
Put the sub_m x sub_n principal submatrix into dest.
void maxloc(T &r, unsigned int &max_id) const
This class is part of the rbOOmit framework.
bool requires_all_elem_center_data
Boolean to indicate whether this parametrized function requires data from the center on the current e...
void apply_normalization_to_solution_snapshots()
Rescale solution snapshots so that they all have unity norm.
numeric_index_type get_n_training_samples() const
Get the number of global training samples.
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
virtual std::unique_ptr< ElemAssembly > build_eim_assembly(unsigned int bf_index)=0
Build an element assembly object that will access basis function bf_index.
BEST_FIT_TYPE best_fit_type_flag
Enum that indicates which type of "best fit" algorithm we should use.
DenseMatrix< Number > _eim_projection_matrix
The matrix we use in order to perform L2 projections of parametrized functions as part of EIM trainin...
EimPointData get_random_point_from_training_sample()
Get a random point using the 0^th training sample as input to get_random_point(). ...
static void scale_parametrized_function(DataMap &local_pf, Number scaling_factor)
Scale all values in pf by scaling_factor.
void set_params_from_training_set(unsigned int global_index)
Set parameters to the RBParameters stored in index global_index of the global training set...
virtual void preevaluate_parametrized_function_on_mesh_nodes(const RBParameters &mu, const std::unordered_map< dof_id_type, Point > &all_xyz, const std::unordered_map< dof_id_type, boundary_id_type > &node_boundary_ids, const System &sys)
Same as preevaluate_parametrized_function_on_mesh() except for mesh nodes.
int _Nmax_from_n_snapshots_increment
virtual unsigned int n_sides() const =0
bool _set_Nmax_from_n_snapshots
If _set_Nmax_from_n_snapshots=true, then we overrule Nmax to be Nmax += _Nmax_from_n_snapshots_increm...
bool set_parameters(const RBParameters ¶ms)
Set the current parameters to params The parameters are checked for validity; an error is thrown if t...
dof_id_type get_interpolation_points_node_id(unsigned int index) const
virtual bool use_eim_error_indicator() const
Virtual function to indicate if we use the EIM error indicator in this case.
void set_rb_eim_evaluation(RBEIMEvaluation &rb_eim_eval_in)
Set the RBEIMEvaluation object.
const Elem * neighbor_ptr(unsigned int i) const
DenseVector< Number > rb_eim_solve(DenseVector< Number > &EIM_rhs)
Calculate the EIM approximation for the given right-hand side vector EIM_rhs.
void lu_solve(const DenseVector< T > &b, DenseVector< T > &x)
Solve the system Ax=b given the input vector b.
Number get_eim_basis_function_node_value(unsigned int basis_function_index, dof_id_type node_id, unsigned int var) const
Same as get_eim_basis_function_value() except for node data.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::map< std::pair< dof_id_type, unsigned int >, boundary_id_type > _local_side_quad_point_boundary_ids
void initialize_rb_property_map()
Initialize the rb_property_map of RBEIMEvaluation (this) from the rb_property_map stored in RBParamet...
std::unordered_map< dof_id_type, Point > _local_node_locations
Same as above except for node data.
const VectorizedEvalInput & get_vec_eval_input() const
Get the VectorizedEvalInput data.
const SideQpDataMap & get_side_parametrized_function_from_training_set(unsigned int training_index) const
virtual void initialize_eim_assembly_objects()
Build a vector of ElemAssembly objects that accesses the basis functions stored in this RBEIMConstruc...
unsigned char side
Current side for side_* to examine.
void max(const T &r, T &o, Request &req) const
static Number get_parametrized_function_side_value(const Parallel::Communicator &comm, const SideQpDataMap &pf, dof_id_type elem_id, unsigned int side_index, unsigned int comp, unsigned int qp)
Same as get_parametrized_function_value() except for side data.
virtual unsigned short dim() const =0
void set_rel_training_tolerance(Real new_training_tolerance)
Get/set the relative tolerance for the basis training.
std::vector< std::unique_ptr< ElemAssembly > > & get_eim_assembly_objects()
void set_value(const std::string ¶m_name, Real value)
Set the value of the specified parameter.
static Point map(const unsigned int dim, const Elem *elem, const Point &reference_point)
Number inner_product(const QpDataMap &v, const QpDataMap &w, bool apply_comp_scaling)
Evaluate the inner product of vec1 and vec2 which specify values at quadrature points.
void set_error_indicator_interpolation_row(const DenseVector< Number > &error_indicator_row)
bool enrich_eim_approximation_on_sides(const SideQpDataMap &side_pf, bool add_basis_function, EimPointData *eim_point_data)
Implementation of enrich_eim_approximation() for the case of element sides.
virtual const Elem & elem_ref(const dof_id_type i) const
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
const std::map< std::pair< dof_id_type, unsigned int >, std::vector< Real > > & get_local_side_quad_point_JxW()
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
void initialize_parametrized_functions_in_training_set()
Compute and store the parametrized function for each parameter in the training set at all the stored ...
dof_id_type get_interpolation_points_elem_id(unsigned int index) const
unsigned int get_Nmax() const
Get/set Nmax, the maximum number of RB functions we are willing to compute.
void disable_set_Nmax_from_n_snapshots()
Call this method to set _set_Nmax_from_n_snapshots=false and reset _Nmax_from_n_snapshots_increment t...
std::pair< Real, unsigned int > compute_max_eim_error()
Find the training sample that has the largest EIM approximation error based on the current EIM approx...
RBEIMEvaluation::NodeDataMap NodeDataMap
Type of the data structure used to map from node id -> [n_vars] data.
bool serial_training_set
This boolean flag indicates whether or not the training set should be the same on all processors...
virtual Number lookup_preevaluated_node_value_on_mesh(unsigned int comp, dof_id_type node_id) const
Look up the preevaluate values of the parametrized function for component comp, node node_id...
RBParameters get_params_from_training_set(unsigned int global_index)
Return the RBParameters in index global_index of the global training set.
This class is part of the rbOOmit framework.
void get_element_fe(unsigned int var, FEGenericBase< OutputShape > *&fe) const
Accessor for interior finite element object for variable var for the largest dimension in the mesh...
std::vector< Real > _component_scaling_in_training_set
Keep track of a scaling factor for each component of the parametrized functions in the training set w...
bool enrich_eim_approximation_on_interiors(const QpDataMap &interior_pf, bool add_basis_function, EimPointData *eim_point_data)
Implementation of enrich_eim_approximation() for the case of element interiors.
void enrich_eim_approximation(unsigned int training_index, bool add_basis_function, EimPointData *eim_point_data)
Add a new basis function to the EIM approximation.
Real _rel_training_tolerance
Relative and absolute tolerances for training the EIM approximation.
RBEIMEvaluation::QpDataMap QpDataMap
Type of the data structure used to map from (elem id) -> [n_vars][n_qp] data.
unsigned int get_n_parametrized_functions_for_training() const
Get the number of parametrized functions used for training.
bool on_mesh_sides() const
Defines a dense vector for use in Finite Element-type computations.
virtual Real train_eim_approximation_with_POD()
Generate the EIM approximation for the specified parametrized function using Proper Orthogonal Decomp...
const std::string & name() const
std::unordered_map< dof_id_type, std::vector< Point > > _local_quad_point_locations
The quadrature point locations, quadrature point weights (JxW), and subdomain IDs on every element lo...
unsigned int n_vars() const
const NodeDataMap & get_node_parametrized_function_from_training_set(unsigned int training_index) const
std::map< std::pair< dof_id_type, unsigned int >, std::vector< Point > > _local_side_quad_point_locations
Same as above except for side data.
RBParametrizedFunction & get_parametrized_function()
Get a reference to the parametrized function.
virtual void initialize_lookup_table()
If this parametrized function is defined based on a lookup table then we can call this function to in...
void initialize_parameters(const RBParameters &mu_min_in, const RBParameters &mu_max_in, const std::map< std::string, std::vector< Real >> &discrete_parameter_values)
Initialize the parameter ranges and set current_parameters.
std::vector< std::unique_ptr< ElemAssembly > > _rb_eim_assembly_objects
The vector of assembly objects that are created to point to this RBEIMConstruction.
RBEIMEvaluation::SideQpDataMap SideQpDataMap
Type of the data structure used to map from (elem id,side_index) -> [n_vars][n_qp] data...
std::map< std::pair< dof_id_type, unsigned int >, std::vector< std::vector< Point > > > _local_side_quad_point_locations_perturbations
This class enables evaluation of an Empirical Interpolation Method (EIM) approximation.
processor_id_type processor_id() const
void initialize_qp_data()
Initialize the data associated with each quad point (location, JxW, etc.) so that we can use this in ...
std::unordered_map< dof_id_type, std::vector< std::vector< Point > > > _local_quad_point_locations_perturbations
EIM approximations often arise when applying a geometric mapping to a Reduced Basis formulation...
virtual ElemType type() const =0
unsigned int get_n_params() const
Get the number of parameters.
A Point defines a location in LIBMESH_DIM dimensional Real space.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
unsigned int get_interpolation_points_qp(unsigned int index) const
const QBase & get_element_qrule() const
Accessor for element interior quadrature rule for the dimension of the current _elem.
static void scale_node_parametrized_function(NodeDataMap &local_pf, Number scaling_factor)
Scale all values in pf by scaling_factor The templated function above handles the elem and side cases...
virtual void clear()
Clear all the data structures associated with the system.
bool is_discrete_parameter(const std::string &mu_name) const
Is parameter mu_name discrete?
Point vertex_average() const
void set_rb_construction_parameters(unsigned int n_training_samples_in, bool deterministic_training_in, int training_parameters_random_seed_in, bool quiet_mode_in, unsigned int Nmax_in, Real rel_training_tolerance_in, Real abs_training_tolerance_in, const RBParameters &mu_min_in, const RBParameters &mu_max_in, const std::map< std::string, std::vector< Real >> &discrete_parameter_values_in, const std::map< std::string, bool > &log_scaling, std::map< std::string, std::vector< RBParameter >> *training_sample_list=nullptr)
Set the state of this RBConstruction object based on the arguments to this function.
const std::set< unsigned char > & elem_dimensions() const
std::unordered_map< dof_id_type, subdomain_id_type > _local_quad_point_subdomain_ids
void print_discrete_parameter_values() const
Print out all the discrete parameter values.
static unsigned int get_random_int_0_to_n(unsigned int n)
Static helper function that is used by get_random_point().
void set_union(T &data, const unsigned int root_id) const
Real fd_delta
The finite difference step size in the case that this function in the case that this function uses fi...
static Number get_parametrized_function_node_value(const Parallel::Communicator &comm, const NodeDataMap &pf, dof_id_type node_id, unsigned int comp)
Same as get_parametrized_function_value() except for node data.