ndelement/
bindings.rs

1//! Bindings for C.
2#![allow(missing_docs)]
3#![allow(clippy::missing_safety_doc)]
4
5pub mod reference_cell {
6    use crate::{orientation, reference_cell, types::ReferenceCellType};
7    use rlst::RlstScalar;
8    use std::slice::from_raw_parts;
9
10    #[unsafe(no_mangle)]
11    pub unsafe extern "C" fn dim(cell: ReferenceCellType) -> usize {
12        reference_cell::dim(cell)
13    }
14    #[unsafe(no_mangle)]
15    pub unsafe extern "C" fn is_simplex(cell: ReferenceCellType) -> bool {
16        reference_cell::is_simplex(cell)
17    }
18    unsafe fn vertices<T: RlstScalar>(cell: ReferenceCellType, vs: *mut T) {
19        let mut i = 0;
20        for v in reference_cell::vertices::<T>(cell) {
21            for c in v {
22                unsafe {
23                    *vs.add(i) = c;
24                }
25                i += 1;
26            }
27        }
28    }
29    #[unsafe(no_mangle)]
30    pub unsafe extern "C" fn vertices_f32(cell: ReferenceCellType, vs: *mut f32) {
31        unsafe {
32            vertices(cell, vs);
33        }
34    }
35    #[unsafe(no_mangle)]
36    pub unsafe extern "C" fn vertices_f64(cell: ReferenceCellType, vs: *mut f64) {
37        unsafe {
38            vertices(cell, vs);
39        }
40    }
41    unsafe fn midpoint<T: RlstScalar>(cell: ReferenceCellType, pt: *mut T) {
42        for (i, c) in reference_cell::midpoint(cell).iter().enumerate() {
43            unsafe {
44                *pt.add(i) = *c;
45            }
46        }
47    }
48    #[unsafe(no_mangle)]
49    pub unsafe extern "C" fn midpoint_f32(cell: ReferenceCellType, pt: *mut f32) {
50        unsafe {
51            midpoint(cell, pt);
52        }
53    }
54    #[unsafe(no_mangle)]
55    pub unsafe extern "C" fn midpoint_f64(cell: ReferenceCellType, pt: *mut f64) {
56        unsafe {
57            midpoint(cell, pt);
58        }
59    }
60    #[unsafe(no_mangle)]
61    pub unsafe extern "C" fn edges(cell: ReferenceCellType, es: *mut usize) {
62        let mut i = 0;
63        for e in reference_cell::edges(cell) {
64            for v in e {
65                unsafe {
66                    *es.add(i) = v;
67                }
68                i += 1
69            }
70        }
71    }
72    #[unsafe(no_mangle)]
73    pub unsafe extern "C" fn faces(cell: ReferenceCellType, es: *mut usize) {
74        let mut i = 0;
75        for e in reference_cell::faces(cell) {
76            for v in e {
77                unsafe {
78                    *es.add(i) = v;
79                }
80                i += 1
81            }
82        }
83    }
84    #[unsafe(no_mangle)]
85    pub unsafe extern "C" fn volumes(cell: ReferenceCellType, es: *mut usize) {
86        let mut i = 0;
87        for e in reference_cell::volumes(cell) {
88            for v in e {
89                unsafe {
90                    *es.add(i) = v;
91                }
92                i += 1
93            }
94        }
95    }
96    #[unsafe(no_mangle)]
97    pub unsafe extern "C" fn entity_types(cell: ReferenceCellType, et: *mut u8) {
98        let mut i = 0;
99        for es in reference_cell::entity_types(cell) {
100            for e in es {
101                unsafe {
102                    *et.add(i) = e as u8;
103                }
104                i += 1
105            }
106        }
107    }
108    #[unsafe(no_mangle)]
109    pub unsafe extern "C" fn entity_counts(cell: ReferenceCellType, ec: *mut usize) {
110        for (i, e) in reference_cell::entity_counts(cell).iter().enumerate() {
111            unsafe {
112                *ec.add(i) = *e;
113            }
114        }
115    }
116    #[unsafe(no_mangle)]
117    pub unsafe extern "C" fn connectivity_size(
118        cell: ReferenceCellType,
119        dim0: usize,
120        index0: usize,
121        dim1: usize,
122    ) -> usize {
123        reference_cell::connectivity(cell)[dim0][index0][dim1].len()
124    }
125    #[unsafe(no_mangle)]
126    pub unsafe extern "C" fn connectivity(
127        cell: ReferenceCellType,
128        dim0: usize,
129        index0: usize,
130        dim1: usize,
131        c: *mut usize,
132    ) {
133        for (i, j) in reference_cell::connectivity(cell)[dim0][index0][dim1]
134            .iter()
135            .enumerate()
136        {
137            unsafe {
138                *c.add(i) = *j;
139            }
140        }
141    }
142    #[unsafe(no_mangle)]
143    pub unsafe extern "C" fn compute_orientation(
144        cell: ReferenceCellType,
145        vertices: *const usize,
146    ) -> i32 {
147        let vertices = unsafe { from_raw_parts(vertices, reference_cell::entity_counts(cell)[0]) };
148        orientation::compute_orientation(cell, vertices)
149    }
150}
151
152pub mod quadrature {
153    use crate::{quadrature, types::ReferenceCellType};
154
155    #[unsafe(no_mangle)]
156    pub unsafe extern "C" fn gauss_jacobi_quadrature_npoints(
157        cell: ReferenceCellType,
158        m: usize,
159    ) -> usize {
160        quadrature::gauss_jacobi_npoints(cell, m)
161    }
162    #[unsafe(no_mangle)]
163    pub unsafe extern "C" fn make_gauss_jacobi_quadrature(
164        cell: ReferenceCellType,
165        m: usize,
166        pts: *mut f64,
167        wts: *mut f64,
168    ) {
169        let rule = quadrature::gauss_jacobi_rule(cell, m).unwrap();
170        for (i, p) in rule.points.iter().enumerate() {
171            unsafe {
172                *pts.add(i) = *p;
173            }
174        }
175        for (i, w) in rule.weights.iter().enumerate() {
176            unsafe {
177                *wts.add(i) = *w;
178            }
179        }
180    }
181}
182
183pub mod polynomials {
184    use crate::{polynomials, reference_cell, types::ReferenceCellType};
185    use rlst::{RlstScalar, SliceArray, SliceArrayMut};
186    use std::slice::{from_raw_parts, from_raw_parts_mut};
187
188    #[unsafe(no_mangle)]
189    pub unsafe extern "C" fn legendre_polynomials_shape(
190        cell: ReferenceCellType,
191        npts: usize,
192        degree: usize,
193        derivatives: usize,
194        shape: *mut usize,
195    ) {
196        unsafe {
197            *shape.add(0) = polynomials::derivative_count(cell, derivatives);
198            *shape.add(1) = polynomials::polynomial_count(cell, degree);
199            *shape.add(2) = npts;
200        }
201    }
202    unsafe fn tabulate_legendre_polynomials<T: RlstScalar, TGeo: RlstScalar>(
203        cell: ReferenceCellType,
204        points: *const TGeo,
205        npts: usize,
206        degree: usize,
207        derivatives: usize,
208        data: *mut T,
209    ) {
210        let tdim = reference_cell::dim(cell);
211        let points = SliceArray::<TGeo, 2>::from_shape(
212            unsafe { from_raw_parts(points, npts * tdim) },
213            [tdim, npts],
214        );
215        let npoly = polynomials::polynomial_count(cell, degree);
216        let nderiv = polynomials::derivative_count(cell, derivatives);
217        let mut data = SliceArrayMut::<T, 3>::from_shape(
218            unsafe { from_raw_parts_mut(data, npts * npoly * nderiv) },
219            [nderiv, npoly, npts],
220        );
221        polynomials::tabulate_legendre_polynomials(cell, &points, degree, derivatives, &mut data);
222    }
223    #[unsafe(no_mangle)]
224    pub unsafe extern "C" fn tabulate_legendre_polynomials_f32(
225        cell: ReferenceCellType,
226        points: *const f32,
227        npts: usize,
228        degree: usize,
229        derivatives: usize,
230        data: *mut f32,
231    ) {
232        unsafe {
233            tabulate_legendre_polynomials(cell, points, npts, degree, derivatives, data);
234        }
235    }
236    #[unsafe(no_mangle)]
237    pub unsafe extern "C" fn tabulate_legendre_polynomials_f64(
238        cell: ReferenceCellType,
239        points: *const f64,
240        npts: usize,
241        degree: usize,
242        derivatives: usize,
243        data: *mut f64,
244    ) {
245        unsafe {
246            tabulate_legendre_polynomials(cell, points, npts, degree, derivatives, data);
247        }
248    }
249}
250
251pub mod ciarlet {
252    use crate::{
253        ciarlet,
254        ciarlet::CiarletElement,
255        map::{ContravariantPiolaMap, CovariantPiolaMap, IdentityMap},
256        reference_cell,
257        traits::{ElementFamily, FiniteElement, Map, MappedFiniteElement},
258        types::{Continuity, ReferenceCellType},
259    };
260    use c_api_tools::{DType, DTypeIdentifier, cfuncs, concretise_types};
261    use rlst::dense::linalg::lapack::interface::{getrf::Getrf, getri::Getri};
262    use rlst::{RlstScalar, SliceArray, SliceArrayMut, c32, c64};
263    use std::ffi::c_void;
264    use std::slice::{from_raw_parts, from_raw_parts_mut};
265
266    #[derive(Debug, PartialEq, Clone, Copy)]
267    #[repr(u8)]
268    pub enum ElementType {
269        Lagrange = 0,
270        RaviartThomas = 1,
271        NedelecFirstKind = 2,
272    }
273
274    #[cfuncs(name = "ciarlet_element_t", create, free, unwrap)]
275    pub struct CiarletElementT;
276
277    #[cfuncs(name = "element_family_t", create, free, unwrap)]
278    pub struct ElementFamilyT;
279
280    #[concretise_types(
281        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
282        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
283        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
284        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
285    )]
286    pub fn element_value_size<E: FiniteElement>(element: &E) -> usize {
287        element.value_size()
288    }
289
290    #[unsafe(no_mangle)]
291    pub extern "C" fn create_lagrange_family(
292        degree: usize,
293        continuity: Continuity,
294        dtype: DType,
295    ) -> *mut ElementFamilyT {
296        let family = element_family_t_create();
297        let family_inner = unsafe { element_family_t_unwrap(family).unwrap() };
298
299        *family_inner = match dtype {
300            DType::F32 => Box::new(ciarlet::LagrangeElementFamily::<f32>::new(
301                degree, continuity,
302            )),
303            DType::F64 => Box::new(ciarlet::LagrangeElementFamily::<f64>::new(
304                degree, continuity,
305            )),
306            DType::C32 => Box::new(ciarlet::LagrangeElementFamily::<c32>::new(
307                degree, continuity,
308            )),
309            DType::C64 => Box::new(ciarlet::LagrangeElementFamily::<c64>::new(
310                degree, continuity,
311            )),
312            _ => panic!("Unsupported dtype"),
313        };
314
315        family
316    }
317
318    #[unsafe(no_mangle)]
319    pub extern "C" fn create_raviart_thomas_family(
320        degree: usize,
321        continuity: Continuity,
322        dtype: DType,
323    ) -> *mut ElementFamilyT {
324        let family = element_family_t_create();
325        let family_inner = unsafe { element_family_t_unwrap(family).unwrap() };
326
327        *family_inner = match dtype {
328            DType::F32 => Box::new(ciarlet::RaviartThomasElementFamily::<f32>::new(
329                degree, continuity,
330            )),
331            DType::F64 => Box::new(ciarlet::RaviartThomasElementFamily::<f64>::new(
332                degree, continuity,
333            )),
334            DType::C32 => Box::new(ciarlet::RaviartThomasElementFamily::<c32>::new(
335                degree, continuity,
336            )),
337            DType::C64 => Box::new(ciarlet::RaviartThomasElementFamily::<c64>::new(
338                degree, continuity,
339            )),
340            _ => panic!("Unsupported dtype"),
341        };
342
343        family
344    }
345
346    #[unsafe(no_mangle)]
347    pub extern "C" fn create_nedelec_family(
348        degree: usize,
349        continuity: Continuity,
350        dtype: DType,
351    ) -> *mut ElementFamilyT {
352        let family = element_family_t_create();
353        let family_inner = unsafe { element_family_t_unwrap(family).unwrap() };
354
355        *family_inner = match dtype {
356            DType::F32 => Box::new(ciarlet::NedelecFirstKindElementFamily::<f32>::new(
357                degree, continuity,
358            )),
359            DType::F64 => Box::new(ciarlet::NedelecFirstKindElementFamily::<f64>::new(
360                degree, continuity,
361            )),
362            DType::C32 => Box::new(ciarlet::NedelecFirstKindElementFamily::<c32>::new(
363                degree, continuity,
364            )),
365            DType::C64 => Box::new(ciarlet::NedelecFirstKindElementFamily::<c64>::new(
366                degree, continuity,
367            )),
368            _ => panic!("Unsupported dtype"),
369        };
370
371        family
372    }
373
374    #[concretise_types(
375        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
376        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
377        field(arg = 0, name = "element_family", wrapper = "ElementFamilyT", replace_with = [
378            "ciarlet::LagrangeElementFamily<{{dtype}}, {{geo_dtype}}>",
379            "ciarlet::RaviartThomasElementFamily<{{dtype}}, {{geo_dtype}}>",
380            "ciarlet::NedelecFirstKindElementFamily<{{dtype}}, {{geo_dtype}}>"
381        ])
382    )]
383    pub fn element_family_create_element<F: ElementFamily<CellType = ReferenceCellType>>(
384        family: &F,
385        cell: ReferenceCellType,
386    ) -> *mut CiarletElementT {
387        let ciarlet_element = ciarlet_element_t_create();
388        let inner = unsafe { ciarlet_element_t_unwrap(ciarlet_element).unwrap() };
389
390        *inner = Box::new(family.element(cell));
391
392        ciarlet_element
393    }
394
395    #[concretise_types(
396        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
397        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
398        field(arg = 0, name = "element_family", wrapper = "ElementFamilyT", replace_with = [
399            "ciarlet::LagrangeElementFamily<{{dtype}}, {{geo_dtype}}>",
400            "ciarlet::RaviartThomasElementFamily<{{dtype}}, {{geo_dtype}}>",
401            "ciarlet::NedelecFirstKindElementFamily<{{dtype}}, {{geo_dtype}}>"
402        ])
403    )]
404    pub fn element_family_dtype<
405        T: RlstScalar + DTypeIdentifier,
406        F: ElementFamily<CellType = ReferenceCellType, T = T>,
407    >(
408        _elem: &F,
409    ) -> DType {
410        <T as DTypeIdentifier>::dtype()
411    }
412
413    #[concretise_types(
414        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
415        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
416        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
417        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
418    )]
419    pub fn ciarlet_element_dtype<T: RlstScalar + DTypeIdentifier, E: FiniteElement<T = T>>(
420        _elem: &E,
421    ) -> DType {
422        <T as DTypeIdentifier>::dtype()
423    }
424
425    #[concretise_types(
426        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
427        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
428        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
429        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
430    )]
431    pub fn ciarlet_element_geo_dtype<
432        T: RlstScalar + DTypeIdentifier,
433        M: Map,
434        TGeo: RlstScalar + DTypeIdentifier,
435    >(
436        _elem: &CiarletElement<T, M, TGeo>,
437    ) -> DType {
438        <TGeo as DTypeIdentifier>::dtype()
439    }
440
441    #[concretise_types(
442        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
443        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
444        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
445        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
446    )]
447    pub fn ciarlet_element_tabulate_array_shape<E: FiniteElement>(
448        element: &E,
449        nderivs: usize,
450        npoints: usize,
451        shape: *mut usize,
452    ) {
453        for (i, j) in element
454            .tabulate_array_shape(nderivs, npoints)
455            .iter()
456            .enumerate()
457        {
458            unsafe {
459                *shape.add(i) = *j;
460            }
461        }
462    }
463
464    pub unsafe fn ciarlet_element_tabulate<
465        E: FiniteElement<CellType = ReferenceCellType>,
466        TGeo: RlstScalar,
467    >(
468        element: &E,
469        points: *const TGeo,
470        npoints: usize,
471        nderivs: usize,
472        data: *mut c_void,
473    ) {
474        let tdim = reference_cell::dim(element.cell_type());
475        let data = data as *mut E::T;
476        let points = SliceArray::<TGeo, 2>::from_shape(
477            unsafe { from_raw_parts(points, npoints * tdim) },
478            [tdim, npoints],
479        );
480        let shape = element.tabulate_array_shape(nderivs, npoints);
481        let mut data = SliceArrayMut::<E::T, 4>::from_shape(
482            unsafe { from_raw_parts_mut(data, shape[0] * shape[1] * shape[2] * shape[3]) },
483            shape,
484        );
485        element.tabulate(&points, nderivs, &mut data);
486    }
487
488    #[concretise_types(
489        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
490        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
491        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
492        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"]),
493    )]
494    pub unsafe fn ciarlet_element_tabulate_f32<E: FiniteElement<CellType = ReferenceCellType>>(
495        element: &E,
496        points: *const f32,
497        npoints: usize,
498        nderivs: usize,
499        data: *mut c_void,
500    ) {
501        unsafe {
502            ciarlet_element_tabulate(element, points, npoints, nderivs, data);
503        }
504    }
505
506    #[concretise_types(
507        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
508        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
509        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
510        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"]),
511    )]
512    pub unsafe fn ciarlet_element_tabulate_f64<E: FiniteElement<CellType = ReferenceCellType>>(
513        element: &E,
514        points: *const f64,
515        npoints: usize,
516        nderivs: usize,
517        data: *mut c_void,
518    ) {
519        unsafe {
520            ciarlet_element_tabulate(element, points, npoints, nderivs, data);
521        }
522    }
523
524    #[concretise_types(
525        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
526        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
527        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
528        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
529    )]
530    pub fn ciarlet_element_value_size<E: FiniteElement>(element: &E) -> usize {
531        element.value_size()
532    }
533
534    #[concretise_types(
535        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
536        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
537        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
538        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
539    )]
540    pub fn ciarlet_element_value_rank<E: FiniteElement>(element: &E) -> usize {
541        element.value_shape().len()
542    }
543
544    #[concretise_types(
545        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
546        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
547        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
548        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
549    )]
550    pub fn ciarlet_element_value_shape<E: FiniteElement>(element: &E, shape: *mut usize) {
551        for (i, j) in element.value_shape().iter().enumerate() {
552            unsafe {
553                *shape.add(i) = *j;
554            }
555        }
556    }
557
558    #[concretise_types(
559        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
560        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
561        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
562        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
563    )]
564    pub fn ciarlet_element_physical_value_size<E: MappedFiniteElement>(
565        element: &E,
566        gdim: usize,
567    ) -> usize {
568        element.physical_value_size(gdim)
569    }
570
571    #[concretise_types(
572        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
573        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
574        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
575        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
576    )]
577    pub fn ciarlet_element_physical_value_rank<E: MappedFiniteElement>(
578        element: &E,
579        gdim: usize,
580    ) -> usize {
581        element.physical_value_shape(gdim).len()
582    }
583
584    #[concretise_types(
585        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
586        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
587        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
588        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
589    )]
590    pub fn ciarlet_element_physical_value_shape<E: MappedFiniteElement>(
591        element: &E,
592        gdim: usize,
593        shape: *mut usize,
594    ) {
595        for (i, j) in element.physical_value_shape(gdim).iter().enumerate() {
596            unsafe {
597                *shape.add(i) = *j;
598            }
599        }
600    }
601
602    #[allow(clippy::too_many_arguments)]
603    pub unsafe fn ciarlet_element_push_forward<
604        E: MappedFiniteElement<CellType = ReferenceCellType>,
605        TGeo: RlstScalar,
606    >(
607        element: &E,
608        npoints: usize,
609        nfunctions: usize,
610        gdim: usize,
611        reference_values: *const TGeo,
612        nderivs: usize,
613        j: *const TGeo,
614        jdet: *const TGeo,
615        jinv: *const TGeo,
616        physical_values: *mut c_void,
617    ) {
618        let tdim = reference_cell::dim(element.cell_type());
619        let deriv_size = element.tabulate_array_shape(nderivs, npoints)[0];
620        let pvs = element.physical_value_size(gdim);
621        let vs = element.value_size();
622        let reference_values = SliceArray::<E::T, 4>::from_shape(
623            unsafe {
624                from_raw_parts(
625                    reference_values as *const E::T,
626                    deriv_size * npoints * nfunctions * vs,
627                )
628            },
629            [deriv_size, npoints, nfunctions, vs],
630        );
631        let j = SliceArray::<TGeo, 3>::from_shape(
632            unsafe { from_raw_parts(j, npoints * gdim * tdim) },
633            [npoints, gdim, tdim],
634        );
635        let jdet = unsafe { from_raw_parts(jdet, npoints) };
636        let jinv = SliceArray::<TGeo, 3>::from_shape(
637            unsafe { from_raw_parts(jinv, npoints * tdim * gdim) },
638            [npoints, tdim, gdim],
639        );
640        let mut physical_values = SliceArrayMut::<E::T, 4>::from_shape(
641            unsafe {
642                from_raw_parts_mut(
643                    physical_values as *mut E::T,
644                    deriv_size * npoints * nfunctions * pvs,
645                )
646            },
647            [deriv_size, npoints, nfunctions, pvs],
648        );
649        element.push_forward(
650            &reference_values,
651            nderivs,
652            &j,
653            jdet,
654            &jinv,
655            &mut physical_values,
656        );
657    }
658
659    #[allow(clippy::too_many_arguments)]
660    #[concretise_types(
661        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
662        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
663        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
664        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
665    )]
666    pub unsafe fn ciarlet_element_push_forward_f32<
667        E: MappedFiniteElement<CellType = ReferenceCellType>,
668    >(
669        element: &E,
670        npoints: usize,
671        nfunctions: usize,
672        gdim: usize,
673        reference_values: *const f32,
674        nderivs: usize,
675        j: *const f32,
676        jdet: *const f32,
677        jinv: *const f32,
678        physical_values: *mut c_void,
679    ) {
680        unsafe {
681            ciarlet_element_push_forward(
682                element,
683                npoints,
684                nfunctions,
685                gdim,
686                reference_values,
687                nderivs,
688                j,
689                jdet,
690                jinv,
691                physical_values,
692            );
693        }
694    }
695
696    #[allow(clippy::too_many_arguments)]
697    #[concretise_types(
698        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
699        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
700        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
701        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
702    )]
703    pub unsafe fn ciarlet_element_push_forward_f64<
704        E: MappedFiniteElement<CellType = ReferenceCellType>,
705    >(
706        element: &E,
707        npoints: usize,
708        nfunctions: usize,
709        gdim: usize,
710        reference_values: *const f64,
711        nderivs: usize,
712        j: *const f64,
713        jdet: *const f64,
714        jinv: *const f64,
715        physical_values: *mut c_void,
716    ) {
717        unsafe {
718            ciarlet_element_push_forward(
719                element,
720                npoints,
721                nfunctions,
722                gdim,
723                reference_values,
724                nderivs,
725                j,
726                jdet,
727                jinv,
728                physical_values,
729            );
730        }
731    }
732
733    #[allow(clippy::too_many_arguments)]
734    pub unsafe fn ciarlet_element_pull_back<
735        E: MappedFiniteElement<CellType = ReferenceCellType>,
736        TGeo: RlstScalar,
737    >(
738        element: &E,
739        npoints: usize,
740        nfunctions: usize,
741        gdim: usize,
742        physical_values: *const TGeo,
743        nderivs: usize,
744        j: *const TGeo,
745        jdet: *const TGeo,
746        jinv: *const TGeo,
747        reference_values: *mut c_void,
748    ) {
749        let tdim = reference_cell::dim(element.cell_type());
750        let deriv_size = element.tabulate_array_shape(nderivs, npoints)[0];
751        let pvs = element.physical_value_size(gdim);
752        let vs = element.value_size();
753        let physical_values = SliceArray::<E::T, 4>::from_shape(
754            unsafe {
755                from_raw_parts(
756                    physical_values as *const E::T,
757                    deriv_size * npoints * nfunctions * pvs,
758                )
759            },
760            [deriv_size, npoints, nfunctions, pvs],
761        );
762        let j = SliceArray::<TGeo, 3>::from_shape(
763            unsafe { from_raw_parts(j, npoints * gdim * tdim) },
764            [npoints, gdim, tdim],
765        );
766        let jdet = unsafe { from_raw_parts(jdet, npoints) };
767        let jinv = SliceArray::<TGeo, 3>::from_shape(
768            unsafe { from_raw_parts(jinv, npoints * tdim * gdim) },
769            [npoints, tdim, gdim],
770        );
771        let mut reference_values = SliceArrayMut::<E::T, 4>::from_shape(
772            unsafe {
773                from_raw_parts_mut(
774                    reference_values as *mut E::T,
775                    deriv_size * npoints * nfunctions * vs,
776                )
777            },
778            [deriv_size, npoints, nfunctions, vs],
779        );
780        element.pull_back(
781            &physical_values,
782            nderivs,
783            &j,
784            jdet,
785            &jinv,
786            &mut reference_values,
787        );
788    }
789
790    #[allow(clippy::too_many_arguments)]
791    #[concretise_types(
792        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
793        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
794        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
795        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
796    )]
797    pub unsafe fn ciarlet_element_pull_back_f32<
798        E: MappedFiniteElement<CellType = ReferenceCellType>,
799    >(
800        element: &E,
801        npoints: usize,
802        nfunctions: usize,
803        gdim: usize,
804        physical_values: *const f32,
805        nderivs: usize,
806        j: *const f32,
807        jdet: *const f32,
808        jinv: *const f32,
809        reference_values: *mut c_void,
810    ) {
811        unsafe {
812            ciarlet_element_pull_back(
813                element,
814                npoints,
815                nfunctions,
816                gdim,
817                physical_values,
818                nderivs,
819                j,
820                jdet,
821                jinv,
822                reference_values,
823            );
824        }
825    }
826
827    #[allow(clippy::too_many_arguments)]
828    #[concretise_types(
829        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
830        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
831        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
832        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
833    )]
834    pub fn ciarlet_element_pull_back_f64<E: MappedFiniteElement<CellType = ReferenceCellType>>(
835        element: &E,
836        npoints: usize,
837        nfunctions: usize,
838        gdim: usize,
839        physical_values: *const f64,
840        nderivs: usize,
841        j: *const f64,
842        jdet: *const f64,
843        jinv: *const f64,
844        reference_values: *mut c_void,
845    ) {
846        unsafe {
847            ciarlet_element_pull_back(
848                element,
849                npoints,
850                nfunctions,
851                gdim,
852                physical_values,
853                nderivs,
854                j,
855                jdet,
856                jinv,
857                reference_values,
858            );
859        }
860    }
861
862    #[concretise_types(
863        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
864        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
865        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
866        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
867    )]
868    pub fn ciarlet_element_degree<
869        T: RlstScalar + DTypeIdentifier + Getrf + Getri,
870        M: Map,
871        TGeo: RlstScalar + DTypeIdentifier,
872    >(
873        element: &CiarletElement<T, M, TGeo>,
874    ) -> usize {
875        element.degree()
876    }
877
878    #[concretise_types(
879        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
880        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
881        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
882        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
883    )]
884    pub fn ciarlet_element_embedded_superdegree<E: MappedFiniteElement>(element: &E) -> usize {
885        element.lagrange_superdegree()
886    }
887
888    #[concretise_types(
889        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
890        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
891        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
892        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
893    )]
894    pub fn ciarlet_element_dim<E: FiniteElement>(element: &E) -> usize {
895        element.dim()
896    }
897
898    #[concretise_types(
899        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
900        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
901        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
902        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
903    )]
904    pub fn ciarlet_element_continuity<
905        T: RlstScalar + DTypeIdentifier + Getrf + Getri,
906        M: Map,
907        TGeo: RlstScalar + DTypeIdentifier,
908    >(
909        element: &CiarletElement<T, M, TGeo>,
910    ) -> Continuity {
911        element.continuity()
912    }
913
914    #[concretise_types(
915        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
916        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
917        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
918        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
919    )]
920    pub fn ciarlet_element_cell_type<E: FiniteElement<CellType = ReferenceCellType>>(
921        element: &E,
922    ) -> ReferenceCellType {
923        element.cell_type()
924    }
925
926    #[concretise_types(
927        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
928        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
929        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
930        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
931    )]
932    pub fn ciarlet_element_entity_dofs_size<E: FiniteElement>(
933        element: &E,
934        entity_dim: usize,
935        entity_index: usize,
936    ) -> usize {
937        element.entity_dofs(entity_dim, entity_index).unwrap().len()
938    }
939
940    #[concretise_types(
941        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
942        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
943        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
944        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
945    )]
946    pub fn ciarlet_element_entity_dofs<E: FiniteElement>(
947        element: &E,
948        entity_dim: usize,
949        entity_index: usize,
950        entity_dofs: *mut usize,
951    ) {
952        for (i, dof) in element
953            .entity_dofs(entity_dim, entity_index)
954            .unwrap()
955            .iter()
956            .enumerate()
957        {
958            unsafe {
959                *entity_dofs.add(i) = *dof;
960            }
961        }
962    }
963
964    #[concretise_types(
965        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
966        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
967        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
968        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
969    )]
970    pub fn ciarlet_element_entity_closure_dofs_size<
971        T: RlstScalar + DTypeIdentifier,
972        M: Map,
973        TGeo: RlstScalar + DTypeIdentifier,
974    >(
975        element: &CiarletElement<T, M, TGeo>,
976        entity_dim: usize,
977        entity_index: usize,
978    ) -> usize {
979        element
980            .entity_closure_dofs(entity_dim, entity_index)
981            .unwrap()
982            .len()
983    }
984
985    #[concretise_types(
986        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
987        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
988        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
989        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
990    )]
991    pub fn ciarlet_element_entity_closure_dofs<
992        T: RlstScalar + DTypeIdentifier,
993        M: Map,
994        TGeo: RlstScalar + DTypeIdentifier,
995    >(
996        element: &CiarletElement<T, M, TGeo>,
997        entity_dim: usize,
998        entity_index: usize,
999        entity_closure_dofs: *mut usize,
1000    ) {
1001        for (i, dof) in element
1002            .entity_closure_dofs(entity_dim, entity_index)
1003            .unwrap()
1004            .iter()
1005            .enumerate()
1006        {
1007            unsafe {
1008                *entity_closure_dofs.add(i) = *dof;
1009            }
1010        }
1011    }
1012
1013    #[concretise_types(
1014        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1015        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1016        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
1017        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
1018    )]
1019    pub fn ciarlet_element_interpolation_npoints<
1020        T: RlstScalar + DTypeIdentifier + Getrf + Getri,
1021        M: Map,
1022        TGeo: RlstScalar + DTypeIdentifier,
1023    >(
1024        element: &CiarletElement<T, M, TGeo>,
1025        entity_dim: usize,
1026        entity_index: usize,
1027    ) -> usize {
1028        element.interpolation_points()[entity_dim][entity_index].shape()[1]
1029    }
1030
1031    #[concretise_types(
1032        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1033        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1034        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
1035        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
1036    )]
1037    pub fn ciarlet_element_interpolation_ndofs<
1038        T: RlstScalar + DTypeIdentifier + Getrf + Getri,
1039        M: Map,
1040        TGeo: RlstScalar + DTypeIdentifier,
1041    >(
1042        element: &CiarletElement<T, M, TGeo>,
1043        entity_dim: usize,
1044        entity_index: usize,
1045    ) -> usize {
1046        element.interpolation_weights()[entity_dim][entity_index].shape()[0]
1047    }
1048
1049    #[concretise_types(
1050        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1051        gen_type(name = "geo_dtype", replace_with = ["f32", "f64"]),
1052        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
1053        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
1054    )]
1055    pub fn ciarlet_element_interpolation_points<
1056        T: RlstScalar + DTypeIdentifier + Getrf + Getri,
1057        TGeo: RlstScalar + DTypeIdentifier + Getrf + Getri,
1058        M: Map,
1059    >(
1060        element: &CiarletElement<T, M, TGeo>,
1061        entity_dim: usize,
1062        entity_index: usize,
1063        points: *mut c_void,
1064    ) {
1065        let points = points as *mut TGeo;
1066        for (i, j) in element.interpolation_points()[entity_dim][entity_index]
1067            .data()
1068            .unwrap()
1069            .iter()
1070            .enumerate()
1071        {
1072            unsafe {
1073                *points.add(i) = *j;
1074            }
1075        }
1076    }
1077
1078    #[concretise_types(
1079        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1080        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1081        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
1082        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
1083    )]
1084    pub fn ciarlet_element_interpolation_weights<
1085        T: RlstScalar + DTypeIdentifier + Getrf + Getri,
1086        M: Map,
1087        TGeo: RlstScalar + DTypeIdentifier,
1088    >(
1089        element: &CiarletElement<T, M, TGeo>,
1090        entity_dim: usize,
1091        entity_index: usize,
1092        weights: *mut c_void,
1093    ) {
1094        let weights = weights as *mut T;
1095        for (i, j) in element.interpolation_weights()[entity_dim][entity_index]
1096            .data()
1097            .unwrap()
1098            .iter()
1099            .enumerate()
1100        {
1101            unsafe {
1102                *weights.add(i) = *j;
1103            }
1104        }
1105    }
1106
1107    #[concretise_types(
1108        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1109        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1110        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
1111        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
1112    )]
1113    pub unsafe fn ciarlet_element_apply_dof_permutations_usize<
1114        T: RlstScalar + DTypeIdentifier + Getrf + Getri,
1115        M: Map,
1116        TGeo: RlstScalar + DTypeIdentifier,
1117    >(
1118        element: &CiarletElement<T, M, TGeo>,
1119        data: *mut usize,
1120        data_size: usize,
1121        orientation: i32,
1122    ) {
1123        unsafe {
1124            element.apply_dof_permutations(from_raw_parts_mut(data, data_size), orientation);
1125        }
1126    }
1127
1128    #[concretise_types(
1129        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1130        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1131        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
1132        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
1133    )]
1134    pub unsafe fn ciarlet_element_apply_dof_permutations<
1135        T: RlstScalar + DTypeIdentifier + Getrf + Getri,
1136        M: Map,
1137        TGeo: RlstScalar + DTypeIdentifier,
1138    >(
1139        element: &CiarletElement<T, M, TGeo>,
1140        data: *mut c_void,
1141        data_size: usize,
1142        orientation: i32,
1143    ) {
1144        unsafe {
1145            element
1146                .apply_dof_permutations(from_raw_parts_mut(data as *mut T, data_size), orientation);
1147        }
1148    }
1149
1150    #[concretise_types(
1151        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1152        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1153        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
1154        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
1155    )]
1156    pub unsafe fn ciarlet_element_apply_dof_transformations<
1157        T: RlstScalar + DTypeIdentifier + Getrf + Getri,
1158        M: Map,
1159        TGeo: RlstScalar + DTypeIdentifier,
1160    >(
1161        element: &CiarletElement<T, M, TGeo>,
1162        data: *mut c_void,
1163        data_size: usize,
1164        orientation: i32,
1165    ) {
1166        unsafe {
1167            element.apply_dof_transformations(
1168                from_raw_parts_mut(data as *mut T, data_size),
1169                orientation,
1170            );
1171        }
1172    }
1173
1174    #[concretise_types(
1175        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1176        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1177        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
1178        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
1179    )]
1180    pub unsafe fn ciarlet_element_apply_dof_permutations_and_transformations<
1181        T: RlstScalar + DTypeIdentifier + Getrf + Getri,
1182        M: Map,
1183        TGeo: RlstScalar + DTypeIdentifier,
1184    >(
1185        element: &CiarletElement<T, M, TGeo>,
1186        data: *mut c_void,
1187        data_size: usize,
1188        orientation: i32,
1189    ) {
1190        unsafe {
1191            element.apply_dof_permutations_and_transformations(
1192                from_raw_parts_mut(data as *mut T, data_size),
1193                orientation,
1194            );
1195        }
1196    }
1197}