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