Skip to main content

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,
270        RaviartThomas,
271        NedelecFirstKind,
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        variant: ciarlet::lagrange::Variant,
295        dtype: DType,
296    ) -> *mut ElementFamilyT {
297        let family = element_family_t_create();
298        let family_inner = unsafe { element_family_t_unwrap(family).unwrap() };
299
300        *family_inner = match dtype {
301            DType::F32 => Box::new(ciarlet::LagrangeElementFamily::<f32>::new(
302                degree, continuity, variant,
303            )),
304            DType::F64 => Box::new(ciarlet::LagrangeElementFamily::<f64>::new(
305                degree, continuity, variant,
306            )),
307            DType::C32 => Box::new(ciarlet::LagrangeElementFamily::<c32>::new(
308                degree, continuity, variant,
309            )),
310            DType::C64 => Box::new(ciarlet::LagrangeElementFamily::<c64>::new(
311                degree, continuity, variant,
312            )),
313            _ => panic!("Unsupported dtype"),
314        };
315
316        family
317    }
318
319    #[unsafe(no_mangle)]
320    pub extern "C" fn create_raviart_thomas_family(
321        degree: usize,
322        continuity: Continuity,
323        dtype: DType,
324    ) -> *mut ElementFamilyT {
325        let family = element_family_t_create();
326        let family_inner = unsafe { element_family_t_unwrap(family).unwrap() };
327
328        *family_inner = match dtype {
329            DType::F32 => Box::new(ciarlet::RaviartThomasElementFamily::<f32>::new(
330                degree, continuity,
331            )),
332            DType::F64 => Box::new(ciarlet::RaviartThomasElementFamily::<f64>::new(
333                degree, continuity,
334            )),
335            DType::C32 => Box::new(ciarlet::RaviartThomasElementFamily::<c32>::new(
336                degree, continuity,
337            )),
338            DType::C64 => Box::new(ciarlet::RaviartThomasElementFamily::<c64>::new(
339                degree, continuity,
340            )),
341            _ => panic!("Unsupported dtype"),
342        };
343
344        family
345    }
346
347    #[unsafe(no_mangle)]
348    pub extern "C" fn create_nedelec_family(
349        degree: usize,
350        continuity: Continuity,
351        dtype: DType,
352    ) -> *mut ElementFamilyT {
353        let family = element_family_t_create();
354        let family_inner = unsafe { element_family_t_unwrap(family).unwrap() };
355
356        *family_inner = match dtype {
357            DType::F32 => Box::new(ciarlet::NedelecFirstKindElementFamily::<f32>::new(
358                degree, continuity,
359            )),
360            DType::F64 => Box::new(ciarlet::NedelecFirstKindElementFamily::<f64>::new(
361                degree, continuity,
362            )),
363            DType::C32 => Box::new(ciarlet::NedelecFirstKindElementFamily::<c32>::new(
364                degree, continuity,
365            )),
366            DType::C64 => Box::new(ciarlet::NedelecFirstKindElementFamily::<c64>::new(
367                degree, continuity,
368            )),
369            _ => panic!("Unsupported dtype"),
370        };
371
372        family
373    }
374
375    #[concretise_types(
376        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
377        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
378        field(arg = 0, name = "element_family", wrapper = "ElementFamilyT", replace_with = [
379            "ciarlet::LagrangeElementFamily<{{dtype}}, {{geo_dtype}}>",
380            "ciarlet::RaviartThomasElementFamily<{{dtype}}, {{geo_dtype}}>",
381            "ciarlet::NedelecFirstKindElementFamily<{{dtype}}, {{geo_dtype}}>"
382        ])
383    )]
384    pub fn element_family_create_element<F: ElementFamily<CellType = ReferenceCellType>>(
385        family: &F,
386        cell: ReferenceCellType,
387    ) -> *mut CiarletElementT {
388        let ciarlet_element = ciarlet_element_t_create();
389        let inner = unsafe { ciarlet_element_t_unwrap(ciarlet_element).unwrap() };
390
391        *inner = Box::new(family.element(cell));
392
393        ciarlet_element
394    }
395
396    #[concretise_types(
397        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
398        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
399        field(arg = 0, name = "element_family", wrapper = "ElementFamilyT", replace_with = [
400            "ciarlet::LagrangeElementFamily<{{dtype}}, {{geo_dtype}}>",
401            "ciarlet::RaviartThomasElementFamily<{{dtype}}, {{geo_dtype}}>",
402            "ciarlet::NedelecFirstKindElementFamily<{{dtype}}, {{geo_dtype}}>"
403        ])
404    )]
405    pub fn element_family_dtype<
406        T: RlstScalar + DTypeIdentifier,
407        F: ElementFamily<CellType = ReferenceCellType, T = T>,
408    >(
409        _elem: &F,
410    ) -> DType {
411        <T as DTypeIdentifier>::dtype()
412    }
413
414    #[concretise_types(
415        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
416        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
417        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
418        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
419    )]
420    pub fn ciarlet_element_dtype<T: RlstScalar + DTypeIdentifier, E: FiniteElement<T = T>>(
421        _elem: &E,
422    ) -> DType {
423        <T as DTypeIdentifier>::dtype()
424    }
425
426    #[concretise_types(
427        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
428        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
429        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
430        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
431    )]
432    pub fn ciarlet_element_geo_dtype<
433        T: RlstScalar + DTypeIdentifier,
434        M: Map,
435        TGeo: RlstScalar + DTypeIdentifier,
436    >(
437        _elem: &CiarletElement<T, M, TGeo>,
438    ) -> DType {
439        <TGeo as DTypeIdentifier>::dtype()
440    }
441
442    #[concretise_types(
443        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
444        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
445        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
446        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
447    )]
448    pub fn ciarlet_element_tabulate_array_shape<E: FiniteElement>(
449        element: &E,
450        nderivs: usize,
451        npoints: usize,
452        shape: *mut usize,
453    ) {
454        for (i, j) in element
455            .tabulate_array_shape(nderivs, npoints)
456            .iter()
457            .enumerate()
458        {
459            unsafe {
460                *shape.add(i) = *j;
461            }
462        }
463    }
464
465    pub unsafe fn ciarlet_element_tabulate<
466        E: FiniteElement<CellType = ReferenceCellType>,
467        TGeo: RlstScalar,
468    >(
469        element: &E,
470        points: *const TGeo,
471        npoints: usize,
472        nderivs: usize,
473        data: *mut c_void,
474    ) {
475        let tdim = reference_cell::dim(element.cell_type());
476        let data = data as *mut E::T;
477        let points = SliceArray::<TGeo, 2>::from_shape(
478            unsafe { from_raw_parts(points, npoints * tdim) },
479            [tdim, npoints],
480        );
481        let shape = element.tabulate_array_shape(nderivs, npoints);
482        let mut data = SliceArrayMut::<E::T, 4>::from_shape(
483            unsafe { from_raw_parts_mut(data, shape[0] * shape[1] * shape[2] * shape[3]) },
484            shape,
485        );
486        element.tabulate(&points, nderivs, &mut data);
487    }
488
489    #[concretise_types(
490        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
491        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
492        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
493        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"]),
494    )]
495    pub unsafe fn ciarlet_element_tabulate_f32<E: FiniteElement<CellType = ReferenceCellType>>(
496        element: &E,
497        points: *const f32,
498        npoints: usize,
499        nderivs: usize,
500        data: *mut c_void,
501    ) {
502        unsafe {
503            ciarlet_element_tabulate(element, points, npoints, nderivs, data);
504        }
505    }
506
507    #[concretise_types(
508        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
509        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
510        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
511        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"]),
512    )]
513    pub unsafe fn ciarlet_element_tabulate_f64<E: FiniteElement<CellType = ReferenceCellType>>(
514        element: &E,
515        points: *const f64,
516        npoints: usize,
517        nderivs: usize,
518        data: *mut c_void,
519    ) {
520        unsafe {
521            ciarlet_element_tabulate(element, points, npoints, nderivs, data);
522        }
523    }
524
525    #[concretise_types(
526        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
527        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
528        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
529        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
530    )]
531    pub fn ciarlet_element_value_size<E: FiniteElement>(element: &E) -> usize {
532        element.value_size()
533    }
534
535    #[concretise_types(
536        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
537        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
538        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
539        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
540    )]
541    pub fn ciarlet_element_value_rank<E: FiniteElement>(element: &E) -> usize {
542        element.value_shape().len()
543    }
544
545    #[concretise_types(
546        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
547        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
548        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
549        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
550    )]
551    pub fn ciarlet_element_value_shape<E: FiniteElement>(element: &E, shape: *mut usize) {
552        for (i, j) in element.value_shape().iter().enumerate() {
553            unsafe {
554                *shape.add(i) = *j;
555            }
556        }
557    }
558
559    #[concretise_types(
560        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
561        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
562        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
563        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
564    )]
565    pub fn ciarlet_element_physical_value_size<E: MappedFiniteElement>(
566        element: &E,
567        gdim: usize,
568    ) -> usize {
569        element.physical_value_size(gdim)
570    }
571
572    #[concretise_types(
573        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
574        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
575        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
576        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
577    )]
578    pub fn ciarlet_element_physical_value_rank<E: MappedFiniteElement>(
579        element: &E,
580        gdim: usize,
581    ) -> usize {
582        element.physical_value_shape(gdim).len()
583    }
584
585    #[concretise_types(
586        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
587        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
588        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
589        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
590    )]
591    pub fn ciarlet_element_physical_value_shape<E: MappedFiniteElement>(
592        element: &E,
593        gdim: usize,
594        shape: *mut usize,
595    ) {
596        for (i, j) in element.physical_value_shape(gdim).iter().enumerate() {
597            unsafe {
598                *shape.add(i) = *j;
599            }
600        }
601    }
602
603    #[allow(clippy::too_many_arguments)]
604    pub unsafe fn ciarlet_element_push_forward<
605        E: MappedFiniteElement<CellType = ReferenceCellType>,
606        TGeo: RlstScalar,
607    >(
608        element: &E,
609        npoints: usize,
610        nfunctions: usize,
611        gdim: usize,
612        reference_values: *const TGeo,
613        nderivs: usize,
614        j: *const TGeo,
615        jdet: *const TGeo,
616        jinv: *const TGeo,
617        physical_values: *mut c_void,
618    ) {
619        let tdim = reference_cell::dim(element.cell_type());
620        let deriv_size = element.tabulate_array_shape(nderivs, npoints)[0];
621        let pvs = element.physical_value_size(gdim);
622        let vs = element.value_size();
623        let reference_values = SliceArray::<E::T, 4>::from_shape(
624            unsafe {
625                from_raw_parts(
626                    reference_values as *const E::T,
627                    deriv_size * npoints * nfunctions * vs,
628                )
629            },
630            [deriv_size, npoints, nfunctions, vs],
631        );
632        let j = SliceArray::<TGeo, 3>::from_shape(
633            unsafe { from_raw_parts(j, npoints * gdim * tdim) },
634            [npoints, gdim, tdim],
635        );
636        let jdet = unsafe { from_raw_parts(jdet, npoints) };
637        let jinv = SliceArray::<TGeo, 3>::from_shape(
638            unsafe { from_raw_parts(jinv, npoints * tdim * gdim) },
639            [npoints, tdim, gdim],
640        );
641        let mut physical_values = SliceArrayMut::<E::T, 4>::from_shape(
642            unsafe {
643                from_raw_parts_mut(
644                    physical_values as *mut E::T,
645                    deriv_size * npoints * nfunctions * pvs,
646                )
647            },
648            [deriv_size, npoints, nfunctions, pvs],
649        );
650        element.push_forward(
651            &reference_values,
652            nderivs,
653            &j,
654            jdet,
655            &jinv,
656            &mut physical_values,
657        );
658    }
659
660    #[allow(clippy::too_many_arguments)]
661    #[concretise_types(
662        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
663        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
664        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
665        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
666    )]
667    pub unsafe fn ciarlet_element_push_forward_f32<
668        E: MappedFiniteElement<CellType = ReferenceCellType>,
669    >(
670        element: &E,
671        npoints: usize,
672        nfunctions: usize,
673        gdim: usize,
674        reference_values: *const f32,
675        nderivs: usize,
676        j: *const f32,
677        jdet: *const f32,
678        jinv: *const f32,
679        physical_values: *mut c_void,
680    ) {
681        unsafe {
682            ciarlet_element_push_forward(
683                element,
684                npoints,
685                nfunctions,
686                gdim,
687                reference_values,
688                nderivs,
689                j,
690                jdet,
691                jinv,
692                physical_values,
693            );
694        }
695    }
696
697    #[allow(clippy::too_many_arguments)]
698    #[concretise_types(
699        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
700        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
701        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
702        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
703    )]
704    pub unsafe fn ciarlet_element_push_forward_f64<
705        E: MappedFiniteElement<CellType = ReferenceCellType>,
706    >(
707        element: &E,
708        npoints: usize,
709        nfunctions: usize,
710        gdim: usize,
711        reference_values: *const f64,
712        nderivs: usize,
713        j: *const f64,
714        jdet: *const f64,
715        jinv: *const f64,
716        physical_values: *mut c_void,
717    ) {
718        unsafe {
719            ciarlet_element_push_forward(
720                element,
721                npoints,
722                nfunctions,
723                gdim,
724                reference_values,
725                nderivs,
726                j,
727                jdet,
728                jinv,
729                physical_values,
730            );
731        }
732    }
733
734    #[allow(clippy::too_many_arguments)]
735    pub unsafe fn ciarlet_element_pull_back<
736        E: MappedFiniteElement<CellType = ReferenceCellType>,
737        TGeo: RlstScalar,
738    >(
739        element: &E,
740        npoints: usize,
741        nfunctions: usize,
742        gdim: usize,
743        physical_values: *const TGeo,
744        nderivs: usize,
745        j: *const TGeo,
746        jdet: *const TGeo,
747        jinv: *const TGeo,
748        reference_values: *mut c_void,
749    ) {
750        let tdim = reference_cell::dim(element.cell_type());
751        let deriv_size = element.tabulate_array_shape(nderivs, npoints)[0];
752        let pvs = element.physical_value_size(gdim);
753        let vs = element.value_size();
754        let physical_values = SliceArray::<E::T, 4>::from_shape(
755            unsafe {
756                from_raw_parts(
757                    physical_values as *const E::T,
758                    deriv_size * npoints * nfunctions * pvs,
759                )
760            },
761            [deriv_size, npoints, nfunctions, pvs],
762        );
763        let j = SliceArray::<TGeo, 3>::from_shape(
764            unsafe { from_raw_parts(j, npoints * gdim * tdim) },
765            [npoints, gdim, tdim],
766        );
767        let jdet = unsafe { from_raw_parts(jdet, npoints) };
768        let jinv = SliceArray::<TGeo, 3>::from_shape(
769            unsafe { from_raw_parts(jinv, npoints * tdim * gdim) },
770            [npoints, tdim, gdim],
771        );
772        let mut reference_values = SliceArrayMut::<E::T, 4>::from_shape(
773            unsafe {
774                from_raw_parts_mut(
775                    reference_values as *mut E::T,
776                    deriv_size * npoints * nfunctions * vs,
777                )
778            },
779            [deriv_size, npoints, nfunctions, vs],
780        );
781        element.pull_back(
782            &physical_values,
783            nderivs,
784            &j,
785            jdet,
786            &jinv,
787            &mut reference_values,
788        );
789    }
790
791    #[allow(clippy::too_many_arguments)]
792    #[concretise_types(
793        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
794        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
795        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
796        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
797    )]
798    pub unsafe fn ciarlet_element_pull_back_f32<
799        E: MappedFiniteElement<CellType = ReferenceCellType>,
800    >(
801        element: &E,
802        npoints: usize,
803        nfunctions: usize,
804        gdim: usize,
805        physical_values: *const f32,
806        nderivs: usize,
807        j: *const f32,
808        jdet: *const f32,
809        jinv: *const f32,
810        reference_values: *mut c_void,
811    ) {
812        unsafe {
813            ciarlet_element_pull_back(
814                element,
815                npoints,
816                nfunctions,
817                gdim,
818                physical_values,
819                nderivs,
820                j,
821                jdet,
822                jinv,
823                reference_values,
824            );
825        }
826    }
827
828    #[allow(clippy::too_many_arguments)]
829    #[concretise_types(
830        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
831        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
832        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
833        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
834    )]
835    pub fn ciarlet_element_pull_back_f64<E: MappedFiniteElement<CellType = ReferenceCellType>>(
836        element: &E,
837        npoints: usize,
838        nfunctions: usize,
839        gdim: usize,
840        physical_values: *const f64,
841        nderivs: usize,
842        j: *const f64,
843        jdet: *const f64,
844        jinv: *const f64,
845        reference_values: *mut c_void,
846    ) {
847        unsafe {
848            ciarlet_element_pull_back(
849                element,
850                npoints,
851                nfunctions,
852                gdim,
853                physical_values,
854                nderivs,
855                j,
856                jdet,
857                jinv,
858                reference_values,
859            );
860        }
861    }
862
863    #[concretise_types(
864        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
865        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
866        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
867        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
868    )]
869    pub fn ciarlet_element_degree<
870        T: RlstScalar + DTypeIdentifier + Getrf + Getri,
871        M: Map,
872        TGeo: RlstScalar + DTypeIdentifier,
873    >(
874        element: &CiarletElement<T, M, TGeo>,
875    ) -> usize {
876        element.degree()
877    }
878
879    #[concretise_types(
880        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
881        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
882        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
883        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
884    )]
885    pub fn ciarlet_element_embedded_superdegree<E: MappedFiniteElement>(element: &E) -> usize {
886        element.lagrange_superdegree()
887    }
888
889    #[concretise_types(
890        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
891        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
892        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
893        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
894    )]
895    pub fn ciarlet_element_dim<E: FiniteElement>(element: &E) -> usize {
896        element.dim()
897    }
898
899    #[concretise_types(
900        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
901        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
902        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
903        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
904    )]
905    pub fn ciarlet_element_continuity<
906        T: RlstScalar + DTypeIdentifier + Getrf + Getri,
907        M: Map,
908        TGeo: RlstScalar + DTypeIdentifier,
909    >(
910        element: &CiarletElement<T, M, TGeo>,
911    ) -> Continuity {
912        element.continuity()
913    }
914
915    #[concretise_types(
916        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
917        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
918        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
919        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
920    )]
921    pub fn ciarlet_element_cell_type<E: FiniteElement<CellType = ReferenceCellType>>(
922        element: &E,
923    ) -> ReferenceCellType {
924        element.cell_type()
925    }
926
927    #[concretise_types(
928        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
929        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
930        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
931        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
932    )]
933    pub fn ciarlet_element_entity_dofs_size<E: FiniteElement>(
934        element: &E,
935        entity_dim: usize,
936        entity_index: usize,
937    ) -> usize {
938        element.entity_dofs(entity_dim, entity_index).unwrap().len()
939    }
940
941    #[concretise_types(
942        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
943        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
944        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
945        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
946    )]
947    pub fn ciarlet_element_entity_dofs<E: FiniteElement>(
948        element: &E,
949        entity_dim: usize,
950        entity_index: usize,
951        entity_dofs: *mut usize,
952    ) {
953        for (i, dof) in element
954            .entity_dofs(entity_dim, entity_index)
955            .unwrap()
956            .iter()
957            .enumerate()
958        {
959            unsafe {
960                *entity_dofs.add(i) = *dof;
961            }
962        }
963    }
964
965    #[concretise_types(
966        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
967        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
968        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
969        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
970    )]
971    pub fn ciarlet_element_entity_closure_dofs_size<
972        T: RlstScalar + DTypeIdentifier,
973        M: Map,
974        TGeo: RlstScalar + DTypeIdentifier,
975    >(
976        element: &CiarletElement<T, M, TGeo>,
977        entity_dim: usize,
978        entity_index: usize,
979    ) -> usize {
980        element
981            .entity_closure_dofs(entity_dim, entity_index)
982            .unwrap()
983            .len()
984    }
985
986    #[concretise_types(
987        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
988        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
989        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
990        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
991    )]
992    pub fn ciarlet_element_entity_closure_dofs<
993        T: RlstScalar + DTypeIdentifier,
994        M: Map,
995        TGeo: RlstScalar + DTypeIdentifier,
996    >(
997        element: &CiarletElement<T, M, TGeo>,
998        entity_dim: usize,
999        entity_index: usize,
1000        entity_closure_dofs: *mut usize,
1001    ) {
1002        for (i, dof) in element
1003            .entity_closure_dofs(entity_dim, entity_index)
1004            .unwrap()
1005            .iter()
1006            .enumerate()
1007        {
1008            unsafe {
1009                *entity_closure_dofs.add(i) = *dof;
1010            }
1011        }
1012    }
1013
1014    #[concretise_types(
1015        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1016        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1017        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
1018        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
1019    )]
1020    pub fn ciarlet_element_interpolation_npoints<
1021        T: RlstScalar + DTypeIdentifier + Getrf + Getri,
1022        M: Map,
1023        TGeo: RlstScalar + DTypeIdentifier,
1024    >(
1025        element: &CiarletElement<T, M, TGeo>,
1026        entity_dim: usize,
1027        entity_index: usize,
1028    ) -> usize {
1029        element.interpolation_points()[entity_dim][entity_index].shape()[1]
1030    }
1031
1032    #[concretise_types(
1033        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1034        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1035        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
1036        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
1037    )]
1038    pub fn ciarlet_element_interpolation_ndofs<
1039        T: RlstScalar + DTypeIdentifier + Getrf + Getri,
1040        M: Map,
1041        TGeo: RlstScalar + DTypeIdentifier,
1042    >(
1043        element: &CiarletElement<T, M, TGeo>,
1044        entity_dim: usize,
1045        entity_index: usize,
1046    ) -> usize {
1047        element.interpolation_weights()[entity_dim][entity_index].shape()[0]
1048    }
1049
1050    #[concretise_types(
1051        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1052        gen_type(name = "geo_dtype", replace_with = ["f32", "f64"]),
1053        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
1054        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
1055    )]
1056    pub fn ciarlet_element_interpolation_points<
1057        T: RlstScalar + DTypeIdentifier + Getrf + Getri,
1058        TGeo: RlstScalar + DTypeIdentifier + Getrf + Getri,
1059        M: Map,
1060    >(
1061        element: &CiarletElement<T, M, TGeo>,
1062        entity_dim: usize,
1063        entity_index: usize,
1064        points: *mut c_void,
1065    ) {
1066        let points = points as *mut TGeo;
1067        for (i, j) in element.interpolation_points()[entity_dim][entity_index]
1068            .data()
1069            .unwrap()
1070            .iter()
1071            .enumerate()
1072        {
1073            unsafe {
1074                *points.add(i) = *j;
1075            }
1076        }
1077    }
1078
1079    #[concretise_types(
1080        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1081        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1082        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
1083        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
1084    )]
1085    pub fn ciarlet_element_interpolation_weights<
1086        T: RlstScalar + DTypeIdentifier + Getrf + Getri,
1087        M: Map,
1088        TGeo: RlstScalar + DTypeIdentifier,
1089    >(
1090        element: &CiarletElement<T, M, TGeo>,
1091        entity_dim: usize,
1092        entity_index: usize,
1093        weights: *mut c_void,
1094    ) {
1095        let weights = weights as *mut T;
1096        for (i, j) in element.interpolation_weights()[entity_dim][entity_index]
1097            .data()
1098            .unwrap()
1099            .iter()
1100            .enumerate()
1101        {
1102            unsafe {
1103                *weights.add(i) = *j;
1104            }
1105        }
1106    }
1107
1108    #[concretise_types(
1109        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1110        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1111        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
1112        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
1113    )]
1114    pub unsafe fn ciarlet_element_apply_dof_permutations_usize<
1115        T: RlstScalar + DTypeIdentifier + Getrf + Getri,
1116        M: Map,
1117        TGeo: RlstScalar + DTypeIdentifier,
1118    >(
1119        element: &CiarletElement<T, M, TGeo>,
1120        data: *mut usize,
1121        data_size: usize,
1122        orientation: i32,
1123    ) {
1124        unsafe {
1125            element.apply_dof_permutations(from_raw_parts_mut(data, data_size), orientation);
1126        }
1127    }
1128
1129    #[concretise_types(
1130        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1131        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1132        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
1133        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
1134    )]
1135    pub unsafe fn ciarlet_element_apply_dof_permutations<
1136        T: RlstScalar + DTypeIdentifier + Getrf + Getri,
1137        M: Map,
1138        TGeo: RlstScalar + DTypeIdentifier,
1139    >(
1140        element: &CiarletElement<T, M, TGeo>,
1141        data: *mut c_void,
1142        data_size: usize,
1143        orientation: i32,
1144    ) {
1145        unsafe {
1146            element
1147                .apply_dof_permutations(from_raw_parts_mut(data as *mut T, data_size), orientation);
1148        }
1149    }
1150
1151    #[concretise_types(
1152        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1153        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1154        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
1155        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
1156    )]
1157    pub unsafe fn ciarlet_element_apply_dof_transformations<
1158        T: RlstScalar + DTypeIdentifier + Getrf + Getri,
1159        M: Map,
1160        TGeo: RlstScalar + DTypeIdentifier,
1161    >(
1162        element: &CiarletElement<T, M, TGeo>,
1163        data: *mut c_void,
1164        data_size: usize,
1165        orientation: i32,
1166    ) {
1167        unsafe {
1168            element.apply_dof_transformations(
1169                from_raw_parts_mut(data as *mut T, data_size),
1170                orientation,
1171            );
1172        }
1173    }
1174
1175    #[concretise_types(
1176        gen_type(name = "dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1177        gen_type(name = "geo_dtype", replace_with = ["f32", "f64", "c32", "c64"]),
1178        gen_type(name = "maptype", replace_with = ["IdentityMap", "CovariantPiolaMap", "ContravariantPiolaMap"]),
1179        field(arg = 0, name = "element", wrapper = "CiarletElementT", replace_with = ["CiarletElement<{{dtype}}, {{maptype}}, {{geo_dtype}}>"])
1180    )]
1181    pub unsafe fn ciarlet_element_apply_dof_permutations_and_transformations<
1182        T: RlstScalar + DTypeIdentifier + Getrf + Getri,
1183        M: Map,
1184        TGeo: RlstScalar + DTypeIdentifier,
1185    >(
1186        element: &CiarletElement<T, M, TGeo>,
1187        data: *mut c_void,
1188        data_size: usize,
1189        orientation: i32,
1190    ) {
1191        unsafe {
1192            element.apply_dof_permutations_and_transformations(
1193                from_raw_parts_mut(data as *mut T, data_size),
1194                orientation,
1195            );
1196        }
1197    }
1198}