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:
2022-08-12 01:42:19 -07:00
parent d5fbb4e9b2
commit 084c5bc342
7 changed files with 133 additions and 145 deletions

7
Cargo.lock generated
View File

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

View File

@@ -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);
}, },

View File

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

View File

@@ -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);

View File

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

View File

@@ -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>,
} }

View File

@@ -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>,
} }