plumb the R type parameter through spirv code
This commit is contained in:
@@ -19,6 +19,7 @@ pub use sim::{SerializedSimMeta, SerializedStepE, SerializedStepH};
|
||||
pub use support::{Optional, UnsizedArray};
|
||||
|
||||
use coremem_types::mat::{Ferroxcube3R1MH, FullyGenericMaterial, IsoConductorOr, Material};
|
||||
use coremem_types::real::Real;
|
||||
use coremem_types::vec::{Vec3, Vec3u};
|
||||
|
||||
type Iso3R1<R> = IsoConductorOr<R, Ferroxcube3R1MH>;
|
||||
@@ -27,14 +28,14 @@ fn glam_vec_to_internal(v: glam::UVec3) -> Vec3u {
|
||||
Vec3u::new(v.x, v.y, v.z)
|
||||
}
|
||||
|
||||
fn step_h<M: Material<f32>>(
|
||||
fn step_h<R: Real, M: Material<R>>(
|
||||
id: Vec3u,
|
||||
meta: &SerializedSimMeta,
|
||||
stimulus_h: &UnsizedArray<Vec3<f32>>,
|
||||
meta: &SerializedSimMeta<R>,
|
||||
stimulus_h: &UnsizedArray<Vec3<R>>,
|
||||
material: &UnsizedArray<M>,
|
||||
e: &UnsizedArray<Vec3<f32>>,
|
||||
h: &mut UnsizedArray<Vec3<f32>>,
|
||||
m: &mut UnsizedArray<Vec3<f32>>,
|
||||
e: &UnsizedArray<Vec3<R>>,
|
||||
h: &mut UnsizedArray<Vec3<R>>,
|
||||
m: &mut UnsizedArray<Vec3<R>>,
|
||||
) {
|
||||
if id.x() < meta.dim.x() && id.y() < meta.dim.y() && id.z() < meta.dim.z() {
|
||||
let sim_state = SerializedStepH::new(meta, stimulus_h, material, e, h, m);
|
||||
@@ -43,13 +44,13 @@ fn step_h<M: Material<f32>>(
|
||||
}
|
||||
}
|
||||
|
||||
fn step_e<M: Material<f32>>(
|
||||
fn step_e<R: Real, M: Material<R>>(
|
||||
id: Vec3u,
|
||||
meta: &SerializedSimMeta,
|
||||
stimulus_e: &UnsizedArray<Vec3<f32>>,
|
||||
meta: &SerializedSimMeta<R>,
|
||||
stimulus_e: &UnsizedArray<Vec3<R>>,
|
||||
material: &UnsizedArray<M>,
|
||||
e: &mut UnsizedArray<Vec3<f32>>,
|
||||
h: &UnsizedArray<Vec3<f32>>,
|
||||
e: &mut UnsizedArray<Vec3<R>>,
|
||||
h: &UnsizedArray<Vec3<R>>,
|
||||
) {
|
||||
if id.x() < meta.dim.x() && id.y() < meta.dim.y() && id.z() < meta.dim.z() {
|
||||
let sim_state = SerializedStepE::new(meta, stimulus_e, material, e, h);
|
||||
@@ -80,19 +81,19 @@ pub fn entry_points<M: 'static>() -> Optional<(&'static str, &'static str)> {
|
||||
}
|
||||
|
||||
macro_rules! steps {
|
||||
($mat:ty, $step_h:ident, $step_e:ident) => {
|
||||
($flt:ty, $mat:ty, $step_h:ident, $step_e:ident) => {
|
||||
// LocalSize/numthreads
|
||||
#[spirv(compute(threads(4, 4, 4)))]
|
||||
pub fn $step_h(
|
||||
#[spirv(global_invocation_id)] id: glam::UVec3,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] meta: &SerializedSimMeta,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] meta: &SerializedSimMeta<$flt>,
|
||||
// XXX: delete this input?
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] _unused_stimulus_e: &UnsizedArray<Vec3<f32>>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 2)] stimulus_h: &UnsizedArray<Vec3<f32>>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] _unused_stimulus_e: &UnsizedArray<Vec3<$flt>>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 2)] stimulus_h: &UnsizedArray<Vec3<$flt>>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 3)] material: &UnsizedArray<$mat>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 4)] e: &UnsizedArray<Vec3<f32>>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 5)] h: &mut UnsizedArray<Vec3<f32>>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 6)] m: &mut UnsizedArray<Vec3<f32>>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 4)] e: &UnsizedArray<Vec3<$flt>>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 5)] h: &mut UnsizedArray<Vec3<$flt>>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 6)] m: &mut UnsizedArray<Vec3<$flt>>,
|
||||
) {
|
||||
step_h(glam_vec_to_internal(id), meta, stimulus_h, material, e, h, m)
|
||||
}
|
||||
@@ -100,20 +101,20 @@ macro_rules! steps {
|
||||
#[spirv(compute(threads(4, 4, 4)))]
|
||||
pub fn $step_e(
|
||||
#[spirv(global_invocation_id)] id: glam::UVec3,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] meta: &SerializedSimMeta,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] stimulus_e: &UnsizedArray<Vec3<f32>>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] meta: &SerializedSimMeta<$flt>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] stimulus_e: &UnsizedArray<Vec3<$flt>>,
|
||||
// XXX: delete this input?
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 2)] _unused_stimulus_h: &UnsizedArray<Vec3<f32>>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 2)] _unused_stimulus_h: &UnsizedArray<Vec3<$flt>>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 3)] material: &UnsizedArray<$mat>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 4)] e: &mut UnsizedArray<Vec3<f32>>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 5)] h: &UnsizedArray<Vec3<f32>>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 4)] e: &mut UnsizedArray<Vec3<$flt>>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 5)] h: &UnsizedArray<Vec3<$flt>>,
|
||||
// XXX: can/should this m input be deleted?
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 6)] _unused_m: &UnsizedArray<Vec3<f32>>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 6)] _unused_m: &UnsizedArray<Vec3<$flt>>,
|
||||
) {
|
||||
step_e(glam_vec_to_internal(id), meta, stimulus_e, material, e, h)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
steps!(FullyGenericMaterial<f32>, step_h_generic_material, step_e_generic_material);
|
||||
steps!(Iso3R1<f32>, step_h_iso_3r1, step_e_iso_3r1);
|
||||
steps!(f32, FullyGenericMaterial<f32>, step_h_generic_material, step_e_generic_material);
|
||||
steps!(f32, Iso3R1<f32>, step_h_iso_3r1, step_e_iso_3r1);
|
||||
|
@@ -3,43 +3,45 @@ use crate::support::{
|
||||
Array3, Array3Mut, ArrayHandle, ArrayHandleMut, Optional, UnsizedArray
|
||||
};
|
||||
use coremem_types::mat::Material;
|
||||
use coremem_types::real::{Real as _};
|
||||
use coremem_types::real::Real;
|
||||
use coremem_types::vec::{Vec3, Vec3u};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct SerializedSimMeta {
|
||||
pub struct SerializedSimMeta<R> {
|
||||
pub dim: Vec3u,
|
||||
pub inv_feature_size: f32,
|
||||
pub time_step: f32,
|
||||
pub feature_size: f32,
|
||||
pub inv_feature_size: R,
|
||||
pub time_step: R,
|
||||
pub feature_size: R,
|
||||
}
|
||||
|
||||
|
||||
/// Whatever data we received from the host in their call to step_h
|
||||
pub struct SerializedStepH<'a, M> {
|
||||
meta: &'a SerializedSimMeta,
|
||||
stimulus_h: &'a UnsizedArray<Vec3<f32>>,
|
||||
pub struct SerializedStepH<'a, R, M> {
|
||||
meta: &'a SerializedSimMeta<R>,
|
||||
stimulus_h: &'a UnsizedArray<Vec3<R>>,
|
||||
material: &'a UnsizedArray<M>,
|
||||
e: &'a UnsizedArray<Vec3<f32>>,
|
||||
h: &'a mut UnsizedArray<Vec3<f32>>,
|
||||
m: &'a mut UnsizedArray<Vec3<f32>>,
|
||||
e: &'a UnsizedArray<Vec3<R>>,
|
||||
h: &'a mut UnsizedArray<Vec3<R>>,
|
||||
m: &'a mut UnsizedArray<Vec3<R>>,
|
||||
}
|
||||
|
||||
impl<'a, M> SerializedStepH<'a, M> {
|
||||
impl<'a, R, M> SerializedStepH<'a, R, M> {
|
||||
pub fn new(
|
||||
meta: &'a SerializedSimMeta,
|
||||
stimulus_h: &'a UnsizedArray<Vec3<f32>>,
|
||||
meta: &'a SerializedSimMeta<R>,
|
||||
stimulus_h: &'a UnsizedArray<Vec3<R>>,
|
||||
material: &'a UnsizedArray<M>,
|
||||
e: &'a UnsizedArray<Vec3<f32>>,
|
||||
h: &'a mut UnsizedArray<Vec3<f32>>,
|
||||
m: &'a mut UnsizedArray<Vec3<f32>>,
|
||||
e: &'a UnsizedArray<Vec3<R>>,
|
||||
h: &'a mut UnsizedArray<Vec3<R>>,
|
||||
m: &'a mut UnsizedArray<Vec3<R>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
meta, stimulus_h, material, e, h, m
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn index(self, idx: Vec3u) -> StepHContext<'a, M> {
|
||||
impl<'a, R: Real, M> SerializedStepH<'a, R, M> {
|
||||
pub fn index(self, idx: Vec3u) -> StepHContext<'a, R, M> {
|
||||
let dim = self.meta.dim;
|
||||
let stim_h_matrix = Array3::new(self.stimulus_h, dim);
|
||||
let mat_matrix = Array3::new(self.material, dim);
|
||||
@@ -71,28 +73,30 @@ impl<'a, M> SerializedStepH<'a, M> {
|
||||
}
|
||||
|
||||
/// Whatever data we received from the host in their call to step_e
|
||||
pub struct SerializedStepE<'a, M> {
|
||||
meta: &'a SerializedSimMeta,
|
||||
stimulus_e: &'a UnsizedArray<Vec3<f32>>,
|
||||
pub struct SerializedStepE<'a, R, M> {
|
||||
meta: &'a SerializedSimMeta<R>,
|
||||
stimulus_e: &'a UnsizedArray<Vec3<R>>,
|
||||
material: &'a UnsizedArray<M>,
|
||||
e: &'a mut UnsizedArray<Vec3<f32>>,
|
||||
h: &'a UnsizedArray<Vec3<f32>>,
|
||||
e: &'a mut UnsizedArray<Vec3<R>>,
|
||||
h: &'a UnsizedArray<Vec3<R>>,
|
||||
}
|
||||
|
||||
impl<'a, M> SerializedStepE<'a, M> {
|
||||
impl<'a, R, M> SerializedStepE<'a, R, M> {
|
||||
pub fn new(
|
||||
meta: &'a SerializedSimMeta,
|
||||
stimulus_e: &'a UnsizedArray<Vec3<f32>>,
|
||||
meta: &'a SerializedSimMeta<R>,
|
||||
stimulus_e: &'a UnsizedArray<Vec3<R>>,
|
||||
material: &'a UnsizedArray<M>,
|
||||
e: &'a mut UnsizedArray<Vec3<f32>>,
|
||||
h: &'a UnsizedArray<Vec3<f32>>,
|
||||
e: &'a mut UnsizedArray<Vec3<R>>,
|
||||
h: &'a UnsizedArray<Vec3<R>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
meta, stimulus_e, material, e, h
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn index(self, idx: Vec3u) -> StepEContext<'a, M> {
|
||||
impl<'a, R: Real, M> SerializedStepE<'a, R, M> {
|
||||
pub fn index(self, idx: Vec3u) -> StepEContext<'a, R, M> {
|
||||
let dim = self.meta.dim;
|
||||
let stim_e_matrix = Array3::new(self.stimulus_e, dim);
|
||||
let mat_matrix = Array3::new(self.material, dim);
|
||||
@@ -140,16 +144,16 @@ impl<'a, M> SerializedStepE<'a, M> {
|
||||
/// Particular those at negative offsets from the midpoint.
|
||||
/// This is used in step_e when looking at the H field deltas.
|
||||
#[derive(Copy, Clone)]
|
||||
struct VolumeSampleNeg {
|
||||
mid: Vec3<f32>,
|
||||
xm1: Optional<Vec3<f32>>,
|
||||
ym1: Optional<Vec3<f32>>,
|
||||
zm1: Optional<Vec3<f32>>,
|
||||
struct VolumeSampleNeg<R> {
|
||||
mid: Vec3<R>,
|
||||
xm1: Optional<Vec3<R>>,
|
||||
ym1: Optional<Vec3<R>>,
|
||||
zm1: Optional<Vec3<R>>,
|
||||
}
|
||||
|
||||
impl VolumeSampleNeg {
|
||||
impl<R: Real> VolumeSampleNeg<R> {
|
||||
/// Calculate the delta in H values amongst this cell and its neighbors (left/up/out)
|
||||
fn delta_h(self) -> FieldDeltas {
|
||||
fn delta_h(self) -> FieldDeltas<R> {
|
||||
let mid = self.mid;
|
||||
// let (dfy_dx, dfz_dx) = self.xm1.map(|xm1| {
|
||||
// (mid.y() - xm1.y(), mid.z() - xm1.z())
|
||||
@@ -166,19 +170,19 @@ impl VolumeSampleNeg {
|
||||
let (dfy_dx, dfz_dx) = if self.xm1.is_some() {
|
||||
(mid.y() - self.xm1.unwrap().y(), mid.z() - self.xm1.unwrap().z())
|
||||
} else {
|
||||
(0.0, 0.0)
|
||||
(R::zero(), R::zero())
|
||||
};
|
||||
|
||||
let (dfx_dy, dfz_dy) = if self.ym1.is_some() {
|
||||
(mid.x() - self.ym1.unwrap().x(), mid.z() - self.ym1.unwrap().z())
|
||||
} else {
|
||||
(0.0, 0.0)
|
||||
(R::zero(), R::zero())
|
||||
};
|
||||
|
||||
let (dfx_dz, dfy_dz) = if self.zm1.is_some() {
|
||||
(mid.x() - self.zm1.unwrap().x(), mid.y() - self.zm1.unwrap().y())
|
||||
} else {
|
||||
(0.0, 0.0)
|
||||
(R::zero(), R::zero())
|
||||
};
|
||||
|
||||
FieldDeltas {
|
||||
@@ -197,16 +201,16 @@ impl VolumeSampleNeg {
|
||||
/// Particular those at positive offsets from the midpoint.
|
||||
/// This is used in step_h when looking at the E field deltas.
|
||||
#[derive(Copy, Clone)]
|
||||
struct VolumeSamplePos {
|
||||
mid: Vec3<f32>,
|
||||
xp1: Optional<Vec3<f32>>,
|
||||
yp1: Optional<Vec3<f32>>,
|
||||
zp1: Optional<Vec3<f32>>
|
||||
struct VolumeSamplePos<R> {
|
||||
mid: Vec3<R>,
|
||||
xp1: Optional<Vec3<R>>,
|
||||
yp1: Optional<Vec3<R>>,
|
||||
zp1: Optional<Vec3<R>>
|
||||
}
|
||||
|
||||
impl VolumeSamplePos {
|
||||
impl<R: Real> VolumeSamplePos<R> {
|
||||
/// Calculate the delta in E values amongst this cell and its neighbors (right/down/in)
|
||||
fn delta_e(self) -> FieldDeltas {
|
||||
fn delta_e(self) -> FieldDeltas<R> {
|
||||
let mid = self.mid;
|
||||
// let (dfy_dx, dfz_dx) = self.xp1.map(|xp1| {
|
||||
// (xp1.y() - mid.y(), xp1.z() - mid.z())
|
||||
@@ -223,19 +227,19 @@ impl VolumeSamplePos {
|
||||
let (dfy_dx, dfz_dx) = if self.xp1.is_some() {
|
||||
(self.xp1.unwrap().y() - mid.y(), self.xp1.unwrap().z() - mid.z())
|
||||
} else {
|
||||
(0.0, 0.0)
|
||||
(R::zero(), R::zero())
|
||||
};
|
||||
|
||||
let (dfx_dy, dfz_dy) = if self.yp1.is_some() {
|
||||
(self.yp1.unwrap().x() - mid.x(), self.yp1.unwrap().z() - mid.z())
|
||||
} else {
|
||||
(0.0, 0.0)
|
||||
(R::zero(), R::zero())
|
||||
};
|
||||
|
||||
let (dfx_dz, dfy_dz) = if self.zp1.is_some() {
|
||||
(self.zp1.unwrap().x() - mid.x(), self.zp1.unwrap().y() - mid.y())
|
||||
} else {
|
||||
(0.0, 0.0)
|
||||
(R::zero(), R::zero())
|
||||
};
|
||||
|
||||
FieldDeltas {
|
||||
@@ -249,17 +253,17 @@ impl VolumeSamplePos {
|
||||
}
|
||||
}
|
||||
|
||||
struct FieldDeltas {
|
||||
dfy_dx: f32,
|
||||
dfz_dx: f32,
|
||||
dfx_dy: f32,
|
||||
dfz_dy: f32,
|
||||
dfx_dz: f32,
|
||||
dfy_dz: f32,
|
||||
struct FieldDeltas<R> {
|
||||
dfy_dx: R,
|
||||
dfz_dx: R,
|
||||
dfx_dy: R,
|
||||
dfz_dy: R,
|
||||
dfx_dz: R,
|
||||
dfy_dz: R,
|
||||
}
|
||||
|
||||
impl FieldDeltas {
|
||||
fn nabla(self) -> Vec3<f32> {
|
||||
impl<R: Real> FieldDeltas<R> {
|
||||
fn nabla(self) -> Vec3<R> {
|
||||
Vec3::new(
|
||||
self.dfz_dy - self.dfy_dz,
|
||||
self.dfx_dz - self.dfz_dx,
|
||||
@@ -268,20 +272,20 @@ impl FieldDeltas {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StepEContext<'a, M> {
|
||||
inv_feature_size: f32,
|
||||
time_step: f32,
|
||||
stim_e: Vec3<f32>,
|
||||
pub struct StepEContext<'a, R, M> {
|
||||
inv_feature_size: R,
|
||||
time_step: R,
|
||||
stim_e: Vec3<R>,
|
||||
mat: ArrayHandle<'a, M>,
|
||||
/// Input field sampled near this location
|
||||
in_h: VolumeSampleNeg,
|
||||
in_h: VolumeSampleNeg<R>,
|
||||
/// Handle to the output field at one specific index.
|
||||
out_e: ArrayHandleMut<'a, Vec3<f32>>,
|
||||
out_e: ArrayHandleMut<'a, Vec3<R>>,
|
||||
}
|
||||
|
||||
impl<'a, M: Material<f32>> StepEContext<'a, M> {
|
||||
impl<'a, R: Real, M: Material<R>> StepEContext<'a, R, M> {
|
||||
pub fn step_e(mut self) {
|
||||
let twice_eps0 = f32::twice_eps0();
|
||||
let twice_eps0 = R::twice_eps0();
|
||||
let deltas = self.in_h.delta_h();
|
||||
// \nabla x H
|
||||
let nabla_h = deltas.nabla() * self.inv_feature_size;
|
||||
@@ -292,29 +296,29 @@ impl<'a, M: Material<f32>> StepEContext<'a, M> {
|
||||
let e_prev = self.out_e.get();
|
||||
let delta_e = (nabla_h - e_prev.elem_mul(sigma)).elem_div(
|
||||
sigma*self.time_step + Vec3::uniform(twice_eps0)
|
||||
)*(2.0*self.time_step);
|
||||
)*(R::two()*self.time_step);
|
||||
// println!("spirv-step_e delta_e: {:?}", delta_e);
|
||||
self.out_e.write(e_prev + delta_e + self.stim_e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct StepHContext<'a, M> {
|
||||
inv_feature_size: f32,
|
||||
time_step: f32,
|
||||
stim_h: Vec3<f32>,
|
||||
pub struct StepHContext<'a, R, M> {
|
||||
inv_feature_size: R,
|
||||
time_step: R,
|
||||
stim_h: Vec3<R>,
|
||||
mat: ArrayHandle<'a, M>,
|
||||
/// Input field sampled near this location
|
||||
in_e: VolumeSamplePos,
|
||||
in_e: VolumeSamplePos<R>,
|
||||
/// Handle to the output field at one specific index.
|
||||
out_h: ArrayHandleMut<'a, Vec3<f32>>,
|
||||
out_m: ArrayHandleMut<'a, Vec3<f32>>,
|
||||
out_h: ArrayHandleMut<'a, Vec3<R>>,
|
||||
out_m: ArrayHandleMut<'a, Vec3<R>>,
|
||||
}
|
||||
|
||||
impl<'a, M: Material<f32>> StepHContext<'a, M> {
|
||||
impl<'a, R: Real, M: Material<R>> StepHContext<'a, R, M> {
|
||||
pub fn step_h(mut self) {
|
||||
let mu0 = f32::mu0();
|
||||
let mu0_inv = f32::mu0_inv();
|
||||
let mu0 = R::mu0();
|
||||
let mu0_inv = R::mu0_inv();
|
||||
let deltas = self.in_e.delta_e();
|
||||
// println!("spirv-step_h delta_e_struct: {:?}", deltas);
|
||||
// \nabla x E
|
||||
|
Reference in New Issue
Block a user