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

#include <fe_test.h>

Inheritance diagram for FETest< order, family, elem_type, CaseName >:
[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
 
std::string _case_name
 Name of the case, can be used in the test to switch cases. More...
 
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, typename CaseName>
class FETest< order, family, elem_type, CaseName >

Definition at line 623 of file fe_test.h.

Member Function Documentation

◆ setUp()

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

Definition at line 356 of file fe_test.h.

357  {
358  _mesh = std::make_unique<Mesh>(*TestCommWorld);
359  _dim = Elem::type_to_dim_map[elem_type];
360  const unsigned int build_ny = (_dim > 1) * build_nx;
361  const unsigned int build_nz = (_dim > 2) * build_nx;
362 
363  unsigned char weight_index = 0;
364 
365  if (family == RATIONAL_BERNSTEIN)
366  {
367  // Make sure we can handle non-zero weight indices
368  _mesh->add_node_integer("buffer integer");
369 
370  // Default weight to 1.0 so we don't get NaN from contains_point
371  // checks with a default GhostPointNeighbors ghosting
372  const Real default_weight = 1.0;
373  weight_index = cast_int<unsigned char>
374  (_mesh->add_node_datum<Real>("rational_weight", true,
375  &default_weight));
376  libmesh_assert_not_equal_to(weight_index, 0);
377 
378  // Set mapping data but not type, since here we're testing
379  // rational basis functions in the FE space but testing then
380  // with Lagrange bases for the mapping space.
381  _mesh->set_default_mapping_data(weight_index);
382  }
383 
384  if (elem_type == C0POLYGON)
385  {
386  // Build a pentagon by hand for testing purposes. Make this
387  // one non-skewed so a MONOMIAL basis will be able to exactly
388  // represent the polynomials we're projecting.
389 
390  _mesh->add_point(Point(0, 0), 0);
391  _mesh->add_point(Point(1, 0), 1);
392  _mesh->add_point(Point(1+cos(2*libMesh::pi/5), sin(2*libMesh::pi/5)), 2);
393  _mesh->add_point(Point(0.5, sin(2*libMesh::pi/5)+sin(libMesh::pi/5)), 3);
394  _mesh->add_point(Point(-cos(2*libMesh::pi/5), sin(2*libMesh::pi/5)), 4);
395 
396  std::unique_ptr<Elem> polygon = std::make_unique<C0Polygon>(5);
397  for (auto i : make_range(5))
398  polygon->set_node(i, _mesh->node_ptr(i));
399  polygon->set_id() = 0;
400 
401  _mesh->add_elem(std::move(polygon));
402  _mesh->prepare_for_use();
403  }
404  else if (elem_type == C0POLYHEDRON)
405  {
406  // Build a plain cube by hand for testing purposes. We could
407  // upgrade this, but it should be to something non-skewed so a
408  // MONOMIAL basis will be able to exactly represent the
409  // polynomials we're projecting.
410  //
411  // See elem_test.h for the limitations here.
412 
413  _mesh->add_point(Point(0, 0, 0), 0);
414  _mesh->add_point(Point(1, 0, 0), 1);
415  _mesh->add_point(Point(1, 1, 0), 2);
416  _mesh->add_point(Point(0, 1, 0), 3);
417  _mesh->add_point(Point(0, 0, 1), 4);
418  _mesh->add_point(Point(1, 0, 1), 5);
419  _mesh->add_point(Point(1, 1, 1), 6);
420  _mesh->add_point(Point(0, 1, 1), 7);
421 
422  // Pick case
423  std::vector<std::vector<unsigned int>> nodes_on_side;
424  if (_case_name == "Default")
425  nodes_on_side = { {0, 1, 2, 3}, // min z
426  {0, 1, 5, 4}, // min y
427  {2, 6, 5, 1}, // max x
428  {2, 3, 7, 6}, // max y
429  {0, 4, 7, 3}, // min x
430  {5, 6, 7, 4} }; // max z
431  else if (_case_name == "MidNode")
432  nodes_on_side = { {0, 1, 2, 3}, // min z
433  {0, 1, 5, 4}, // min y
434  {1, 2, 6, 5}, // max x
435  {2, 3, 7, 6}, // max y
436  {3, 0, 4, 7}, // min x
437  {4, 5, 6, 7} }; // max z
438  else
439  libmesh_error_msg("Unknown case name: " + _case_name);
440 
441  // Build all the sides.
442  std::vector<std::shared_ptr<Polygon>> sides(nodes_on_side.size());
443 
444  for (auto s : index_range(nodes_on_side))
445  {
446  const auto & nodes_on_s = nodes_on_side[s];
447  sides[s] = std::make_shared<C0Polygon>(nodes_on_s.size());
448  for (auto i : index_range(nodes_on_s))
449  sides[s]->set_node(i, _mesh->node_ptr(nodes_on_s[i]));
450  }
451 
452  std::unique_ptr<libMesh::Node> mid_elem_node;
453  std::unique_ptr<Elem> polyhedron = std::make_unique<C0Polyhedron>(sides, mid_elem_node);
454  _mesh->add_elem(std::move(polyhedron));
455  if (mid_elem_node)
456  _mesh->add_node(std::move(mid_elem_node));
457  _mesh->prepare_for_use();
458  }
459  else
460  {
462  build_nx, build_ny, build_nz,
463  0., 1., 0., 1., 0., 1.,
464  elem_type);
465  }
466 
467  // For debugging purposes it can be helpful to only consider one
468  // element even when we're using an element type that requires
469  // more than one element to fill out a square or cube.
470 #if 0
471  for (dof_id_type i = 0; i != _mesh->max_elem_id(); ++i)
472  {
473  Elem * elem = _mesh->query_elem_ptr(i);
474  if (elem && elem->id())
475  _mesh->delete_elem(elem);
476  }
477  _mesh->prepare_for_use();
478  CPPUNIT_ASSERT_EQUAL(_mesh->n_elem(), dof_id_type(1));
479 #endif
480 
481  // Permute our elements randomly and rotate and skew our mesh so
482  // we test all sorts of orientations ... except with Hermite
483  // elements, which are only designed to support meshes with a
484  // single orientation shared by all elements. We're also not
485  // rotating and/or skewing the rational elements, since our test
486  // solution was designed for a specific weighted mesh.
487  if (family != HERMITE &&
488  family != RATIONAL_BERNSTEIN)
489  {
491 
492  // Not yet testing manifolds embedded in higher-D space
493  if (_dim > 1)
495  8*(_dim>2), 16*(_dim>2));
496 
497  SkewFunc skew_func;
499  }
500 
501  // Set rational weights so we can exactly match our test solution
502  if (family == RATIONAL_BERNSTEIN)
503  {
504  for (auto elem : _mesh->active_element_ptr_range())
505  {
506  const unsigned int nv = elem->n_vertices();
507  const unsigned int nn = elem->n_nodes();
508  // We want interiors in lower dimensional elements treated
509  // like edges or faces as appropriate.
510  const unsigned int n_edges =
511  (elem->type() == EDGE3) ? 1 : elem->n_edges();
512  const unsigned int n_faces =
513  (elem->type() == QUAD9) ? 1 : elem->n_faces();
514  const unsigned int nve = std::min(nv + n_edges, nn);
515  const unsigned int nvef = std::min(nve + n_faces, nn);
516 
517  for (unsigned int i = 0; i != nv; ++i)
518  elem->node_ref(i).set_extra_datum<Real>(weight_index, 1.);
519  for (unsigned int i = nv; i != nve; ++i)
520  elem->node_ref(i).set_extra_datum<Real>(weight_index, rational_w);
521  const Real w2 = rational_w * rational_w;
522  for (unsigned int i = nve; i != nvef; ++i)
523  elem->node_ref(i).set_extra_datum<Real>(weight_index, w2);
524  const Real w3 = rational_w * w2;
525  for (unsigned int i = nvef; i != nn; ++i)
526  elem->node_ref(i).set_extra_datum<Real>(weight_index, w3);
527  }
528  }
529 
530  _es = std::make_unique<EquationSystems>(*_mesh);
531  _sys = &(_es->add_system<System> ("SimpleSystem"));
532  _sys->add_variable("u", order, family);
533  _es->init();
534 
535  if (family == RATIONAL_BERNSTEIN && order > 1)
536  {
538  }
539  else if (order > 3)
540  {
542  }
543  // Lagrange "cubic" on Tet7 only supports a bubble function, not
544  // all of P^3
545  else if (FE_CAN_TEST_CUBIC)
546  {
548  }
549  else if (order > 1)
550  {
552  }
553  else
554  {
556  }
557 
558  FEType fe_type = _sys->variable_type(0);
559  _fe = FEBase::build(_dim, fe_type);
560 
561  // Create quadrature rule for use in computing dual shape coefficients
562  _qrule = std::make_unique<QGauss>(_dim, fe_type.default_quadrature_order());
563  _fe->attach_quadrature_rule(_qrule.get());
564 
565  auto rng = _mesh->active_local_element_ptr_range();
566  this->_elem = rng.begin() == rng.end() ? nullptr : *(rng.begin());
567 
569 
570  _nx = 10;
571  _ny = (_dim > 1) ? _nx : 1;
572  _nz = (_dim > 2) ? _nx : 1;
573 
574  this->_value_tol = TOLERANCE * sqrt(TOLERANCE);
575 
576  // We see 6.5*tol*sqrt(tol) errors on cubic Hermites with the fe_cubic
577  // hermite test function
578  // On Tri7 we see 10*tol*sqrt(tol) errors, even!
579  // On Tet14 Monomial gives us at least 13*tol*sqrt(tol) in some
580  // cases
581  this->_grad_tol = 15 * TOLERANCE * sqrt(TOLERANCE);
582 
583  this->_hess_tol = sqrt(TOLERANCE); // FIXME: we see some ~1e-5 errors?!?
584 
585  // Prerequest everything we'll want to calculate later.
586  _fe->get_phi();
587  _fe->get_dphi();
588  _fe->get_dphidx();
589 #if LIBMESH_DIM > 1
590  _fe->get_dphidy();
591 #endif
592 #if LIBMESH_DIM > 2
593  _fe->get_dphidz();
594 #endif
595 
596 #if LIBMESH_ENABLE_SECOND_DERIVATIVES
597 
598  // Szabab elements don't have second derivatives yet
599  if (family == SZABAB)
600  return;
601 
602  _fe->get_d2phi();
603  _fe->get_d2phidx2();
604 #if LIBMESH_DIM > 1
605  _fe->get_d2phidxdy();
606  _fe->get_d2phidy2();
607 #endif
608 #if LIBMESH_DIM > 2
609  _fe->get_d2phidxdz();
610  _fe->get_d2phidydz();
611  _fe->get_d2phidz2();
612 #endif
613 
614 #endif
615  }
std::unique_ptr< EquationSystems > _es
Definition: fe_test.h:282
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition: fe_type.h:196
std::string _case_name
Name of the case, can be used in the test to switch cases.
Definition: fe_test.h:275
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Definition: dof_map.C:2201
static constexpr Real TOLERANCE
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:415
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)...
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:2535
dof_id_type id() const
Definition: dof_object.h:819
virtual unsigned int n_nodes() const =0
Manages consistently variables, degrees of freedom, and coefficient vectors.
Definition: system.h:98
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:1344
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:1102
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
void project_solution(FunctionBase< Number > *f, FunctionBase< Gradient > *g=nullptr, std::optional< ConstElemRange > active_local_range=std::nullopt, std::optional< std::vector< unsigned int >> variable_numbers=std::nullopt) const
Projects arbitrary functions onto the current solution.
RealTensorValue rotate(MeshBase &mesh, const Real phi, const Real theta=0., const Real psi=0.)
Rotates the mesh in the xy plane.
virtual unsigned int n_vertices() const =0
const FEType & variable_type(const unsigned int i) const
Definition: system.C:2721
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
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:176
void redistribute(MeshBase &mesh, const FunctionBase< Real > &mapfunc)
Deterministically perturb the nodal locations.
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:2417
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:153
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:292

◆ tearDown()

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

Definition at line 617 of file fe_test.h.

617 {}

◆ testCustomReinit()

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

Definition at line 1007 of file fe_test.h.

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

1008  {
1009  LOG_UNIT_TEST;
1010 
1011  std::vector<Point> q_points;
1012  std::vector<Real> weights;
1013  q_points.resize(3); weights.resize(3);
1014  q_points[0](0) = 0.0; q_points[0](1) = 0.0; weights[0] = Real(1)/6;
1015  q_points[1](0) = 1.0; q_points[1](1) = 0.0; weights[1] = weights[0];
1016  q_points[2](0) = 0.0; q_points[2](1) = 1.0; weights[2] = weights[0];
1017 
1018  FEType fe_type = this->_sys->variable_type(0);
1019  std::unique_ptr<FEBase> fe (FEBase::build(this->_dim, fe_type));
1020  const int extraorder = 3;
1021  std::unique_ptr<QBase> qrule (fe_type.default_quadrature_rule (this->_dim, extraorder));
1022  fe->attach_quadrature_rule (qrule.get());
1023 
1024  const std::vector<Point> & q_pos = fe->get_xyz();
1025 
1026  for (const auto & elem : this->_mesh->active_local_element_ptr_range()) {
1027  fe->reinit (elem, &q_points, &weights);
1028  CPPUNIT_ASSERT_EQUAL(q_points.size(), std::size_t(3));
1029  CPPUNIT_ASSERT_EQUAL(q_pos.size(), std::size_t(3)); // 6? bug?
1030  }
1031  }
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
const FEType & variable_type(const unsigned int i) const
Definition: system.C:2721
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

◆ testDualDoesntScreamAndDie()

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

Definition at line 820 of file fe_test.h.

821  {
822  LOG_UNIT_TEST;
823 
824  // Handle the "more processors than elements" case
825  if (!this->_elem)
826  return;
827 
828  // Request dual calculations
829  this->_fe->get_dual_phi();
830 
831  // reinit using the default quadrature rule in order to calculate the dual coefficients
832  this->_fe->reinit(this->_elem);
833  }

◆ testFEInterface()

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

Definition at line 743 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().

744  {
745  LOG_UNIT_TEST;
746 
747  // Handle the "more processors than elements" case
748  if (!this->_elem)
749  return;
750 
751  this->_fe->reinit(this->_elem);
752 
753  const FEType fe_type = this->_sys->variable_type(0);
754 
755  unsigned int my_n_dofs = 0;
756 
757  switch (this->_elem->dim())
758  {
759  case 0:
760  my_n_dofs = FE<0,family>::n_dofs(this->_elem, order);
761  break;
762  case 1:
763  my_n_dofs = FE<1,family>::n_dofs(this->_elem, order);
764  break;
765  case 2:
766  my_n_dofs = FE<2,family>::n_dofs(this->_elem, order);
767  break;
768  case 3:
769  my_n_dofs = FE<3,family>::n_dofs(this->_elem, order);
770  break;
771  default:
772  libmesh_error();
773  }
774 
775  CPPUNIT_ASSERT_EQUAL(
776  FEInterface::n_shape_functions(fe_type, this->_elem),
777  my_n_dofs);
778 
779  CPPUNIT_ASSERT_EQUAL(
780  FEInterface::get_continuity(fe_type),
781  this->_fe->get_continuity());
782 
783  CPPUNIT_ASSERT_EQUAL(
784  FEInterface::is_hierarchic(fe_type),
785  this->_fe->is_hierarchic());
786  }
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.C:2721
virtual unsigned short dim() const =0

◆ testGradU()

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

Definition at line 836 of file fe_test.h.

837  {
838  LOG_UNIT_TEST;
839 
840  auto f = [this](Point p)
841  {
842  Parameters dummy;
843 
844  Gradient grad_u = 0;
845  for (std::size_t d = 0; d != this->_dof_indices.size(); ++d)
846  grad_u += this->_fe->get_dphi()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
847 
848  RealGradient true_grad = this->true_gradient(p);
849 
850  LIBMESH_ASSERT_NUMBERS_EQUAL
851  (grad_u(0), true_grad(0), this->_grad_tol);
852  if (this->_dim > 1)
853  LIBMESH_ASSERT_NUMBERS_EQUAL
854  (grad_u(1), true_grad(1), this->_grad_tol);
855  if (this->_dim > 2)
856  LIBMESH_ASSERT_NUMBERS_EQUAL
857  (grad_u(2), true_grad(2), this->_grad_tol);
858  };
859 
860  testLoop(f);
861  }
This class provides the ability to map between arbitrary, user-defined strings and several data types...
Definition: parameters.h:74
void testLoop(Functor f)
Definition: fe_test.h:628
static RealGradient true_gradient(Point p)
Definition: fe_test.h:289
This class defines a vector in LIBMESH_DIM dimensional Real or Complex space.
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:1667
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39

◆ testGradUComp()

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

Definition at line 863 of file fe_test.h.

864  {
865  LOG_UNIT_TEST;
866 
867  auto f = [this](Point p)
868  {
869  Parameters dummy;
870 
871  Number grad_u_x = 0, grad_u_y = 0, grad_u_z = 0;
872  for (std::size_t d = 0; d != this->_dof_indices.size(); ++d)
873  {
874  grad_u_x += this->_fe->get_dphidx()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
875 #if LIBMESH_DIM > 1
876  grad_u_y += this->_fe->get_dphidy()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
877 #endif
878 #if LIBMESH_DIM > 2
879  grad_u_z += this->_fe->get_dphidz()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
880 #endif
881  }
882 
883  RealGradient true_grad = this->true_gradient(p);
884 
885  LIBMESH_ASSERT_NUMBERS_EQUAL(grad_u_x,
886  true_grad(0), this->_grad_tol);
887  if (this->_dim > 1)
888  LIBMESH_ASSERT_NUMBERS_EQUAL
889  (grad_u_y, true_grad(1), this->_grad_tol);
890  if (this->_dim > 2)
891  LIBMESH_ASSERT_NUMBERS_EQUAL
892  (grad_u_z, true_grad(2), this->_grad_tol);
893  };
894 
895  testLoop(f);
896  }
This class provides the ability to map between arbitrary, user-defined strings and several data types...
Definition: parameters.h:74
void testLoop(Functor f)
Definition: fe_test.h:628
static RealGradient true_gradient(Point p)
Definition: fe_test.h:289
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:1667
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39

◆ testHessU()

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

Definition at line 899 of file fe_test.h.

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

900  {
901  LOG_UNIT_TEST;
902 
903  // Szabab elements don't have second derivatives yet
904  if (family == SZABAB)
905  return;
906 
907 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
908  auto f = [this](Point p)
909  {
910  Tensor hess_u;
911  for (std::size_t d = 0; d != this->_dof_indices.size(); ++d)
912  hess_u += this->_fe->get_d2phi()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
913 
914  // TODO: Yeah we'll test the ugly expressions later.
915  if (family == RATIONAL_BERNSTEIN && order > 1)
916  return;
917 
918  RealTensor true_hess = this->true_hessian(p);
919 
920  LIBMESH_ASSERT_NUMBERS_EQUAL
921  (true_hess(0,0), hess_u(0,0), this->_hess_tol);
922  if (this->_dim > 1)
923  {
924  LIBMESH_ASSERT_NUMBERS_EQUAL
925  (hess_u(0,1), hess_u(1,0), this->_hess_tol);
926  LIBMESH_ASSERT_NUMBERS_EQUAL
927  (true_hess(0,1), hess_u(0,1), this->_hess_tol);
928  LIBMESH_ASSERT_NUMBERS_EQUAL
929  (true_hess(1,1), hess_u(1,1), this->_hess_tol);
930  }
931  if (this->_dim > 2)
932  {
933  LIBMESH_ASSERT_NUMBERS_EQUAL
934  (hess_u(0,2), hess_u(2,0), this->_hess_tol);
935  LIBMESH_ASSERT_NUMBERS_EQUAL
936  (hess_u(1,2), hess_u(2,1), this->_hess_tol);
937  LIBMESH_ASSERT_NUMBERS_EQUAL
938  (true_hess(0,2), hess_u(0,2), this->_hess_tol);
939  LIBMESH_ASSERT_NUMBERS_EQUAL
940  (true_hess(1,2), hess_u(1,2), this->_hess_tol);
941  LIBMESH_ASSERT_NUMBERS_EQUAL
942  (true_hess(2,2), hess_u(2,2), this->_hess_tol);
943  }
944  };
945 
946  testLoop(f);
947 #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES
948  }
void testLoop(Functor f)
Definition: fe_test.h:628
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:1667
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, typename CaseName >
void FETest< order, family, elem_type, CaseName >::testHessUComp ( )
inline

Definition at line 950 of file fe_test.h.

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

951  {
952 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
953  LOG_UNIT_TEST;
954 
955  // Szabab elements don't have second derivatives yet
956  if (family == SZABAB)
957  return;
958 
959  auto f = [this](Point p)
960  {
961  Number hess_u_xx = 0, hess_u_xy = 0, hess_u_yy = 0,
962  hess_u_xz = 0, hess_u_yz = 0, hess_u_zz = 0;
963  for (std::size_t d = 0; d != this->_dof_indices.size(); ++d)
964  {
965  hess_u_xx += this->_fe->get_d2phidx2()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
966 #if LIBMESH_DIM > 1
967  hess_u_xy += this->_fe->get_d2phidxdy()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
968  hess_u_yy += this->_fe->get_d2phidy2()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
969 #endif
970 #if LIBMESH_DIM > 2
971  hess_u_xz += this->_fe->get_d2phidxdz()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
972  hess_u_yz += this->_fe->get_d2phidydz()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
973  hess_u_zz += this->_fe->get_d2phidz2()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
974 #endif
975  }
976 
977  // TODO: Yeah we'll test the ugly expressions later.
978  if (family == RATIONAL_BERNSTEIN && order > 1)
979  return;
980 
981  RealTensor true_hess = this->true_hessian(p);
982 
983  LIBMESH_ASSERT_NUMBERS_EQUAL
984  (true_hess(0,0), hess_u_xx, this->_hess_tol);
985  if (this->_dim > 1)
986  {
987  LIBMESH_ASSERT_NUMBERS_EQUAL
988  (true_hess(0,1), hess_u_xy, this->_hess_tol);
989  LIBMESH_ASSERT_NUMBERS_EQUAL
990  (true_hess(1,1), hess_u_yy, this->_hess_tol);
991  }
992  if (this->_dim > 2)
993  {
994  LIBMESH_ASSERT_NUMBERS_EQUAL
995  (true_hess(0,2), hess_u_xz, this->_hess_tol);
996  LIBMESH_ASSERT_NUMBERS_EQUAL
997  (true_hess(1,2), hess_u_yz, this->_hess_tol);
998  LIBMESH_ASSERT_NUMBERS_EQUAL
999  (true_hess(2,2), hess_u_zz, this->_hess_tol);
1000  }
1001  };
1002 
1003  testLoop(f);
1004 #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES
1005  }
void testLoop(Functor f)
Definition: fe_test.h:628
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:1667
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, typename CaseName >
template<typename Functor >
void FETest< order, family, elem_type, CaseName >::testLoop ( Functor  f)
inline

Definition at line 628 of file fe_test.h.

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

629  {
630  // Handle the "more processors than elements" case
631  if (!this->_elem)
632  return;
633 
634  // These tests require exceptions to be enabled because a
635  // TypeTensor::solve() call down in Elem::contains_point()
636  // actually throws a non-fatal exception for a certain Point which
637  // is not in the Elem. When exceptions are not enabled, this test
638  // simply aborts.
639 #ifdef LIBMESH_ENABLE_EXCEPTIONS
640  for (unsigned int i=0; i != this->_nx; ++i)
641  for (unsigned int j=0; j != this->_ny; ++j)
642  for (unsigned int k=0; k != this->_nz; ++k)
643  {
644  Point p = Real(i)/this->_nx;
645  if (j > 0)
646  p(1) = Real(j)/this->_ny;
647  if (k > 0)
648  p(2) = Real(k)/this->_nz;
649  if (!this->_elem->contains_point(p))
650  continue;
651 
652  // If at a singular node, cannot use FEMap::map
653  if (this->_elem->local_singular_node(p) != invalid_uint)
654  continue;
655 
656  std::vector<Point> master_points
657  (1, FEMap::inverse_map(this->_dim, this->_elem, p));
658 
659  // Reinit at point to test against analytic solution
660  this->_fe->reinit(this->_elem, &master_points);
661 
662  f(p);
663  }
664 #endif // LIBMESH_ENABLE_EXCEPTIONS
665  }
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:303
virtual bool contains_point(const Point &p, Real tol=TOLERANCE) const
Definition: elem.C:2784
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:1837
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39

◆ testPartitionOfUnity()

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

Definition at line 667 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.

668  {
669  if (!this->_elem)
670  return;
671 
672  this->_fe->reinit(this->_elem);
673 
674  bool satisfies_partition_of_unity = true;
675  for (const auto qp : make_range(this->_qrule->n_points()))
676  {
677  Real phi_sum = 0;
678  for (std::size_t d = 0; d != this->_dof_indices.size(); ++d)
679  phi_sum += this->_fe->get_phi()[d][qp];
680  if (phi_sum < (1 - TOLERANCE) || phi_sum > (1 + TOLERANCE))
681  {
682  satisfies_partition_of_unity = false;
683  break;
684  }
685  }
686 
687  switch (this->_fe->get_family())
688  {
689  case MONOMIAL:
690  {
691  switch (this->_fe->get_order())
692  {
693  case CONSTANT:
694  CPPUNIT_ASSERT(satisfies_partition_of_unity);
695  break;
696 
697  default:
698  CPPUNIT_ASSERT(!satisfies_partition_of_unity);
699  break;
700  }
701  break;
702  }
703  case SZABAB:
704  case HIERARCHIC:
705  case L2_HIERARCHIC:
706  {
707  switch (this->_fe->get_order())
708  {
709  case FIRST:
710  CPPUNIT_ASSERT(satisfies_partition_of_unity);
711  break;
712 
713  default:
714  CPPUNIT_ASSERT(!satisfies_partition_of_unity);
715  break;
716  }
717  break;
718  }
719 
720  case XYZ:
721  case CLOUGH:
722  case HERMITE:
723  {
724  CPPUNIT_ASSERT(!satisfies_partition_of_unity);
725  break;
726  }
727 
728  case LAGRANGE:
729  case L2_LAGRANGE:
730  case BERNSTEIN:
731  case RATIONAL_BERNSTEIN:
732  {
733  CPPUNIT_ASSERT(satisfies_partition_of_unity);
734  break;
735  }
736 
737  default:
738  CPPUNIT_FAIL("Uncovered FEFamily");
739  }
740  }
static constexpr Real TOLERANCE
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
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:176

◆ testU()

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

Definition at line 788 of file fe_test.h.

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

789  {
790  LOG_UNIT_TEST;
791 
792  auto f = [this](Point p)
793  {
794  Parameters dummy;
795 
796  Number u = 0;
797  for (std::size_t d = 0; d != this->_dof_indices.size(); ++d)
798  u += this->_fe->get_phi()[d][0] * (*this->_sys->current_local_solution)(this->_dof_indices[d]);
799 
800  Number true_u;
801 
802  if (family == RATIONAL_BERNSTEIN && order > 1)
803  true_u = rational_test(p, dummy, "", "");
804  else if (order > 3)
805  true_u = fe_quartic_test(p, dummy, "", "");
806  else if (FE_CAN_TEST_CUBIC)
807  true_u = fe_cubic_test(p, dummy, "", "");
808  else if (order > 1)
809  true_u = p(0)*p(0) + 0.5*p(1)*p(1) + 0.25*p(2)*p(2) +
810  0.125*p(0)*p(1) + 0.0625*p(0)*p(2) + 0.03125*p(1)*p(2);
811  else
812  true_u = p(0) + 0.25*p(1) + 0.0625*p(2);
813 
814  LIBMESH_ASSERT_NUMBERS_EQUAL (true_u, u, this->_value_tol);
815  };
816 
817  testLoop(f);
818  }
This class provides the ability to map between arbitrary, user-defined strings and several data types...
Definition: parameters.h:74
void testLoop(Functor f)
Definition: fe_test.h:628
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::unique_ptr< NumericVector< Number > > current_local_solution
All the values I need to compute my contribution to the simulation at hand.
Definition: system.h:1667
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, CaseName >::true_gradient ( Point  p)
inlinestaticprotectedinherited

Definition at line 289 of file fe_test.h.

290  {
291  Parameters dummy;
292 
293  Gradient true_grad;
294  RealGradient returnval;
295 
296  if (family == RATIONAL_BERNSTEIN && order > 1)
297  true_grad = rational_test_grad(p, dummy, "", "");
298  else if (order > 3)
299  true_grad = fe_quartic_test_grad(p, dummy, "", "");
300  else if (FE_CAN_TEST_CUBIC)
301  true_grad = fe_cubic_test_grad(p, dummy, "", "");
302  else if (order > 1)
303  {
304  const Real & x = p(0);
305  const Real & y = (LIBMESH_DIM > 1) ? p(1) : 0;
306  const Real & z = (LIBMESH_DIM > 2) ? p(2) : 0;
307 
308  true_grad = Gradient(2*x+0.125*y+0.0625*z,
309  y+0.125*x+0.03125*z,
310  0.5*z+0.0625*x+0.03125*y);
311  }
312  else
313  true_grad = Gradient(1.0, 0.25, 0.0625);
314 
315  for (unsigned int d=0; d != LIBMESH_DIM; ++d)
316  {
317  CPPUNIT_ASSERT(true_grad(d) ==
318  Number(libmesh_real(true_grad(d))));
319 
320  returnval(d) = libmesh_real(true_grad(d));
321  }
322 
323  return returnval;
324  }
T libmesh_real(T a)
This class provides the ability to map between arbitrary, user-defined strings and several data types...
Definition: parameters.h:74
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, CaseName >::true_hessian ( Point  p)
inlinestaticprotectedinherited

Definition at line 327 of file fe_test.h.

328  {
329  const Real & x = p(0);
330  const Real & y = LIBMESH_DIM > 1 ? p(1) : 0;
331  const Real & z = LIBMESH_DIM > 2 ? p(2) : 0;
332 
333  if (order > 3)
334  return RealTensor
335  { 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),
336  -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),
337  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 };
338  else if (FE_CAN_TEST_CUBIC)
339  return RealTensor
340  { 6*x-4+2*(1-y), -2*x+z-1, y-1,
341  -2*x+z-1, -2*z, x+1-2*y,
342  y-1, x+1-2*y, 6*z-4 };
343  else if (order > 1)
344  return RealTensor
345  { 2, 0.125, 0.0625,
346  0.125, 1, 0.03125,
347  0.0625, 0.03125, 0.5 };
348 
349  return RealTensor
350  { 0, 0, 0,
351  0, 0, 0,
352  0, 0, 0 };
353  }
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

◆ _case_name

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

Name of the case, can be used in the test to switch cases.

Definition at line 275 of file fe_test.h.

◆ _dim

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

Definition at line 277 of file fe_test.h.

◆ _dof_indices

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

Definition at line 279 of file fe_test.h.

◆ _elem

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

Definition at line 278 of file fe_test.h.

◆ _es

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

Definition at line 282 of file fe_test.h.

◆ _fe

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

Definition at line 283 of file fe_test.h.

◆ _grad_tol

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

Definition at line 286 of file fe_test.h.

◆ _hess_tol

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

Definition at line 286 of file fe_test.h.

◆ _mesh

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

Definition at line 281 of file fe_test.h.

◆ _nx

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

Definition at line 277 of file fe_test.h.

◆ _ny

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

Definition at line 277 of file fe_test.h.

◆ _nz

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

Definition at line 277 of file fe_test.h.

◆ _qrule

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

Definition at line 284 of file fe_test.h.

◆ _sys

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

Definition at line 280 of file fe_test.h.

◆ _value_tol

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

Definition at line 286 of file fe_test.h.

◆ libmesh_suite_name

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

Definition at line 272 of file fe_test.h.


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