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 { 14*2027fb9dSSirAlienTheGreat unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { 15*2027fb9dSSirAlienTheGreat 0 as *mut u8 16*2027fb9dSSirAlienTheGreat } 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] 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] 42*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] 100*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