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`).
This commit is contained in:
colin 2022-07-22 02:56:00 -07:00
parent 4cbcc46d50
commit 847b95f036
10 changed files with 196 additions and 112 deletions

View File

@ -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<spirv::FullyGenericMaterial> = Driver::new_spirv(Meters::new(width, height, depth), feat_size);
let mut driver: SpirvDriver<mat::FullyGenericMaterial<f32>> = 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));

View File

@ -36,7 +36,7 @@ pub struct Driver<S=SimState> {
}
pub type CpuDriver<R=real::R32, M=mat::GenericMaterial<R>> = Driver<SimState<R, M>>;
pub type SpirvDriver<M=spirv::FullyGenericMaterial> = Driver<SpirvSim<M>>;
pub type SpirvDriver<M=mat::FullyGenericMaterial<f32>> = Driver<SpirvSim<M>>;
impl<R: Real, M: Default> Driver<SimState<R, M>> {
pub fn new<C: Coord>(size: C, feature_size: f32) -> Self {

View File

@ -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]

View File

@ -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<f32> {
identity!( => MHPgram<f32>);
identity!( => Ferroxcube3R1MH);
identity!( => FullyGenericMaterial<f32>);
identity!(R, M, => IsoConductorOr<R, M>);
#[derive(Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct FullyGenericMaterial {
pub conductivity: Vec3<f32>,
pub m_b_curve: Option<MBPgram<f32>>,
pub m_h_curve: Option<MHPgram<f32>>,
}
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<Static<f32>> for FullyGenericMaterial {
// N.B.: this isn't fully correct, as Static also encodes the magnetic component
impl From<Static<f32>> for FullyGenericMaterial<f32> {
fn from(m: Static<f32>) -> Self {
FullyGenericMaterial {
conductivity: m.conductivity(),
.. Default::default()
}
AnisomorphicConductor::new(m.conductivity).into()
}
}
impl From<AnisomorphicConductor<f32>> for FullyGenericMaterial {
fn from(m: AnisomorphicConductor<f32>) -> Self {
FullyGenericMaterial {
conductivity: m.conductivity(),
.. Default::default()
}
}
}
impl From<IsomorphicConductor<f32>> for FullyGenericMaterial {
fn from(m: IsomorphicConductor<f32>) -> Self {
FullyGenericMaterial {
conductivity: m.conductivity(),
.. Default::default()
}
}
}
impl From<MBFerromagnet<f32>> for FullyGenericMaterial {
impl From<MBFerromagnet<f32>> for FullyGenericMaterial<f32> {
fn from(m: MBFerromagnet<f32>) -> Self {
FullyGenericMaterial {
m_b_curve: Some(m.curve()),
.. Default::default()
}
}
}
impl From<MHPgram<f32>> for FullyGenericMaterial {
fn from(m: MHPgram<f32>) -> Self {
FullyGenericMaterial {
m_h_curve: Some(m),
.. Default::default()
}
}
}
impl From<Ferroxcube3R1MH> for FullyGenericMaterial {
fn from(m: Ferroxcube3R1MH) -> Self {
let curve: MHPgram<f32> = m.into();
curve.into()
m.curve().into_ffi().into()
}
}

View File

@ -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<Lib=M>"))]
#[serde(bound(deserialize = "M: Deserialize<'de> + IntoFfi, M::Ffi: IntoLib<Lib=M>"))]
pub struct SpirvSim<M=FullyGenericMaterial>
pub struct SpirvSim<M=FullyGenericMaterial<f32>>
where M: IntoFfi,
{
meta: SimMeta,
@ -70,7 +70,7 @@ impl WgpuData {
impl Default for WgpuData {
fn default() -> Self {
Self::new::<FullyGenericMaterial>(0)
Self::new::<FullyGenericMaterial<f32>>(0)
}
}

View File

@ -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<f32>,
pub m_b_curve: Optional<MBPgram<f32>>,
pub m_h_curve: Optional<MHPgram<f32>>,
}
impl Material<f32> for FullyGenericMaterial {
fn conductivity(&self) -> Vec3<f32> {
self.conductivity
}
fn move_b_vec(&self, m: Vec3<f32>, target_b: Vec3<f32>) -> Vec3<f32> {
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<f32>;
pub type IsoConductorOr<M> = coremem_types::mat::IsoConductorOr<f32, M>;

View File

@ -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<Mats>(Enum<(), Mats>);
pub type DiscrMat2<M0, M1> = DiscrMat<List2<M0, M1>>;
pub type DiscrMat3<M0, M1, M2> = DiscrMat<List3<M0, M1, M2>>;
@ -36,6 +44,7 @@ impl<Mats: Default> DiscrMat<Mats> {
}
}
/// invokes Material::conductivity on any Material
struct ConductivityDispatcher;
impl<P: Peano, R: Real, T: Material<R>> VariantHandler<P, T, Vec3<R>> for ConductivityDispatcher {
fn call(self, v: T) -> Vec3<R> {
@ -43,6 +52,7 @@ impl<P: Peano, R: Real, T: Material<R>> VariantHandler<P, T, Vec3<R>> for Conduc
}
}
/// invokes Material::move_b_vec on any Material
struct MoveBVecDispatcher<R> {
m: Vec3<R>,
target_b: Vec3<R>,
@ -80,6 +90,7 @@ where
}
}
/// represents a Material which is either an isomorphic conductor, or some other Material `M1`
pub type IsoConductorOr<R, M1> = DiscrMat2<IsomorphicConductor<R>, M1>;
// XXX: can't do this for generic M, because that creates duplicate `From` impls for the
@ -95,6 +106,105 @@ impl<R: Real> From<IsomorphicConductor<R>> for IsoConductorOr<R, Ferroxcube3R1MH
}
}
/// muxes operations to either the conductor or the magnetic material
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[cfg_attr(feature = "fmt", derive(Debug))]
#[derive(Copy, Clone, Default, PartialEq)]
pub struct DualMaterial<C, M> {
conductor: C,
magnetic: M,
}
impl<C, M> DualMaterial<C, M> {
pub fn new(conductor: C, magnetic: M) -> Self {
Self { conductor, magnetic }
}
}
impl<R: Real, C: Material<R>, M: Material<R>> Material<R> for DualMaterial<C, M> {
fn conductivity(&self) -> Vec3<R> {
self.conductor.conductivity()
}
fn move_b_vec(&self, m: Vec3<R>, target_b: Vec3<R>) -> Vec3<R> {
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<R>(DiscrMat3<MBPgram<R>, MHPgram<R>, Vacuum>);
impl<R: Real> Default for GenericMagnetic<R> {
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<R: Real> Material<R> for GenericMagnetic<R> {
fn conductivity(&self) -> Vec3<R> {
self.0.conductivity()
}
fn move_b_vec(&self, m: Vec3<R>, target_b: Vec3<R>) -> Vec3<R> {
self.0.move_b_vec(m, target_b)
}
}
impl<R: Real> From<MBPgram<R>> for GenericMagnetic<R> {
fn from(mat: MBPgram<R>) -> Self {
GenericMagnetic(DiscrMat3::new::<P0>(mat))
}
}
impl<R: Real> From<MHPgram<R>> for GenericMagnetic<R> {
fn from(mat: MHPgram<R>) -> Self {
GenericMagnetic(DiscrMat3::new::<P1>(mat))
}
}
impl<R: Real> From<Vacuum> for GenericMagnetic<R> {
fn from(mat: Vacuum) -> Self {
GenericMagnetic(DiscrMat3::new::<P2>(mat))
}
}
/// "Fully Generic" in that one can set both the conductivity,
/// and set any of the well-known magnetic materials, simultaneously.
pub type FullyGenericMaterial<R> = DualMaterial<
AnisomorphicConductor<R>,
GenericMagnetic<R>,
>;
impl<R: Real> From<AnisomorphicConductor<R>> for FullyGenericMaterial<R> {
fn from(mat: AnisomorphicConductor<R>) -> Self {
Self::new(mat, Default::default())
}
}
impl<R: Real> From<MBPgram<R>> for FullyGenericMaterial<R> {
fn from(mat: MBPgram<R>) -> Self {
Self::new(Default::default(), mat.into())
}
}
impl<R: Real> From<MHPgram<R>> for FullyGenericMaterial<R> {
fn from(mat: MHPgram<R>) -> Self {
Self::new(Default::default(), mat.into())
}
}
impl<R: Real> From<IsomorphicConductor<R>> for FullyGenericMaterial<R> {
fn from(mat: IsomorphicConductor<R>) -> Self {
let mat: AnisomorphicConductor<R> = mat.into();
mat.into()
}
}
impl<R: Real> From<Ferroxcube3R1MH> for FullyGenericMaterial<R> {
fn from(mat: Ferroxcube3R1MH) -> Self {
let mat: MHPgram<R> = mat.into();
mat.into()
}
}
#[cfg(test)]
mod test {
use super::*;

View File

@ -50,6 +50,23 @@ impl<R: Real> Material<R> for IsomorphicConductor<R> {
}
}
impl<R: Real, P: Peano> DiscriminantCodable<P> for AnisomorphicConductor<R> {
fn decode_discr(&self) -> Discr<P> {
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<P>) -> Self {
Self::new(Vec3::new_x(
R::from_primitive(-(d.value() as i32))
))
}
}
impl<R: Real, P: Peano> DiscriminantCodable<P> for IsomorphicConductor<R> {
fn decode_discr(&self) -> Discr<P> {
let cond = self.iso_conductivity();

View File

@ -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<R: Real> Material<R> for MBPgram<R> {
}
}
impl<R: Real, P: Peano> DiscriminantCodable<P> for MBPgram<R> {
fn decode_discr(&self) -> Discr<P> {
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<P>) -> Self {
Self {
max_m: R::from_primitive(-(d.value() as i32)),
..Default::default()
}
}
}
#[cfg(test)]
mod test {

View File

@ -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<R: Real>: Sized {
fn conductivity(&self) -> Vec3<R> {
Default::default()
@ -21,3 +25,11 @@ pub trait Material<R: Real>: 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<R: Real> Material<R> for Vacuum {}