libMesh
Public Member Functions | Private Attributes | List of all members
libMesh::SmoothnessEstimator::EstimateSmoothness Class Reference

Class to compute the error contribution for a range of elements. More...

Public Member Functions

 EstimateSmoothness (const System &sys, const SmoothnessEstimator &ee, ErrorVector &epc)
 
void operator() (const ConstElemRange &range) const
 

Private Attributes

const Systemsystem
 
const SmoothnessEstimatorsmoothness_estimator
 
ErrorVectorsmoothness_per_cell
 

Detailed Description

Class to compute the error contribution for a range of elements.

May be executed in parallel on separate threads.

Definition at line 118 of file smoothness_estimator.h.

Constructor & Destructor Documentation

◆ EstimateSmoothness()

libMesh::SmoothnessEstimator::EstimateSmoothness::EstimateSmoothness ( const System sys,
const SmoothnessEstimator ee,
ErrorVector epc 
)
inline

Member Function Documentation

◆ operator()()

void libMesh::SmoothnessEstimator::EstimateSmoothness::operator() ( const ConstElemRange range) const

Definition at line 197 of file smoothness_estimator.C.

References libMesh::SmoothnessEstimator::_extra_order, libMesh::FEGenericBase< OutputType >::build(), libMesh::SmoothnessEstimator::compute_slope(), libMesh::System::current_solution(), libMesh::FEType::default_quadrature_rule(), dim, libMesh::DofMap::dof_indices(), libMesh::System::get_dof_map(), libMesh::System::get_mesh(), libMesh::SmoothnessEstimator::legepoly(), libMesh::DenseMatrix< T >::lu_solve(), mesh, n_vars, libMesh::System::n_vars(), std::norm(), libMesh::TensorTools::norm(), libMesh::FEType::order, libMesh::DenseVector< T >::resize(), libMesh::DenseVector< T >::size(), smoothness_estimator, smoothness_per_cell, libMesh::Threads::spin_mtx, system, libMesh::DofMap::variable_type(), and libMesh::zero.

198 {
199  // The current mesh
200  const MeshBase & mesh = system.get_mesh();
201 
202  // The dimensionality of the mesh
203  const unsigned int dim = mesh.mesh_dimension();
204 
205  // The number of variables in the system
206  const unsigned int n_vars = system.n_vars();
207 
208  // The DofMap for this system
209  const DofMap & dof_map = system.get_dof_map();
210 
211  //------------------------------------------------------------
212  // Iterate over all the elements in the range.
213 for (const auto & elem : range)
214 {
215  const dof_id_type e_id = elem->id();
216  // Loop over each variable
217  for (unsigned int var=0; var<n_vars; var++)
218  {
219  const FEType & fe_type = dof_map.variable_type(var);
220  const Order element_order = fe_type.order + elem->p_level();
221 
222  std::unique_ptr<FEBase> fe(FEBase::build(dim, fe_type));
223  std::unique_ptr<QBase> qrule(fe_type.default_quadrature_rule(dim, smoothness_estimator._extra_order));
224  fe->attach_quadrature_rule(qrule.get());
225 
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());
229 
230  std::vector<dof_id_type> dof_indices;
231 
232  unsigned int matsize = element_order + 1;
233  if (dim > 1)
234  {
235  matsize *= (element_order + 2);
236  matsize /= 2;
237  }
238  if (dim > 2)
239  {
240  matsize *= (element_order + 3);
241  matsize /= 3;
242  }
243 
244  DenseMatrix<Number> Kp(matsize, matsize);
245  DenseVector<Number> F;
246  DenseVector<Number> Pu_h;
247 
248  F.resize(matsize);
249  Pu_h.resize(matsize);
250 
251 
252  fe->reinit(elem);
253 
254  dof_map.dof_indices(elem, dof_indices, var);
255  libmesh_assert_equal_to(dof_indices.size(), phi->size());
256 
257  const unsigned int n_dofs = cast_int<unsigned int>(dof_indices.size());
258  const unsigned int n_qp = qrule->n_points();
259 
260  for (unsigned int qp = 0; qp < n_qp; qp++)
261  {
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());
264 
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];
268 
269  Number u_h = libMesh::zero;
270  for (unsigned int i = 0; i < n_dofs; i++)
271  u_h += (*phi)[i][qp] * system.current_solution(dof_indices[i]);
272 
273  for (unsigned int i = 0; i < psi_size; i++)
274  F(i) += JxW[qp] * u_h * psi[i];
275  }
276 
277  Kp.lu_solve(F, Pu_h);
278 
279  // Generate index to total degree map. Total_degree_per_index[i] gives the degree ith basis function
280  std::vector<unsigned int> total_degree_per_index;
281 
282  for (unsigned int poly_deg = 0; poly_deg <= static_cast<unsigned int>(element_order); ++poly_deg)
283  {
284  switch (dim)
285  {
286  case 3:
287  for (int i = poly_deg; i >= 0; --i)
288  for (int j = poly_deg - i; j >= 0; --j)
289  {
290  int k = poly_deg - i - j;
291  total_degree_per_index.push_back(i + j + k);
292  }
293  break;
294 
295  case 2:
296  for (int i = poly_deg; i >= 0; --i)
297  {
298  int j = poly_deg - i;
299  total_degree_per_index.push_back(i + j);
300  }
301  break;
302 
303  case 1:
304  total_degree_per_index.push_back(poly_deg);
305  break;
306 
307  default:
308  libmesh_error_msg("Invalid dimension dim " << dim);
309  }
310  }
311 
312  // Group coefficients |c_k| by degree k
313  std::map<unsigned int, std::vector<Number>> coeff_by_degree;
314 
315  for (unsigned int i = 0; i < Pu_h.size(); ++i)
316  {
317  unsigned int degree = total_degree_per_index[i];
318  // Excluding the constant mode i.e, zeroth order coefficient as we use ln|order| later
319  // Constant order term often dominates the scale and doesn't inform about regularity.
320  if (degree > 0)
321  coeff_by_degree[degree].push_back(Pu_h(i));
322  }
323 
324  // Compute L2 norm of each group |c_k|
325  std::vector<unsigned int> degrees;
326  std::vector<double> norms;
327 
328  for (const auto & pair : coeff_by_degree)
329  {
330  unsigned int deg = pair.first;
331  const std::vector<Number> & coeffs = pair.second;
332 
333  double norm = 0.;
334  for (const auto & c : coeffs)
335  norm += std::norm(c);
336 
337  norm = std::sqrt(norm);
338 
339  degrees.push_back(deg);
340  norms.push_back(norm);
341  }
342 
343 
344  // Collect log |c_k| and log |k|
345  std::vector<double> log_norms, log_degrees;
346 
347  for (unsigned int i = 0; i < degrees.size(); ++i)
348  {
349  // filter tiny terms
350  if (norms[i] > 1e-12)
351  {
352  log_degrees.push_back(std::log(static_cast<double>(degrees[i])));
353  log_norms.push_back(std::log(norms[i]));
354  }
355  }
356 
357 
358  // Fit log-log line - we use least-squares fit
359  double Sx = 0., Sy = 0., Sxx = 0., Sxy = 0.;
360  const size_t N = log_degrees.size();
361 
362  for (size_t i = 0; i < N; ++i)
363  {
364  Sx += log_degrees[i];
365  Sy += log_norms[i];
366  Sxx += log_degrees[i] * log_degrees[i];
367  Sxy += log_degrees[i] * log_norms[i];
368  }
369 
370  const double regularity = -compute_slope(N, Sx, Sy, Sxx, Sxy);
371  // const double intercept = (Sy - slope * Sx) / N;
372 
373  Threads::spin_mutex::scoped_lock acquire(Threads::spin_mtx);
374  smoothness_per_cell[e_id] = regularity;
375  } // end variables loop
376 
377 } // end element loop
378 
379 } // End () operator definition
Order
defines an enum for polynomial orders.
Definition: enum_order.h:40
unsigned int dim
static std::vector< Real > legepoly(const unsigned int dim, const Order order, const Point p, const unsigned int matsize)
MeshBase & mesh
int _extra_order
Extra order to use for quadrature rule.
const Number zero
.
Definition: libmesh.h:304
const MeshBase & get_mesh() const
Definition: system.h:2358
Number current_solution(const dof_id_type global_dof_number) const
Definition: system.C:165
unsigned int n_vars
static Real compute_slope(int N, Real Sx, Real Sy, Real Sxx, Real Sxy)
Computes slop in a linear regression.
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type.
auto norm(const T &a) -> decltype(std::abs(a))
Definition: tensor_tools.h:74
auto norm(const libMesh::TypeVector< T > &vector) -> decltype(std::norm(T()))
Definition: type_vector.h:1206
unsigned int n_vars() const
Definition: system.h:2430
const DofMap & get_dof_map() const
Definition: system.h:2374
uint8_t dof_id_type
Definition: id_types.h:67
spin_mutex spin_mtx
A convenient spin mutex object which can be used for obtaining locks.
Definition: threads.C:30

Member Data Documentation

◆ smoothness_estimator

const SmoothnessEstimator& libMesh::SmoothnessEstimator::EstimateSmoothness::smoothness_estimator
private

Definition at line 133 of file smoothness_estimator.h.

Referenced by operator()().

◆ smoothness_per_cell

ErrorVector& libMesh::SmoothnessEstimator::EstimateSmoothness::smoothness_per_cell
private

Definition at line 134 of file smoothness_estimator.h.

Referenced by operator()().

◆ system

const System& libMesh::SmoothnessEstimator::EstimateSmoothness::system
private

Definition at line 132 of file smoothness_estimator.h.

Referenced by operator()().


The documentation for this class was generated from the following files: