20 #include "libmesh/libmesh_common.h"    21 #include "libmesh/smoothness_estimator.h"    22 #include "libmesh/dof_map.h"    23 #include "libmesh/fe_base.h"    24 #include "libmesh/error_vector.h"    25 #include "libmesh/libmesh_logging.h"    26 #include "libmesh/elem.h"    27 #include "libmesh/quadrature.h"    28 #include "libmesh/system.h"    29 #include "libmesh/mesh_base.h"    30 #include "libmesh/numeric_vector.h"    31 #include "libmesh/enum_to_string.h"    54                                                 const unsigned int matsize)
    56   std::vector<Real> psi;
    60   const int npols = 
static_cast<int>(order) + 1;
    62   std::vector<Real> Lx(npols, 0.), Ly(npols, 1.), Lz(npols, 1.);
    67   for (
int n = 2; n < npols; ++n)
    68     Lx[n] = ((2. * n - 1) * x * Lx[n - 1] - (n - 1) * Lx[n - 2]) / n;
    76     for (
int n = 2; n < npols; ++n)
    77       Ly[n] = ((2. * n - 1) * y * Ly[n - 1] - (n - 1) * Ly[n - 2]) / n;
    86     for (
int n = 2; n < npols; ++n)
    87       Lz[n] = ((2. * n - 1) * z * Lz[n - 1] - (n - 1) * Lz[n - 2]) / n;
    91   for (
unsigned int poly_deg = 0; poly_deg <= static_cast<unsigned int>(order); poly_deg++)
    96         for (
int i = poly_deg; i >= 0; --i)
    97           for (
int j = poly_deg - i; j >= 0; --j)
    99             int k = poly_deg - i - j;
   100             psi.push_back(Lx[i] * Ly[j] * Lz[k]);
   105         for (
int i = poly_deg; i >= 0; --i)
   107           int j = poly_deg - i;
   108           psi.push_back(Lx[i] * Ly[j]);
   113         psi.push_back(Lx[poly_deg]);
   117         libmesh_error_msg(
"Invalid dimension dim " << 
dim);
   126     const Real denom = (N * Sxx - Sx * Sx);
   129     if (std::abs(denom) < std::numeric_limits<Real>::epsilon()) {
   130         return std::numeric_limits<Real>::max();
   132     return (N * Sxy - Sx * Sy) / denom;
   140   comm.
sum(smoothness_per_cell);
   147   LOG_SCOPE(
"estimate_smoothness()", 
"SmoothnessEstimator");
   154   smoothness_per_cell.resize (
mesh.max_elem_id());
   155   std::fill (smoothness_per_cell.begin(), smoothness_per_cell.end(), 0.);
   159   if (solution_vector && solution_vector != system.
solution.get())
   164       newsol->
swap(*sys.solution);
   172                                         mesh.active_local_elements_end(),
   187   if (solution_vector && solution_vector != system.
solution.get())
   191       newsol->
swap(*sys.solution);
   203   const unsigned int dim = 
mesh.mesh_dimension();
   213 for (
const auto & elem : range)
   217   for (
unsigned int var=0; var<
n_vars; var++)
   220     const Order element_order = fe_type.
order + elem->p_level();
   224     fe->attach_quadrature_rule(qrule.get());
   226     const std::vector<Real> & JxW = fe->get_JxW();
   227     const std::vector<Point> & q_point = fe->get_xyz();
   228     const std::vector<std::vector<Real>> * phi = &(fe->get_phi());
   230     std::vector<dof_id_type> dof_indices;
   232     unsigned int matsize = element_order + 1;
   235       matsize *= (element_order + 2);
   240       matsize *= (element_order + 3);
   255     libmesh_assert_equal_to(dof_indices.size(), phi->size());
   257     const unsigned int n_dofs = cast_int<unsigned int>(dof_indices.size());
   258     const unsigned int n_qp   = qrule->n_points();
   260     for (
unsigned int qp = 0; qp < n_qp; qp++)
   262       std::vector<Real> psi = 
legepoly(
dim, element_order, q_point[qp], matsize);
   263       const unsigned int psi_size = cast_int<unsigned int>(psi.size());
   265       for (
unsigned int i = 0; i < matsize; i++)
   266         for (
unsigned int j = 0; j < matsize; j++)
   267           Kp(i, j) += JxW[qp] * psi[i] * psi[j];
   270       for (
unsigned int i = 0; i < n_dofs; i++)
   273       for (
unsigned int i = 0; i < psi_size; i++)
   274         F(i) += JxW[qp] * u_h * psi[i];
   280     std::vector<unsigned int> total_degree_per_index;
   282     for (
unsigned int poly_deg = 0; poly_deg <= static_cast<unsigned int>(element_order); ++poly_deg)
   287           for (
int i = poly_deg; i >= 0; --i)
   288             for (
int j = poly_deg - i; j >= 0; --j)
   290               int k = poly_deg - i - j;
   291               total_degree_per_index.push_back(i + j + k);
   296           for (
int i = poly_deg; i >= 0; --i)
   298             int j = poly_deg - i;
   299             total_degree_per_index.push_back(i + j);
   304           total_degree_per_index.push_back(poly_deg);
   308           libmesh_error_msg(
"Invalid dimension dim " << 
dim);
   313     std::map<unsigned int, std::vector<Number>> coeff_by_degree;
   315     for (
unsigned int i = 0; i < Pu_h.
size(); ++i)
   317       unsigned int degree = total_degree_per_index[i];
   321         coeff_by_degree[degree].push_back(Pu_h(i));
   325     std::vector<unsigned int> degrees;
   326     std::vector<double> norms;
   328     for (
const auto & pair : coeff_by_degree)
   330       unsigned int deg = pair.first;
   331       const std::vector<Number> & coeffs = pair.second;
   334       for (
const auto & c : coeffs)
   339       degrees.push_back(deg);
   340       norms.push_back(
norm);
   345     std::vector<double> log_norms, log_degrees;
   347     for (
unsigned int i = 0; i < degrees.size(); ++i)
   350       if (norms[i] > 1e-12)
   352         log_degrees.push_back(std::log(static_cast<double>(degrees[i])));
   353         log_norms.push_back(std::log(norms[i]));
   359     double Sx = 0., Sy = 0., Sxx = 0., Sxy = 0.;
   360     const size_t N = log_degrees.size();
   362     for (
size_t i = 0; i < N; ++i)
   364       Sx += log_degrees[i];
   366       Sxx += log_degrees[i] * log_degrees[i];
   367       Sxy += log_degrees[i] * log_norms[i];
   370     const double regularity = -
compute_slope(N, Sx, Sy, Sxx, Sxy);
 class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
 
SmoothnessEstimator()
Constructor. 
 
Order
defines an enum for polynomial orders. 
 
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
 
void parallel_for(const Range &range, const Body &body)
Execute the provided function object in parallel on the specified range. 
 
ErrorVector & smoothness_per_cell
 
The ErrorVector is a specialization of the StatisticsVector for error data computed on a finite eleme...
 
static std::vector< Real > legepoly(const unsigned int dim, const Order order, const Point p, const unsigned int matsize)
 
void resize(const unsigned int n)
Resize the vector. 
 
int _extra_order
Extra order to use for quadrature rule. 
 
const Parallel::Communicator & comm() const
 
OrderWrapper order
The approximation order of the element. 
 
The StoredRange class defines a contiguous, divisible set of objects. 
 
The libMesh namespace provides an interface to certain functionality in the library. 
 
const MeshBase & get_mesh() const
 
This is the MeshBase class. 
 
StoredRange< MeshBase::const_element_iterator, const Elem * > ConstElemRange
 
Number current_solution(const dof_id_type global_dof_number) const
 
This class handles the numbering of degrees of freedom on a mesh. 
 
std::unique_ptr< QBase > default_quadrature_rule(const unsigned int dim, const int extraorder=0) const
 
friend class EstimateSmoothness
 
void operator()(const ConstElemRange &range) const
 
static Real compute_slope(int N, Real Sx, Real Sy, Real Sxx, Real Sxy)
Computes slop in a linear regression. 
 
Manages consistently variables, degrees of freedom, and coefficient vectors. 
 
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values. 
 
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type. 
 
const FEType & variable_type(const unsigned int i) const
 
virtual void estimate_smoothness(const System &system, ErrorVector &smoothness_per_cell, const NumericVector< Number > *solution_vector=nullptr)
This function uses the Legendre expansion of solution to estimate coefficient decay to quantify the s...
 
const SmoothnessEstimator & smoothness_estimator
 
void lu_solve(const DenseVector< T > &b, DenseVector< T > &x)
Solve the system Ax=b given the input vector b. 
 
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
 
virtual void swap(NumericVector< T > &v)
Swaps the contents of this with v. 
 
virtual unsigned int size() const override final
 
void reduce_smoothness(std::vector< ErrorVectorReal > &error_per_cell, const Parallel::Communicator &comm)
 
auto norm(const libMesh::TypeVector< T > &vector) -> decltype(std::norm(T()))
 
unsigned int n_vars() const
 
const DofMap & get_dof_map() const
 
A Point defines a location in LIBMESH_DIM dimensional Real space. 
 
spin_mutex spin_mtx
A convenient spin mutex object which can be used for obtaining locks.