21 #include "libmesh/dof_map.h"    22 #include "libmesh/elem.h"    23 #include "libmesh/enum_to_string.h"    24 #include "libmesh/fe.h"    25 #include "libmesh/fe_interface.h"    26 #include "libmesh/fe_macro.h"    27 #include "libmesh/remote_elem.h"    28 #include "libmesh/threads.h"    31 #ifdef LIBMESH_ENABLE_AMR    32 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS    34 #include "libmesh/fe_interface_macros.h"    35 #include "libmesh/inf_fe.h"    45                          const std::vector<Number> & elem_soln,
    46                          std::vector<Number> &       nodal_soln,
    47                          const bool add_p_level)
    52   const Order totalorder = order + add_p_level*elem->
p_level();
    67               libmesh_assert_equal_to (elem_soln.size(), 2);
    68               libmesh_assert_equal_to (nodal_soln.size(), 3);
    70               nodal_soln[0] = elem_soln[0];
    71               nodal_soln[1] = elem_soln[1];
    72               nodal_soln[2] = .5*(elem_soln[0] + elem_soln[1]);
    79               libmesh_assert_equal_to (elem_soln.size(), 2);
    80               libmesh_assert_equal_to (nodal_soln.size(), 4);
    82               nodal_soln[0] = elem_soln[0];
    83               nodal_soln[1] = elem_soln[1];
    84               nodal_soln[2] = (2.*elem_soln[0] + elem_soln[1])/3.;
    85               nodal_soln[3] = (elem_soln[0] + 2.*elem_soln[1])/3.;
    92             libmesh_assert_equal_to (nodal_soln.size(), 7);
    93             nodal_soln[6] = (elem_soln[0] + elem_soln[1] + elem_soln[2])/3.;
    94             libmesh_fallthrough();
    98               libmesh_assert_equal_to (elem_soln.size(), 3);
   100               nodal_soln[0] = elem_soln[0];
   101               nodal_soln[1] = elem_soln[1];
   102               nodal_soln[2] = elem_soln[2];
   103               nodal_soln[3] = .5*(elem_soln[0] + elem_soln[1]);
   104               nodal_soln[4] = .5*(elem_soln[1] + elem_soln[2]);
   105               nodal_soln[5] = .5*(elem_soln[2] + elem_soln[0]);
   114               libmesh_assert_equal_to (elem_soln.size(), 4);
   117                 libmesh_assert_equal_to (nodal_soln.size(), 8);
   119                 libmesh_assert_equal_to (nodal_soln.size(), 9);
   122               nodal_soln[0] = elem_soln[0];
   123               nodal_soln[1] = elem_soln[1];
   124               nodal_soln[2] = elem_soln[2];
   125               nodal_soln[3] = elem_soln[3];
   126               nodal_soln[4] = .5*(elem_soln[0] + elem_soln[1]);
   127               nodal_soln[5] = .5*(elem_soln[1] + elem_soln[2]);
   128               nodal_soln[6] = .5*(elem_soln[2] + elem_soln[3]);
   129               nodal_soln[7] = .5*(elem_soln[3] + elem_soln[0]);
   132                 nodal_soln[8] = .25*(elem_soln[0] + elem_soln[1] + elem_soln[2] + elem_soln[3]);
   139             libmesh_assert_equal_to (nodal_soln.size(), 14);
   140             nodal_soln[10] = (elem_soln[0] + elem_soln[1] + elem_soln[2])/3.;
   141             nodal_soln[11] = (elem_soln[0] + elem_soln[1] + elem_soln[3])/3.;
   142             nodal_soln[12] = (elem_soln[1] + elem_soln[2] + elem_soln[3])/3.;
   143             nodal_soln[13] = (elem_soln[0] + elem_soln[2] + elem_soln[3])/3.;
   144             libmesh_fallthrough();
   147               libmesh_assert_equal_to (elem_soln.size(), 4);
   150               nodal_soln[0] = elem_soln[0];
   151               nodal_soln[1] = elem_soln[1];
   152               nodal_soln[2] = elem_soln[2];
   153               nodal_soln[3] = elem_soln[3];
   154               nodal_soln[4] = .5*(elem_soln[0] + elem_soln[1]);
   155               nodal_soln[5] = .5*(elem_soln[1] + elem_soln[2]);
   156               nodal_soln[6] = .5*(elem_soln[2] + elem_soln[0]);
   157               nodal_soln[7] = .5*(elem_soln[3] + elem_soln[0]);
   158               nodal_soln[8] = .5*(elem_soln[3] + elem_soln[1]);
   159               nodal_soln[9] = .5*(elem_soln[3] + elem_soln[2]);
   168               libmesh_assert_equal_to (elem_soln.size(), 8);
   171                 libmesh_assert_equal_to (nodal_soln.size(), 20);
   173                 libmesh_assert_equal_to (nodal_soln.size(), 27);
   175               nodal_soln[0]  = elem_soln[0];
   176               nodal_soln[1]  = elem_soln[1];
   177               nodal_soln[2]  = elem_soln[2];
   178               nodal_soln[3]  = elem_soln[3];
   179               nodal_soln[4]  = elem_soln[4];
   180               nodal_soln[5]  = elem_soln[5];
   181               nodal_soln[6]  = elem_soln[6];
   182               nodal_soln[7]  = elem_soln[7];
   183               nodal_soln[8]  = .5*(elem_soln[0] + elem_soln[1]);
   184               nodal_soln[9]  = .5*(elem_soln[1] + elem_soln[2]);
   185               nodal_soln[10] = .5*(elem_soln[2] + elem_soln[3]);
   186               nodal_soln[11] = .5*(elem_soln[3] + elem_soln[0]);
   187               nodal_soln[12] = .5*(elem_soln[0] + elem_soln[4]);
   188               nodal_soln[13] = .5*(elem_soln[1] + elem_soln[5]);
   189               nodal_soln[14] = .5*(elem_soln[2] + elem_soln[6]);
   190               nodal_soln[15] = .5*(elem_soln[3] + elem_soln[7]);
   191               nodal_soln[16] = .5*(elem_soln[4] + elem_soln[5]);
   192               nodal_soln[17] = .5*(elem_soln[5] + elem_soln[6]);
   193               nodal_soln[18] = .5*(elem_soln[6] + elem_soln[7]);
   194               nodal_soln[19] = .5*(elem_soln[4] + elem_soln[7]);
   198                   nodal_soln[20] = .25*(elem_soln[0] + elem_soln[1] + elem_soln[2] + elem_soln[3]);
   199                   nodal_soln[21] = .25*(elem_soln[0] + elem_soln[1] + elem_soln[4] + elem_soln[5]);
   200                   nodal_soln[22] = .25*(elem_soln[1] + elem_soln[2] + elem_soln[5] + elem_soln[6]);
   201                   nodal_soln[23] = .25*(elem_soln[2] + elem_soln[3] + elem_soln[6] + elem_soln[7]);
   202                   nodal_soln[24] = .25*(elem_soln[3] + elem_soln[0] + elem_soln[7] + elem_soln[4]);
   203                   nodal_soln[25] = .25*(elem_soln[4] + elem_soln[5] + elem_soln[6] + elem_soln[7]);
   205                   nodal_soln[26] = .125*(elem_soln[0] + elem_soln[1] + elem_soln[2] + elem_soln[3] +
   206                                          elem_soln[4] + elem_soln[5] + elem_soln[6] + elem_soln[7]);
   214             nodal_soln[20]  = (elem_soln[9] + elem_soln[10] + elem_soln[11])/
Real(3);
   215             libmesh_fallthrough();
   218               libmesh_assert_equal_to (nodal_soln.size(), 20);
   219             nodal_soln[18]  = (elem_soln[0] + elem_soln[1] + elem_soln[2])/
Real(3);
   220             nodal_soln[19]  = (elem_soln[3] + elem_soln[4] + elem_soln[5])/
Real(3);
   221             libmesh_fallthrough();
   224               libmesh_assert_equal_to (nodal_soln.size(), 18);
   225             nodal_soln[15] = .25*(elem_soln[0] + elem_soln[1] + elem_soln[4] + elem_soln[3]);
   226             nodal_soln[16] = .25*(elem_soln[1] + elem_soln[2] + elem_soln[5] + elem_soln[4]);
   227             nodal_soln[17] = .25*(elem_soln[2] + elem_soln[0] + elem_soln[3] + elem_soln[5]);
   228             libmesh_fallthrough();
   231               libmesh_assert_equal_to (elem_soln.size(), 6);
   234                 libmesh_assert_equal_to (nodal_soln.size(), 15);
   236               nodal_soln[0]  = elem_soln[0];
   237               nodal_soln[1]  = elem_soln[1];
   238               nodal_soln[2]  = elem_soln[2];
   239               nodal_soln[3]  = elem_soln[3];
   240               nodal_soln[4]  = elem_soln[4];
   241               nodal_soln[5]  = elem_soln[5];
   242               nodal_soln[6]  = .5*(elem_soln[0] + elem_soln[1]);
   243               nodal_soln[7]  = .5*(elem_soln[1] + elem_soln[2]);
   244               nodal_soln[8]  = .5*(elem_soln[0] + elem_soln[2]);
   245               nodal_soln[9]  = .5*(elem_soln[0] + elem_soln[3]);
   246               nodal_soln[10] = .5*(elem_soln[1] + elem_soln[4]);
   247               nodal_soln[11] = .5*(elem_soln[2] + elem_soln[5]);
   248               nodal_soln[12] = .5*(elem_soln[3] + elem_soln[4]);
   249               nodal_soln[13] = .5*(elem_soln[4] + elem_soln[5]);
   250               nodal_soln[14] = .5*(elem_soln[3] + elem_soln[5]);
   257               libmesh_assert_equal_to (nodal_soln.size(), 18);
   259               nodal_soln[14] = (elem_soln[0] + elem_soln[1] + elem_soln[4])/
Real(3);
   260               nodal_soln[15] = (elem_soln[1] + elem_soln[2] + elem_soln[4])/
Real(3);
   261               nodal_soln[16] = (elem_soln[2] + elem_soln[3] + elem_soln[4])/
Real(3);
   262               nodal_soln[17] = (elem_soln[0] + elem_soln[3] + elem_soln[4])/
Real(3);
   264               libmesh_fallthrough();
   270                 libmesh_assert_equal_to (nodal_soln.size(), 14);
   272               nodal_soln[13] = .25*(elem_soln[0] + elem_soln[1] + elem_soln[2] + elem_soln[3]);
   274               libmesh_fallthrough();
   279               libmesh_assert_equal_to (elem_soln.size(), 5);
   282                 libmesh_assert_equal_to (nodal_soln.size(), 13);
   284               nodal_soln[0]  = elem_soln[0];
   285               nodal_soln[1]  = elem_soln[1];
   286               nodal_soln[2]  = elem_soln[2];
   287               nodal_soln[3]  = elem_soln[3];
   288               nodal_soln[4]  = elem_soln[4];
   289               nodal_soln[5]  = .5*(elem_soln[0] + elem_soln[1]);
   290               nodal_soln[6]  = .5*(elem_soln[1] + elem_soln[2]);
   291               nodal_soln[7]  = .5*(elem_soln[2] + elem_soln[3]);
   292               nodal_soln[8]  = .5*(elem_soln[3] + elem_soln[0]);
   293               nodal_soln[9]  = .5*(elem_soln[0] + elem_soln[4]);
   294               nodal_soln[10] = .5*(elem_soln[1] + elem_soln[4]);
   295               nodal_soln[11] = .5*(elem_soln[2] + elem_soln[4]);
   296               nodal_soln[12] = .5*(elem_soln[3] + elem_soln[4]);
   304               nodal_soln = elem_soln;
   317               libmesh_assert_equal_to (elem_soln.size(), 3);
   318               libmesh_assert_equal_to (nodal_soln.size(), 4);
   321               nodal_soln[0] = elem_soln[0];
   322               nodal_soln[1] = elem_soln[1];
   323               nodal_soln[2] = (2.*elem_soln[0] - elem_soln[1] +
   325               nodal_soln[3] = (-elem_soln[0] + 2.*elem_soln[1] +
   332               libmesh_assert_equal_to (elem_soln.size(), 6);
   333               libmesh_assert_equal_to (nodal_soln.size(), 7);
   335               for (
int i=0; i != 6; ++i)
   336                 nodal_soln[i] = elem_soln[i];
   338               nodal_soln[6] = -1./9. * (elem_soln[0] + elem_soln[1] + elem_soln[2])
   339                               +4./9. * (elem_soln[3] + elem_soln[4] + elem_soln[5]);
   346               libmesh_assert_equal_to (elem_soln.size(), 10);
   347               libmesh_assert_equal_to (nodal_soln.size(), 14);
   349               for (
int i=0; i != 10; ++i)
   350                 nodal_soln[i] = elem_soln[i];
   352               nodal_soln[10] = -1./9. * (elem_soln[0] + elem_soln[1] + elem_soln[2])
   353                                +4./9. * (elem_soln[4] + elem_soln[5] + elem_soln[6]);
   354               nodal_soln[11] = -1./9. * (elem_soln[0] + elem_soln[1] + elem_soln[3])
   355                                +4./9. * (elem_soln[4] + elem_soln[7] + elem_soln[8]);
   356               nodal_soln[12] = -1./9. * (elem_soln[1] + elem_soln[2] + elem_soln[3])
   357                                +4./9. * (elem_soln[5] + elem_soln[8] + elem_soln[9]);
   358               nodal_soln[13] = -1./9. * (elem_soln[0] + elem_soln[2] + elem_soln[3])
   359                                +4./9. * (elem_soln[6] + elem_soln[7] + elem_soln[9]);
   366               nodal_soln[20]  = (elem_soln[9] + elem_soln[10] + elem_soln[11])/
Real(3);
   367               libmesh_fallthrough();
   372                 libmesh_assert_equal_to (nodal_soln.size(), 20);
   374               for (
int i=0; i != 18; ++i)
   375                 nodal_soln[i] = elem_soln[i];
   377               nodal_soln[18]  = (elem_soln[0] + elem_soln[1] + elem_soln[2])/
Real(3);
   378               nodal_soln[19]  = (elem_soln[3] + elem_soln[4] + elem_soln[5])/
Real(3);
   384               libmesh_assert_equal_to (nodal_soln.size(), 18);
   386               for (
int i=0; i != 14; ++i)
   387                 nodal_soln[i] = elem_soln[i];
   389               nodal_soln[14] = (elem_soln[0] + elem_soln[1] + elem_soln[4])/
Real(3);
   390               nodal_soln[15] = (elem_soln[1] + elem_soln[2] + elem_soln[4])/
Real(3);
   391               nodal_soln[16] = (elem_soln[2] + elem_soln[3] + elem_soln[4])/
Real(3);
   392               nodal_soln[17] = (elem_soln[0] + elem_soln[3] + elem_soln[4])/
Real(3);
   394               libmesh_fallthrough();
   403               libmesh_assert_less_equal(nodal_soln.size(), elem_soln.size());
   405                 nodal_soln[i] = elem_soln[i];
   421         libmesh_assert_less_equal(nodal_soln.size(), elem_soln.size());
   423           nodal_soln[i] = elem_soln[i];
   433 unsigned int lagrange_n_dofs(
const ElemType t, 
const Elem * e, 
const Order o)
   510               libmesh_error_msg(
"Code (see stack trace) used an outdated FE function overload.\n"   511                                 "n_dofs() on a polygon or polyhedron is not defined by ElemType alone.");
   610       libmesh_error_msg(
"ERROR: Invalid Order " << 
Utility::enum_to_string(o) << 
" selected for LAGRANGE FE family!");
   616 unsigned int lagrange_n_dofs_at_node(
const ElemType t,
   618                                      const unsigned int n)
   852       libmesh_error_msg(
"Unsupported order: " << o );
   858 unsigned int lagrange_n_dofs_at_node(
const Elem & e,
   860                                      const unsigned int n)
   862   return lagrange_n_dofs_at_node(e.type(), o, n);
   866 #ifdef LIBMESH_ENABLE_AMR   867 void lagrange_compute_constraints (DofConstraints & constraints,
   869                                    const unsigned int variable_number,
   880   if (elem->subactive())
   883 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS   884    if (elem->infinite())
   886       const FEType fe_t = dof_map.variable_type(variable_number);
   893             inf_fe_family_mapping_switch(2, inf_compute_constraints (constraints, dof_map, variable_number, elem) , ,; 
break;);
   898             inf_fe_family_mapping_switch(3, inf_compute_constraints (constraints, dof_map, variable_number, elem) , ,; 
break;);
   902            libmesh_error_msg(
"Invalid dim = " << Dim);
   908   const Variable & var = dof_map.variable(variable_number);
   909   const FEType fe_type = var.type();
   910   const bool add_p_level = dof_map.should_p_refine_var(variable_number);
   913   std::vector<dof_id_type> my_dof_indices, parent_dof_indices;
   914   std::unique_ptr<const Elem> my_side, parent_side;
   918   for (
auto s : elem->side_index_range())
   919     if (
const Elem * 
const neigh = elem->neighbor_ptr(s);
   923         if (neigh->level() < elem->level() &&
   924             var.active_on_subdomain(neigh->subdomain_id()))
   928             const Elem * parent = elem->parent();
   935             elem->build_side_ptr(my_side, s);
   936             parent->build_side_ptr(parent_side, s);
   941             FEType side_fe_type = fe_type;
   943             if (my_side->default_order() < fe_type.order)
   945                 side_fe_type.order = my_side->default_order();
   946                 extra_order = (
int)(side_fe_type.order) -
   947                               (
int)(fe_type.order);
   954             my_dof_indices.reserve (my_side->n_nodes());
   955             parent_dof_indices.reserve (parent_side->n_nodes());
   957             dof_map.dof_indices (my_side.get(), my_dof_indices,
   958                                  variable_number, extra_order);
   959             dof_map.dof_indices (parent_side.get(), parent_dof_indices,
   960                                  variable_number, extra_order);
   962             const unsigned int n_side_dofs =
   964             const unsigned int n_parent_side_dofs =
   966             for (
unsigned int my_dof=0; my_dof != n_side_dofs; my_dof++)
   968                 libmesh_assert_less (my_dof, my_side->n_nodes());
   971                 const dof_id_type my_dof_g = my_dof_indices[my_dof];
   975                 bool self_constraint = 
false;
   976                 for (
unsigned int their_dof=0;
   977                      their_dof != n_parent_side_dofs; their_dof++)
   979                     libmesh_assert_less (their_dof, parent_side->n_nodes());
   983                       parent_dof_indices[their_dof];
   985                     if (their_dof_g == my_dof_g)
   987                         self_constraint = 
true;
  1003                   if (dof_map.is_constrained_dof(my_dof_g))
  1006                   constraint_row = &(constraints[my_dof_g]);
  1011                 const Point & support_point = my_side->point(my_dof);
  1019                 for (
unsigned int their_dof=0;
  1020                      their_dof != n_parent_side_dofs; their_dof++)
  1022                     libmesh_assert_less (their_dof, parent_side->n_nodes());
  1026                       parent_dof_indices[their_dof];
  1035                     if ((std::abs(their_dof_value) > 1.e-5) &&
  1036                         (std::abs(their_dof_value) < .999))
  1038                         constraint_row->emplace(their_dof_g, their_dof_value);
  1043                     else if (their_dof_value >= .999)
  1044                       libmesh_assert_equal_to (my_dof_g, their_dof_g);
  1050         if (elem->active() && add_p_level)
  1056             const unsigned int min_p_level =
  1057               neigh->min_p_level_by_neighbor(elem, elem->p_level());
  1058             if (min_p_level < elem->p_level())
  1060                 "Mismatched p-refinement levels for LAGRANGE is not currently supported");
  1064 #endif // #ifdef LIBMESH_ENABLE_AMR  1135 #ifdef LIBMESH_ENABLE_AMR  1139                                           const unsigned int variable_number,
  1141 { lagrange_compute_constraints(constraints, dof_map, variable_number, elem, 2); }
  1146                                           const unsigned int variable_number,
  1148 { lagrange_compute_constraints(constraints, dof_map, variable_number, elem, 3); }
  1149 #endif // LIBMESH_ENABLE_AMR 
static unsigned int n_dofs(const ElemType t, const Order o)
ElemType
Defines an enum for geometric element types. 
Order
defines an enum for polynomial orders. 
static unsigned int n_dofs(const unsigned int dim, const FEType &fe_t, const ElemType t)
static Point inverse_map(const unsigned int dim, const Elem *elem, const Point &p, const Real tolerance=TOLERANCE, const bool secure=true, const bool extra_checks=true)
This is the base class from which all geometric element types are derived. 
static unsigned int n_dofs_at_node(const ElemType t, const Order o, const unsigned int n)
unsigned int p_level() const
virtual bool shapes_need_reinit() const override
The libMesh namespace provides an interface to certain functionality in the library. 
LIBMESH_FE_NODAL_SOLN(LIBMESH_FE_SIDE_NODAL_SOLN() LIBMESH_DEFAULT_NDOFS(BERNSTEIN) template<> FEContinuity FE< 0 BERNSTEIN, bernstein_nodal_soln)
virtual bool is_hierarchic() const override
This class handles the numbering of degrees of freedom on a mesh. 
LIBMESH_FE_SIDE_NODAL_SOLN(HIERARCHIC_VEC)
const dof_id_type n_nodes
virtual unsigned int n_nodes() const =0
static Real shape(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int i, const Point &p)
static unsigned int n_dofs_per_elem(const ElemType t, const Order o)
virtual FEContinuity get_continuity() const override
void lagrange_nodal_soln(const Elem *elem, const Order order, const std::vector< Number > &elem_soln, std::vector< Number > &nodal_soln, bool add_p_level=true)
Helper functions for Lagrange-based basis functions. 
std::string enum_to_string(const T e)
static void compute_constraints(DofConstraints &constraints, DofMap &dof_map, const unsigned int variable_number, const Elem *elem)
Computes the constraint matrix contributions (for non-conforming adapted meshes) corresponding to var...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
FEContinuity
defines an enum for finite element types to libmesh_assert a certain level (or type? Hcurl?) of continuity. 
std::map< dof_id_type, Real, std::less< dof_id_type >, Threads::scalable_allocator< std::pair< const dof_id_type, Real > > > DofConstraintRow
A row of the Dof constraint matrix. 
virtual ElemType type() const =0
The constraint matrix storage format. 
void ErrorVector unsigned int
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
spin_mutex spin_mtx
A convenient spin mutex object which can be used for obtaining locks. 
const RemoteElem * remote_elem