Allow conductivity to be specified as a vector
This is necessary to implement UPML boundary conditions
This commit is contained in:
@@ -3,20 +3,29 @@ use coremem::geom::Point;
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
coremem::init_logging();
|
coremem::init_logging();
|
||||||
let width = 700;
|
let feat_size = 20e-6; // feature size
|
||||||
let buffer = 80;
|
let from_m = |m| (m/feat_size) as u32;
|
||||||
let feat_size = 1e-5; // feature size
|
let to_um = |px| px * (feat_size*1e6) as u32;
|
||||||
|
let width = from_m(8000e-6);
|
||||||
|
let conductor_inner_rad = from_m(0e-6);
|
||||||
|
let conductor_outer_rad = from_m(200e-6);
|
||||||
|
let ferro_inner_rad = from_m(200e-6);
|
||||||
|
let ferro_outer_rad = from_m(300e-6);
|
||||||
|
let buffer = from_m(800e-6);
|
||||||
let peak_current = 2.5e6;
|
let peak_current = 2.5e6;
|
||||||
let conductivity = 1.0e5;
|
let conductivity = 1.0e5;
|
||||||
let ferro_inner_rad = 60;
|
|
||||||
let ferro_outer_rad = 150;
|
|
||||||
let conductor_inner_rad = 0;
|
|
||||||
let conductor_outer_rad = 50;
|
|
||||||
let half_width = width / 2;
|
let half_width = width / 2;
|
||||||
let mut driver = Driver::new(width, width, feat_size);
|
let mut driver = Driver::new(width, width, feat_size);
|
||||||
driver.set_steps_per_frame(8);
|
//driver.set_steps_per_frame(8);
|
||||||
//driver.set_steps_per_frame(40);
|
//driver.set_steps_per_frame(40);
|
||||||
driver.add_y4m_renderer("toroid25d.y4m");
|
driver.set_steps_per_frame(200);
|
||||||
|
driver.add_y4m_renderer(&*format!("-toroid25d-feat{}um-{}A--radii{}um-{}um-{}um.y4m",
|
||||||
|
(feat_size * 1e6) as u32,
|
||||||
|
peak_current as u32,
|
||||||
|
to_um(conductor_outer_rad),
|
||||||
|
to_um(ferro_inner_rad),
|
||||||
|
to_um(ferro_outer_rad),
|
||||||
|
));
|
||||||
// driver.add_term_renderer();
|
// driver.add_term_renderer();
|
||||||
driver.add_measurement(meas::Label(format!("Conductivity: {}, Imax: {:.2e}", conductivity, peak_current)));
|
driver.add_measurement(meas::Label(format!("Conductivity: {}, Imax: {:.2e}", conductivity, peak_current)));
|
||||||
driver.add_measurement(meas::Current(half_width + (conductor_inner_rad + conductor_outer_rad) / 2, half_width));
|
driver.add_measurement(meas::Current(half_width + (conductor_inner_rad + conductor_outer_rad) / 2, half_width));
|
||||||
|
@@ -12,6 +12,7 @@ pub struct Driver {
|
|||||||
renderer: MultiRenderer,
|
renderer: MultiRenderer,
|
||||||
steps_per_frame: u64,
|
steps_per_frame: u64,
|
||||||
time_spent_stepping: Duration,
|
time_spent_stepping: Duration,
|
||||||
|
time_spent_rendering: Duration,
|
||||||
measurements: Vec<Box<dyn AbstractMeasurement>>,
|
measurements: Vec<Box<dyn AbstractMeasurement>>,
|
||||||
start_time: SystemTime,
|
start_time: SystemTime,
|
||||||
}
|
}
|
||||||
@@ -23,6 +24,7 @@ impl Driver {
|
|||||||
renderer: Default::default(),
|
renderer: Default::default(),
|
||||||
steps_per_frame: 1,
|
steps_per_frame: 1,
|
||||||
time_spent_stepping: Default::default(),
|
time_spent_stepping: Default::default(),
|
||||||
|
time_spent_rendering: Default::default(),
|
||||||
measurements: vec![Box::new(meas::Time), Box::new(meas::Meta), Box::new(meas::Energy)],
|
measurements: vec![Box::new(meas::Time), Box::new(meas::Meta), Box::new(meas::Energy)],
|
||||||
start_time: SystemTime::now(),
|
start_time: SystemTime::now(),
|
||||||
}
|
}
|
||||||
@@ -71,22 +73,34 @@ impl Driver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn step(&mut self) {
|
pub fn step(&mut self) {
|
||||||
let start_time = SystemTime::now();
|
|
||||||
if self.state.step_no() % self.steps_per_frame == 0 {
|
if self.state.step_no() % self.steps_per_frame == 0 {
|
||||||
trace!("render begin");
|
trace!("render begin");
|
||||||
|
let start_time = SystemTime::now();
|
||||||
self.renderer.render(&self.state, &*self.measurements);
|
self.renderer.render(&self.state, &*self.measurements);
|
||||||
|
self.time_spent_rendering += start_time.elapsed().unwrap();
|
||||||
trace!("render end");
|
trace!("render end");
|
||||||
}
|
}
|
||||||
trace!("step begin");
|
trace!("step begin");
|
||||||
|
let start_time = SystemTime::now();
|
||||||
self.state.step();
|
self.state.step();
|
||||||
trace!("step end");
|
|
||||||
self.time_spent_stepping += start_time.elapsed().unwrap();
|
self.time_spent_stepping += start_time.elapsed().unwrap();
|
||||||
|
trace!("step end");
|
||||||
let step = self.state.step_no();
|
let step = self.state.step_no();
|
||||||
if step % (10*self.steps_per_frame) == 0 {
|
if step % (10*self.steps_per_frame) == 0 {
|
||||||
let driver_time = self.time_spent_stepping.as_secs_f64() as Flt;
|
let driver_time = self.time_spent_stepping.as_secs_f64() as Flt;
|
||||||
|
let render_time = self.time_spent_rendering.as_secs_f64() as Flt;
|
||||||
let overall_time = self.start_time.elapsed().unwrap().as_secs_f64() as Flt;
|
let overall_time = self.start_time.elapsed().unwrap().as_secs_f64() as Flt;
|
||||||
let fps = (self.state.step_no() as Flt) / overall_time;
|
let fps = (self.state.step_no() as Flt) / overall_time;
|
||||||
info!("frame {:6}/fps: {:6.2} (driver: {:.1}s, rest: {:.1}s)", step, fps, driver_time, overall_time - driver_time);
|
let sim_time = self.state.time();
|
||||||
|
info!(
|
||||||
|
"t={:.2e} frame {:06} fps: {:6.2} (sim: {:.1}s, render: {:.1}s, other: {:.1}s)",
|
||||||
|
sim_time,
|
||||||
|
step,
|
||||||
|
fps,
|
||||||
|
driver_time,
|
||||||
|
render_time,
|
||||||
|
overall_time - driver_time - render_time
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
18
src/mat.rs
18
src/mat.rs
@@ -10,8 +10,8 @@ use std::cmp::Ordering;
|
|||||||
pub trait Material {
|
pub trait Material {
|
||||||
/// Return \sigma, the electrical conductivity.
|
/// Return \sigma, the electrical conductivity.
|
||||||
/// For a vacuum, this is zero. For a perfect conductor, \inf.
|
/// For a vacuum, this is zero. For a perfect conductor, \inf.
|
||||||
fn conductivity(&self) -> Flt {
|
fn conductivity(&self) -> Vec3 {
|
||||||
0.0
|
Default::default()
|
||||||
}
|
}
|
||||||
/// Return the magnetization.
|
/// Return the magnetization.
|
||||||
fn m(&self) -> Vec3 {
|
fn m(&self) -> Vec3 {
|
||||||
@@ -26,21 +26,21 @@ pub trait Material {
|
|||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct Static {
|
pub struct Static {
|
||||||
pub conductivity: Flt,
|
pub conductivity: Vec3,
|
||||||
pub m: Vec3,
|
pub m: Vec3,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Static {
|
impl Static {
|
||||||
pub fn conductor(conductivity: Flt) -> Self {
|
pub fn conductor(conductivity: Flt) -> Self {
|
||||||
Self {
|
Self {
|
||||||
conductivity,
|
conductivity: Vec3::unit() * conductivity,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Material for Static {
|
impl Material for Static {
|
||||||
fn conductivity(&self) -> Flt {
|
fn conductivity(&self) -> Vec3 {
|
||||||
self.conductivity
|
self.conductivity
|
||||||
}
|
}
|
||||||
fn m(&self) -> Vec3 {
|
fn m(&self) -> Vec3 {
|
||||||
@@ -140,7 +140,7 @@ impl MHCurve {
|
|||||||
pub struct PiecewiseLinearFerromagnet {
|
pub struct PiecewiseLinearFerromagnet {
|
||||||
/// Instantaneous magnetization in the z direction.
|
/// Instantaneous magnetization in the z direction.
|
||||||
pub m: Vec3,
|
pub m: Vec3,
|
||||||
pub conductivity: Flt,
|
pub conductivity: Vec3,
|
||||||
mh_curve_x: MHCurve,
|
mh_curve_x: MHCurve,
|
||||||
mh_curve_y: MHCurve,
|
mh_curve_y: MHCurve,
|
||||||
mh_curve_z: MHCurve,
|
mh_curve_z: MHCurve,
|
||||||
@@ -157,7 +157,7 @@ impl PiecewiseLinearFerromagnet {
|
|||||||
|
|
||||||
Self {
|
Self {
|
||||||
m: Vec3::default(),
|
m: Vec3::default(),
|
||||||
conductivity: 0.0,
|
conductivity: Default::default(),
|
||||||
mh_curve_x: MHCurve::new(&*mh_points),
|
mh_curve_x: MHCurve::new(&*mh_points),
|
||||||
mh_curve_y: MHCurve::new(&*mh_points),
|
mh_curve_y: MHCurve::new(&*mh_points),
|
||||||
mh_curve_z: MHCurve::new(&*mh_points),
|
mh_curve_z: MHCurve::new(&*mh_points),
|
||||||
@@ -169,7 +169,7 @@ impl Material for PiecewiseLinearFerromagnet {
|
|||||||
fn m(&self) -> Vec3 {
|
fn m(&self) -> Vec3 {
|
||||||
self.m
|
self.m
|
||||||
}
|
}
|
||||||
fn conductivity(&self) -> Flt {
|
fn conductivity(&self) -> Vec3 {
|
||||||
self.conductivity
|
self.conductivity
|
||||||
}
|
}
|
||||||
fn step_h(&mut self, context: &CellState, delta_b: Vec3) -> Vec3 {
|
fn step_h(&mut self, context: &CellState, delta_b: Vec3) -> Vec3 {
|
||||||
@@ -223,7 +223,7 @@ pub mod db {
|
|||||||
( 50.0, 0.340),
|
( 50.0, 0.340),
|
||||||
( 0.0, 0.325),
|
( 0.0, 0.325),
|
||||||
]);
|
]);
|
||||||
m.conductivity = 1e3;
|
m.conductivity = Vec3::unit() * 1e3; // XXX colin: should be 1e-3!!?
|
||||||
m
|
m
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -61,7 +61,7 @@ struct RenderSteps<'a> {
|
|||||||
impl<'a> RenderSteps<'a> {
|
impl<'a> RenderSteps<'a> {
|
||||||
fn render(state: &'a SimSnapshot, measurements: &'a [Box<dyn AbstractMeasurement>]) -> RgbImage {
|
fn render(state: &'a SimSnapshot, measurements: &'a [Box<dyn AbstractMeasurement>]) -> RgbImage {
|
||||||
let mut me = Self::new(state, measurements);
|
let mut me = Self::new(state, measurements);
|
||||||
me.render_scalar_field(10.0, false, 2, |cell| cell.mat().conductivity());
|
me.render_scalar_field(10.0, false, 2, |cell| cell.mat().conductivity().mag());
|
||||||
me.render_scalar_field(100.0, true, 0, |cell| cell.mat().m().mag());
|
me.render_scalar_field(100.0, true, 0, |cell| cell.mat().m().mag());
|
||||||
if false {
|
if false {
|
||||||
me.render_b_z_field();
|
me.render_b_z_field();
|
||||||
@@ -91,7 +91,7 @@ impl<'a> RenderSteps<'a> {
|
|||||||
self.render_vector_field(Rgb([0xff, 0xff, 0xff]), 100.0, |cell| cell.e().xy());
|
self.render_vector_field(Rgb([0xff, 0xff, 0xff]), 100.0, |cell| cell.e().xy());
|
||||||
// current
|
// current
|
||||||
self.render_vector_field(Rgb([0x00, 0xa0, 0x30]), 1.0e-12, |cell| {
|
self.render_vector_field(Rgb([0x00, 0xa0, 0x30]), 1.0e-12, |cell| {
|
||||||
cell.e().xy()*cell.mat().conductivity()
|
cell.e().elem_mul(cell.mat().conductivity()).xy()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -219,7 +219,7 @@ impl<M: Material> Cell<M> {
|
|||||||
|
|
||||||
pub fn current(&self) -> Vec3 {
|
pub fn current(&self) -> Vec3 {
|
||||||
let conductivity = self.mat.conductivity();
|
let conductivity = self.mat.conductivity();
|
||||||
self.e()*conductivity
|
self.e().elem_mul(conductivity)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn impulse_bz(&mut self, delta_bz: Flt) {
|
fn impulse_bz(&mut self, delta_bz: Flt) {
|
||||||
@@ -288,7 +288,7 @@ impl<M: Material> Cell<M> {
|
|||||||
|
|
||||||
use consts::real::{EPS0, ONE, TWO};
|
use consts::real::{EPS0, ONE, TWO};
|
||||||
|
|
||||||
let sigma: Real = self.mat.conductivity().into();
|
let sigma: Vec3 = self.mat.conductivity();
|
||||||
let inv_feature_size = Real::from_inner(1.0) / feature_size;
|
let inv_feature_size = Real::from_inner(1.0) / feature_size;
|
||||||
|
|
||||||
let delta_hz_y = inv_feature_size * (self.hz() - up.hz());
|
let delta_hz_y = inv_feature_size * (self.hz() - up.hz());
|
||||||
@@ -300,8 +300,8 @@ impl<M: Material> Cell<M> {
|
|||||||
let nabla_h = Vec3::from((delta_hz_y - delta_hy_z, delta_hx_z - delta_hz_x, delta_hy_x - delta_hx_y));
|
let nabla_h = Vec3::from((delta_hz_y - delta_hy_z, delta_hx_z - delta_hz_x, delta_hy_x - delta_hx_y));
|
||||||
let delta_t_eps = delta_t/EPS0();
|
let delta_t_eps = delta_t/EPS0();
|
||||||
|
|
||||||
let rhs = self.state.e() * (ONE() - sigma*delta_t_eps) + nabla_h * (TWO()*delta_t_eps);
|
let rhs = self.state.e().elem_mul(Vec3::unit() - sigma*delta_t_eps) + nabla_h * (TWO()*delta_t_eps);
|
||||||
let e_next = rhs / (ONE() + sigma*delta_t_eps);
|
let e_next = rhs.elem_div(Vec3::unit() + sigma*delta_t_eps);
|
||||||
|
|
||||||
|
|
||||||
Cell {
|
Cell {
|
||||||
|
18
src/vec3.rs
18
src/vec3.rs
@@ -40,6 +40,24 @@ impl Vec3 {
|
|||||||
let Vec3 { x, y, z } = *self;
|
let Vec3 { x, y, z } = *self;
|
||||||
(x*x + y*y + z*z).into_inner().sqrt()
|
(x*x + y*y + z*z).into_inner().sqrt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Perform element-wise multiplication with `other`.
|
||||||
|
pub fn elem_mul(&self, other: Self) -> Self {
|
||||||
|
Self {
|
||||||
|
x: self.x * other.x,
|
||||||
|
y: self.y * other.y,
|
||||||
|
z: self.z * other.z,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Perform element-wise division with `other`.
|
||||||
|
pub fn elem_div(&self, other: Self) -> Self {
|
||||||
|
Self {
|
||||||
|
x: self.x / other.x,
|
||||||
|
y: self.y / other.y,
|
||||||
|
z: self.z / other.z,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<(Real, Real, Real)> for Vec3 {
|
impl From<(Real, Real, Real)> for Vec3 {
|
||||||
|
Reference in New Issue
Block a user