1*2027fb9dSSirAlienTheGreat #![no_std]
2*2027fb9dSSirAlienTheGreat #![allow(internal_features)]
3*2027fb9dSSirAlienTheGreat #![feature(asm_experimental_arch, abi_ptx, core_intrinsics)]
4*2027fb9dSSirAlienTheGreat use core::ffi::c_void;
5*2027fb9dSSirAlienTheGreat use core::intrinsics::abort;
6*2027fb9dSSirAlienTheGreat use core::panic::PanicInfo;
7*2027fb9dSSirAlienTheGreat
8*2027fb9dSSirAlienTheGreat use ndarray::ArrayView;
9*2027fb9dSSirAlienTheGreat
10*2027fb9dSSirAlienTheGreat // This is a dummy allocator that always returns null. Heap allocations do not work on GPUs
11*2027fb9dSSirAlienTheGreat use core::alloc::{GlobalAlloc, Layout};
12*2027fb9dSSirAlienTheGreat pub struct Allocator;
13*2027fb9dSSirAlienTheGreat unsafe impl GlobalAlloc for Allocator {
alloc(&self, _layout: Layout) -> *mut u814*2027fb9dSSirAlienTheGreat unsafe fn alloc(&self, _layout: Layout) -> *mut u8 {
15*2027fb9dSSirAlienTheGreat 0 as *mut u8
16*2027fb9dSSirAlienTheGreat }
dealloc(&self, _ptr: *mut u8, _layout: Layout)17*2027fb9dSSirAlienTheGreat unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {
18*2027fb9dSSirAlienTheGreat abort(); // since we never allocate
19*2027fb9dSSirAlienTheGreat }
20*2027fb9dSSirAlienTheGreat }
21*2027fb9dSSirAlienTheGreat #[global_allocator]
22*2027fb9dSSirAlienTheGreat static GLOBAL_ALLOCATOR: Allocator = Allocator;
23*2027fb9dSSirAlienTheGreat
24*2027fb9dSSirAlienTheGreat // This is a copy of the same data structure defined in the .h file. It can be autogenerated using bindgen/cbindgen
25*2027fb9dSSirAlienTheGreat #[doc = " A structure used to pass additional data to f_build_mass"]
26*2027fb9dSSirAlienTheGreat #[repr(C)]
27*2027fb9dSSirAlienTheGreat #[derive(Debug, Copy, Clone)]
28*2027fb9dSSirAlienTheGreat pub struct BuildContext {
29*2027fb9dSSirAlienTheGreat pub dim: i32,
30*2027fb9dSSirAlienTheGreat pub space_dim: i32,
31*2027fb9dSSirAlienTheGreat }
32*2027fb9dSSirAlienTheGreat
33*2027fb9dSSirAlienTheGreat // On no_std targets, its required to implement your own panic function.
34*2027fb9dSSirAlienTheGreat #[panic_handler]
panic(_info: &PanicInfo) -> !35*2027fb9dSSirAlienTheGreat fn panic(_info: &PanicInfo) -> ! {
36*2027fb9dSSirAlienTheGreat abort()
37*2027fb9dSSirAlienTheGreat }
38*2027fb9dSSirAlienTheGreat
39*2027fb9dSSirAlienTheGreat /* The no_mangle is required because rust "mangles" names (changes them to prevent namespace conflicts)
40*2027fb9dSSirAlienTheGreat Also note that this function ends in _rs, even though the C call `CEED_QFUNCTION_RUST(build_mass)` doesn't */
41*2027fb9dSSirAlienTheGreat #[no_mangle]
build_mass_rs( ctx: *mut c_void, q: i32, in_: *const *const f64, out: *mut *mut f64, ) -> i842*2027fb9dSSirAlienTheGreat pub unsafe extern "C" fn build_mass_rs(
43*2027fb9dSSirAlienTheGreat ctx: *mut c_void,
44*2027fb9dSSirAlienTheGreat q: i32,
45*2027fb9dSSirAlienTheGreat in_: *const *const f64,
46*2027fb9dSSirAlienTheGreat out: *mut *mut f64,
47*2027fb9dSSirAlienTheGreat ) -> i8 {
48*2027fb9dSSirAlienTheGreat let ctx: *mut BuildContext = unsafe { core::mem::transmute(ctx) };
49*2027fb9dSSirAlienTheGreat let ctx: &mut BuildContext = &mut *ctx;
50*2027fb9dSSirAlienTheGreat
51*2027fb9dSSirAlienTheGreat let in_slice = core::slice::from_raw_parts(in_, 2);
52*2027fb9dSSirAlienTheGreat
53*2027fb9dSSirAlienTheGreat // in_slice[0] is Jacobians with shape [dim, dim, Q]
54*2027fb9dSSirAlienTheGreat // in_slice[1] is quadrature weights with shape [1, Q]
55*2027fb9dSSirAlienTheGreat let j_ptr = in_slice[0];
56*2027fb9dSSirAlienTheGreat let w_ptr = in_slice[1];
57*2027fb9dSSirAlienTheGreat
58*2027fb9dSSirAlienTheGreat let j = ArrayView::from_shape_ptr((ctx.dim as usize, ctx.dim as usize, q as usize), j_ptr);
59*2027fb9dSSirAlienTheGreat
60*2027fb9dSSirAlienTheGreat let w = core::slice::from_raw_parts(w_ptr, q as usize);
61*2027fb9dSSirAlienTheGreat
62*2027fb9dSSirAlienTheGreat let out_slice = core::slice::from_raw_parts_mut(out, 1);
63*2027fb9dSSirAlienTheGreat let q_data = core::slice::from_raw_parts_mut(out_slice[0], q as usize);
64*2027fb9dSSirAlienTheGreat
65*2027fb9dSSirAlienTheGreat match ctx.dim * 10 + ctx.space_dim {
66*2027fb9dSSirAlienTheGreat 11 => {
67*2027fb9dSSirAlienTheGreat // Quadrature Point Loop
68*2027fb9dSSirAlienTheGreat for i in 0..q as usize {
69*2027fb9dSSirAlienTheGreat q_data[i] = j[[0, 0, i]] * w[i];
70*2027fb9dSSirAlienTheGreat }
71*2027fb9dSSirAlienTheGreat }
72*2027fb9dSSirAlienTheGreat 22 => {
73*2027fb9dSSirAlienTheGreat // Quadrature Point Loop
74*2027fb9dSSirAlienTheGreat for i in 0..q as usize {
75*2027fb9dSSirAlienTheGreat q_data[i] = (j[[0, 0, i]] * j[[1, 1, i]] - j[[0, 1, i]] * j[[1, 0, i]]) * w[i];
76*2027fb9dSSirAlienTheGreat }
77*2027fb9dSSirAlienTheGreat }
78*2027fb9dSSirAlienTheGreat 33 => {
79*2027fb9dSSirAlienTheGreat // Quadrature Point Loop
80*2027fb9dSSirAlienTheGreat for i in 0..q as usize {
81*2027fb9dSSirAlienTheGreat q_data[i] = (j[[0, 0, i]]
82*2027fb9dSSirAlienTheGreat * (j[[1, 1, i]] * j[[2, 2, i]] - j[[1, 2, i]] * j[[2, 1, i]])
83*2027fb9dSSirAlienTheGreat - j[[0, 1, i]] * (j[[1, 0, i]] * j[[2, 2, i]] - j[[1, 2, i]] * j[[2, 0, i]])
84*2027fb9dSSirAlienTheGreat + j[[0, 2, i]] * (j[[1, 0, i]] * j[[2, 1, i]] - j[[1, 1, i]] * j[[2, 0, i]]))
85*2027fb9dSSirAlienTheGreat * w[i];
86*2027fb9dSSirAlienTheGreat }
87*2027fb9dSSirAlienTheGreat }
88*2027fb9dSSirAlienTheGreat _ => {
89*2027fb9dSSirAlienTheGreat abort();
90*2027fb9dSSirAlienTheGreat }
91*2027fb9dSSirAlienTheGreat }
92*2027fb9dSSirAlienTheGreat
93*2027fb9dSSirAlienTheGreat 0
94*2027fb9dSSirAlienTheGreat }
95*2027fb9dSSirAlienTheGreat
96*2027fb9dSSirAlienTheGreat /* The no_mangle is required because rust "mangles" names (changes them to prevent namespace conflicts)
97*2027fb9dSSirAlienTheGreat Also note that this function ends in _rs, even though the C call `CEED_QFUNCTION_RUST(apply_mass)` doesn't
98*2027fb9dSSirAlienTheGreat For FFI reasons, it is also required to include all parameters in this exact form, even if you don't use all of them*/
99*2027fb9dSSirAlienTheGreat #[no_mangle]
apply_mass_rs( _ctx: *mut c_void, q: i32, in_: *const *const f64, out: *mut *mut f64, ) -> i8100*2027fb9dSSirAlienTheGreat pub unsafe extern "C" fn apply_mass_rs(
101*2027fb9dSSirAlienTheGreat _ctx: *mut c_void,
102*2027fb9dSSirAlienTheGreat q: i32,
103*2027fb9dSSirAlienTheGreat in_: *const *const f64,
104*2027fb9dSSirAlienTheGreat out: *mut *mut f64,
105*2027fb9dSSirAlienTheGreat ) -> i8 {
106*2027fb9dSSirAlienTheGreat let in_slice = core::slice::from_raw_parts(in_, 2);
107*2027fb9dSSirAlienTheGreat
108*2027fb9dSSirAlienTheGreat let u_ptr = in_slice[0];
109*2027fb9dSSirAlienTheGreat let q_data_ptr = in_slice[1];
110*2027fb9dSSirAlienTheGreat
111*2027fb9dSSirAlienTheGreat let u = core::slice::from_raw_parts(u_ptr, q as usize);
112*2027fb9dSSirAlienTheGreat let q_data = core::slice::from_raw_parts(q_data_ptr, q as usize);
113*2027fb9dSSirAlienTheGreat
114*2027fb9dSSirAlienTheGreat let out_slice = core::slice::from_raw_parts_mut(out, 1);
115*2027fb9dSSirAlienTheGreat
116*2027fb9dSSirAlienTheGreat let v_ptr = out_slice[0];
117*2027fb9dSSirAlienTheGreat let v = core::slice::from_raw_parts_mut(v_ptr, q as usize);
118*2027fb9dSSirAlienTheGreat
119*2027fb9dSSirAlienTheGreat for i in 0..q as usize {
120*2027fb9dSSirAlienTheGreat v[i] = q_data[i] * u[i];
121*2027fb9dSSirAlienTheGreat }
122*2027fb9dSSirAlienTheGreat
123*2027fb9dSSirAlienTheGreat 0
124*2027fb9dSSirAlienTheGreat }
125