libMesh
Public Member Functions | Static Protected Member Functions | Protected Attributes | List of all members
FETest< order, family, elem_type > Class Template Reference

#include <fe_test.h>

Inheritance diagram for FETest< order, family, elem_type >:
[legend]

Public Member Functions

template<typename Functor >
void testLoop (Functor f)
 
void testPartitionOfUnity ()
 
void testFEInterface ()
 
void testU ()
 
void testDualDoesntScreamAndDie ()
 
void testGradU ()
 
void testGradUComp ()
 
void testHessU ()
 
void testHessUComp ()
 
void testCustomReinit ()
 
void setUp ()
 
void tearDown ()
 

Static Protected Member Functions

static RealGradient true_gradient (Point p)
 
static RealTensor true_hessian (Point p)
 

Protected Attributes

std::string libmesh_suite_name
 
unsigned int _dim
 
unsigned int _nx
 
unsigned int _ny
 
unsigned int _nz
 
Elem_elem
 
std::vector< dof_id_type_dof_indices
 
System_sys
 
std::unique_ptr< Mesh_mesh
 
std::unique_ptr< EquationSystems_es
 
std::unique_ptr< FEBase_fe
 
std::unique_ptr< QGauss_qrule
 
Real _value_tol
 
Real _grad_tol
 
Real _hess_tol
 

Detailed Description

template<Order order, FEFamily family, ElemType elem_type>
class FETest< order, family, elem_type >

Definition at line 603 of file fe_test.h.

Member Function Documentation

◆ setUp()

void FETestBase< order, family, elem_type, build_nx >::setUp ( )
inlineinherited

Definition at line 350 of file fe_test.h.

References libMesh::System::add_variable(), libMesh::FEGenericBase< OutputType >::build(), libMesh::MeshTools::Generation::build_cube(), libMesh::C0POLYGON, libMesh::C0POLYHEDRON, libMesh::FEType::default_quadrature_order(), libMesh::DofMap::dof_indices(), libMesh::EDGE3, fe_cubic_test(), fe_cubic_test_grad(), fe_quartic_test(), fe_quartic_test_grad(), libMesh::System::get_dof_map(), libMesh::HERMITE, libMesh::DofObject::id(), libMesh::index_range(), linear_test(), linear_test_grad(), libMesh::make_range(), libMesh::MeshTools::Modification::permute_elements(), libMesh::pi, libMesh::System::project_solution(), libMesh::QUAD9, quadratic_test(), quadratic_test_grad(), libMesh::RATIONAL_BERNSTEIN, rational_test(), rational_test_grad(), rational_w, libMesh::Real, libMesh::MeshTools::Modification::redistribute(), libMesh::MeshTools::Modification::rotate(), libMesh::SZABAB, libMesh::TOLERANCE, libMesh::Elem::type_to_dim_map, and libMesh::System::variable_type().

351  {
352  _mesh = std::make_unique<Mesh>(*TestCommWorld);
353  _dim = Elem::type_to_dim_map[elem_type];
354  const unsigned int build_ny = (_dim > 1) * build_nx;
355  const unsigned int build_nz = (_dim > 2) * build_nx;
356 
357  unsigned char weight_index = 0;
358 
359  if (family == RATIONAL_BERNSTEIN)
360  {
361  // Make sure we can handle non-zero weight indices
362  _mesh->add_node_integer("buffer integer");
363 
364  // Default weight to 1.0 so we don't get NaN from contains_point
365  // checks with a default GhostPointNeighbors ghosting
366  const Real default_weight = 1.0;
367  weight_index = cast_int<unsigned char>
368  (_mesh->add_node_datum<Real>("rational_weight", true,
369  &default_weight));
370  libmesh_assert_not_equal_to(weight_index, 0);
371 
372  // Set mapping data but not type, since here we're testing
373  // rational basis functions in the FE space but testing then
374  // with Lagrange bases for the mapping space.
375  _mesh->set_default_mapping_data(weight_index);
376  }
377 
378  if (elem_type == C0POLYGON)
379  {
380  // Build a pentagon by hand for testing purposes. Make this
381  // one non-skewed so a MONOMIAL basis will be able to exactly
382  // represent the polynomials we're projecting.
383 
384  _mesh->add_point(Point(0, 0), 0);
385  _mesh->add_point(Point(1, 0), 1);
386  _mesh->add_point(Point(1+cos(2*libMesh::pi/5), sin(2*libMesh::pi/5)), 2);
387  _mesh->add_point(Point(0.5, sin(2*libMesh::pi/5)+sin(libMesh::pi/5)), 3);
388  _mesh->add_point(Point(-cos(2*libMesh::pi/5), sin(2*libMesh::pi/5)), 4);
389 
390  std::unique_ptr<Elem> polygon = std::make_unique<C0Polygon>(5);
391  for (auto i : make_range(5))
392  polygon->set_node(i, _mesh->node_ptr(i));
393  polygon->set_id() = 0;
394 
395  _mesh->add_elem(std::move(polygon));
396  _mesh->prepare_for_use();
397  }
398  else if (elem_type == C0POLYHEDRON)
399  {
400  // Build a plain cube by hand for testing purposes. We could
401  // upgrade this, but it should be to something non-skewed so a
402  // MONOMIAL basis will be able to exactly represent the
403  // polynomials we're projecting.
404  //
405  // See elem_test.h for the limitations here.
406 
407  _mesh->add_point(Point(0, 0, 0), 0);
408  _mesh->add_point(Point(1, 0, 0), 1);
409  _mesh->add_point(Point(1, 1, 0), 2);
410  _mesh->add_point(Point(0, 1, 0), 3);
411  _mesh->add_point(Point(0, 0, 1), 4);
412  _mesh->add_point(Point(1, 0, 1), 5);
413  _mesh->add_point(Point(1, 1, 1), 6);
414  _mesh->add_point(Point(0, 1, 1), 7);
415 
416  const std::vector<std::vector<unsigned int>> nodes_on_side =
417  { {0, 1, 2, 3}, // min z
418  {0, 1, 5, 4}, // min y
419  {2, 6, 5, 1}, // max x
420  {2, 3, 7, 6}, // max y
421  {0, 4, 7, 3}, // min x
422  {5, 6, 7, 4} }; // max z
423 
424  // Build all the sides.
425  std::vector<std::shared_ptr<Polygon>> sides(nodes_on_side.size());
426 
427  for (auto s : index_range(nodes_on_side))
428  {
429  const auto & nodes_on_s = nodes_on_side[s];
430  sides[s] = std::make_shared<C0Polygon>(nodes_on_s.size());
431  for (auto i : index_range(nodes_on_s))
432  sides[s]->set_node(i, _mesh->node_ptr(nodes_on_s[i]));
433  }
434 
435  std::unique_ptr<Elem> polyhedron = std::make_unique<C0Polyhedron>(sides);
436  _mesh->add_elem(std::move(polyhedron));
437  _mesh->prepare_for_use();
438  }
439  else
440  {
442  build_nx, build_ny, build_nz,
443  0., 1., 0., 1., 0., 1.,
444  elem_type);
445  }
446 
447  // For debugging purposes it can be helpful to only consider one
448  // element even when we're using an element type that requires
449  // more than one element to fill out a square or cube.
450 #if 0
451  for (dof_id_type i = 0; i != _mesh->max_elem_id(); ++i)
452  {
453  Elem * elem = _mesh->query_elem_ptr(i);
454  if (elem && elem->id())
455  _mesh->delete_elem(elem);
456  }
457  _mesh->prepare_for_use();
458  CPPUNIT_ASSERT_EQUAL(_mesh->n_elem(), dof_id_type(1));
459 #endif
460 
461  // Permute our elements randomly and rotate and skew our mesh so
462  // we test all sorts of orientations ... except with Hermite
463  // elements, which are only designed to support meshes with a
464  // single orientation shared by all elements. We're also not
465  // rotating and/or skewing the rational elements, since our test
466  // solution was designed for a specific weighted mesh.
467  if (family != HERMITE &&
468  family != RATIONAL_BERNSTEIN)
469  {
471 
472  // Not yet testing manifolds embedded in higher-D space
473  if (_dim > 1)
475  8*(_dim>2), 16*(_dim>2));
476 
477  SkewFunc skew_func;
479  }
480 
481  // Set rational weights so we can exactly match our test solution
482  if (family == RATIONAL_BERNSTEIN)
483  {
484  for (auto elem : _mesh->active_element_ptr_range())
485  {
486  const unsigned int nv = elem->n_vertices();
487  const unsigned int nn = elem->n_nodes();
488  // We want interiors in lower dimensional elements treated
489  // like edges or faces as appropriate.
490  const unsigned int n_edges =
491  (elem->type() == EDGE3) ? 1 : elem->n_edges();
492  const unsigned int n_faces =
493  (elem->type() == QUAD9) ? 1 : elem->n_faces();
494  const unsigned int nve = std::min(nv + n_edges, nn);
495  const unsigned int nvef = std::min(nve + n_faces, nn);
496 
497  for (unsigned int i = 0; i != nv; ++i)
498  elem->node_ref(i).set_extra_datum<Real>(weight_index, 1.);
499  for (unsigned int i = nv; i != nve; ++i)
500  elem->node_ref(i).set_extra_datum<Real>(weight_index, rational_w);
501  const Real w2 = rational_w * rational_w;
502  for (unsigned int i = nve; i != nvef; ++i)
503  elem->node_ref(i).set_extra_datum<Real>(weight_index, w2);
504  const Real w3 = rational_w * w2;
505  for (unsigned int i = nvef; i != nn; ++i)
506  elem->node_ref(i).set_extra_datum<Real>(weight_index, w3);
507  }
508  }
509 
510  _es = std::make_unique<EquationSystems>(*_mesh);
511  _sys = &(_es->add_system<System> ("SimpleSystem"));
512  _sys->add_variable("u", order, family);
513  _es->init();
514 
515  if (family == RATIONAL_BERNSTEIN && order > 1)
516  {
518  }
519  else if (order > 3)
520  {
522  }
523  // Lagrange "cubic" on Tet7 only supports a bubble function, not
524  // all of P^3
525  else if (FE_CAN_TEST_CUBIC)
526  {
528  }
529  else if (order > 1)
530  {
532  }
533  else
534  {
536  }
537 
538  FEType fe_type = _sys->variable_type(0);
539  _fe = FEBase::build(_dim, fe_type);
540 
541  // Create quadrature rule for use in computing dual shape coefficients
542  _qrule = std::make_unique<QGauss>(_dim, fe_type.default_quadrature_order());
543  _fe->attach_quadrature_rule(_qrule.get());
544 
545  auto rng = _mesh->active_local_element_ptr_range();
546  this->_elem = rng.begin() == rng.end() ? nullptr : *(rng.begin());
547 
549 
550  _nx = 10;
551  _ny = (_dim > 1) ? _nx : 1;
552  _nz = (_dim > 2) ? _nx : 1;
553 
554  this->_value_tol = TOLERANCE * sqrt(TOLERANCE);
555 
556  // We see 6.5*tol*sqrt(tol) errors on cubic Hermites with the fe_cubic
557  // hermite test function
558  // On Tri7 we see 10*tol*sqrt(tol) errors, even!
559  // On Tet14 Monomial gives us at least 13*tol*sqrt(tol) in some
560  // cases
561  this->_grad_tol = 15 * TOLERANCE * sqrt(TOLERANCE);
562 
563  this->_hess_tol = sqrt(TOLERANCE); // FIXME: we see some ~1e-5 errors?!?
564 
565  // Prerequest everything we'll want to calculate later.
566  _fe->get_phi();
567  _fe->get_dphi();
568  _fe->get_dphidx();
569 #if LIBMESH_DIM > 1
570  _fe->get_dphidy();
571 #endif
572 #if LIBMESH_DIM > 2
573  _fe->get_dphidz();
574 #endif
575 
576 #if LIBMESH_ENABLE_SECOND_DERIVATIVES
577 
578  // Szabab elements don't have second derivatives yet
579  if (family == SZABAB)
580  return;
581 
582  _fe->get_d2phi();
583  _fe->get_d2phidx2();
584 #if LIBMESH_DIM > 1
585  _fe->get_d2phidxdy();
586  _fe->get_d2phidy2();
587 #endif
588 #if LIBMESH_DIM > 2
589  _fe->get_d2phidxdz();
590  _fe->get_d2phidydz();
591  _fe->get_d2phidz2();
592 #endif
593 
594 #endif
595  }
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition: fe_type.h:196
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Definition: dof_map.C:2164
static constexpr Real TOLERANCE
std::unique_ptr< QGauss > _qrule
Definition: fe_test.h:278
Gradient quadratic_test_grad(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: fe_test.h:111
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
Gradient rational_test_grad(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: fe_test.h:220
Order default_quadrature_order() const
Definition: fe_type.h:371
Gradient fe_cubic_test_grad(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: fe_test.h:144
Gradient fe_quartic_test_grad(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: fe_test.h:177
Number fe_cubic_test(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: fe_test.h:131
static const Real rational_w
Definition: fe_test.h:200
void permute_elements(MeshBase &mesh)
Randomly permute the nodal ordering of each element (without twisting the element mapping)...
std::unique_ptr< EquationSystems > _es
Definition: fe_test.h:276
void project_solution(FunctionBase< Number > *f, FunctionBase< Gradient > *g=nullptr) const
Projects arbitrary functions onto the current solution.
Number linear_test(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: fe_test.h:69
Number rational_test(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: fe_test.h:203
const Node & node_ref(const unsigned int i) const
Definition: elem.h:2529
dof_id_type id() const
Definition: dof_object.h:828
virtual unsigned int n_nodes() const =0
Manages consistently variables, degrees of freedom, and coefficient vectors.
Definition: system.h:96
unsigned int add_variable(std::string_view var, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
Adds the variable var to the list of variables for this system.
Definition: system.C:1357
void set_extra_datum(const unsigned int index, const T value)
Sets the value on this object of the extra datum associated with index, which should have been obtain...
Definition: dof_object.h:1126
Number quadratic_test(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: fe_test.h:98
virtual unsigned int n_edges() const =0
RealTensorValue rotate(MeshBase &mesh, const Real phi, const Real theta=0., const Real psi=0.)
Rotates the mesh in the xy plane.
std::unique_ptr< Mesh > _mesh
Definition: fe_test.h:275
virtual unsigned int n_vertices() const =0
const FEType & variable_type(const unsigned int i) const
Definition: system.h:2508
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::vector< dof_id_type > _dof_indices
Definition: fe_test.h:273
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...
Definition: int_range.h:140
void redistribute(MeshBase &mesh, const FunctionBase< Real > &mapfunc)
Deterministically perturb the nodal locations.
std::unique_ptr< FEBase > _fe
Definition: fe_test.h:277
virtual unsigned int n_faces() const =0
Number fe_quartic_test(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: fe_test.h:164
Gradient linear_test_grad(const Point &, const Parameters &, const std::string &, const std::string &)
Definition: fe_test.h:82
const DofMap & get_dof_map() const
Definition: system.h:2374
virtual ElemType type() const =0
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition: int_range.h:117
void build_cube(UnstructuredMesh &mesh, const unsigned int nx=0, const unsigned int ny=0, const unsigned int nz=0, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const Real zmin=0., const Real zmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
Builds a (elements) cube.
uint8_t dof_id_type
Definition: id_types.h:67
const Real pi
.
Definition: libmesh.h:299

◆ tearDown()

void FETestBase< order, family, elem_type, build_nx >::tearDown ( )
inlineinherited

Definition at line 597 of file fe_test.h.

597 {}

◆ testCustomReinit()

template<Order order, FEFamily family, ElemType elem_type>
void FETest< order, family, elem_type >::testCustomReinit ( )
inline

Definition at line 987 of file fe_test.h.

References libMesh::FEGenericBase< OutputType >::build(), libMesh::FEType::default_quadrature_rule(), and libMesh::Real.

988  {
989  LOG_UNIT_TEST;
990 
991  std::vector<Point> q_points;
992  std::vector<Real> weights;
993  q_points.resize(3); weights.resize(3);
994  q_points[0](0) = 0.0; q_points[0](1) = 0.0; weights[0] = Real(1)/6;
995  q_points[1](0) = 1.0; q_points[1](1) = 0.0; weights[1] = weights[0];
996  q_points[2](0) = 0.0; q_points[2](1) = 1.0; weights[2] = weights[0];
997 
998  FEType fe_type = this->_sys->variable_type(0);
999  std::unique_ptr<FEBase> fe (FEBase::build(this->_dim, fe_type));
1000  const int extraorder = 3;
1001  std::unique_ptr<QBase> qrule (fe_type.default_quadrature_rule (this->_dim, extraorder));
1002  fe->attach_quadrature_rule (qrule.get());
1003 
1004  const std::vector<Point> & q_pos = fe->get_xyz();
1005 
1006  for (const auto & elem : this->_mesh->active_local_element_ptr_range()) {
1007  fe->reinit (elem, &q_points, &weights);
1008  CPPUNIT_ASSERT_EQUAL(q_points.size(), std::size_t(3));
1009  CPPUNIT_ASSERT_EQUAL(q_pos.size(), std::size_t(3)); // 6? bug?
1010  }
1011  }
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition: fe_type.h:196
std::unique_ptr< QBase > default_quadrature_rule(const unsigned int dim, const int extraorder=0) const
Definition: fe_type.C:34
std::unique_ptr< Mesh > _mesh
Definition: fe_test.h:275
const FEType & variable_type(const unsigned int i) const
Definition: system.h:2508
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

◆ testDualDoesntScreamAndDie()

template<Order order, FEFamily family, ElemType elem_type>
void FETest< order, family, elem_type >::testDualDoesntScreamAndDie ( )
inline

Definition at line 800 of file fe_test.h.

801  {
802  LOG_UNIT_TEST;
803 
804  // Handle the "more processors than elements" case
805  if (!this->_elem)
806  return;
807 
808  // Request dual calculations
809  this->_fe->get_dual_phi();
810 
811  // reinit using the default quadrature rule in order to calculate the dual coefficients
812  this->_fe->reinit(this->_elem);
813  }
std::unique_ptr< FEBase > _fe
Definition: fe_test.h:277

◆ testFEInterface()

template<Order order, FEFamily family, ElemType elem_type>
void FETest< order, family, elem_type >::testFEInterface ( )
inline

Definition at line 723 of file fe_test.h.

References libMesh::FEInterface::get_continuity(), libMesh::FEInterface::is_hierarchic(), libMesh::FE< Dim, T >::n_dofs(), and libMesh::FEInterface::n_shape_functions().

724  {
725  LOG_UNIT_TEST;
726 
727  // Handle the "more processors than elements" case
728  if (!this->_elem)
729  return;
730 
731  this->_fe->reinit(this->_elem);
732 
733  const FEType fe_type = this->_sys->variable_type(0);
734 
735  unsigned int my_n_dofs = 0;
736 
737  switch (this->_elem->dim())
738  {
739  case 0:
740  my_n_dofs = FE<0,family>::n_dofs(this->_elem, order);
741  break;
742  case 1:
743  my_n_dofs = FE<1,family>::n_dofs(this->_elem, order);
744  break;
745  case 2:
746  my_n_dofs = FE<2,family>::n_dofs(this->_elem, order);
747  break;
748  case 3:
749  my_n_dofs = FE<3,family>::n_dofs(this->_elem, order);
750  break;
751  default:
752  libmesh_error();
753  }
754 
755  CPPUNIT_ASSERT_EQUAL(
756  FEInterface::n_shape_functions(fe_type, this->_elem),
757  my_n_dofs);
758 
759  CPPUNIT_ASSERT_EQUAL(
760  FEInterface::get_continuity(fe_type),
761  this->_fe->get_continuity());
762 
763  CPPUNIT_ASSERT_EQUAL(
764  FEInterface::is_hierarchic(fe_type),
765  this->_fe->is_hierarchic());
766  }
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition: fe_type.h:196
A specific instantiation of the FEBase class.
Definition: fe.h:127
const FEType & variable_type(const unsigned int i) const
Definition: system.h:2508
virtual unsigned short dim() const =0
std::unique_ptr< FEBase > _fe
Definition: fe_test.h:277

◆ testGradU()

template<Order order, FEFamily family, ElemType elem_type>
void FETest< order, family, elem_type >::testGradU ( )
inline

Definition at line 816 of file fe_test.h.

817  {
818  LOG_UNIT_TEST;
819 
820  auto f = [this](Point p)
821  {
822  Parameters dummy;
823 
824  Gradient grad_u = 0;
825  for (std::size_t d = 0; d != this->_dof_indices.size(); ++d)
826  grad_u += this->_fe->get_dphi()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
827 
828  RealGradient true_grad = this->true_gradient(p);
829 
830  LIBMESH_ASSERT_NUMBERS_EQUAL
831  (grad_u(0), true_grad(0), this->_grad_tol);
832  if (this->_dim > 1)
833  LIBMESH_ASSERT_NUMBERS_EQUAL
834  (grad_u(1), true_grad(1), this->_grad_tol);
835  if (this->_dim > 2)
836  LIBMESH_ASSERT_NUMBERS_EQUAL
837  (grad_u(2), true_grad(2), this->_grad_tol);
838  };
839 
840  testLoop(f);
841  }
This class provides the ability to map between arbitrary, user-defined strings and several data types...
Definition: parameters.h:67
void testLoop(Functor f)
Definition: fe_test.h:608
This class defines a vector in LIBMESH_DIM dimensional Real or Complex space.
std::vector< dof_id_type > _dof_indices
Definition: fe_test.h:273
static RealGradient true_gradient(Point p)
Definition: fe_test.h:283
std::unique_ptr< NumericVector< Number > > current_local_solution
All the values I need to compute my contribution to the simulation at hand.
Definition: system.h:1605
std::unique_ptr< FEBase > _fe
Definition: fe_test.h:277
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39

◆ testGradUComp()

template<Order order, FEFamily family, ElemType elem_type>
void FETest< order, family, elem_type >::testGradUComp ( )
inline

Definition at line 843 of file fe_test.h.

844  {
845  LOG_UNIT_TEST;
846 
847  auto f = [this](Point p)
848  {
849  Parameters dummy;
850 
851  Number grad_u_x = 0, grad_u_y = 0, grad_u_z = 0;
852  for (std::size_t d = 0; d != this->_dof_indices.size(); ++d)
853  {
854  grad_u_x += this->_fe->get_dphidx()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
855 #if LIBMESH_DIM > 1
856  grad_u_y += this->_fe->get_dphidy()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
857 #endif
858 #if LIBMESH_DIM > 2
859  grad_u_z += this->_fe->get_dphidz()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
860 #endif
861  }
862 
863  RealGradient true_grad = this->true_gradient(p);
864 
865  LIBMESH_ASSERT_NUMBERS_EQUAL(grad_u_x,
866  true_grad(0), this->_grad_tol);
867  if (this->_dim > 1)
868  LIBMESH_ASSERT_NUMBERS_EQUAL
869  (grad_u_y, true_grad(1), this->_grad_tol);
870  if (this->_dim > 2)
871  LIBMESH_ASSERT_NUMBERS_EQUAL
872  (grad_u_z, true_grad(2), this->_grad_tol);
873  };
874 
875  testLoop(f);
876  }
This class provides the ability to map between arbitrary, user-defined strings and several data types...
Definition: parameters.h:67
void testLoop(Functor f)
Definition: fe_test.h:608
std::vector< dof_id_type > _dof_indices
Definition: fe_test.h:273
static RealGradient true_gradient(Point p)
Definition: fe_test.h:283
std::unique_ptr< NumericVector< Number > > current_local_solution
All the values I need to compute my contribution to the simulation at hand.
Definition: system.h:1605
std::unique_ptr< FEBase > _fe
Definition: fe_test.h:277
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39

◆ testHessU()

template<Order order, FEFamily family, ElemType elem_type>
void FETest< order, family, elem_type >::testHessU ( )
inline

Definition at line 879 of file fe_test.h.

References libMesh::RATIONAL_BERNSTEIN, and libMesh::SZABAB.

880  {
881  LOG_UNIT_TEST;
882 
883  // Szabab elements don't have second derivatives yet
884  if (family == SZABAB)
885  return;
886 
887 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
888  auto f = [this](Point p)
889  {
890  Tensor hess_u;
891  for (std::size_t d = 0; d != this->_dof_indices.size(); ++d)
892  hess_u += this->_fe->get_d2phi()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
893 
894  // TODO: Yeah we'll test the ugly expressions later.
895  if (family == RATIONAL_BERNSTEIN && order > 1)
896  return;
897 
898  RealTensor true_hess = this->true_hessian(p);
899 
900  LIBMESH_ASSERT_NUMBERS_EQUAL
901  (true_hess(0,0), hess_u(0,0), this->_hess_tol);
902  if (this->_dim > 1)
903  {
904  LIBMESH_ASSERT_NUMBERS_EQUAL
905  (hess_u(0,1), hess_u(1,0), this->_hess_tol);
906  LIBMESH_ASSERT_NUMBERS_EQUAL
907  (true_hess(0,1), hess_u(0,1), this->_hess_tol);
908  LIBMESH_ASSERT_NUMBERS_EQUAL
909  (true_hess(1,1), hess_u(1,1), this->_hess_tol);
910  }
911  if (this->_dim > 2)
912  {
913  LIBMESH_ASSERT_NUMBERS_EQUAL
914  (hess_u(0,2), hess_u(2,0), this->_hess_tol);
915  LIBMESH_ASSERT_NUMBERS_EQUAL
916  (hess_u(1,2), hess_u(2,1), this->_hess_tol);
917  LIBMESH_ASSERT_NUMBERS_EQUAL
918  (true_hess(0,2), hess_u(0,2), this->_hess_tol);
919  LIBMESH_ASSERT_NUMBERS_EQUAL
920  (true_hess(1,2), hess_u(1,2), this->_hess_tol);
921  LIBMESH_ASSERT_NUMBERS_EQUAL
922  (true_hess(2,2), hess_u(2,2), this->_hess_tol);
923  }
924  };
925 
926  testLoop(f);
927 #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES
928  }
void testLoop(Functor f)
Definition: fe_test.h:608
static RealTensor true_hessian(Point p)
Definition: fe_test.h:321
std::vector< dof_id_type > _dof_indices
Definition: fe_test.h:273
std::unique_ptr< NumericVector< Number > > current_local_solution
All the values I need to compute my contribution to the simulation at hand.
Definition: system.h:1605
std::unique_ptr< FEBase > _fe
Definition: fe_test.h:277
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
This class defines a tensor in LIBMESH_DIM dimensional Real or Complex space.

◆ testHessUComp()

template<Order order, FEFamily family, ElemType elem_type>
void FETest< order, family, elem_type >::testHessUComp ( )
inline

Definition at line 930 of file fe_test.h.

References libMesh::RATIONAL_BERNSTEIN, and libMesh::SZABAB.

931  {
932 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
933  LOG_UNIT_TEST;
934 
935  // Szabab elements don't have second derivatives yet
936  if (family == SZABAB)
937  return;
938 
939  auto f = [this](Point p)
940  {
941  Number hess_u_xx = 0, hess_u_xy = 0, hess_u_yy = 0,
942  hess_u_xz = 0, hess_u_yz = 0, hess_u_zz = 0;
943  for (std::size_t d = 0; d != this->_dof_indices.size(); ++d)
944  {
945  hess_u_xx += this->_fe->get_d2phidx2()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
946 #if LIBMESH_DIM > 1
947  hess_u_xy += this->_fe->get_d2phidxdy()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
948  hess_u_yy += this->_fe->get_d2phidy2()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
949 #endif
950 #if LIBMESH_DIM > 2
951  hess_u_xz += this->_fe->get_d2phidxdz()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
952  hess_u_yz += this->_fe->get_d2phidydz()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
953  hess_u_zz += this->_fe->get_d2phidz2()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
954 #endif
955  }
956 
957  // TODO: Yeah we'll test the ugly expressions later.
958  if (family == RATIONAL_BERNSTEIN && order > 1)
959  return;
960 
961  RealTensor true_hess = this->true_hessian(p);
962 
963  LIBMESH_ASSERT_NUMBERS_EQUAL
964  (true_hess(0,0), hess_u_xx, this->_hess_tol);
965  if (this->_dim > 1)
966  {
967  LIBMESH_ASSERT_NUMBERS_EQUAL
968  (true_hess(0,1), hess_u_xy, this->_hess_tol);
969  LIBMESH_ASSERT_NUMBERS_EQUAL
970  (true_hess(1,1), hess_u_yy, this->_hess_tol);
971  }
972  if (this->_dim > 2)
973  {
974  LIBMESH_ASSERT_NUMBERS_EQUAL
975  (true_hess(0,2), hess_u_xz, this->_hess_tol);
976  LIBMESH_ASSERT_NUMBERS_EQUAL
977  (true_hess(1,2), hess_u_yz, this->_hess_tol);
978  LIBMESH_ASSERT_NUMBERS_EQUAL
979  (true_hess(2,2), hess_u_zz, this->_hess_tol);
980  }
981  };
982 
983  testLoop(f);
984 #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES
985  }
void testLoop(Functor f)
Definition: fe_test.h:608
static RealTensor true_hessian(Point p)
Definition: fe_test.h:321
std::vector< dof_id_type > _dof_indices
Definition: fe_test.h:273
std::unique_ptr< NumericVector< Number > > current_local_solution
All the values I need to compute my contribution to the simulation at hand.
Definition: system.h:1605
std::unique_ptr< FEBase > _fe
Definition: fe_test.h:277
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
This class defines a tensor in LIBMESH_DIM dimensional Real or Complex space.

◆ testLoop()

template<Order order, FEFamily family, ElemType elem_type>
template<typename Functor >
void FETest< order, family, elem_type >::testLoop ( Functor  f)
inline

Definition at line 608 of file fe_test.h.

References libMesh::invalid_uint, libMesh::FEMap::inverse_map(), and libMesh::Real.

609  {
610  // Handle the "more processors than elements" case
611  if (!this->_elem)
612  return;
613 
614  // These tests require exceptions to be enabled because a
615  // TypeTensor::solve() call down in Elem::contains_point()
616  // actually throws a non-fatal exception for a certain Point which
617  // is not in the Elem. When exceptions are not enabled, this test
618  // simply aborts.
619 #ifdef LIBMESH_ENABLE_EXCEPTIONS
620  for (unsigned int i=0; i != this->_nx; ++i)
621  for (unsigned int j=0; j != this->_ny; ++j)
622  for (unsigned int k=0; k != this->_nz; ++k)
623  {
624  Point p = Real(i)/this->_nx;
625  if (j > 0)
626  p(1) = Real(j)/this->_ny;
627  if (k > 0)
628  p(2) = Real(k)/this->_nz;
629  if (!this->_elem->contains_point(p))
630  continue;
631 
632  // If at a singular node, cannot use FEMap::map
633  if (this->_elem->local_singular_node(p) != invalid_uint)
634  continue;
635 
636  std::vector<Point> master_points
637  (1, FEMap::inverse_map(this->_dim, this->_elem, p));
638 
639  // Reinit at point to test against analytic solution
640  this->_fe->reinit(this->_elem, &master_points);
641 
642  f(p);
643  }
644 #endif // LIBMESH_ENABLE_EXCEPTIONS
645  }
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
Definition: libmesh.h:310
virtual bool contains_point(const Point &p, Real tol=TOLERANCE) const
Definition: elem.C:2751
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual unsigned int local_singular_node(const Point &, const Real=TOLERANCE *TOLERANCE) const
Definition: elem.h:1831
std::unique_ptr< FEBase > _fe
Definition: fe_test.h:277
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39

◆ testPartitionOfUnity()

template<Order order, FEFamily family, ElemType elem_type>
void FETest< order, family, elem_type >::testPartitionOfUnity ( )
inline

Definition at line 647 of file fe_test.h.

References libMesh::BERNSTEIN, libMesh::CLOUGH, libMesh::CONSTANT, libMesh::FIRST, libMesh::HERMITE, libMesh::HIERARCHIC, libMesh::L2_HIERARCHIC, libMesh::L2_LAGRANGE, libMesh::LAGRANGE, libMesh::make_range(), libMesh::MONOMIAL, libMesh::RATIONAL_BERNSTEIN, libMesh::Real, libMesh::SZABAB, libMesh::TOLERANCE, and libMesh::XYZ.

648  {
649  if (!this->_elem)
650  return;
651 
652  this->_fe->reinit(this->_elem);
653 
654  bool satisfies_partition_of_unity = true;
655  for (const auto qp : make_range(this->_qrule->n_points()))
656  {
657  Real phi_sum = 0;
658  for (std::size_t d = 0; d != this->_dof_indices.size(); ++d)
659  phi_sum += this->_fe->get_phi()[d][qp];
660  if (phi_sum < (1 - TOLERANCE) || phi_sum > (1 + TOLERANCE))
661  {
662  satisfies_partition_of_unity = false;
663  break;
664  }
665  }
666 
667  switch (this->_fe->get_family())
668  {
669  case MONOMIAL:
670  {
671  switch (this->_fe->get_order())
672  {
673  case CONSTANT:
674  CPPUNIT_ASSERT(satisfies_partition_of_unity);
675  break;
676 
677  default:
678  CPPUNIT_ASSERT(!satisfies_partition_of_unity);
679  break;
680  }
681  break;
682  }
683  case SZABAB:
684  case HIERARCHIC:
685  case L2_HIERARCHIC:
686  {
687  switch (this->_fe->get_order())
688  {
689  case FIRST:
690  CPPUNIT_ASSERT(satisfies_partition_of_unity);
691  break;
692 
693  default:
694  CPPUNIT_ASSERT(!satisfies_partition_of_unity);
695  break;
696  }
697  break;
698  }
699 
700  case XYZ:
701  case CLOUGH:
702  case HERMITE:
703  {
704  CPPUNIT_ASSERT(!satisfies_partition_of_unity);
705  break;
706  }
707 
708  case LAGRANGE:
709  case L2_LAGRANGE:
710  case BERNSTEIN:
711  case RATIONAL_BERNSTEIN:
712  {
713  CPPUNIT_ASSERT(satisfies_partition_of_unity);
714  break;
715  }
716 
717  default:
718  CPPUNIT_FAIL("Uncovered FEFamily");
719  }
720  }
static constexpr Real TOLERANCE
std::unique_ptr< QGauss > _qrule
Definition: fe_test.h:278
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::vector< dof_id_type > _dof_indices
Definition: fe_test.h:273
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...
Definition: int_range.h:140
std::unique_ptr< FEBase > _fe
Definition: fe_test.h:277

◆ testU()

template<Order order, FEFamily family, ElemType elem_type>
void FETest< order, family, elem_type >::testU ( )
inline

Definition at line 768 of file fe_test.h.

References fe_cubic_test(), fe_quartic_test(), libMesh::RATIONAL_BERNSTEIN, and rational_test().

769  {
770  LOG_UNIT_TEST;
771 
772  auto f = [this](Point p)
773  {
774  Parameters dummy;
775 
776  Number u = 0;
777  for (std::size_t d = 0; d != this->_dof_indices.size(); ++d)
778  u += this->_fe->get_phi()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
779 
780  Number true_u;
781 
782  if (family == RATIONAL_BERNSTEIN && order > 1)
783  true_u = rational_test(p, dummy, "", "");
784  else if (order > 3)
785  true_u = fe_quartic_test(p, dummy, "", "");
786  else if (FE_CAN_TEST_CUBIC)
787  true_u = fe_cubic_test(p, dummy, "", "");
788  else if (order > 1)
789  true_u = p(0)*p(0) + 0.5*p(1)*p(1) + 0.25*p(2)*p(2) +
790  0.125*p(0)*p(1) + 0.0625*p(0)*p(2) + 0.03125*p(1)*p(2);
791  else
792  true_u = p(0) + 0.25*p(1) + 0.0625*p(2);
793 
794  LIBMESH_ASSERT_NUMBERS_EQUAL (true_u, u, this->_value_tol);
795  };
796 
797  testLoop(f);
798  }
This class provides the ability to map between arbitrary, user-defined strings and several data types...
Definition: parameters.h:67
void testLoop(Functor f)
Definition: fe_test.h:608
Number fe_cubic_test(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: fe_test.h:131
Number rational_test(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: fe_test.h:203
std::vector< dof_id_type > _dof_indices
Definition: fe_test.h:273
std::unique_ptr< NumericVector< Number > > current_local_solution
All the values I need to compute my contribution to the simulation at hand.
Definition: system.h:1605
std::unique_ptr< FEBase > _fe
Definition: fe_test.h:277
Number fe_quartic_test(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: fe_test.h:164
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39

◆ true_gradient()

static RealGradient FETestBase< order, family, elem_type, build_nx >::true_gradient ( Point  p)
inlinestaticprotectedinherited

Definition at line 283 of file fe_test.h.

References fe_cubic_test_grad(), fe_quartic_test_grad(), libMesh::libmesh_real(), libMesh::RATIONAL_BERNSTEIN, rational_test_grad(), and libMesh::Real.

284  {
285  Parameters dummy;
286 
287  Gradient true_grad;
288  RealGradient returnval;
289 
290  if (family == RATIONAL_BERNSTEIN && order > 1)
291  true_grad = rational_test_grad(p, dummy, "", "");
292  else if (order > 3)
293  true_grad = fe_quartic_test_grad(p, dummy, "", "");
294  else if (FE_CAN_TEST_CUBIC)
295  true_grad = fe_cubic_test_grad(p, dummy, "", "");
296  else if (order > 1)
297  {
298  const Real & x = p(0);
299  const Real & y = (LIBMESH_DIM > 1) ? p(1) : 0;
300  const Real & z = (LIBMESH_DIM > 2) ? p(2) : 0;
301 
302  true_grad = Gradient(2*x+0.125*y+0.0625*z,
303  y+0.125*x+0.03125*z,
304  0.5*z+0.0625*x+0.03125*y);
305  }
306  else
307  true_grad = Gradient(1.0, 0.25, 0.0625);
308 
309  for (unsigned int d=0; d != LIBMESH_DIM; ++d)
310  {
311  CPPUNIT_ASSERT(true_grad(d) ==
312  Number(libmesh_real(true_grad(d))));
313 
314  returnval(d) = libmesh_real(true_grad(d));
315  }
316 
317  return returnval;
318  }
T libmesh_real(T a)
This class provides the ability to map between arbitrary, user-defined strings and several data types...
Definition: parameters.h:67
Gradient rational_test_grad(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: fe_test.h:220
This class defines a vector in LIBMESH_DIM dimensional Real or Complex space.
Gradient fe_cubic_test_grad(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: fe_test.h:144
Gradient fe_quartic_test_grad(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: fe_test.h:177
NumberVectorValue Gradient
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

◆ true_hessian()

static RealTensor FETestBase< order, family, elem_type, build_nx >::true_hessian ( Point  p)
inlinestaticprotectedinherited

Definition at line 321 of file fe_test.h.

References libMesh::Real.

322  {
323  const Real & x = p(0);
324  const Real & y = LIBMESH_DIM > 1 ? p(1) : 0;
325  const Real & z = LIBMESH_DIM > 2 ? p(2) : 0;
326 
327  if (order > 3)
328  return RealTensor
329  { 12*x*x-12*x+2+2*z*(1-y)-2*(1-y)*(1-z), -2*x*z-(1-2*x)*(1-z)-(1-2*y)*z, 2*x*(1-y)-(1-2*x)*(1-y)-y*(1-y),
330  -2*x*z-(1-2*x)*(1-z)-(1-2*y)*z, -2*(1-x)*z, -x*x+x*(1-x)+(1-x)*(1-2*y),
331  2*x*(1-y)-(1-2*x)*(1-y)-y*(1-y), -x*x+x*(1-x)+(1-x)*(1-2*y), 12*z*z-12*z+2 };
332  else if (FE_CAN_TEST_CUBIC)
333  return RealTensor
334  { 6*x-4+2*(1-y), -2*x+z-1, y-1,
335  -2*x+z-1, -2*z, x+1-2*y,
336  y-1, x+1-2*y, 6*z-4 };
337  else if (order > 1)
338  return RealTensor
339  { 2, 0.125, 0.0625,
340  0.125, 1, 0.03125,
341  0.0625, 0.03125, 0.5 };
342 
343  return RealTensor
344  { 0, 0, 0,
345  0, 0, 0,
346  0, 0, 0 };
347  }
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
This class defines a tensor in LIBMESH_DIM dimensional Real or Complex space.

Member Data Documentation

◆ _dim

unsigned int FETestBase< order, family, elem_type, build_nx >::_dim
protectedinherited

Definition at line 271 of file fe_test.h.

◆ _dof_indices

std::vector<dof_id_type> FETestBase< order, family, elem_type, build_nx >::_dof_indices
protectedinherited

Definition at line 273 of file fe_test.h.

◆ _elem

Elem* FETestBase< order, family, elem_type, build_nx >::_elem
protectedinherited

Definition at line 272 of file fe_test.h.

◆ _es

std::unique_ptr<EquationSystems> FETestBase< order, family, elem_type, build_nx >::_es
protectedinherited

Definition at line 276 of file fe_test.h.

◆ _fe

std::unique_ptr<FEBase> FETestBase< order, family, elem_type, build_nx >::_fe
protectedinherited

Definition at line 277 of file fe_test.h.

◆ _grad_tol

Real FETestBase< order, family, elem_type, build_nx >::_grad_tol
protectedinherited

Definition at line 280 of file fe_test.h.

◆ _hess_tol

Real FETestBase< order, family, elem_type, build_nx >::_hess_tol
protectedinherited

Definition at line 280 of file fe_test.h.

◆ _mesh

std::unique_ptr<Mesh> FETestBase< order, family, elem_type, build_nx >::_mesh
protectedinherited

Definition at line 275 of file fe_test.h.

◆ _nx

unsigned int FETestBase< order, family, elem_type, build_nx >::_nx
protectedinherited

Definition at line 271 of file fe_test.h.

◆ _ny

unsigned int FETestBase< order, family, elem_type, build_nx >::_ny
protectedinherited

Definition at line 271 of file fe_test.h.

◆ _nz

unsigned int FETestBase< order, family, elem_type, build_nx >::_nz
protectedinherited

Definition at line 271 of file fe_test.h.

◆ _qrule

std::unique_ptr<QGauss> FETestBase< order, family, elem_type, build_nx >::_qrule
protectedinherited

Definition at line 278 of file fe_test.h.

◆ _sys

System* FETestBase< order, family, elem_type, build_nx >::_sys
protectedinherited

Definition at line 274 of file fe_test.h.

◆ _value_tol

Real FETestBase< order, family, elem_type, build_nx >::_value_tol
protectedinherited

Definition at line 280 of file fe_test.h.

◆ libmesh_suite_name

std::string FETestBase< order, family, elem_type, build_nx >::libmesh_suite_name
protectedinherited

Definition at line 269 of file fe_test.h.


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