Region: remove Clone
from the trait, and also parameterize everything
i didn't necessarily *want* to parameterize it all, but it turned out to be easier to do that than to force all users to workaround the lack of Clone.
This commit is contained in:
7
Cargo.lock
generated
7
Cargo.lock
generated
@@ -317,7 +317,6 @@ dependencies = [
|
|||||||
"crossterm",
|
"crossterm",
|
||||||
"csv",
|
"csv",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
"dyn-clone",
|
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"float_eq",
|
"float_eq",
|
||||||
"font8x8",
|
"font8x8",
|
||||||
@@ -554,12 +553,6 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "dyn-clone"
|
|
||||||
version = "1.0.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "140206b78fb2bc3edbcfc9b5ccbd0b30699cfe8d348b8b31b330e47df5291a5a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.7.0"
|
version = "1.7.0"
|
||||||
|
@@ -3,7 +3,20 @@
|
|||||||
//! search for the conditions which maximize energy transfer from the one core to the other.
|
//! search for the conditions which maximize energy transfer from the one core to the other.
|
||||||
|
|
||||||
use coremem::{Driver, mat, meas};
|
use coremem::{Driver, mat, meas};
|
||||||
use coremem::geom::{region, Cube, Dilate, Memoize, Meters, Spiral, SwapYZ, Torus, Translate, Wrap};
|
use coremem::geom::Meters;
|
||||||
|
use coremem::geom::region::{
|
||||||
|
self,
|
||||||
|
Cube,
|
||||||
|
Dilate,
|
||||||
|
Intersection,
|
||||||
|
InvertedRegion,
|
||||||
|
Memoize,
|
||||||
|
Spiral,
|
||||||
|
SwapYZ,
|
||||||
|
Torus,
|
||||||
|
Translate,
|
||||||
|
Wrap
|
||||||
|
};
|
||||||
use coremem::mat::{Ferroxcube3R1MH, IsoConductorOr};
|
use coremem::mat::{Ferroxcube3R1MH, IsoConductorOr};
|
||||||
use coremem::real::{R32, Real as _};
|
use coremem::real::{R32, Real as _};
|
||||||
use coremem::render::CsvRenderer;
|
use coremem::render::CsvRenderer;
|
||||||
@@ -13,9 +26,8 @@ use coremem::stim::{CurlStimulus, Exp1, Gated, Sinusoid1, TimeVarying as _};
|
|||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
// XXX: cache was disabled during Region rework.
|
mod cache;
|
||||||
// mod cache;
|
use cache::DiskCache;
|
||||||
// use cache::DiskCache;
|
|
||||||
|
|
||||||
type Mat = IsoConductorOr<f32, Ferroxcube3R1MH>;
|
type Mat = IsoConductorOr<f32, Ferroxcube3R1MH>;
|
||||||
|
|
||||||
@@ -142,14 +154,18 @@ struct Params {
|
|||||||
dump_frames: (u64, Option<u64>),
|
dump_frames: (u64, Option<u64>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default, Serialize, Deserialize)]
|
||||||
struct Geometries {
|
struct Geometries {
|
||||||
dim: Meters,
|
dim: Meters,
|
||||||
ferro1_region: Torus,
|
ferro1_region: Torus,
|
||||||
ferro2_region: Torus,
|
ferro2_region: Torus,
|
||||||
set1_region: Torus,
|
set1_region: Torus,
|
||||||
set2_region: Torus,
|
set2_region: Torus,
|
||||||
coupling_region: region::Union,
|
coupling_region: region::Union3<
|
||||||
|
Memoize<Dilate<Wrap<Translate<SwapYZ<Intersection<Spiral, Cube>>>>>>,
|
||||||
|
Memoize<Dilate<Wrap<Translate<SwapYZ<Intersection<Spiral, InvertedRegion<Cube>>>>>>>,
|
||||||
|
region::Union3<Cube, Cube, region::Union4<Cube, Cube, Cube, Cube>>
|
||||||
|
>,
|
||||||
coupling_wire_top: Cube,
|
coupling_wire_top: Cube,
|
||||||
coupling_wire_bot: Cube,
|
coupling_wire_bot: Cube,
|
||||||
wrap1_len: f32,
|
wrap1_len: f32,
|
||||||
@@ -285,29 +301,29 @@ fn derive_geometries(p: GeomParams) -> Option<Geometries> {
|
|||||||
wrap2_bot - feat_sizes*2.0,
|
wrap2_bot - feat_sizes*2.0,
|
||||||
wrap2_bot.with_y(coupling_wire_bot.top()) + feat_sizes*2.0,
|
wrap2_bot.with_y(coupling_wire_bot.top()) + feat_sizes*2.0,
|
||||||
);
|
);
|
||||||
let coupling_stubs = region::Union::new()
|
let coupling_stubs = region::Union::new4(
|
||||||
.with(coupling_stub_top_left.clone())
|
coupling_stub_top_left.clone(),
|
||||||
.with(coupling_stub_top_right.clone())
|
coupling_stub_top_right.clone(),
|
||||||
.with(coupling_stub_bot_left.clone())
|
coupling_stub_bot_left.clone(),
|
||||||
.with(coupling_stub_bot_right.clone())
|
coupling_stub_bot_right.clone(),
|
||||||
;
|
);
|
||||||
|
|
||||||
let coupling_wires = region::Union::new()
|
let coupling_wires = region::Union::new3(
|
||||||
.with(coupling_wire_top.clone())
|
coupling_wire_top.clone(),
|
||||||
.with(coupling_wire_bot.clone())
|
coupling_wire_bot.clone(),
|
||||||
.with(coupling_stubs.clone())
|
coupling_stubs.clone(),
|
||||||
;
|
);
|
||||||
|
|
||||||
let coupling_region = region::Union::new()
|
let coupling_region = region::Union::new3(
|
||||||
.with(coupling_region1.clone())
|
coupling_region1.clone(),
|
||||||
.with(coupling_region2.clone())
|
coupling_region2.clone(),
|
||||||
.with(coupling_wires.clone())
|
coupling_wires.clone(),
|
||||||
;
|
);
|
||||||
|
|
||||||
let wrap1_with_coupling = region::union(
|
let wrap1_with_coupling = region::Union::new2(
|
||||||
coupling_region1.clone(), coupling_wires.clone()
|
coupling_region1.clone(), coupling_wires.clone()
|
||||||
);
|
);
|
||||||
let wrap2_with_coupling = region::union(
|
let wrap2_with_coupling = region::Union::new2(
|
||||||
coupling_region2.clone(), coupling_wires.clone()
|
coupling_region2.clone(), coupling_wires.clone()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -657,14 +673,10 @@ fn main() {
|
|||||||
variants.len() / post_times.len(),
|
variants.len() / post_times.len(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// let mut geom_cache = DiskCache::new_with_supplier(
|
let mut geom_cache = DiskCache::new_with_supplier(
|
||||||
// &format!("{}/.geom_cache", ensure_out_dir(i)),
|
&format!("{}/.geom_cache", ensure_out_dir(i)),
|
||||||
// |geom: &GeomParams| derive_geometries(geom.clone())
|
|geom: &GeomParams| derive_geometries(geom.clone())
|
||||||
// );
|
);
|
||||||
// TODO: re-enable geometry cache. had to disable during Region serialization rework
|
|
||||||
fn geom_cache_get_or_insert_from_supplier(geom: GeomParams) -> Option<Geometries> {
|
|
||||||
derive_geometries(geom)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (peak_clock_current, clock_duration, post_time, clock_type, ferro_major, wrap1_coverage, wrap2_coverage, wrap1_density, wrap2_density) in variants {
|
for (peak_clock_current, clock_duration, post_time, clock_type, ferro_major, wrap1_coverage, wrap2_coverage, wrap1_density, wrap2_density) in variants {
|
||||||
info!("{}A/{}s {}s {}m {}:{}cov {}:{}density", peak_clock_current, clock_duration, post_time, ferro_major, wrap1_coverage, wrap2_coverage, wrap1_density, wrap2_density);
|
info!("{}A/{}s {}s {}m {}:{}cov {}:{}density", peak_clock_current, clock_duration, post_time, ferro_major, wrap1_coverage, wrap2_coverage, wrap1_density, wrap2_density);
|
||||||
@@ -713,7 +725,7 @@ fn main() {
|
|||||||
wraps1: (wraps1 * 4) as f32,
|
wraps1: (wraps1 * 4) as f32,
|
||||||
..base_params.geom
|
..base_params.geom
|
||||||
};
|
};
|
||||||
let geoms = geom_cache_get_or_insert_from_supplier(params.clone())?;
|
let geoms = geom_cache.get_or_insert_from_supplier(params.clone())?;
|
||||||
Some((params, geoms))
|
Some((params, geoms))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
@@ -738,7 +750,7 @@ fn main() {
|
|||||||
wraps2: (wraps2 * 4) as f32,
|
wraps2: (wraps2 * 4) as f32,
|
||||||
..base_params.geom
|
..base_params.geom
|
||||||
};
|
};
|
||||||
let geoms = geom_cache_get_or_insert_from_supplier(params.clone())?;
|
let geoms = geom_cache.get_or_insert_from_supplier(params.clone())?;
|
||||||
Some((params, geoms))
|
Some((params, geoms))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
@@ -759,7 +771,7 @@ fn main() {
|
|||||||
let mut params = base_params;
|
let mut params = base_params;
|
||||||
params.geom.wraps1 = wraps1;
|
params.geom.wraps1 = wraps1;
|
||||||
params.geom.wraps2 = wraps2;
|
params.geom.wraps2 = wraps2;
|
||||||
match geom_cache_get_or_insert_from_supplier(params.geom.clone()) {
|
match geom_cache.get_or_insert_from_supplier(params.geom.clone()) {
|
||||||
Some(geoms) => {
|
Some(geoms) => {
|
||||||
run_sim(i, params, geoms);
|
run_sim(i, params, geoms);
|
||||||
},
|
},
|
||||||
|
@@ -15,7 +15,6 @@ common_macros = "0.1" # MIT or Apache 2.0
|
|||||||
crossterm = "0.24" # MIT
|
crossterm = "0.24" # MIT
|
||||||
csv = "1.1" # MIT or Unlicense
|
csv = "1.1" # MIT or Unlicense
|
||||||
dashmap = "5.3" # MIT
|
dashmap = "5.3" # MIT
|
||||||
dyn-clone = "1.0" # MIT or Apache 2.0
|
|
||||||
env_logger = "0.9" # MIT or Apache 2.0
|
env_logger = "0.9" # MIT or Apache 2.0
|
||||||
float_eq = "1.0" # MIT or Apache 2.0
|
float_eq = "1.0" # MIT or Apache 2.0
|
||||||
font8x8 = "0.3" # MIT
|
font8x8 = "0.3" # MIT
|
||||||
|
@@ -2,7 +2,6 @@ use crate::geom::{Coord, Meters, OrdMeters};
|
|||||||
|
|
||||||
use coremem_cross::vec::Vec3;
|
use coremem_cross::vec::Vec3;
|
||||||
|
|
||||||
use dyn_clone::{self, DynClone};
|
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
@@ -12,10 +11,9 @@ mod primitives;
|
|||||||
pub use primitives::*;
|
pub use primitives::*;
|
||||||
|
|
||||||
|
|
||||||
pub trait Region: Send + Sync + DynClone {
|
pub trait Region: Send + Sync {
|
||||||
fn contains(&self, p: Meters) -> bool;
|
fn contains(&self, p: Meters) -> bool;
|
||||||
}
|
}
|
||||||
dyn_clone::clone_trait_object!(Region);
|
|
||||||
|
|
||||||
/// some (volume) which has a tangent vector everywhere inside/on it.
|
/// some (volume) which has a tangent vector everywhere inside/on it.
|
||||||
/// for example, a cylinder has tangents everywhere except its axis.
|
/// for example, a cylinder has tangents everywhere except its axis.
|
||||||
@@ -24,16 +22,16 @@ pub trait HasCrossSection {
|
|||||||
fn cross_section_normal(&self, p: Meters) -> Vec3<f32>;
|
fn cross_section_normal(&self, p: Meters) -> Vec3<f32>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn and<T1: Region + 'static, T2: Region + 'static>(r1: T1, r2: T2) -> Intersection {
|
pub fn and<T1: Region + 'static, T2: Region + 'static>(r1: T1, r2: T2) -> Intersection<T1, T2> {
|
||||||
Intersection::new().and(r1).and(r2)
|
Intersection::new2(r1, r2)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn and_not<T1: Region + 'static, T2: Region + 'static>(r1: T1, r2: T2) -> Intersection {
|
pub fn and_not<T1: Region + 'static, T2: Region + 'static>(r1: T1, r2: T2) -> Intersection<T1, InvertedRegion<T2>> {
|
||||||
and(r1, InvertedRegion::new(r2))
|
and(r1, InvertedRegion::new(r2))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn union<T1: Region + 'static, T2: Region + 'static>(r1: T1, r2: T2) -> Union {
|
pub fn union<T1: Region + 'static, T2: Region + 'static>(r1: T1, r2: T2) -> Union<T1, T2> {
|
||||||
Union::new().with(r1).with(r2)
|
Union::new2(r1, r2)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns true if there's a path (via the cardinal directions) from p0 to p1 within this region.
|
/// returns true if there's a path (via the cardinal directions) from p0 to p1 within this region.
|
||||||
@@ -75,7 +73,7 @@ pub fn distance_to<R: Region, C: Coord>(r: &R, p0: C, p1: C, feat_size: f32) ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Region describing the entire simulation space
|
/// Region describing the entire simulation space
|
||||||
#[derive(Copy, Clone, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Default, Serialize, Deserialize)]
|
||||||
pub struct WorldRegion;
|
pub struct WorldRegion;
|
||||||
|
|
||||||
impl Region for WorldRegion {
|
impl Region for WorldRegion {
|
||||||
@@ -84,121 +82,115 @@ impl Region for WorldRegion {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Default, Serialize, Deserialize)]
|
||||||
pub struct InvertedRegion(Box<dyn Region>);
|
pub struct InvertedRegion<R>(R);
|
||||||
|
|
||||||
impl InvertedRegion {
|
impl<R> InvertedRegion<R> {
|
||||||
pub fn new<R: Region + 'static>(r: R) -> Self {
|
pub fn new(r: R) -> Self {
|
||||||
Self(Box::new(r))
|
Self(r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Region for InvertedRegion {
|
impl<R: Region> Region for InvertedRegion<R> {
|
||||||
fn contains(&self, p: Meters) -> bool {
|
fn contains(&self, p: Meters) -> bool {
|
||||||
!self.0.contains(p)
|
!self.0.contains(p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default, Serialize, Deserialize)]
|
||||||
pub struct Union(Vec<Box<dyn Region>>);
|
pub struct Union<R1, R2>(R1, R2);
|
||||||
|
|
||||||
impl Union {
|
pub type Union3<R1, R2, R3> = Union<Union<R1, R2>, R3>;
|
||||||
pub fn new() -> Self {
|
pub type Union4<R1, R2, R3, R4> = Union<Union3<R1, R2, R3>, R4>;
|
||||||
Self(Vec::new())
|
|
||||||
|
impl<R1, R2> Union<R1, R2> {
|
||||||
|
pub fn with<R: Region>(self, r: R) -> Union<Self, R> {
|
||||||
|
Union::new2(self, r)
|
||||||
}
|
}
|
||||||
pub fn new_with<R: Region + 'static>(r: R) -> Self {
|
pub fn new2(r1: R1, r2: R2) -> Self {
|
||||||
Self::new().with(r)
|
Self(r1, r2)
|
||||||
}
|
}
|
||||||
pub fn with<R: Region + 'static>(self, r: R) -> Self {
|
pub fn new3<R3: Region>(r1: R1, r2: R2, r3: R3) -> Union<Self, R3> {
|
||||||
self.with_box(Box::new(r))
|
Union::new2(r1, r2).with(r3)
|
||||||
}
|
}
|
||||||
pub fn with_box(mut self, r: Box<dyn Region>) -> Self {
|
pub fn new4<R3: Region, R4: Region>(r1: R1, r2: R2, r3: R3, r4: R4) -> Union<Union<Self, R3>, R4> {
|
||||||
self.0.push(r);
|
Union::new2(r1, r2).with(r3).with(r4)
|
||||||
self
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Region for Union {
|
impl<R1: Region, R2: Region> Region for Union<R1, R2> {
|
||||||
fn contains(&self, p: Meters) -> bool {
|
fn contains(&self, p: Meters) -> bool {
|
||||||
self.0.iter().any(|r| r.contains(p))
|
self.0.contains(p) || self.1.contains(p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Default, Serialize, Deserialize)]
|
||||||
pub struct Intersection(Vec<Box<dyn Region>>);
|
pub struct Intersection<R1, R2>(R1, R2);
|
||||||
|
|
||||||
|
|
||||||
impl Intersection {
|
impl<R1, R2> Intersection<R1, R2> {
|
||||||
pub fn new() -> Self {
|
pub fn and<R3: Region>(self, r: R3) -> Intersection<Self, R3> {
|
||||||
Self(Vec::new())
|
Intersection::new2(self, r)
|
||||||
}
|
}
|
||||||
pub fn new_with<R: Region + 'static>(r: R) -> Self {
|
pub fn new2(r1: R1, r2: R2) -> Self {
|
||||||
Self::new().and(r)
|
Self(r1, r2)
|
||||||
}
|
|
||||||
pub fn and<R: Region + 'static>(self, r: R) -> Self {
|
|
||||||
self.and_box(Box::new(r))
|
|
||||||
}
|
|
||||||
pub fn and_box(mut self, r: Box<dyn Region>) -> Self {
|
|
||||||
self.0.push(r);
|
|
||||||
self
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Region for Intersection {
|
impl<R1: Region, R2: Region> Region for Intersection<R1, R2> {
|
||||||
fn contains(&self, p: Meters) -> bool {
|
fn contains(&self, p: Meters) -> bool {
|
||||||
self.0.iter().all(|r| r.contains(p))
|
self.0.contains(p) && self.1.contains(p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Default, Serialize, Deserialize)]
|
||||||
pub struct Translate {
|
pub struct Translate<R> {
|
||||||
inner: Box<dyn Region>,
|
inner: R,
|
||||||
shift: Meters,
|
shift: Meters,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Translate {
|
impl<R> Translate<R> {
|
||||||
pub fn new<T: Region + 'static>(inner: T, shift: Meters) -> Self {
|
pub fn new(inner: R, shift: Meters) -> Self {
|
||||||
Self { inner: Box::new(inner), shift }
|
Self { inner, shift }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Region for Translate {
|
impl<R: Region> Region for Translate<R> {
|
||||||
fn contains(&self, p: Meters) -> bool {
|
fn contains(&self, p: Meters) -> bool {
|
||||||
self.inner.contains(p - self.shift)
|
self.inner.contains(p - self.shift)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Default, Serialize, Deserialize)]
|
||||||
pub struct SwapXZ {
|
pub struct SwapXZ<R> {
|
||||||
inner: Box<dyn Region>,
|
inner: R,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SwapXZ {
|
impl<R> SwapXZ<R> {
|
||||||
pub fn new<T: Region + 'static>(inner: T) -> Self {
|
pub fn new(inner: R) -> Self {
|
||||||
Self { inner: Box::new(inner) }
|
Self { inner }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Region for SwapXZ {
|
impl<R: Region> Region for SwapXZ<R> {
|
||||||
fn contains(&self, p: Meters) -> bool {
|
fn contains(&self, p: Meters) -> bool {
|
||||||
let p = Meters::new(p.z(), p.y(), p.z());
|
let p = Meters::new(p.z(), p.y(), p.z());
|
||||||
self.inner.contains(p)
|
self.inner.contains(p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Serialize, Deserialize)]
|
||||||
#[derive(Clone)]
|
pub struct SwapYZ<R> {
|
||||||
pub struct SwapYZ {
|
inner: R,
|
||||||
inner: Box<dyn Region>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SwapYZ {
|
impl<R> SwapYZ<R> {
|
||||||
pub fn new<T: Region + 'static>(inner: T) -> Self {
|
pub fn new(inner: R) -> Self {
|
||||||
Self { inner: Box::new(inner) }
|
Self { inner }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Region for SwapYZ {
|
impl<R: Region> Region for SwapYZ<R> {
|
||||||
fn contains(&self, p: Meters) -> bool {
|
fn contains(&self, p: Meters) -> bool {
|
||||||
let mapped = Meters::new(p.x(), p.z(), p.y());
|
let mapped = Meters::new(p.x(), p.z(), p.y());
|
||||||
self.inner.contains(mapped)
|
self.inner.contains(mapped)
|
||||||
@@ -211,20 +203,20 @@ impl Region for SwapYZ {
|
|||||||
/// the resulting region is mapped onto the original region y=[0, y_max]. x is just the radius
|
/// the resulting region is mapped onto the original region y=[0, y_max]. x is just the radius
|
||||||
/// so that (0, 0) is mapped to (0, 0), and (1, 0) is mapped to (1, 0) and (0, 1) is mapped to
|
/// so that (0, 0) is mapped to (0, 0), and (1, 0) is mapped to (1, 0) and (0, 1) is mapped to
|
||||||
/// (1, 0.5*y_max) and (-5, 0) is mapped to (5, 0.5*y_max).
|
/// (1, 0.5*y_max) and (-5, 0) is mapped to (5, 0.5*y_max).
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Default, Serialize, Deserialize)]
|
||||||
pub struct Wrap {
|
pub struct Wrap<R> {
|
||||||
inner: Box<dyn Region>,
|
inner: R,
|
||||||
y_max: f32,
|
y_max: f32,
|
||||||
about: Meters,
|
about: Meters,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Wrap {
|
impl<R> Wrap<R> {
|
||||||
pub fn new<T: Region + 'static>(inner: T, y_max: f32) -> Self {
|
pub fn new(inner: R, y_max: f32) -> Self {
|
||||||
Self::new_about(inner, y_max, Meters::new(0.0, 0.0, 0.0))
|
Self::new_about(inner, y_max, Meters::new(0.0, 0.0, 0.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_about<T: Region + 'static>(inner: T, y_max: f32, about: Meters) -> Self {
|
pub fn new_about(inner: R, y_max: f32, about: Meters) -> Self {
|
||||||
Self { inner: Box::new(inner), y_max, about }
|
Self { inner, y_max, about }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map(&self, p: Meters) -> Meters {
|
fn map(&self, p: Meters) -> Meters {
|
||||||
@@ -236,26 +228,26 @@ impl Wrap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Region for Wrap {
|
impl<R: Region> Region for Wrap<R> {
|
||||||
fn contains(&self, p: Meters) -> bool {
|
fn contains(&self, p: Meters) -> bool {
|
||||||
self.inner.contains(self.map(p))
|
self.inner.contains(self.map(p))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Default, Serialize, Deserialize)]
|
||||||
pub struct Dilate {
|
pub struct Dilate<R> {
|
||||||
inner: Box<dyn Region>,
|
inner: R,
|
||||||
rad: f32,
|
rad: f32,
|
||||||
res: f32,
|
res: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dilate {
|
impl<R> Dilate<R> {
|
||||||
pub fn new<T: Region + 'static>(inner: T, rad: f32, res: f32) -> Self {
|
pub fn new(inner: R, rad: f32, res: f32) -> Self {
|
||||||
Self { inner: Box::new(inner), rad, res }
|
Self { inner, rad, res }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Region for Dilate {
|
impl<R: Region> Region for Dilate<R> {
|
||||||
fn contains(&self, p: Meters) -> bool {
|
fn contains(&self, p: Meters) -> bool {
|
||||||
let rad_iters = (self.rad / self.res).ceil() as i32;
|
let rad_iters = (self.rad / self.res).ceil() as i32;
|
||||||
let rad_range = -rad_iters..=rad_iters;
|
let rad_range = -rad_iters..=rad_iters;
|
||||||
@@ -278,22 +270,23 @@ impl Region for Dilate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Default, Serialize, Deserialize)]
|
||||||
pub struct Memoize {
|
pub struct Memoize<R> {
|
||||||
|
#[serde(skip)]
|
||||||
lut: Arc<dashmap::DashMap<OrdMeters, bool>>,
|
lut: Arc<dashmap::DashMap<OrdMeters, bool>>,
|
||||||
inner: Box<dyn Region>,
|
inner: R,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Memoize {
|
impl<R> Memoize<R> {
|
||||||
pub fn new<R: Region + 'static>(inner: R) -> Self {
|
pub fn new(inner: R) -> Self {
|
||||||
Self {
|
Self {
|
||||||
lut: Arc::new(dashmap::DashMap::new()),
|
lut: Arc::new(dashmap::DashMap::new()),
|
||||||
inner: Box::new(inner),
|
inner,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Region for Memoize {
|
impl<R: Region> Region for Memoize<R> {
|
||||||
fn contains(&self, p: Meters) -> bool {
|
fn contains(&self, p: Meters) -> bool {
|
||||||
*self.lut.entry(OrdMeters(p)).or_insert_with(|| self.inner.contains(p))
|
*self.lut.entry(OrdMeters(p)).or_insert_with(|| self.inner.contains(p))
|
||||||
}
|
}
|
||||||
@@ -304,7 +297,7 @@ mod test {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use float_eq::assert_float_eq;
|
use float_eq::assert_float_eq;
|
||||||
|
|
||||||
fn assert_map(w: &Wrap, from: Meters, to: Meters) {
|
fn assert_map<R>(w: &Wrap<R>, from: Meters, to: Meters) {
|
||||||
let mapped = w.map(from);
|
let mapped = w.map(from);
|
||||||
assert_float_eq!(mapped.x(), to.x(), abs <= 0.01);
|
assert_float_eq!(mapped.x(), to.x(), abs <= 0.01);
|
||||||
assert_float_eq!(mapped.y(), to.y(), abs <= 0.01);
|
assert_float_eq!(mapped.y(), to.y(), abs <= 0.01);
|
||||||
|
@@ -8,7 +8,7 @@ use std::ops::Range;
|
|||||||
|
|
||||||
use super::{HasCrossSection, Region};
|
use super::{HasCrossSection, Region};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Default, Serialize, Deserialize)]
|
||||||
pub struct CylinderZ {
|
pub struct CylinderZ {
|
||||||
center: Vec2<f32>,
|
center: Vec2<f32>,
|
||||||
radius: f32,
|
radius: f32,
|
||||||
@@ -111,7 +111,7 @@ impl HasCrossSection for Torus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Default, Serialize, Deserialize)]
|
||||||
pub struct Sphere {
|
pub struct Sphere {
|
||||||
center: Meters,
|
center: Meters,
|
||||||
rad: f32,
|
rad: f32,
|
||||||
@@ -243,7 +243,7 @@ impl Region for Cube {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// a Spiral traces out a circle on the xy plane as z increases.
|
/// a Spiral traces out a circle on the xy plane as z increases.
|
||||||
#[derive(Copy, Clone, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Default, Serialize, Deserialize)]
|
||||||
pub struct Spiral {
|
pub struct Spiral {
|
||||||
/// radius of the spiral
|
/// radius of the spiral
|
||||||
major: f32,
|
major: f32,
|
||||||
|
@@ -212,7 +212,6 @@ impl<S: AbstractSim> AbstractMeasurement<S> for Meta {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Volume {
|
pub struct Volume {
|
||||||
name: String,
|
name: String,
|
||||||
region: Box<dyn Region>,
|
region: Box<dyn Region>,
|
||||||
@@ -241,7 +240,6 @@ impl<S: AbstractSim> AbstractMeasurement<S> for Volume {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Current {
|
pub struct Current {
|
||||||
name: String,
|
name: String,
|
||||||
region: Box<dyn Region>,
|
region: Box<dyn Region>,
|
||||||
@@ -471,7 +469,6 @@ impl<S: AbstractSim> AbstractMeasurement<S> for MagneticLoop {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// mean M over a region
|
/// mean M over a region
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct MagneticFlux {
|
pub struct MagneticFlux {
|
||||||
name: String,
|
name: String,
|
||||||
region: Box<dyn Region>,
|
region: Box<dyn Region>,
|
||||||
@@ -508,7 +505,6 @@ impl<S: AbstractSim> AbstractMeasurement<S> for MagneticFlux {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// mean B over a region
|
/// mean B over a region
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Magnetization {
|
pub struct Magnetization {
|
||||||
name: String,
|
name: String,
|
||||||
region: Box<dyn Region>,
|
region: Box<dyn Region>,
|
||||||
@@ -604,7 +600,6 @@ impl<S: AbstractSim> AbstractMeasurement<S> for ElectricField {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Energy {
|
pub struct Energy {
|
||||||
name: String,
|
name: String,
|
||||||
region: Box<dyn Region>,
|
region: Box<dyn Region>,
|
||||||
@@ -648,7 +643,6 @@ impl<S: AbstractSim> AbstractMeasurement<S> for Energy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Power {
|
pub struct Power {
|
||||||
name: String,
|
name: String,
|
||||||
region: Box<dyn Region>
|
region: Box<dyn Region>
|
||||||
@@ -732,7 +726,6 @@ pub mod test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
|
||||||
struct MockRegion {
|
struct MockRegion {
|
||||||
normal: Vec3<f32>,
|
normal: Vec3<f32>,
|
||||||
}
|
}
|
||||||
|
@@ -362,7 +362,6 @@ impl<T: TimeVarying3> TimeVarying3 for Shifted<T> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use serde::{Serialize, Deserialize};
|
|
||||||
|
|
||||||
macro_rules! assert_approx_eq {
|
macro_rules! assert_approx_eq {
|
||||||
($x:expr, $e:expr, $h:expr) => {
|
($x:expr, $e:expr, $h:expr) => {
|
||||||
@@ -396,7 +395,6 @@ mod test {
|
|||||||
assert_approx_eq!(s.at(0.00075), Vec3::new(-10.0, -1.0, 100.0), Vec3::zero());
|
assert_approx_eq!(s.at(0.00075), Vec3::new(-10.0, -1.0, 100.0), Vec3::zero());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
|
||||||
struct MockRegion {
|
struct MockRegion {
|
||||||
normal: Vec3<f32>,
|
normal: Vec3<f32>,
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user