@@ -94,13 +94,36 @@ Real fe_lagrange_1D_cubic_shape(const unsigned int i,
9494
9595
9696
97+ inline
98+ Real fe_lagrange_1D_any_shape (const Order order,
99+ const unsigned int i,
100+ const Real xi)
101+ {
102+ libmesh_assert_greater_equal (order, 0 );
103+ libmesh_assert_less (i, order + 1 );
104+
105+ // So the interval endpoints are at i = 0 and i = 1
106+ const unsigned ii = i == 0 ? 0 : i == 1 ? int (order) : i - 1 ;
107+
108+ auto root = [&](const unsigned int k) { return 1 . * k / order; };
109+ const unsigned int nzeros = order + 1 ;
110+ Real x = (xi + 1 .) / 2 .;
111+ Real val = 1 .;
112+
113+ for (const auto z : make_range (nzeros))
114+ if (z != ii)
115+ val *= (x - root (z)) / (root (ii) - root (z));
116+
117+ return val;
118+ }
119+
120+
121+
97122inline
98123Real fe_lagrange_1D_shape (const Order order,
99124 const unsigned int i,
100125 const Real xi)
101126{
102- libmesh_assert_less_equal (order, THIRD);
103-
104127 switch (order)
105128 {
106129 // Lagrange linears
@@ -112,9 +135,12 @@ Real fe_lagrange_1D_shape(const Order order,
112135 return fe_lagrange_1D_quadratic_shape (i, xi);
113136
114137 // Lagrange cubics
115- // case THIRD
116- default :
138+ case THIRD:
117139 return fe_lagrange_1D_cubic_shape (i, xi);
140+
141+ // Lagrange arbitrary shape functions
142+ default :
143+ return fe_lagrange_1D_any_shape (order, i, xi);
118144 }
119145}
120146
@@ -196,14 +222,51 @@ Real fe_lagrange_1D_cubic_shape_deriv(const unsigned int i,
196222
197223
198224
225+ inline
226+ Real fe_lagrange_1D_any_shape_deriv (const Order order,
227+ const unsigned int i,
228+ const unsigned int libmesh_dbg_var (j),
229+ const Real xi)
230+ {
231+ // only d()/dxi in 1D!
232+ libmesh_assert_equal_to (j, 0 );
233+
234+ libmesh_assert_greater_equal (order, 0 );
235+ libmesh_assert_less (i, order + 1 );
236+
237+ // So the interval endpoints are at i = 0 and i = 1
238+ const unsigned ii = i == 0 ? 0 : i == 1 ? int (order) : i - 1 ;
239+
240+ auto root = [&](const unsigned int k) { return 1 . * k / order; };
241+ const unsigned int nzeros = order + 1 ;
242+ Real x = (xi + 1 .) / 2 .;
243+ Real val = 0 .;
244+
245+ for (const auto z : make_range (nzeros))
246+ if (z != ii)
247+ {
248+ Real prod = .5 ;
249+ for (const auto zz : make_range (nzeros))
250+ if (zz != z && zz != ii)
251+ prod *= (x - root (zz));
252+ val += prod;
253+ }
254+
255+ for (const auto z : make_range (nzeros))
256+ if (z != ii)
257+ val /= (root (ii) - root (z));
258+
259+ return val;
260+ }
261+
262+
263+
199264inline
200265Real fe_lagrange_1D_shape_deriv (const Order order,
201266 const unsigned int i,
202267 const unsigned int j,
203268 const Real xi)
204269{
205- libmesh_assert_less_equal (order, THIRD);
206-
207270 switch (order)
208271 {
209272 case FIRST:
@@ -212,10 +275,12 @@ Real fe_lagrange_1D_shape_deriv(const Order order,
212275 case SECOND:
213276 return fe_lagrange_1D_quadratic_shape_deriv (i, j, xi);
214277
215- // case THIRD
216- default :
278+ case THIRD:
217279 return fe_lagrange_1D_cubic_shape_deriv (i, j, xi);
218- }
280+
281+ default :
282+ return fe_lagrange_1D_any_shape_deriv (order, i, j, xi);
283+ }
219284}
220285
221286
@@ -229,9 +294,9 @@ Real fe_lagrange_1D_quadratic_shape_second_deriv(const unsigned int i,
229294 const unsigned int libmesh_dbg_var (j),
230295 const Real)
231296{
232- // Don't need to switch on j. 1D shape functions
233- // depend on xi only!
297+ // Don't need to switch on j. 1D shape functions depend on xi only!
234298 libmesh_assert_equal_to (j, 0 );
299+
235300 libmesh_assert_less (i, 3 );
236301
237302 switch (i)
@@ -254,9 +319,9 @@ Real fe_lagrange_1D_cubic_shape_second_deriv(const unsigned int i,
254319 const unsigned int libmesh_dbg_var (j),
255320 const Real xi)
256321{
257- // Don't need to switch on j. 1D shape functions
258- // depend on xi only!
322+ // Don't need to switch on j. 1D shape functions depend on xi only!
259323 libmesh_assert_equal_to (j, 0 );
324+
260325 libmesh_assert_less (i, 4 );
261326
262327 switch (i)
@@ -278,14 +343,53 @@ Real fe_lagrange_1D_cubic_shape_second_deriv(const unsigned int i,
278343
279344
280345
346+ inline
347+ Real fe_lagrange_1D_any_shape_second_deriv (const Order order,
348+ const unsigned int i,
349+ const unsigned int libmesh_dbg_var (j),
350+ const Real xi)
351+ {
352+ // Don't need to switch on j. 1D shape functions depend on xi only!
353+ libmesh_assert_equal_to (j, 0 );
354+
355+ libmesh_assert_greater_equal (order, 0 );
356+ libmesh_assert_less (i, order + 1 );
357+
358+ // So the interval endpoints are at i = 0 and i = 1
359+ const unsigned ii = i == 0 ? 0 : i == 1 ? int (order) : i - 1 ;
360+
361+ auto root = [&](const unsigned int k) { return 1 . * k / order; };
362+ const unsigned int nzeros = order + 1 ;
363+ Real x = (xi + 1 .) / 2 .;
364+ Real val = 0 .;
365+
366+ for (const auto z : make_range (nzeros))
367+ if (z != ii)
368+ for (const auto zz : make_range (nzeros))
369+ if (zz != z && zz != ii)
370+ {
371+ Real prod = .25 ;
372+ for (const auto zzz : make_range (nzeros))
373+ if (zzz != zz && zzz != z && zzz != ii)
374+ prod *= (x - root (zzz));
375+ val += prod;
376+ }
377+
378+ for (const auto z : make_range (nzeros))
379+ if (z != ii)
380+ val /= (root (ii) - root (z));
381+
382+ return val;
383+ }
384+
385+
386+
281387inline
282388Real fe_lagrange_1D_shape_second_deriv (const Order order,
283389 const unsigned int i,
284390 const unsigned int j,
285391 const Real xi)
286392{
287- libmesh_assert_less_equal (order, THIRD);
288-
289393 switch (order)
290394 {
291395 // All second derivatives of linears are zero....
@@ -295,9 +399,11 @@ Real fe_lagrange_1D_shape_second_deriv(const Order order,
295399 case SECOND:
296400 return fe_lagrange_1D_quadratic_shape_second_deriv (i, j, xi);
297401
298- // case THIRD
299- default :
402+ case THIRD:
300403 return fe_lagrange_1D_cubic_shape_second_deriv (i, j, xi);
404+
405+ default :
406+ return fe_lagrange_1D_any_shape_second_deriv (order, i, j, xi);
301407 } // end switch (order)
302408}
303409
0 commit comments