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