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)
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 Order o)
586 libmesh_error_msg(
"ERROR: Invalid Order " <<
Utility::enum_to_string(o) <<
" selected for LAGRANGE FE family!");
593 unsigned int lagrange_n_dofs_at_node(
const ElemType t,
595 const unsigned int n)
811 libmesh_error_msg(
"Unsupported order: " << o );
816 #ifdef LIBMESH_ENABLE_AMR 817 void lagrange_compute_constraints (DofConstraints & constraints,
819 const unsigned int variable_number,
830 if (elem->subactive())
833 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 834 if (elem->infinite())
836 const FEType fe_t = dof_map.variable_type(variable_number);
843 inf_fe_family_mapping_switch(2, inf_compute_constraints (constraints, dof_map, variable_number, elem) , ,;
break;);
848 inf_fe_family_mapping_switch(3, inf_compute_constraints (constraints, dof_map, variable_number, elem) , ,;
break;);
852 libmesh_error_msg(
"Invalid dim = " << Dim);
858 const Variable & var = dof_map.variable(variable_number);
859 const FEType fe_type = var.type();
860 const bool add_p_level = dof_map.should_p_refine_var(variable_number);
863 std::vector<dof_id_type> my_dof_indices, parent_dof_indices;
864 std::unique_ptr<const Elem> my_side, parent_side;
868 for (
auto s : elem->side_index_range())
869 if (
const Elem *
const neigh = elem->neighbor_ptr(s);
873 if (neigh->level() < elem->level() &&
874 var.active_on_subdomain(neigh->subdomain_id()))
878 const Elem * parent = elem->parent();
885 elem->build_side_ptr(my_side, s);
886 parent->build_side_ptr(parent_side, s);
891 FEType side_fe_type = fe_type;
893 if (my_side->default_order() < fe_type.order)
895 side_fe_type.order = my_side->default_order();
896 extra_order = (
int)(side_fe_type.order) -
897 (
int)(fe_type.order);
904 my_dof_indices.reserve (my_side->n_nodes());
905 parent_dof_indices.reserve (parent_side->n_nodes());
907 dof_map.dof_indices (my_side.get(), my_dof_indices,
908 variable_number, extra_order);
909 dof_map.dof_indices (parent_side.get(), parent_dof_indices,
910 variable_number, extra_order);
912 const unsigned int n_side_dofs =
914 const unsigned int n_parent_side_dofs =
916 for (
unsigned int my_dof=0; my_dof != n_side_dofs; my_dof++)
918 libmesh_assert_less (my_dof, my_side->n_nodes());
921 const dof_id_type my_dof_g = my_dof_indices[my_dof];
925 bool self_constraint =
false;
926 for (
unsigned int their_dof=0;
927 their_dof != n_parent_side_dofs; their_dof++)
929 libmesh_assert_less (their_dof, parent_side->n_nodes());
933 parent_dof_indices[their_dof];
935 if (their_dof_g == my_dof_g)
937 self_constraint =
true;
953 if (dof_map.is_constrained_dof(my_dof_g))
956 constraint_row = &(constraints[my_dof_g]);
961 const Point & support_point = my_side->point(my_dof);
969 for (
unsigned int their_dof=0;
970 their_dof != n_parent_side_dofs; their_dof++)
972 libmesh_assert_less (their_dof, parent_side->n_nodes());
976 parent_dof_indices[their_dof];
986 if ((
std::abs(their_dof_value) > 1.e-5) &&
989 constraint_row->emplace(their_dof_g, their_dof_value);
994 else if (their_dof_value >= .999)
995 libmesh_assert_equal_to (my_dof_g, their_dof_g);
1001 if (elem->active() && add_p_level)
1007 const unsigned int min_p_level =
1008 neigh->min_p_level_by_neighbor(elem, elem->p_level());
1009 if (min_p_level < elem->p_level())
1011 "Mismatched p-refinement levels for LAGRANGE is not currently supported");
1015 #endif // #ifdef LIBMESH_ENABLE_AMR 1071 #ifdef LIBMESH_ENABLE_AMR 1075 const unsigned int variable_number,
1077 { lagrange_compute_constraints(constraints, dof_map, variable_number, elem, 2); }
1082 const unsigned int variable_number,
1084 { lagrange_compute_constraints(constraints, dof_map, variable_number, elem, 3); }
1085 #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.
virtual bool is_hierarchic() const override
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
This class handles the numbering of degrees of freedom on a mesh.
LIBMESH_FE_NODAL_SOLN(BERNSTEIN, bernstein_nodal_soln)
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