libMesh
fe_l2_hierarchic.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 // Local includes
21 #include "libmesh/elem.h"
22 #include "libmesh/enum_to_string.h"
23 #include "libmesh/fe.h"
24 #include "libmesh/fe_interface.h"
25 #include "libmesh/fe_macro.h"
26 
27 namespace libMesh
28 {
29 
30 // ------------------------------------------------------------
31 // Hierarchic-specific implementations
32 
33 // Anonymous namespace for local helper functions
34 namespace {
35 
36 void l2_hierarchic_nodal_soln(const Elem * elem,
37  const Order order,
38  const std::vector<Number> & elem_soln,
39  std::vector<Number> & nodal_soln,
40  const bool add_p_level)
41 {
42  const unsigned int n_nodes = elem->n_nodes();
43 
44  const ElemType elem_type = elem->type();
45 
46  nodal_soln.resize(n_nodes);
47 
48  const Order totalorder = order + add_p_level*elem->p_level();
49 
50  // FEType object to be passed to various FEInterface functions below.
51  FEType fe_type(order, L2_HIERARCHIC);
52 
53  switch (totalorder)
54  {
55  // Constant shape functions
56  case CONSTANT:
57  {
58  libmesh_assert_equal_to (elem_soln.size(), 1);
59 
60  std::fill(nodal_soln.begin(), nodal_soln.end(), elem_soln[0]);
61 
62  return;
63  }
64 
65 
66  // For other orders do interpolation at the nodes
67  // explicitly.
68  default:
69  {
70  const unsigned int n_sf =
71  FEInterface::n_shape_functions(fe_type, elem);
72 
73  std::vector<Point> refspace_nodes;
74  FEBase::get_refspace_nodes(elem_type,refspace_nodes);
75  libmesh_assert_equal_to (refspace_nodes.size(), n_nodes);
76  libmesh_assert_equal_to (elem_soln.size(), n_sf);
77 
78  // Zero before summation
79  std::fill(nodal_soln.begin(), nodal_soln.end(), 0);
80 
81  for (unsigned int n=0; n<n_nodes; n++)
82  // u_i = Sum (alpha_i phi_i)
83  for (unsigned int i=0; i<n_sf; i++)
84  nodal_soln[n] += elem_soln[i] *
85  FEInterface::shape(fe_type, elem, i, refspace_nodes[n]);
86 
87  return;
88  }
89  }
90 } // l2_hierarchic_nodal_soln()
91 
92 
93 
94 unsigned int l2_hierarchic_n_dofs(const ElemType t, const Order o)
95 {
96  libmesh_assert_greater (o, 0);
97  switch (t)
98  {
99  case NODEELEM:
100  return 1;
101  case EDGE2:
102  case EDGE3:
103  return (o+1);
104  case QUAD4:
105  case QUADSHELL4:
106  case QUAD8:
107  case QUADSHELL8:
108  case QUAD9:
109  case QUADSHELL9:
110  return ((o+1)*(o+1));
111  case HEX8:
112  case HEX20:
113  case HEX27:
114  return ((o+1)*(o+1)*(o+1));
115  case PRISM6:
116  case PRISM15:
117  case PRISM18:
118  case PRISM20:
119  case PRISM21:
120  return ((o+1)*(o+1)*(o+2)/2);
121  case TRI3:
122  case TRI6:
123  case TRI7:
124  return ((o+1)*(o+2)/2);
125  case TET4:
126  case TET10:
127  case TET14:
128  return ((o+1)*(o+2)*(o+3)/6);
129  case INVALID_ELEM:
130  return 0;
131  default:
132  libmesh_error_msg("ERROR: Invalid ElemType " << Utility::enum_to_string(t) << " selected for L2_HIERARCHIC FE family!");
133  }
134 } // l2_hierarchic_n_dofs()
135 
136 
137 
138 unsigned int l2_hierarchic_n_dofs(const Elem * e, const Order o)
139 {
140  libmesh_assert(e);
141  return l2_hierarchic_n_dofs(e->type(), o);
142 }
143 
144 
145 } // anonymous namespace
146 
147 
148 // Instantiate (side_) nodal_soln() function for every dimension
149 LIBMESH_FE_NODAL_SOLN(L2_HIERARCHIC, l2_hierarchic_nodal_soln)
151 
152 
153 // Full specialization of n_dofs() function for every dimension
154 template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
155 template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
156 template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
157 template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
158 
159 template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs(const Elem * e, const Order o) { return l2_hierarchic_n_dofs(e, o); }
160 template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs(const Elem * e, const Order o) { return l2_hierarchic_n_dofs(e, o); }
161 template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs(const Elem * e, const Order o) { return l2_hierarchic_n_dofs(e, o); }
162 template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs(const Elem * e, const Order o) { return l2_hierarchic_n_dofs(e, o); }
163 
164 // Full specialization of n_dofs_at_node() function for every dimension.
165 // Discontinuous L2 elements only have interior nodes
166 template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
167 template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
168 template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
169 template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
170 
171 template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs_at_node(const Elem &, const Order, const unsigned int) { return 0; }
172 template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs_at_node(const Elem &, const Order, const unsigned int) { return 0; }
173 template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs_at_node(const Elem &, const Order, const unsigned int) { return 0; }
174 template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs_at_node(const Elem &, const Order, const unsigned int) { return 0; }
175 
176 // Full specialization of n_dofs_per_elem() function for every dimension.
177 template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
178 template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
179 template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
180 template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
181 
182 template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs_per_elem(const Elem & e, const Order o) { return l2_hierarchic_n_dofs(&e, o); }
183 template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs_per_elem(const Elem & e, const Order o) { return l2_hierarchic_n_dofs(&e, o); }
184 template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs_per_elem(const Elem & e, const Order o) { return l2_hierarchic_n_dofs(&e, o); }
185 template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs_per_elem(const Elem & e, const Order o) { return l2_hierarchic_n_dofs(&e, o); }
186 
187 // L2 Hierarchic FEMs are C^0 continuous
192 
193 // L2 Hierarchic FEMs are hierarchic (duh!)
194 template <> bool FE<0,L2_HIERARCHIC>::is_hierarchic() const { return true; }
195 template <> bool FE<1,L2_HIERARCHIC>::is_hierarchic() const { return true; }
196 template <> bool FE<2,L2_HIERARCHIC>::is_hierarchic() const { return true; }
197 template <> bool FE<3,L2_HIERARCHIC>::is_hierarchic() const { return true; }
198 
199 #ifdef LIBMESH_ENABLE_AMR
200 // compute_constraints() is a NOOP for DISCONTINUOUS FE's
201 template <>
203  DofMap &,
204  const unsigned int,
205  const Elem *)
206 { }
207 
208 template <>
210  DofMap &,
211  const unsigned int,
212  const Elem *)
213 { }
214 #endif // #ifdef LIBMESH_ENABLE_AMR
215 
216 // L2-Hierarchic FEM shapes need reinit
217 template <> bool FE<0,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }
218 template <> bool FE<1,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }
219 template <> bool FE<2,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }
220 template <> bool FE<3,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }
221 
222 } // namespace libMesh
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.
Definition: enum_order.h:40
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
static unsigned int n_dofs_at_node(const ElemType t, const Order o, const unsigned int n)
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)
Definition: fe_bernstein.C:415
virtual bool is_hierarchic() const override
This class handles the numbering of degrees of freedom on a mesh.
Definition: dof_map.h:179
LIBMESH_FE_SIDE_NODAL_SOLN(HIERARCHIC_VEC)
const dof_id_type n_nodes
Definition: tecplot_io.C:67
static unsigned int n_shape_functions(const unsigned int dim, const FEType &fe_t, const ElemType t)
Definition: fe_interface.C:272
static Real shape(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int i, const Point &p)
Definition: fe_interface.C:760
static void get_refspace_nodes(const ElemType t, std::vector< Point > &nodes)
Definition: fe_abstract.C:400
libmesh_assert(ctx)
static unsigned int n_dofs_per_elem(const ElemType t, const Order o)
virtual FEContinuity get_continuity() const override
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...
FEContinuity
defines an enum for finite element types to libmesh_assert a certain level (or type? Hcurl?) of continuity.
The constraint matrix storage format.
Definition: dof_map.h:108