this solves an issue in the Nix build, where managing multiple Cargo.lock files is otherwise tricky. it causes (or fails to fix?) an adjacent issue where the spirv builder doesn't seem to have everything it needs vendored.
315 lines
9.7 KiB
Rust
315 lines
9.7 KiB
Rust
use crate::CellState;
|
|
use crate::geom::Vec3;
|
|
use crate::real::Real;
|
|
use crate::sim::{PmlParameters, PmlState, StepParameters, StepParametersMut};
|
|
|
|
use enum_dispatch::enum_dispatch;
|
|
use serde::{Serialize, Deserialize};
|
|
|
|
pub mod db;
|
|
mod bh_ferromagnet;
|
|
mod mb_ferromagnet;
|
|
mod mh_ferromagnet;
|
|
mod linear;
|
|
|
|
pub use bh_ferromagnet::*;
|
|
pub use mb_ferromagnet::*;
|
|
pub use mh_ferromagnet::*;
|
|
pub use linear::*;
|
|
|
|
#[enum_dispatch]
|
|
pub trait Material<R: Real> {
|
|
fn step_parameters_mut<'a>(&'a mut self) -> StepParametersMut<'a, R> {
|
|
// by default, behave as a vacuum
|
|
StepParametersMut::default()
|
|
}
|
|
/// Return the magnetization.
|
|
fn m(&self) -> Vec3<R> {
|
|
Vec3::zero()
|
|
}
|
|
/// Called just before magnetic field is updated. Optionally change any internal state (e.g. magnetization).
|
|
fn step_b(&mut self, _context: &CellState<R>, _delta_b: Vec3<R>) {
|
|
}
|
|
}
|
|
|
|
pub trait MaterialExt<R> {
|
|
fn step_parameters<'a>(&'a self) -> StepParameters<'a, R>;
|
|
fn conductivity(&self) -> Vec3<R>;
|
|
}
|
|
|
|
impl<R: Real, M: Material<R>> MaterialExt<R> for M {
|
|
fn step_parameters<'a>(&'a self) -> StepParameters<'a, R> {
|
|
unsafe { &mut *(self as *const M as *mut M) }.step_parameters_mut().into()
|
|
}
|
|
fn conductivity(&self) -> Vec3<R> {
|
|
self.step_parameters().conductivity()
|
|
}
|
|
}
|
|
|
|
/// Capable of capturing all field-related information about a material at any
|
|
/// snapshot moment-in-time. Useful for serializing state.
|
|
#[derive(Clone, Default, PartialEq, Serialize, Deserialize)]
|
|
pub struct Static<R> {
|
|
pub conductivity: Vec3<R>,
|
|
// pub pml: Option<(PmlState, PmlParameters)>,
|
|
pub m: Vec3<R>,
|
|
}
|
|
|
|
impl<R: Real> Static<R> {
|
|
pub fn from_material<M: Material<R>>(m: &M) -> Self {
|
|
let p = m.step_parameters();
|
|
Self {
|
|
conductivity: p.conductivity(),
|
|
// pml: p.pml().map(|(s, p)| (*s, p)),
|
|
m: m.m(),
|
|
}
|
|
}
|
|
|
|
// pub fn from_pml(pseudo_conductivity: Vec3<flt::Real>) -> Self {
|
|
// Self::from_material(&Pml::new(pseudo_conductivity))
|
|
// }
|
|
}
|
|
|
|
impl<R: Real> Material<R> for Static<R> {
|
|
fn step_parameters_mut<'a>(&'a mut self) -> StepParametersMut<'a, R> {
|
|
StepParametersMut::new(
|
|
self.conductivity,
|
|
None, // self.pml.as_mut().map(|(s, p)| (s, *p)),
|
|
)
|
|
}
|
|
fn m(&self) -> Vec3<R> {
|
|
self.m
|
|
}
|
|
}
|
|
|
|
impl<R: Real, T> From<T> for Static<R>
|
|
where T: Into<GenericMaterial<R>>
|
|
{
|
|
fn from(mat: T) -> Self {
|
|
let generic = mat.into();
|
|
Self::from_material(&generic)
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Default, PartialEq, Serialize, Deserialize)]
|
|
pub struct Pml<R>(PmlState<R>, PmlParameters<R>);
|
|
|
|
impl<R: Real> Pml<R> {
|
|
pub fn new<R2: Real>(pseudo_conductivity: Vec3<R2>) -> Self {
|
|
Self(PmlState::new(), PmlParameters::new(pseudo_conductivity))
|
|
}
|
|
}
|
|
|
|
impl<R: Real> Material<R> for Pml<R> {
|
|
fn step_parameters_mut<'a>(&'a mut self) -> StepParametersMut<'a, R> {
|
|
StepParametersMut::default().with_pml(&mut self.0, self.1)
|
|
}
|
|
}
|
|
|
|
|
|
// #[enum_dispatch(Material)]
|
|
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
|
pub enum GenericMaterial<R> {
|
|
Conductor(AnisomorphicConductor<R>),
|
|
LinearMagnet(LinearMagnet<R>),
|
|
Pml(Pml<R>),
|
|
MBFerromagnet(MBFerromagnet<R>),
|
|
Ferroxcube3R1(Ferroxcube3R1<R>),
|
|
MinimalSquare(MinimalSquare<R>),
|
|
}
|
|
|
|
impl<R: Real> Default for GenericMaterial<R> {
|
|
fn default() -> Self {
|
|
Self::Conductor(Default::default())
|
|
}
|
|
}
|
|
|
|
impl<R> From<AnisomorphicConductor<R>> for GenericMaterial<R> {
|
|
fn from(inner: AnisomorphicConductor<R>) -> Self {
|
|
Self::Conductor(inner)
|
|
}
|
|
}
|
|
|
|
impl<R: Real, V: Real> From<IsomorphicConductor<V>> for GenericMaterial<R> {
|
|
fn from(inner: IsomorphicConductor<V>) -> Self {
|
|
let iso_r = IsomorphicConductor::new(inner.conductivity.cast::<R>());
|
|
Self::Conductor(iso_r.into())
|
|
}
|
|
}
|
|
|
|
impl<R> From<LinearMagnet<R>> for GenericMaterial<R> {
|
|
fn from(inner: LinearMagnet<R>) -> Self {
|
|
Self::LinearMagnet(inner)
|
|
}
|
|
}
|
|
|
|
impl<R> From<Pml<R>> for GenericMaterial<R> {
|
|
fn from(inner: Pml<R>) -> Self {
|
|
Self::Pml(inner)
|
|
}
|
|
}
|
|
|
|
impl<R> From<MBFerromagnet<R>> for GenericMaterial<R> {
|
|
fn from(inner: MBFerromagnet<R>) -> Self {
|
|
Self::MBFerromagnet(inner)
|
|
}
|
|
}
|
|
|
|
impl<R> From<Ferroxcube3R1<R>> for GenericMaterial<R> {
|
|
fn from(inner: Ferroxcube3R1<R>) -> Self {
|
|
Self::Ferroxcube3R1(inner)
|
|
}
|
|
}
|
|
|
|
impl<R> From<MinimalSquare<R>> for GenericMaterial<R> {
|
|
fn from(inner: MinimalSquare<R>) -> Self {
|
|
Self::MinimalSquare(inner)
|
|
}
|
|
}
|
|
|
|
impl<R: Real> Material<R> for GenericMaterial<R> {
|
|
fn step_parameters_mut<'a>(&'a mut self) -> StepParametersMut<'a, R> {
|
|
use GenericMaterial::*;
|
|
match self {
|
|
Conductor(inner) => inner.step_parameters_mut(),
|
|
LinearMagnet(inner) => inner.step_parameters_mut(),
|
|
Pml(inner) => inner.step_parameters_mut(),
|
|
MBFerromagnet(inner) => inner.step_parameters_mut(),
|
|
Ferroxcube3R1(inner) => inner.step_parameters_mut(),
|
|
MinimalSquare(inner) => inner.step_parameters_mut(),
|
|
}
|
|
}
|
|
/// Return the magnetization.
|
|
fn m(&self) -> Vec3<R> {
|
|
use GenericMaterial::*;
|
|
match self {
|
|
Conductor(inner) => inner.m(),
|
|
LinearMagnet(inner) => inner.m(),
|
|
Pml(inner) => inner.m(),
|
|
MBFerromagnet(inner) => inner.m(),
|
|
Ferroxcube3R1(inner) => Material::m(inner),
|
|
MinimalSquare(inner) => Material::m(inner),
|
|
}
|
|
}
|
|
/// Called just before magnetic field is updated. Optionally change any internal state (e.g. magnetization).
|
|
fn step_b(&mut self, context: &CellState<R>, delta_b: Vec3<R>) {
|
|
use GenericMaterial::*;
|
|
match self {
|
|
Conductor(inner) => inner.step_b(context, delta_b),
|
|
LinearMagnet(inner) => inner.step_b(context, delta_b),
|
|
Pml(inner) => inner.step_b(context, delta_b),
|
|
MBFerromagnet(inner) => inner.step_b(context, delta_b),
|
|
Ferroxcube3R1(inner) => inner.step_b(context, delta_b),
|
|
MinimalSquare(inner) => inner.step_b(context, delta_b),
|
|
}
|
|
}
|
|
}
|
|
|
|
// #[enum_dispatch(Material)]
|
|
#[derive(Clone, Serialize, Deserialize)]
|
|
pub enum GenericMaterialNoPml<R> {
|
|
Conductor(Conductor<R>),
|
|
LinearMagnet(LinearMagnet<R>),
|
|
MBFerromagnet(MBFerromagnet<R>),
|
|
Ferroxcube3R1(Ferroxcube3R1<R>),
|
|
MinimalSquare(MinimalSquare<R>),
|
|
}
|
|
|
|
impl<R: Real> Default for GenericMaterialNoPml<R> {
|
|
fn default() -> Self {
|
|
Conductor::default().into()
|
|
}
|
|
}
|
|
|
|
impl<R> From<Conductor<R>> for GenericMaterialNoPml<R> {
|
|
fn from(inner: Conductor<R>) -> Self {
|
|
Self::Conductor(inner)
|
|
}
|
|
}
|
|
|
|
impl<R: Real> Material<R> for GenericMaterialNoPml<R> {
|
|
fn step_parameters_mut<'a>(&'a mut self) -> StepParametersMut<'a, R> {
|
|
use GenericMaterialNoPml::*;
|
|
match self {
|
|
Conductor(inner) => inner.step_parameters_mut(),
|
|
LinearMagnet(inner) => inner.step_parameters_mut(),
|
|
MBFerromagnet(inner) => inner.step_parameters_mut(),
|
|
Ferroxcube3R1(inner) => inner.step_parameters_mut(),
|
|
MinimalSquare(inner) => inner.step_parameters_mut(),
|
|
}
|
|
}
|
|
/// Return the magnetization.
|
|
fn m(&self) -> Vec3<R> {
|
|
use GenericMaterialNoPml::*;
|
|
match self {
|
|
Conductor(inner) => inner.m(),
|
|
LinearMagnet(inner) => inner.m(),
|
|
MBFerromagnet(inner) => inner.m(),
|
|
Ferroxcube3R1(inner) => Material::m(inner),
|
|
MinimalSquare(inner) => Material::m(inner),
|
|
}
|
|
}
|
|
/// Called just before magnetic field is updated. Optionally change any internal state (e.g. magnetization).
|
|
fn step_b(&mut self, context: &CellState<R>, delta_b: Vec3<R>) {
|
|
use GenericMaterialNoPml::*;
|
|
match self {
|
|
Conductor(inner) => inner.step_b(context, delta_b),
|
|
LinearMagnet(inner) => inner.step_b(context, delta_b),
|
|
MBFerromagnet(inner) => inner.step_b(context, delta_b),
|
|
Ferroxcube3R1(inner) => inner.step_b(context, delta_b),
|
|
MinimalSquare(inner) => inner.step_b(context, delta_b),
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// Materials which have only 1 Vec3.
|
|
// #[enum_dispatch(Material)]
|
|
#[derive(Clone, Serialize, Deserialize)]
|
|
pub enum GenericMaterialOneField<R> {
|
|
Conductor(Conductor<R>),
|
|
Ferroxcube3R1(Ferroxcube3R1<R>),
|
|
MinimalSquare(MinimalSquare<R>),
|
|
}
|
|
|
|
impl<R: Real> Default for GenericMaterialOneField<R> {
|
|
fn default() -> Self {
|
|
Conductor::default().into()
|
|
}
|
|
}
|
|
|
|
impl<R> From<Conductor<R>> for GenericMaterialOneField<R> {
|
|
fn from(inner: Conductor<R>) -> Self {
|
|
Self::Conductor(inner)
|
|
}
|
|
}
|
|
|
|
impl<R: Real> Material<R> for GenericMaterialOneField<R> {
|
|
fn step_parameters_mut<'a>(&'a mut self) -> StepParametersMut<'a, R> {
|
|
use GenericMaterialOneField::*;
|
|
match self {
|
|
Conductor(inner) => inner.step_parameters_mut(),
|
|
Ferroxcube3R1(inner) => inner.step_parameters_mut(),
|
|
MinimalSquare(inner) => inner.step_parameters_mut(),
|
|
}
|
|
}
|
|
/// Return the magnetization.
|
|
fn m(&self) -> Vec3<R> {
|
|
use GenericMaterialOneField::*;
|
|
match self {
|
|
Conductor(inner) => inner.m(),
|
|
Ferroxcube3R1(inner) => Material::m(inner),
|
|
MinimalSquare(inner) => Material::m(inner),
|
|
}
|
|
}
|
|
/// Called just before magnetic field is updated. Optionally change any internal state (e.g. magnetization).
|
|
fn step_b(&mut self, context: &CellState<R>, delta_b: Vec3<R>) {
|
|
use GenericMaterialOneField::*;
|
|
match self {
|
|
Conductor(inner) => inner.step_b(context, delta_b),
|
|
Ferroxcube3R1(inner) => inner.step_b(context, delta_b),
|
|
MinimalSquare(inner) => inner.step_b(context, delta_b),
|
|
}
|
|
}
|
|
}
|