21 #include "libmesh/rb_parametrized_function.h"    22 #include "libmesh/int_range.h"    23 #include "libmesh/point.h"    24 #include "libmesh/libmesh_logging.h"    25 #include "libmesh/utility.h"    26 #include "libmesh/rb_parameters.h"    27 #include "libmesh/system.h"    28 #include "libmesh/elem.h"    29 #include "libmesh/fem_context.h"    30 #include "libmesh/quadrature.h"    61 requires_xyz_perturbations(false),
    62 requires_all_elem_qp_data(false),
    63 requires_all_elem_center_data(false),
    64 is_lookup_table(false),
    66 _is_nodal_boundary(false)
    78                                       const std::vector<Point> & xyz_perturb,
    79                                       const std::vector<Real> & phi_i_qp)
    81   std::vector<Number> values = 
evaluate(mu, xyz, elem_id, qp, subdomain_id, xyz_perturb, phi_i_qp);
    83   libmesh_error_msg_if(comp >= values.size(), 
"Error: Invalid value of comp");
    93                                            unsigned int side_index,
    97                                            const std::vector<Point> & xyz_perturb,
    98                                            const std::vector<Real> & phi_i_qp)
   100   std::vector<Number> values = 
side_evaluate(mu, xyz, elem_id, side_index, qp, subdomain_id, boundary_id, xyz_perturb, phi_i_qp);
   102   libmesh_error_msg_if(comp >= values.size(), 
"Error: Invalid value of comp");
   114   std::vector<Number> values = 
node_evaluate(mu, xyz, node_id, boundary_id);
   116   libmesh_error_msg_if(comp >= values.size(), 
"Error: Invalid value of comp");
   127                                  const std::vector<Point> & ,
   128                                  const std::vector<Real> & )
   131   libmesh_not_implemented();
   133   return std::vector<Number>();
   144                                       const std::vector<Point> & ,
   145                                       const std::vector<Real> & )
   148   libmesh_not_implemented();
   150   return std::vector<Number>();
   160   libmesh_not_implemented();
   162   return std::vector<Number>();
   167                                                  std::vector<std::vector<std::vector<Number>>> & output)
   169   LOG_SCOPE(
"vectorized_evaluate()", 
"RBParametrizedFunction");
   172   unsigned int n_points = v.
all_xyz.size();
   174   libmesh_error_msg_if(v.
sbd_ids.size() != n_points, 
"Error: invalid vector sizes");
   178   std::vector<Point> empty_perturbs;
   188   std::vector<std::vector<std::vector<Number>>> all_evals(mus.size());
   192       all_evals[mu_index].resize(n_points);
   193       for (
auto point_index : 
index_range(all_evals[mu_index]))
   196           all_evals[mu_index][point_index] =
   213           auto n_samples = mus[mu_index].n_samples();
   214           auto received_data = all_evals[mu_index][point_index].size();
   215           libmesh_error_msg_if(received_data != n_components * n_samples,
   216                                "Recieved " << received_data <<
   217                                " evaluated values but expected to receive " << n_components * n_samples);
   224   unsigned int output_size = 0;
   225   for (
const auto & mu : mus)
   226     output_size += mu.n_samples();
   228   output.resize(output_size);
   232   for (
auto [mu_index, output_index] = std::make_tuple(0u, 0u); mu_index < mus.size(); ++mu_index)
   234       auto n_samples = mus[mu_index].n_samples();
   235       for (
auto mu_sample_idx = 0u; mu_sample_idx < n_samples; ++mu_sample_idx, ++output_index)
   237           output[output_index].resize(n_points);
   240               output[output_index][point_index].resize(n_components);
   243                 output[output_index][point_index][comp] = all_evals[mu_index][point_index][n_components*mu_sample_idx + comp];
   251                                                       std::vector<std::vector<std::vector<Number>>> & output)
   253   LOG_SCOPE(
"side_vectorized_evaluate()", 
"RBParametrizedFunction");
   256   unsigned int n_points = v.
all_xyz.size();
   258   libmesh_error_msg_if(v.
sbd_ids.size() != n_points, 
"Error: invalid vector sizes");
   262   std::vector<Point> empty_perturbs;
   272   std::vector<std::vector<std::vector<Number>>> all_evals(mus.size());
   276       all_evals[mu_index].resize(n_points);
   277       for (
auto point_index : 
index_range(all_evals[mu_index]))
   280           all_evals[mu_index][point_index] =
   299           auto n_samples = mus[mu_index].n_samples();
   300           auto received_data = all_evals[mu_index][point_index].size();
   301           libmesh_error_msg_if(received_data != n_components * n_samples,
   302                                "Recieved " << received_data <<
   303                                " evaluated values but expected to receive " << n_components * n_samples);
   310   unsigned int output_size = 0;
   311   for (
const auto & mu : mus)
   312     output_size += mu.n_samples();
   314   output.resize(output_size);
   318   for (
auto [mu_index, output_index] = std::make_tuple(0u, 0u); mu_index < mus.size(); ++mu_index)
   320       auto n_samples = mus[mu_index].n_samples();
   321       for (
auto mu_sample_idx = 0u; mu_sample_idx < n_samples; ++mu_sample_idx, ++output_index)
   323           output[output_index].resize(n_points);
   326               output[output_index][point_index].resize(n_components);
   329                 output[output_index][point_index][comp] = all_evals[mu_index][point_index][n_components*mu_sample_idx + comp];
   337                                                       std::vector<std::vector<std::vector<Number>>> & output)
   339   LOG_SCOPE(
"node_vectorized_evaluate()", 
"RBParametrizedFunction");
   342   unsigned int n_points = v.
all_xyz.size();
   352   std::vector<std::vector<std::vector<Number>>> all_evals(mus.size());
   356       all_evals[mu_index].resize(n_points);
   357       for (
auto point_index : 
index_range(all_evals[mu_index]))
   360           all_evals[mu_index][point_index] =
   374           auto n_samples = mus[mu_index].n_samples();
   375           auto received_data = all_evals[mu_index][point_index].size();
   376           libmesh_error_msg_if(received_data != n_components * n_samples,
   377                                "Recieved " << received_data <<
   378                                " evaluated values but expected to receive " << n_components * n_samples);
   385   unsigned int output_size = 0;
   386   for (
const auto & mu : mus)
   387     output_size += mu.n_samples();
   389   output.resize(output_size);
   393   for (
auto [mu_index, output_index] = std::make_tuple(0u, 0u); mu_index < mus.size(); ++mu_index)
   395       auto n_samples = mus[mu_index].n_samples();
   396       for (
auto mu_sample_idx = 0u; mu_sample_idx < n_samples; ++mu_sample_idx, ++output_index)
   398           output[output_index].resize(n_points);
   401               output[output_index][point_index].resize(n_components);
   404                 output[output_index][point_index][comp] = all_evals[mu_index][point_index][n_components*mu_sample_idx + comp];
   411                                                                        const std::unordered_map<
dof_id_type, std::vector<Point>> & all_xyz,
   412                                                                        const std::unordered_map<dof_id_type, subdomain_id_type> & sbd_ids,
   413                                                                        const std::unordered_map<
dof_id_type, std::vector<std::vector<Point>> > & all_xyz_perturb,
   418   unsigned int n_elems = all_xyz.size();
   419   unsigned int n_points = 0;
   420   for (
const auto & xyz_pair : all_xyz)
   422     const std::vector<Point> & xyz_vec = xyz_pair.second;
   423     n_points += xyz_vec.size();
   429   v.
qps.resize(n_points);
   451   std::vector<Point> empty_perturbs;
   464   unsigned int counter = 0;
   465   unsigned int elem_counter = 0;
   466   for (
const auto & [elem_id, xyz_vec] : all_xyz)
   471       auto n_qp = xyz_vec.size();
   479       const std::vector<std::vector<Real>> & phi = elem_fe->get_phi();
   480       const std::vector<Real> & JxW = elem_fe->get_JxW();
   481       const auto & dxyzdxi = elem_fe->get_dxyzdxi();
   482       const auto & dxyzdeta = elem_fe->get_dxyzdeta();
   484       elem_fe->reinit(&elem_ref);
   490           v.
all_xyz[counter] = xyz_vec[qp];
   493           v.
sbd_ids[counter] = subdomain_id;
   496           v.
phi_i_qp[counter].resize(phi.size());
   498             v.
phi_i_qp[counter][i] = phi[i][qp];
   502               const auto & qps_and_perturbs =
   503                 libmesh_map_find(all_xyz_perturb, elem_id);
   504               libmesh_error_msg_if(qp >= qps_and_perturbs.size(), 
"Error: Invalid qp");
   519                   v.
JxW_all_qp[elem_counter].resize(JxW.size());
   544           elem_fe->reinit (&elem_ref, &nodes);
   551           Point dxyzdxi_pt, dxyzdeta_pt;
   553             dxyzdxi_pt = dxyzdxi[0];
   555             dxyzdeta_pt = dxyzdeta[0];
   568   std::vector<RBParameters> mus {mu};
   575                                                                              const std::map<std::pair<dof_id_type,unsigned int>, std::vector<Point>> & side_all_xyz,
   576                                                                              const std::map<std::pair<dof_id_type,unsigned int>, 
subdomain_id_type> & sbd_ids,
   577                                                                              const std::map<std::pair<dof_id_type,unsigned int>, 
boundary_id_type> & side_boundary_ids,
   578                                                                              const std::map<std::pair<dof_id_type,unsigned int>, 
unsigned int> & side_types,
   579                                                                              const std::map<std::pair<dof_id_type,unsigned int>, std::vector<std::vector<Point>> > & side_all_xyz_perturb,
   584   unsigned int n_points = 0;
   585   for (
const auto & xyz_pair : side_all_xyz)
   587     const std::vector<Point> & xyz_vec = xyz_pair.second;
   588     n_points += xyz_vec.size();
   595   v.
qps.resize(n_points);
   602   std::vector<Point> empty_perturbs;
   615   unsigned int counter = 0;
   616   for (
const auto & xyz_pair : side_all_xyz)
   618       auto elem_side_pair = xyz_pair.first;
   620       unsigned int side_index = elem_side_pair.second;
   622       const std::vector<Point> & xyz_vec = xyz_pair.second;
   625       boundary_id_type boundary_id = libmesh_map_find(side_boundary_ids, elem_side_pair);
   626       unsigned int side_type = libmesh_map_find(side_types, elem_side_pair);
   629       auto n_qp = xyz_vec.size();
   639           std::unique_ptr<const Elem> elem_side;
   643           side_fe->reinit(&elem_ref, side_index);
   645           const std::vector<std::vector<Real>> & phi = side_fe->get_phi();
   650               v.
all_xyz[counter] = xyz_vec[qp];
   651               v.
elem_ids[counter] = elem_side_pair.first;
   654               v.
sbd_ids[counter] = subdomain_id;
   657               v.
phi_i_qp[counter].resize(phi.size());
   659                 v.
phi_i_qp[counter][i] = phi[i][qp];
   663                   const auto & qps_and_perturbs =
   664                     libmesh_map_find(side_all_xyz_perturb, elem_side_pair);
   665                   libmesh_error_msg_if(qp >= qps_and_perturbs.size(), 
"Error: Invalid qp");
   676       else if (side_type == 1)
   679           const std::vector<std::vector<Real>> & phi = elem_fe->get_phi();
   681           elem_fe->reinit(&elem_ref);
   687               v.
all_xyz[counter] = xyz_vec[qp];
   688               v.
elem_ids[counter] = elem_side_pair.first;
   691               v.
sbd_ids[counter] = subdomain_id;
   694               v.
phi_i_qp[counter].resize(phi.size());
   696                 v.
phi_i_qp[counter][i] = phi[i][qp];
   700                   const auto & qps_and_perturbs =
   701                     libmesh_map_find(side_all_xyz_perturb, elem_side_pair);
   702                   libmesh_error_msg_if(qp >= qps_and_perturbs.size(), 
"Error: Invalid qp");
   714         libmesh_error_msg (
"Unrecognized side_type: " << side_type);
   717   std::vector<RBParameters> mus {mu};
   724                                                                              const std::unordered_map<dof_id_type, Point> & all_xyz,
   725                                                                              const std::unordered_map<dof_id_type, boundary_id_type> & node_boundary_ids,
   730   unsigned int n_points = all_xyz.size();
   738   std::vector<Point> empty_perturbs;
   740   unsigned int counter = 0;
   741   for (
const auto & [node_id, p] : all_xyz)
   743       boundary_id_type boundary_id = libmesh_map_find(node_boundary_ids, node_id);
   754   std::vector<RBParameters> mus {mu};
   762                                                                  unsigned int qp)
 const   764   const std::vector<unsigned int> & indices_at_qps =
   767   libmesh_error_msg_if(qp >= indices_at_qps.size(), 
"Error: invalid qp");
   769   unsigned int index = indices_at_qps[qp];
   770   libmesh_error_msg_if(
preevaluated_values.size() != 1, 
"Error: we expect only one parameter index");
   778                                                                       unsigned int side_index,
   779                                                                       unsigned int qp)
 const   781   const std::vector<unsigned int> & indices_at_qps =
   784   libmesh_error_msg_if(qp >= indices_at_qps.size(), 
"Error: invalid qp");
   786   unsigned int index = indices_at_qps[qp];
   787   libmesh_error_msg_if(
preevaluated_values.size() != 1, 
"Error: we expect only one parameter index");
   799   libmesh_error_msg_if(
preevaluated_values.size() != 1, 
"Error: we expect only one parameter index");
   840   bool insert_succeed = 
_rb_property_map.insert({property_name, entity_ids}).second;
   841   libmesh_error_msg_if(!insert_succeed, 
"Entry already added, duplicate detected.");
   846   std::unordered_map<std::string, std::set<dof_id_type>> & ,
 virtual unsigned int get_n_components() const =0
Specify the number of components in this parametrized function. 
virtual void get_spatial_indices(std::vector< std::vector< unsigned int >> &spatial_indices, const VectorizedEvalInput &v)
In some cases a parametrized function is defined based on array data that we index into based on the ...
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. 
virtual void initialize_spatial_indices(const std::vector< std::vector< unsigned int >> &spatial_indices, const VectorizedEvalInput &v)
The Online stage counterpart of get_spatial_indices(). 
Order
defines an enum for polynomial orders. 
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. 
virtual void add_interpolation_data_to_rb_property_map(const Parallel::Communicator &comm, std::unordered_map< std::string, std::set< dof_id_type >> &rb_property_map, dof_id_type elem_id)
Virtual function that can be overridden in RBParametrizedFunction subclasses to store properties in t...
void set_parametrized_function_boundary_ids(const std::set< boundary_id_type > &boundary_ids, bool is_nodal_boundary)
std::unordered_map< dof_id_type, unsigned int > mesh_to_preevaluated_node_values_map
Indexing into preevaluated_values for the case where the preevaluated values were obtained from evalu...
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 ...
virtual std::unique_ptr< Elem > build_side_ptr(const unsigned int i)=0
unsigned char get_elem_dim() const
std::set< boundary_id_type > _parametrized_function_boundary_ids
In the case of an RBParametrizedFunction defined on element sides, this defines the set of boundary I...
std::unordered_map< std::string, std::set< dof_id_type > > _rb_property_map
Generic property map used to store data during mesh pre-evaluation. 
This is the base class from which all geometric element types are derived. 
virtual void side_vectorized_evaluate(const std::vector< RBParameters > &mus, const VectorizedEvalInput &v, std::vector< std::vector< std::vector< Number >>> &output)
Same as vectorized_evaluate() but on element sides. 
The libMesh namespace provides an interface to certain functionality in the library. 
const MeshBase & get_mesh() const
const std::unordered_map< std::string, std::set< dof_id_type > > & get_rb_property_map() const
Function that returns a reference to the rb_property_map stored in the RBParametrizedFunction. 
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. 
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...
void add_rb_property_map_entry(std::string &property_name, std::set< dof_id_type > &entity_ids)
Function that adds a property to the RBParametrizedFunction rb_property_map. 
virtual Number side_evaluate_comp(const RBParameters &mu, unsigned int comp, const Point &xyz, dof_id_type elem_id, unsigned int side_index, unsigned int qp, subdomain_id_type subdomain_id, boundary_id_type boundary_id, const std::vector< Point > &xyz_perturb, const std::vector< Real > &phi_i_qp)
Same as evaluate_comp() but for element sides. 
Manages consistently variables, degrees of freedom, and coefficient vectors. 
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 Number node_evaluate_comp(const RBParameters &mu, unsigned int comp, const Point &xyz, dof_id_type node_id, boundary_id_type boundary_id)
Same as evaluate_comp() but for element nodes. 
This class provides all data required for a physics package (e.g. 
bool on_mesh_nodes() const
const Elem * reference_elem() const
virtual std::vector< Number > side_evaluate(const RBParameters &mu, const Point &xyz, dof_id_type elem_id, unsigned int side_index, unsigned int qp, subdomain_id_type subdomain_id, boundary_id_type boundary_id, const std::vector< Point > &xyz_perturb, const std::vector< Real > &phi_i_qp)
Same as evaluate() but for element sides. 
std::map< std::string, std::map< subdomain_id_type, Number > > _parameter_independent_data
In some cases we need to store parameter-independent data which is related to this function but since...
bool requires_all_elem_qp_data
Boolean to indicate whether this parametrized function requires data from all qps on the current elem...
virtual void preevaluate_parametrized_function_cleanup()
Virtual function that performs cleanup after each "preevaluate parametrized function" evaluation...
This class is part of the rbOOmit framework. 
virtual Number evaluate_comp(const RBParameters &mu, unsigned int comp, const Point &xyz, dof_id_type elem_id, unsigned int qp, subdomain_id_type subdomain_id, const std::vector< Point > &xyz_perturb, const std::vector< Real > &phi_i_qp)
Evaluate the parametrized function at the specified point for parameter mu. 
bool requires_all_elem_center_data
Boolean to indicate whether this parametrized function requires data from the center on the current e...
std::map< std::pair< dof_id_type, unsigned int >, std::vector< unsigned int > > mesh_to_preevaluated_side_values_map
Similar to the above except this map stores the data on element sides. 
bool requires_xyz_perturbations
Boolean to indicate whether this parametrized function requires xyz perturbations in order to evaluat...
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. 
bool _is_nodal_boundary
In the case that _parametrized_function_boundary_ids is not empty, then this parametrized function is...
virtual ~RBParametrizedFunction()
RBParametrizedFunction()
Constructor. 
Number get_parameter_independent_data(const std::string &property_name, subdomain_id_type sbd_id) const
Get the value stored in _parameter_independent_data associated with region_name and property_name...
std::vector< std::vector< std::vector< Number > > > preevaluated_values
Storage for pre-evaluated values. 
virtual unsigned short dim() const =0
virtual const Elem & elem_ref(const dof_id_type i) const
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...
virtual void node_vectorized_evaluate(const std::vector< RBParameters > &mus, const VectorizedEvalInput &v, std::vector< std::vector< std::vector< Number >>> &output)
Same as vectorized_evaluate() but on element nodes. 
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...
virtual std::vector< Number > evaluate(const RBParameters &mu, const Point &xyz, dof_id_type elem_id, unsigned int qp, subdomain_id_type subdomain_id, const std::vector< Point > &xyz_perturb, const std::vector< Real > &phi_i_qp)
Evaluate the parametrized function at the specified point for parameter mu. 
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::unordered_map< dof_id_type, std::vector< unsigned int > > mesh_to_preevaluated_values_map
Indexing into preevaluated_values for the case where the preevaluated values were obtained from evalu...
bool on_mesh_sides() const
virtual void initialize_lookup_table()
If this parametrized function is defined based on a lookup table then we can call this function to in...
virtual ElemType type() const =0
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...
const QBase & get_element_qrule() const
Accessor for element interior quadrature rule for the dimension of the current _elem. 
Point vertex_average() const
const std::set< unsigned char > & elem_dimensions() const
virtual std::vector< Number > node_evaluate(const RBParameters &mu, const Point &xyz, dof_id_type node_id, boundary_id_type boundary_id)
Same as evaluate() but for element nodes. 
virtual void vectorized_evaluate(const std::vector< RBParameters > &mus, const VectorizedEvalInput &v, std::vector< std::vector< std::vector< Number >>> &output)
Vectorized version of evaluate.