Skip to content

Commit 831d1be

Browse files
committed
Add support to generate 1d Lagrange shape functions of arbitrary order
1 parent 9e7634c commit 831d1be

File tree

1 file changed

+123
-17
lines changed

1 file changed

+123
-17
lines changed

include/fe/fe_lagrange_shape_1D.h

Lines changed: 123 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
97122
inline
98123
Real 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+
199264
inline
200265
Real 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+
281387
inline
282388
Real 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

Comments
 (0)