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 std::cout <<
"Maximum absolute value in the training set is " 464 Real greedy_error = -1.;
465 std::vector<RBParameters> greedy_param_list;
476 bool exit_on_next_iteration =
false;
481 bool bfs_equals_n_samples =
false;
488 <<
") equals number of training samples." << std::endl;
490 bfs_equals_n_samples =
true;
494 if (!exit_on_next_iteration)
498 libMesh::out <<
"Greedily selected parameter vector:" << std::endl;
502 libMesh::out <<
"Enriching the EIM approximation" << std::endl;
505 bool is_zero_bf = bfs_equals_n_samples || (greedy_error == 0.);
512 std::unique_ptr<EimPointData> eim_point_data;
520 !exit_on_next_iteration,
521 eim_point_data.get());
536 libMesh::out <<
"Computing EIM error on training set" << std::endl;
540 libMesh::out <<
"Maximum EIM error is " << greedy_error << std::endl << std::endl;
542 #ifdef LIBMESH_ENABLE_EXCEPTIONS 543 catch (
const std::exception & e)
547 if (exit_on_next_iteration)
549 std::cout <<
"Exception occurred when enriching basis for error indicator hence we skip the error indicator in this case" << std::endl;
557 if (exit_on_next_iteration)
559 libMesh::out <<
"Extra EIM iteration for error indicator is complete, hence exiting EIM training now" << std::endl;
565 bool exit_condition_satisfied =
false;
569 libMesh::out <<
"Maximum number of basis functions reached: Nmax = " 571 exit_condition_satisfied =
true;
576 if (!exit_condition_satisfied)
579 libMesh::out <<
"Relative error tolerance reached." << std::endl;
580 exit_condition_satisfied =
true;
583 if (!exit_condition_satisfied)
586 libMesh::out <<
"Absolute error tolerance reached." << std::endl;
587 exit_condition_satisfied =
true;
591 if (!exit_condition_satisfied)
593 bool do_exit =
false;
597 for (
auto & param : greedy_param_list)
600 libMesh::out <<
"Exiting greedy because the same parameters were selected twice" 607 exit_condition_satisfied =
true;
610 if (exit_condition_satisfied)
618 exit_on_next_iteration =
true;
619 libMesh::out <<
"EIM error indicator is active, hence we will run one extra EIM iteration before exiting" 641 LOG_SCOPE(
"apply_normalization_to_solution_snapshots()",
"RBEIMConstruction");
643 libMesh::out <<
"Normalizing solution snapshots" << std::endl;
649 for (
unsigned int i=0; i<n_snapshots; i++)
657 apply_comp_scaling)));
667 apply_comp_scaling)));
677 apply_comp_scaling)));
699 libMesh::out <<
"Maximum absolute value in the training set after normalization: " 705 LOG_SCOPE(
"train_eim_approximation_with_POD()",
"RBEIMConstruction");
718 if (updated_Nmax > 0)
719 _Nmax =
static_cast<unsigned int>(updated_Nmax);
733 "Error: We currently only support EIM training starting from an empty basis");
735 libMesh::out << std::endl <<
"---- Performing POD EIM basis enrichment ----" << std::endl;
742 std::cout <<
"Start computing correlation matrix" << std::endl;
745 for (
unsigned int i=0; i<n_snapshots; i++)
747 for (
unsigned int j=0; j<=i; j++)
773 correlation_matrix(i,j) = inner_prod;
781 if ( (i+1) % 10 == 0)
782 std::cout <<
"Finished row " << (i+1) <<
" of " << n_snapshots << std::endl;
784 std::cout <<
"Finished computing correlation matrix" << std::endl;
802 correlation_matrix.
svd(sigma, U, VT );
807 bool exit_on_next_iteration =
false;
816 bool j_equals_n_snapshots =
false;
819 bool exit_condition_satisfied =
false;
821 if ((j == 0) && (sigma(0) == 0.))
823 libMesh::out <<
"Terminating EIM POD with empty basis because first singular value is zero" << std::endl;
824 exit_condition_satisfied =
true;
827 else if (j >= n_snapshots)
829 libMesh::out <<
"Number of basis functions equals number of training samples." << std::endl;
830 exit_condition_satisfied =
true;
831 j_equals_n_snapshots =
true;
843 rel_err = std::sqrt(sigma(j)) / std::sqrt(sigma(0));
846 if (exit_on_next_iteration)
848 libMesh::out <<
"Extra EIM iteration for error indicator is complete, POD error norm for extra iteration: " << rel_err << std::endl;
853 <<
", POD error norm: " << rel_err << std::endl;
855 if (!exit_condition_satisfied)
858 libMesh::out <<
"Maximum number of basis functions (" << j <<
") reached." << std::endl;
859 exit_condition_satisfied =
true;
862 if (!exit_condition_satisfied)
865 libMesh::out <<
"Training tolerance reached." << std::endl;
866 exit_condition_satisfied =
true;
869 if (exit_condition_satisfied)
878 exit_on_next_iteration =
true;
879 libMesh::out <<
"EIM error indicator is active, hence we will run one extra EIM iteration before exiting" 886 bool is_zero_bf = j_equals_n_snapshots || (rel_err == 0.);
896 for (
unsigned int i=0; i<n_snapshots; ++i )
899 Real norm_v = std::sqrt(sigma(j));
910 std::unique_ptr<EimPointData> eim_point_data;
918 !exit_on_next_iteration,
919 eim_point_data.get());
921 if (is_linearly_dependent && !is_zero_bf)
932 !exit_on_next_iteration,
933 eim_point_data.get());
938 #ifdef LIBMESH_ENABLE_EXCEPTIONS 939 catch (
const std::exception & e)
943 if (exit_on_next_iteration)
945 std::cout <<
"Exception occurred when enriching basis for error indicator hence we skip the error indicator in this case" << std::endl;
962 for (
unsigned int i=0; i<n_snapshots; ++i )
965 Real norm_v = std::sqrt(sigma(j));
976 std::unique_ptr<EimPointData> eim_point_data;
984 !exit_on_next_iteration,
985 eim_point_data.get());
987 if (is_linearly_dependent && !is_zero_bf)
998 !exit_on_next_iteration,
999 eim_point_data.get());
1004 #ifdef LIBMESH_ENABLE_EXCEPTIONS 1005 catch (
const std::exception & e)
1009 if (exit_on_next_iteration)
1011 std::cout <<
"Exception occurred when enriching basis for error indicator hence we skip the error indicator in this case" << std::endl;
1028 for (
unsigned int i=0; i<n_snapshots; ++i )
1031 Real norm_v = std::sqrt(sigma(j));
1042 std::unique_ptr<EimPointData> eim_point_data;
1050 !exit_on_next_iteration,
1051 eim_point_data.get());
1053 if (is_linearly_dependent && !is_zero_bf)
1064 !exit_on_next_iteration,
1065 eim_point_data.get());
1070 #ifdef LIBMESH_ENABLE_EXCEPTIONS 1071 catch (
const std::exception & e)
1075 if (exit_on_next_iteration)
1077 std::cout <<
"Exception occurred when enriching basis for error indicator hence we skip the error indicator in this case" << std::endl;
1091 std::cout <<
"Zero basis function encountered, hence exiting." << std::endl;
1124 if (
mesh.elem_dimensions().count(
dim))
1188 LOG_SCOPE(
"store_eim_solutions_for_training_set()",
"RBEIMConstruction");
1193 eim_solutions.clear();
1210 for (
unsigned int j=0; j<RB_size; j++)
1233 for (
unsigned int j=0; j<RB_size; j++)
1254 for (
unsigned int j=0; j<RB_size; j++)
1272 "Invalid index: " << training_index);
1279 "Invalid index: " << training_index);
1286 "Invalid index: " << training_index);
1322 LOG_SCOPE(
"compute_max_eim_error()",
"RBEIMConstruction");
1327 return std::make_pair(0.,0);
1331 unsigned int max_err_index = 0;
1335 "Error: Training samples should be the same on all procs");
1352 for (
unsigned int i=0; i<RB_size; i++)
1364 RB_inner_product_matrix_N.
lu_solve(best_fit_rhs, best_fit_coeffs);
1369 if (best_fit_error > max_err)
1371 max_err_index = training_index;
1372 max_err = best_fit_error;
1384 for (
unsigned int i=0; i<RB_size; i++)
1396 RB_inner_product_matrix_N.
lu_solve(best_fit_rhs, best_fit_coeffs);
1401 if (best_fit_error > max_err)
1403 max_err_index = training_index;
1404 max_err = best_fit_error;
1416 for (
unsigned int i=0; i<RB_size; i++)
1428 RB_inner_product_matrix_N.
lu_solve(best_fit_rhs, best_fit_coeffs);
1433 if (best_fit_error > max_err)
1435 max_err_index = training_index;
1436 max_err = best_fit_error;
1465 if (best_fit_error > max_err)
1467 max_err_index = training_index;
1468 max_err = best_fit_error;
1477 if (best_fit_error > max_err)
1479 max_err_index = training_index;
1480 max_err = best_fit_error;
1489 if (best_fit_error > max_err)
1491 max_err_index = training_index;
1492 max_err = best_fit_error;
1499 libmesh_error_msg(
"EIM best fit type not recognized");
1502 return std::make_pair(max_err,max_err_index);
1507 LOG_SCOPE(
"initialize_parametrized_functions_in_training_set()",
"RBEIMConstruction");
1510 "Error: We must have serial_training_set==true in " 1511 "RBEIMConstruction::initialize_parametrized_functions_in_training_set");
1513 libMesh::out <<
"Initializing parametrized functions in training set..." << std::endl;
1535 std::vector<Real> max_abs_value_per_component_in_training_set(n_comps);
1542 libMesh::out <<
"Initializing parametrized function for training sample " 1557 std::vector<std::vector<Number>> comps_and_qps(n_comps);
1558 for (
unsigned int comp=0; comp<n_comps; comp++)
1560 comps_and_qps[comp].resize(xyz_vector.size());
1565 elem_side_pair.first,
1566 elem_side_pair.second,
1568 comps_and_qps[comp][qp] =
value;
1577 if (abs_value > max_abs_value_per_component_in_training_set[comp])
1578 max_abs_value_per_component_in_training_set[comp] = abs_value;
1586 libMesh::out <<
"Parametrized functions in training set initialized" << std::endl;
1588 unsigned int max_id = 0;
1591 libMesh::out <<
"Maximum absolute value in the training set: " 1596 comm().
max(max_abs_value_per_component_in_training_set);
1605 max_abs_value_per_component_in_training_set[i] == 0.)
1616 libMesh::out <<
"Initializing parametrized function for training sample " 1628 const auto & node_id = pr.first;
1630 std::vector<Number> comps(n_comps);
1631 for (
unsigned int comp=0; comp<n_comps; comp++)
1636 comps[comp] =
value;
1645 if (abs_value > max_abs_value_per_component_in_training_set[comp])
1646 max_abs_value_per_component_in_training_set[comp] = abs_value;
1653 libMesh::out <<
"Parametrized functions in training set initialized" << std::endl;
1655 unsigned int max_id = 0;
1658 libMesh::out <<
"Maximum absolute value in the training set: " 1663 comm().
max(max_abs_value_per_component_in_training_set);
1672 max_abs_value_per_component_in_training_set[i] == 0.)
1683 libMesh::out <<
"Initializing parametrized function for training sample " 1696 std::vector<std::vector<Number>> comps_and_qps(n_comps);
1697 for (
unsigned int comp=0; comp<n_comps; comp++)
1699 comps_and_qps[comp].resize(xyz_vector.size());
1704 comps_and_qps[comp][qp] =
value;
1713 if (abs_value > max_abs_value_per_component_in_training_set[comp])
1714 max_abs_value_per_component_in_training_set[comp] = abs_value;
1722 libMesh::out <<
"Parametrized functions in training set initialized" << std::endl;
1724 unsigned int max_id = 0;
1727 libMesh::out <<
"Maximum absolute value in the training set: " 1732 comm().
max(max_abs_value_per_component_in_training_set);
1741 max_abs_value_per_component_in_training_set[i] == 0.)
1755 LOG_SCOPE(
"initialize_qp_data()",
"RBEIMConstruction");
1759 libMesh::out <<
"Initializing quadrature point locations" << std::endl;
1763 libMesh::out <<
"Initializing quadrature point and perturbation locations" << std::endl;
1774 const std::set<boundary_id_type> & parametrized_function_boundary_ids =
1776 libmesh_error_msg_if (parametrized_function_boundary_ids.empty(),
1777 "Need to have non-empty boundary IDs to initialize side data");
1788 const auto & binfo =
mesh.get_boundary_info();
1789 std::vector<boundary_id_type> side_boundary_ids;
1791 for (
const auto & elem :
mesh.active_local_element_ptr_range())
1799 const std::vector<Real> & JxW = elem_fe->get_JxW();
1800 const std::vector<Point> & xyz = elem_fe->get_xyz();
1803 auto side_fe = context.
get_side_fe(0, elem->dim());
1804 const std::vector<Real> & JxW_side = side_fe->get_JxW();
1805 const std::vector< Point > & xyz_side = side_fe->get_xyz();
1807 for (context.
side = 0;
1814 binfo.boundary_ids(elem, context.
side, side_boundary_ids);
1816 bool has_side_boundary_id =
false;
1819 if(parametrized_function_boundary_ids.count(side_boundary_id))
1821 has_side_boundary_id =
true;
1822 matching_boundary_id = side_boundary_id;
1826 if(has_side_boundary_id)
1830 auto elem_side_pair = std::make_pair(elem_id, context.
side);
1844 std::vector<std::vector<Point>> xyz_perturb_vec_at_qps;
1846 for (
const Point & xyz_qp : xyz_side)
1848 std::vector<Point> xyz_perturb_vec;
1849 if (elem->dim() == 3)
1860 std::unique_ptr<const Elem> elem_side;
1861 elem->build_side_ptr(elem_side, context.
side);
1873 Point xi_eta_perturb = xi_eta;
1875 xi_eta_perturb(0) += fd_delta;
1876 Point xyz_perturb_0 =
1880 xi_eta_perturb(0) -= fd_delta;
1882 xi_eta_perturb(1) += fd_delta;
1883 Point xyz_perturb_1 =
1887 xi_eta_perturb(1) -= fd_delta;
1892 Point unit_0 = (xyz_perturb_0-xyz_qp).unit();
1893 Point unit_1 = (xyz_perturb_1-xyz_qp).unit();
1895 xyz_perturb_vec.emplace_back(xyz_qp + fd_delta*unit_0);
1896 xyz_perturb_vec.emplace_back(xyz_qp + fd_delta*unit_1);
1905 xyz_perturb_vec_at_qps.emplace_back(xyz_perturb_vec);
1915 if (elem->dim() == 2)
1916 for (
unsigned int shellface_index=0; shellface_index<2; shellface_index++)
1918 binfo.shellface_boundary_ids(elem, shellface_index, side_boundary_ids);
1920 bool has_side_boundary_id =
false;
1923 if(parametrized_function_boundary_ids.count(side_boundary_id))
1925 has_side_boundary_id =
true;
1926 matching_boundary_id = side_boundary_id;
1930 if(has_side_boundary_id)
1936 auto elem_side_pair = std::make_pair(elem_id, shellface_index);
1950 std::vector<std::vector<Point>> xyz_perturb_vec_at_qps;
1952 for (
const Point & xyz_qp : xyz)
1954 std::vector<Point> xyz_perturb_vec;
1968 Point xi_eta_perturb = xi_eta;
1970 xi_eta_perturb(0) += fd_delta;
1971 Point xyz_perturb_0 =
1975 xi_eta_perturb(0) -= fd_delta;
1977 xi_eta_perturb(1) += fd_delta;
1978 Point xyz_perturb_1 =
1982 xi_eta_perturb(1) -= fd_delta;
1987 Point unit_0 = (xyz_perturb_0-xyz_qp).unit();
1988 Point unit_1 = (xyz_perturb_1-xyz_qp).unit();
1990 xyz_perturb_vec.emplace_back(xyz_qp + fd_delta*unit_0);
1991 xyz_perturb_vec.emplace_back(xyz_qp + fd_delta*unit_1);
1994 xyz_perturb_vec_at_qps.emplace_back(xyz_perturb_vec);
2005 const std::set<boundary_id_type> & parametrized_function_boundary_ids =
2007 libmesh_error_msg_if (parametrized_function_boundary_ids.empty(),
2008 "Need to have non-empty boundary IDs to initialize node data");
2013 const auto & binfo =
mesh.get_boundary_info();
2019 std::set<dof_id_type> nodes_with_nodesets;
2020 for (
const auto & t : binfo.build_node_list())
2021 nodes_with_nodesets.insert(std::get<0>(t));
2024 std::vector<boundary_id_type> node_boundary_ids;
2028 const Node * node =
mesh.node_ptr(node_id);
2033 binfo.boundary_ids(node, node_boundary_ids);
2035 bool has_node_boundary_id =
false;
2040 has_node_boundary_id =
true;
2045 if(has_node_boundary_id)
2060 for (
const auto & elem :
mesh.active_local_element_ptr_range())
2063 const std::vector<Real> & JxW = elem_fe->get_JxW();
2064 const std::vector<Point> & xyz = elem_fe->get_xyz();
2079 std::vector<std::vector<Point>> xyz_perturb_vec_at_qps;
2081 for (
const Point & xyz_qp : xyz)
2083 std::vector<Point> xyz_perturb_vec;
2084 if (elem->dim() == 3)
2086 Point xyz_perturb = xyz_qp;
2088 xyz_perturb(0) += fd_delta;
2089 xyz_perturb_vec.emplace_back(xyz_perturb);
2090 xyz_perturb(0) -= fd_delta;
2092 xyz_perturb(1) += fd_delta;
2093 xyz_perturb_vec.emplace_back(xyz_perturb);
2094 xyz_perturb(1) -= fd_delta;
2096 xyz_perturb(2) += fd_delta;
2097 xyz_perturb_vec.emplace_back(xyz_perturb);
2098 xyz_perturb(2) -= fd_delta;
2100 else if (elem->dim() == 2)
2121 Point xi_eta_perturb = xi_eta;
2123 xi_eta_perturb(0) += fd_delta;
2124 Point xyz_perturb_0 =
2128 xi_eta_perturb(0) -= fd_delta;
2130 xi_eta_perturb(1) += fd_delta;
2131 Point xyz_perturb_1 =
2135 xi_eta_perturb(1) -= fd_delta;
2140 Point unit_0 = (xyz_perturb_0-xyz_qp).unit();
2141 Point unit_1 = (xyz_perturb_1-xyz_qp).unit();
2143 xyz_perturb_vec.emplace_back(xyz_qp + fd_delta*unit_0);
2144 xyz_perturb_vec.emplace_back(xyz_qp + fd_delta*unit_1);
2154 xyz_perturb_vec_at_qps.emplace_back(xyz_perturb_vec);
2166 LOG_SCOPE(
"inner_product()",
"RBEIMConstruction");
2170 for (
const auto & [elem_id, v_comp_and_qp] : v)
2172 const auto & w_comp_and_qp = libmesh_map_find(w, elem_id);
2175 for (
const auto & comp :
index_range(v_comp_and_qp))
2177 const std::vector<Number> & v_qp = v_comp_and_qp[comp];
2178 const std::vector<Number> & w_qp = w_comp_and_qp[comp];
2180 Real comp_scaling = 1.;
2181 if (apply_comp_scaling)
2189 val += JxW[qp] * comp_scaling * v_qp[qp] *
libmesh_conj(w_qp[qp]);
2200 LOG_SCOPE(
"side_inner_product()",
"RBEIMConstruction");
2204 for (
const auto & [elem_and_side, v_comp_and_qp] : v)
2206 const auto & w_comp_and_qp = libmesh_map_find(w, elem_and_side);
2209 for (
const auto & comp :
index_range(v_comp_and_qp))
2211 const std::vector<Number> & v_qp = v_comp_and_qp[comp];
2212 const std::vector<Number> & w_qp = w_comp_and_qp[comp];
2214 Real comp_scaling = 1.;
2215 if (apply_comp_scaling)
2223 val += JxW[qp] * comp_scaling * v_qp[qp] *
libmesh_conj(w_qp[qp]);
2234 LOG_SCOPE(
"node_inner_product()",
"RBEIMConstruction");
2238 for (
const auto & [node_id, v_comps] : v)
2240 const auto & w_comps = libmesh_map_find(w, node_id);
2247 Real comp_scaling = 1.;
2248 if (apply_comp_scaling)
2255 val += comp_scaling * v_comps[comp] *
libmesh_conj(w_comps[comp]);
2265 Real max_value = 0.;
2267 for (
const auto & pr : v)
2269 const auto & values = pr.second;
2272 const auto &
value = values[comp];
2274 Real comp_scaling = 1.;
2279 "Invalid vector index");
2283 max_value = std::max(max_value, std::abs(
value * comp_scaling));
2292 bool add_basis_function,
2295 LOG_SCOPE(
"enrich_eim_approximation()",
"RBEIMConstruction");
2318 bool add_basis_function,
2337 for (
unsigned int i=0; i<RB_size; i++)
2358 Number optimal_value = 0.;
2359 Point optimal_point;
2360 unsigned int optimal_comp = 0;
2362 unsigned int optimal_side_index = 0;
2365 unsigned int optimal_qp = 0;
2366 std::vector<Point> optimal_point_perturbs;
2367 std::vector<Real> optimal_point_phi_i_qp;
2370 Real largest_abs_value = -1.;
2376 for (
const auto & [elem_and_side, comp_and_qp] : local_pf)
2379 unsigned int side_index = elem_and_side.second;
2386 std::vector<std::vector<Real>> phi;
2395 side_fe->reinit(&elem_ref, side_index);
2397 phi = side_fe->get_phi();
2399 else if (side_type == 1)
2404 phi = elem_fe->get_phi();
2407 libmesh_error_msg (
"Unrecognized side_type: " << side_type);
2409 for (
const auto & comp :
index_range(comp_and_qp))
2411 const std::vector<Number> & qp_values = comp_and_qp[comp];
2418 bool update_optimal_point =
false;
2419 if (!eim_point_data)
2420 update_optimal_point = (abs_value > largest_abs_value);
2422 update_optimal_point = (elem_id == eim_point_data->
elem_id) &&
2423 (side_index == eim_point_data->
side_index) &&
2427 if (update_optimal_point)
2429 largest_abs_value = abs_value;
2430 optimal_value =
value;
2431 optimal_comp = comp;
2432 optimal_elem_id = elem_id;
2433 optimal_side_index = side_index;
2436 optimal_point_phi_i_qp.resize(phi.size());
2438 optimal_point_phi_i_qp[i] = phi[i][qp];
2440 const auto & point_list =
2443 libmesh_error_msg_if(qp >= point_list.size(),
"Error: Invalid qp");
2445 optimal_point = point_list[qp];
2452 const auto & perturb_list =
2455 libmesh_error_msg_if(qp >= perturb_list.size(),
"Error: Invalid qp");
2457 optimal_point_perturbs = perturb_list[qp];
2466 unsigned int proc_ID_index;
2467 this->
comm().
maxloc(largest_abs_value, proc_ID_index);
2474 this->
comm().
broadcast(optimal_subdomain_id, proc_ID_index);
2477 this->
comm().
broadcast(optimal_point_perturbs, proc_ID_index);
2478 this->
comm().
broadcast(optimal_point_phi_i_qp, proc_ID_index);
2482 if (add_basis_function)
2484 if (optimal_value == 0.)
2486 libMesh::out <<
"Encountered linearly dependent data in EIM enrichment, hence skip adding new basis function" << std::endl;
2502 optimal_subdomain_id,
2503 optimal_boundary_id,
2505 optimal_point_perturbs,
2506 optimal_point_phi_i_qp);
2513 bool add_basis_function,
2532 for (
unsigned int i=0; i<RB_size; i++)
2551 Number optimal_value = 0.;
2552 Point optimal_point;
2553 unsigned int optimal_comp = 0;
2558 Real largest_abs_value = -1.;
2560 for (
const auto & [node_id, values] : local_pf)
2567 bool update_optimal_point =
false;
2568 if (!eim_point_data)
2569 update_optimal_point = (abs_value > largest_abs_value);
2571 update_optimal_point = (node_id == eim_point_data->
node_id) &&
2574 if (update_optimal_point)
2576 largest_abs_value = abs_value;
2577 optimal_value =
value;
2578 optimal_comp = comp;
2579 optimal_node_id = node_id;
2590 unsigned int proc_ID_index;
2591 this->
comm().
maxloc(largest_abs_value, proc_ID_index);
2601 if (add_basis_function)
2603 if (optimal_value == 0.)
2605 libMesh::out <<
"Encountered linearly dependent data in EIM enrichment, hence skip adding new basis function" << std::endl;
2620 optimal_boundary_id);
2627 bool add_basis_function,
2646 for (
unsigned int i=0; i<RB_size; i++)
2666 Number optimal_value = 0.;
2667 Point optimal_point;
2668 unsigned int optimal_comp = 0;
2671 unsigned int optimal_qp = 0;
2672 std::vector<Point> optimal_point_perturbs;
2673 std::vector<Real> optimal_point_phi_i_qp;
2675 std::vector<Real> optimal_JxW_all_qp;
2676 std::vector<std::vector<Real>> optimal_phi_i_all_qp;
2678 Point optimal_dxyzdxi_elem_center;
2679 Point optimal_dxyzdeta_elem_center;
2682 Real largest_abs_value = -1.;
2695 for (
const auto & [elem_id, comp_and_qp] : local_pf)
2702 const std::vector<std::vector<Real>> & phi = elem_fe->get_phi();
2703 const auto & JxW = elem_fe->get_JxW();
2704 const auto & dxyzdxi = elem_fe->get_dxyzdxi();
2705 const auto & dxyzdeta = elem_fe->get_dxyzdeta();
2707 elem_fe->reinit(&elem_ref);
2709 for (
const auto & comp :
index_range(comp_and_qp))
2711 const std::vector<Number> & qp_values = comp_and_qp[comp];
2721 bool update_optimal_point =
false;
2722 if (!eim_point_data)
2723 update_optimal_point = (abs_value > largest_abs_value);
2725 update_optimal_point = (elem_id == eim_point_data->
elem_id) &&
2729 if (update_optimal_point)
2731 largest_abs_value = abs_value;
2732 optimal_value =
value;
2733 optimal_comp = comp;
2734 optimal_elem_id = elem_id;
2736 optimal_elem_type = elem_ref.
type();
2738 optimal_point_phi_i_qp.resize(phi.size());
2740 optimal_point_phi_i_qp[i] = phi[i][qp];
2742 const auto & point_list =
2745 libmesh_error_msg_if(qp >= point_list.size(),
"Error: Invalid qp");
2747 optimal_point = point_list[qp];
2753 const auto & perturb_list =
2756 libmesh_error_msg_if(qp >= perturb_list.size(),
"Error: Invalid qp");
2758 optimal_point_perturbs = perturb_list[qp];
2763 optimal_JxW_all_qp = JxW;
2764 optimal_phi_i_all_qp = phi;
2772 elem_fe->reinit (&elem_ref, &nodes);
2774 Point dxyzdxi_pt, dxyzdeta_pt;
2776 dxyzdxi_pt = dxyzdxi[0];
2778 dxyzdeta_pt = dxyzdeta[0];
2780 optimal_dxyzdxi_elem_center = dxyzdxi_pt;
2781 optimal_dxyzdeta_elem_center = dxyzdeta_pt;
2783 elem_fe->reinit(&elem_ref);
2792 unsigned int proc_ID_index;
2793 this->
comm().
maxloc(largest_abs_value, proc_ID_index);
2799 this->
comm().
broadcast(optimal_subdomain_id, proc_ID_index);
2801 this->
comm().
broadcast(optimal_point_perturbs, proc_ID_index);
2802 this->
comm().
broadcast(optimal_point_phi_i_qp, proc_ID_index);
2804 this->
comm().
broadcast(optimal_phi_i_all_qp, proc_ID_index);
2805 this->
comm().
broadcast(optimal_dxyzdxi_elem_center, proc_ID_index);
2806 this->
comm().
broadcast(optimal_dxyzdeta_elem_center, proc_ID_index);
2810 int optimal_elem_type_int =
static_cast<int>(optimal_elem_type);
2811 this->
comm().
broadcast(optimal_elem_type_int, proc_ID_index);
2812 optimal_elem_type =
static_cast<ElemType>(optimal_elem_type_int);
2817 int optimal_qrule_order_int =
static_cast<int>(optimal_qrule_order);
2818 this->
comm().
broadcast(optimal_qrule_order_int, proc_ID_index);
2819 optimal_qrule_order =
static_cast<Order>(optimal_qrule_order_int);
2824 if (add_basis_function)
2826 if (optimal_value == 0.)
2828 libMesh::out <<
"Encountered linearly dependent data in EIM enrichment, hence skip adding new basis function" << std::endl;
2843 optimal_subdomain_id,
2845 optimal_point_perturbs,
2846 optimal_point_phi_i_qp,
2849 optimal_phi_i_all_qp,
2850 optimal_qrule_order,
2851 optimal_dxyzdxi_elem_center,
2852 optimal_dxyzdeta_elem_center);
2860 LOG_SCOPE(
"update_eim_matrices()",
"RBEIMConstruction");
2865 libmesh_assert_msg(RB_size >= 1,
"Must have at least 1 basis function.");
2867 if (set_eim_error_indicator)
2878 for (
unsigned int j=0; j<RB_size; j++)
2888 extra_point_row(j) =
value;
2894 for (
unsigned int j=0; j<RB_size; j++)
2902 extra_point_row(j) =
value;
2908 for (
unsigned int j=0; j<RB_size; j++)
2917 extra_point_row(j) =
value;
2929 for (
unsigned int i=(RB_size-1); i<RB_size; i++)
2931 for (
unsigned int j=0; j<RB_size; j++)
2947 for (
unsigned int j=0; j<RB_size; j++)
2964 for (
unsigned int i=(RB_size-1); i<RB_size; i++)
2966 for (
unsigned int j=0; j<RB_size; j++)
2982 for (
unsigned int j=0; j<RB_size; j++)
2997 for (
unsigned int i=(RB_size-1); i<RB_size; i++)
2999 for (
unsigned int j=0; j<RB_size; j++)
3015 for (
unsigned int j=0; j<RB_size; j++)
3032 for (
auto & pr : local_pf)
3034 auto & values = pr.second;
3035 for (
auto &
value : values)
3036 value *= scaling_factor;
3047 std::default_random_engine gen;
3048 std::uniform_int_distribution<> dist{0,
static_cast<int>(n)};
3063 if (
comm().size() > 1)
3078 bool error_finding_new_element =
false;
3079 if (
comm().rank() == 0)
3084 std::set<dof_id_type> previous_elem_ids(vec_eval_input.
elem_ids.begin(), vec_eval_input.
elem_ids.end());
3100 std::set<dof_id_type> new_elem_ids;
3101 for (
const auto & v_pair : *v_ptr)
3102 if (previous_elem_ids.count(v_pair.first) == 0)
3103 new_elem_ids.insert(v_pair.first);
3109 error_finding_new_element = (new_elem_ids.empty());
3111 if (!error_finding_new_element)
3115 auto item = new_elem_ids.begin();
3116 std::advance(item, random_elem_idx);
3117 eim_point_data.
elem_id = *item;
3121 if (!error_finding_new_element)
3124 const auto & vars_and_qps = libmesh_map_find(*v_ptr,eim_point_data.
elem_id);
3129 const auto & qps = libmesh_map_find(*v_ptr,eim_point_data.
elem_id)[eim_point_data.
comp_index];
3136 libmesh_error_msg_if(error_finding_new_element,
"Could not find new element in get_random_point()");
3143 return eim_point_data;
3157 if (
comm().size() > 1)
3172 bool error_finding_new_element_and_side =
false;
3173 if (
comm().rank() == 0)
3177 std::pair<dof_id_type,unsigned int> elem_and_side;
3179 std::set<std::pair<dof_id_type,unsigned int>> previous_elem_and_side_ids;
3182 previous_elem_and_side_ids.insert(
3189 std::set<std::pair<dof_id_type,unsigned int>> new_elem_and_side_ids;
3190 for (
const auto & v_pair : *v_ptr)
3191 if (previous_elem_and_side_ids.count(v_pair.first) == 0)
3192 new_elem_and_side_ids.insert(v_pair.first);
3198 error_finding_new_element_and_side = (new_elem_and_side_ids.empty());
3200 if (!error_finding_new_element_and_side)
3204 auto item = new_elem_and_side_ids.begin();
3205 std::advance(item, random_elem_and_side_idx);
3206 elem_and_side = *item;
3207 eim_point_data.
elem_id = elem_and_side.first;
3208 eim_point_data.
side_index = elem_and_side.second;
3212 if (!error_finding_new_element_and_side)
3215 const auto & vars_and_qps = libmesh_map_find(*v_ptr,elem_and_side);
3220 const auto & qps = libmesh_map_find(*v_ptr,elem_and_side)[eim_point_data.
comp_index];
3227 libmesh_error_msg_if(error_finding_new_element_and_side,
"Could not find new (element,side) in get_random_point()");
3235 return eim_point_data;
3249 if (
comm().size() > 1)
3264 bool error_finding_new_node =
false;
3265 if (
comm().rank() == 0)
3270 std::set<dof_id_type> previous_node_ids(vec_eval_input.
node_ids.begin(), vec_eval_input.
node_ids.end());
3274 std::set<dof_id_type> new_node_ids;
3275 for (
const auto & v_pair : *v_ptr)
3276 if (previous_node_ids.count(v_pair.first) == 0)
3277 new_node_ids.insert(v_pair.first);
3283 error_finding_new_node = (new_node_ids.empty());
3285 if (!error_finding_new_node)
3289 auto item = new_node_ids.begin();
3290 std::advance(item, random_node_idx);
3291 eim_point_data.
node_id = *item;
3295 if (!error_finding_new_node)
3297 const auto & vars = libmesh_map_find(*v_ptr,eim_point_data.
node_id);
3303 libmesh_error_msg_if(error_finding_new_node,
"Could not find new node in get_random_point()");
3309 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.