From 847b95f036576dfc8d300b722bdb7c27b08c3a2f Mon Sep 17 00:00:00 2001 From: colin Date: Fri, 22 Jul 2022 02:56:00 -0700 Subject: [PATCH] replace the FullyGenericMaterial in spirv with an analog type from coremem_types this represents the last spirv-specific material. next steps are to start removing the materials from `coremem` itself (i.e. re-exporting more from `coremem_types::mat`). --- crates/applications/sr_latch/src/main.rs | 2 +- crates/coremem/src/driver.rs | 2 +- crates/coremem/src/mat/mod.rs | 9 +- crates/coremem/src/sim/spirv/bindings.rs | 93 ++++-------------- crates/coremem/src/sim/spirv/mod.rs | 8 +- crates/spirv_backend/src/mat.rs | 29 +----- crates/types/src/mat/compound.rs | 114 ++++++++++++++++++++++- crates/types/src/mat/conductor.rs | 17 ++++ crates/types/src/mat/mb_pgram.rs | 20 ++++ crates/types/src/mat/mod.rs | 14 ++- 10 files changed, 196 insertions(+), 112 deletions(-) diff --git a/crates/applications/sr_latch/src/main.rs b/crates/applications/sr_latch/src/main.rs index 38fe2eb..1916a86 100644 --- a/crates/applications/sr_latch/src/main.rs +++ b/crates/applications/sr_latch/src/main.rs @@ -59,7 +59,7 @@ fn main() { let coupling_region = Torus::new_xz(Meters::new(0.5*(ferro1_center + ferro2_center), ferro_center_y, half_depth), wire_coupling_major, wire_minor); let sense_region = Torus::new_xz(Meters::new(ferro2_center + ferro_major, ferro_center_y, half_depth), wire_major, wire_minor); - let mut driver: SpirvDriver = Driver::new_spirv(Meters::new(width, height, depth), feat_size); + let mut driver: SpirvDriver> = Driver::new_spirv(Meters::new(width, height, depth), feat_size); // mu_r=881.33, starting at H=25 to H=75. driver.fill_region(&ferro1_region, mat::MHPgram::new(25.0, 881.33, 44000.0)); diff --git a/crates/coremem/src/driver.rs b/crates/coremem/src/driver.rs index 6f087ab..f7f763c 100644 --- a/crates/coremem/src/driver.rs +++ b/crates/coremem/src/driver.rs @@ -36,7 +36,7 @@ pub struct Driver { } pub type CpuDriver> = Driver>; -pub type SpirvDriver = Driver>; +pub type SpirvDriver> = Driver>; impl Driver> { pub fn new(size: C, feature_size: f32) -> Self { diff --git a/crates/coremem/src/mat/mod.rs b/crates/coremem/src/mat/mod.rs index c7f0baa..a37b63b 100644 --- a/crates/coremem/src/mat/mod.rs +++ b/crates/coremem/src/mat/mod.rs @@ -13,7 +13,14 @@ mod linear; pub use bh_ferromagnet::*; pub use mb_ferromagnet::*; -pub use coremem_types::mat::{AnisomorphicConductor, Ferroxcube3R1MH, IsoConductorOr, IsomorphicConductor, MHPgram}; +pub use coremem_types::mat::{ + AnisomorphicConductor, + Ferroxcube3R1MH, + FullyGenericMaterial, + IsoConductorOr, + IsomorphicConductor, + MHPgram +}; pub use linear::*; #[enum_dispatch] diff --git a/crates/coremem/src/sim/spirv/bindings.rs b/crates/coremem/src/sim/spirv/bindings.rs index 5fd671c..5b9a64a 100644 --- a/crates/coremem/src/sim/spirv/bindings.rs +++ b/crates/coremem/src/sim/spirv/bindings.rs @@ -2,7 +2,18 @@ use serde::de::Deserializer; use serde::ser::Serializer; use serde::{Deserialize, Serialize}; -use crate::mat::{AnisomorphicConductor, IsoConductorOr, IsomorphicConductor, Ferroxcube3R1MH, MaterialExt as _, MBFerromagnet, MBPgram, MHPgram, Static}; +use crate::mat::{ + AnisomorphicConductor, + IsoConductorOr, + IsomorphicConductor, + Ferroxcube3R1MH, + FullyGenericMaterial, + MaterialExt as _, + MBFerromagnet, + MBPgram, + MHPgram, + Static +}; use crate::geom::{Index, Vec3, Vec3u}; /// hide the actual spirv backend structures inside a submodule to make their use/boundary clear. @@ -10,7 +21,6 @@ mod ffi { pub use spirv_backend::entry_points; pub use spirv_backend::sim::SerializedSimMeta; pub use spirv_backend::support::Optional; - pub use spirv_backend::mat::FullyGenericMaterial; pub use coremem_types::mat::MBPgram; } @@ -88,86 +98,19 @@ impl IntoLib for ffi::MBPgram { identity!( => MHPgram); identity!( => Ferroxcube3R1MH); +identity!( => FullyGenericMaterial); identity!(R, M, => IsoConductorOr); -#[derive(Clone, Default, PartialEq, Serialize, Deserialize)] -pub struct FullyGenericMaterial { - pub conductivity: Vec3, - pub m_b_curve: Option>, - pub m_h_curve: Option>, -} - -impl IntoFfi for FullyGenericMaterial { - type Ffi = ffi::FullyGenericMaterial; - fn into_ffi(self) -> Self::Ffi { - Self::Ffi { - conductivity: self.conductivity.into_ffi(), - m_b_curve: self.m_b_curve.into_ffi(), - m_h_curve: self.m_h_curve.into_ffi(), - } - } -} - -impl IntoLib for ffi::FullyGenericMaterial { - type Lib = FullyGenericMaterial; - fn into_lib(self) -> Self::Lib { - Self::Lib { - conductivity: self.conductivity.into_lib(), - m_b_curve: self.m_b_curve.into_lib(), - m_h_curve: self.m_h_curve.into_lib(), - } - } -} - -impl From> for FullyGenericMaterial { +// N.B.: this isn't fully correct, as Static also encodes the magnetic component +impl From> for FullyGenericMaterial { fn from(m: Static) -> Self { - FullyGenericMaterial { - conductivity: m.conductivity(), - .. Default::default() - } + AnisomorphicConductor::new(m.conductivity).into() } } -impl From> for FullyGenericMaterial { - fn from(m: AnisomorphicConductor) -> Self { - FullyGenericMaterial { - conductivity: m.conductivity(), - .. Default::default() - } - } -} - -impl From> for FullyGenericMaterial { - fn from(m: IsomorphicConductor) -> Self { - FullyGenericMaterial { - conductivity: m.conductivity(), - .. Default::default() - } - } -} - -impl From> for FullyGenericMaterial { +impl From> for FullyGenericMaterial { fn from(m: MBFerromagnet) -> Self { - FullyGenericMaterial { - m_b_curve: Some(m.curve()), - .. Default::default() - } - } -} - -impl From> for FullyGenericMaterial { - fn from(m: MHPgram) -> Self { - FullyGenericMaterial { - m_h_curve: Some(m), - .. Default::default() - } - } -} - -impl From for FullyGenericMaterial { - fn from(m: Ferroxcube3R1MH) -> Self { - let curve: MHPgram = m.into(); - curve.into() + m.curve().into_ffi().into() } } diff --git a/crates/coremem/src/sim/spirv/mod.rs b/crates/coremem/src/sim/spirv/mod.rs index 233947c..ef3f0bb 100644 --- a/crates/coremem/src/sim/spirv/mod.rs +++ b/crates/coremem/src/sim/spirv/mod.rs @@ -12,16 +12,16 @@ use crate::geom::{Coord, Index, Meters, Vec3}; use crate::real::Real as _; use crate::sim::{CellStateWithM, GenericSim, MaterialSim, Sample, SampleableSim}; use crate::stim::AbstractStimulus; -use coremem_types::mat::Material; +use coremem_types::mat::{FullyGenericMaterial, Material}; mod bindings; -pub use bindings::{entry_points, IntoFfi, IntoLib, FullyGenericMaterial, Remote, SimMeta}; +pub use bindings::{entry_points, IntoFfi, IntoLib, Remote, SimMeta}; /// Wrapper around an inner state object which offloads stepping onto a spirv backend (e.g. GPU). #[derive(Clone, Default, Serialize, Deserialize)] #[serde(bound(serialize = "M: Serialize + IntoFfi, M::Ffi: Clone + IntoLib"))] #[serde(bound(deserialize = "M: Deserialize<'de> + IntoFfi, M::Ffi: IntoLib"))] -pub struct SpirvSim +pub struct SpirvSim> where M: IntoFfi, { meta: SimMeta, @@ -70,7 +70,7 @@ impl WgpuData { impl Default for WgpuData { fn default() -> Self { - Self::new::(0) + Self::new::>(0) } } diff --git a/crates/spirv_backend/src/mat.rs b/crates/spirv_backend/src/mat.rs index 028ca6f..c41c1e0 100644 --- a/crates/spirv_backend/src/mat.rs +++ b/crates/spirv_backend/src/mat.rs @@ -1,29 +1,4 @@ -use crate::support::Optional; -use coremem_types::mat::{Material, MBPgram, MHPgram}; -use coremem_types::vec::Vec3; - - -#[derive(Copy, Clone, Default, PartialEq)] -pub struct FullyGenericMaterial { - pub conductivity: Vec3, - pub m_b_curve: Optional>, - pub m_h_curve: Optional>, -} - -impl Material for FullyGenericMaterial { - fn conductivity(&self) -> Vec3 { - self.conductivity - } - fn move_b_vec(&self, m: Vec3, target_b: Vec3) -> Vec3 { - if self.m_b_curve.is_some() { - self.m_b_curve.unwrap().move_b_vec(m, target_b) - } else if self.m_h_curve.is_some() { - self.m_h_curve.unwrap().move_b_vec(m, target_b) - } else { - Default::default() - } - } -} - +// TODO: plumb the R parameter through and remove this. +pub type FullyGenericMaterial = coremem_types::mat::FullyGenericMaterial; pub type IsoConductorOr = coremem_types::mat::IsoConductorOr; diff --git a/crates/types/src/mat/compound.rs b/crates/types/src/mat/compound.rs index 7a70d65..60d88af 100644 --- a/crates/types/src/mat/compound.rs +++ b/crates/types/src/mat/compound.rs @@ -3,7 +3,15 @@ use crate::compound::list::{Indexable, List2, List3}; use crate::compound::peano::{Peano, P0, P1, P2, P3}; use crate::real::Real; use crate::vec::Vec3; -use crate::mat::{Ferroxcube3R1MH, IsomorphicConductor, Material}; +use crate::mat::{ + AnisomorphicConductor, + Ferroxcube3R1MH, + IsomorphicConductor, + Material, + MBPgram, + MHPgram, + Vacuum, +}; #[cfg(feature = "serde")] use serde::{Serialize, Deserialize}; @@ -13,7 +21,7 @@ use serde::{Serialize, Deserialize}; /// (i.e. that it implements DiscriminantCodable). #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[cfg_attr(feature = "fmt", derive(Debug))] -#[derive(Clone, Default, PartialEq)] +#[derive(Copy, Clone, Default, PartialEq)] pub struct DiscrMat(Enum<(), Mats>); pub type DiscrMat2 = DiscrMat>; pub type DiscrMat3 = DiscrMat>; @@ -36,6 +44,7 @@ impl DiscrMat { } } +/// invokes Material::conductivity on any Material struct ConductivityDispatcher; impl> VariantHandler> for ConductivityDispatcher { fn call(self, v: T) -> Vec3 { @@ -43,6 +52,7 @@ impl> VariantHandler> for Conduc } } +/// invokes Material::move_b_vec on any Material struct MoveBVecDispatcher { m: Vec3, target_b: Vec3, @@ -80,6 +90,7 @@ where } } +/// represents a Material which is either an isomorphic conductor, or some other Material `M1` pub type IsoConductorOr = DiscrMat2, M1>; // XXX: can't do this for generic M, because that creates duplicate `From` impls for the @@ -95,6 +106,105 @@ impl From> for IsoConductorOr { + conductor: C, + magnetic: M, +} + +impl DualMaterial { + pub fn new(conductor: C, magnetic: M) -> Self { + Self { conductor, magnetic } + } +} + +impl, M: Material> Material for DualMaterial { + fn conductivity(&self) -> Vec3 { + self.conductor.conductivity() + } + fn move_b_vec(&self, m: Vec3, target_b: Vec3) -> Vec3 { + self.magnetic.move_b_vec(m, target_b) + } +} + +/// Material which can encode any of the well-known magnetic materials (or Vacuum) +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +#[cfg_attr(feature = "fmt", derive(Debug))] +#[derive(Copy, Clone, PartialEq)] +pub struct GenericMagnetic(DiscrMat3, MHPgram, Vacuum>); + +impl Default for GenericMagnetic { + fn default() -> Self { + // N.B.: the default is not the first variant. + // we order the variants specifically so that the first one can store the descriminant, but + // we NEED Vacuum to be the default. + Vacuum.into() + } +} + +impl Material for GenericMagnetic { + fn conductivity(&self) -> Vec3 { + self.0.conductivity() + } + fn move_b_vec(&self, m: Vec3, target_b: Vec3) -> Vec3 { + self.0.move_b_vec(m, target_b) + } +} + +impl From> for GenericMagnetic { + fn from(mat: MBPgram) -> Self { + GenericMagnetic(DiscrMat3::new::(mat)) + } +} +impl From> for GenericMagnetic { + fn from(mat: MHPgram) -> Self { + GenericMagnetic(DiscrMat3::new::(mat)) + } +} +impl From for GenericMagnetic { + fn from(mat: Vacuum) -> Self { + GenericMagnetic(DiscrMat3::new::(mat)) + } +} + +/// "Fully Generic" in that one can set both the conductivity, +/// and set any of the well-known magnetic materials, simultaneously. +pub type FullyGenericMaterial = DualMaterial< + AnisomorphicConductor, + GenericMagnetic, +>; + +impl From> for FullyGenericMaterial { + fn from(mat: AnisomorphicConductor) -> Self { + Self::new(mat, Default::default()) + } +} +impl From> for FullyGenericMaterial { + fn from(mat: MBPgram) -> Self { + Self::new(Default::default(), mat.into()) + } +} +impl From> for FullyGenericMaterial { + fn from(mat: MHPgram) -> Self { + Self::new(Default::default(), mat.into()) + } +} +impl From> for FullyGenericMaterial { + fn from(mat: IsomorphicConductor) -> Self { + let mat: AnisomorphicConductor = mat.into(); + mat.into() + } +} +impl From for FullyGenericMaterial { + fn from(mat: Ferroxcube3R1MH) -> Self { + let mat: MHPgram = mat.into(); + mat.into() + } +} + #[cfg(test)] mod test { use super::*; diff --git a/crates/types/src/mat/conductor.rs b/crates/types/src/mat/conductor.rs index 6a2dc8d..a3ee51c 100644 --- a/crates/types/src/mat/conductor.rs +++ b/crates/types/src/mat/conductor.rs @@ -50,6 +50,23 @@ impl Material for IsomorphicConductor { } } +impl DiscriminantCodable

for AnisomorphicConductor { + fn decode_discr(&self) -> Discr

{ + let cond = self.conductivity().x(); + let d = if cond < R::zero() { + (-cond.to_f32()) as u32 + } else { + 0 + }; + Discr::new(d) + } + fn encode_discr(d: Discr

) -> Self { + Self::new(Vec3::new_x( + R::from_primitive(-(d.value() as i32)) + )) + } +} + impl DiscriminantCodable

for IsomorphicConductor { fn decode_discr(&self) -> Discr

{ let cond = self.iso_conductivity(); diff --git a/crates/types/src/mat/mb_pgram.rs b/crates/types/src/mat/mb_pgram.rs index 2ff9bf3..079aaf2 100644 --- a/crates/types/src/mat/mb_pgram.rs +++ b/crates/types/src/mat/mb_pgram.rs @@ -1,3 +1,5 @@ +use crate::compound::enumerated::{Discr, DiscriminantCodable}; +use crate::compound::peano::Peano; use crate::mat::Material; use crate::real::Real; use crate::vec::Vec3; @@ -67,6 +69,24 @@ impl Material for MBPgram { } } +impl DiscriminantCodable

for MBPgram { + fn decode_discr(&self) -> Discr

{ + let max_m = self.max_m; + let d = if max_m < R::zero() { + (-max_m.to_f32()) as u32 + } else { + 0 + }; + Discr::new(d) + } + fn encode_discr(d: Discr

) -> Self { + Self { + max_m: R::from_primitive(-(d.value() as i32)), + ..Default::default() + } + } +} + #[cfg(test)] mod test { diff --git a/crates/types/src/mat/mod.rs b/crates/types/src/mat/mod.rs index ed9d2e5..23cdbdf 100644 --- a/crates/types/src/mat/mod.rs +++ b/crates/types/src/mat/mod.rs @@ -5,11 +5,15 @@ mod compound; mod conductor; mod mb_pgram; mod mh_pgram; -pub use compound::IsoConductorOr; +pub use compound::{FullyGenericMaterial, IsoConductorOr}; pub use conductor::{AnisomorphicConductor, IsomorphicConductor}; pub use mb_pgram::MBPgram; pub use mh_pgram::{Ferroxcube3R1MH, MHPgram}; + +#[cfg(feature = "serde")] +use serde::{Serialize, Deserialize}; + pub trait Material: Sized { fn conductivity(&self) -> Vec3 { Default::default() @@ -21,3 +25,11 @@ pub trait Material: Sized { m } } + +/// Default, non-interesting Material. +/// has 0 conductivity (electrical and magnetic) +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +#[cfg_attr(feature = "fmt", derive(Debug))] +#[derive(Copy, Clone, Default, PartialEq)] +pub struct Vacuum; +impl Material for Vacuum {}