diff --git a/examples/minimal_torus.rs b/examples/minimal_torus.rs index ae0b7d7..82670ad 100644 --- a/examples/minimal_torus.rs +++ b/examples/minimal_torus.rs @@ -1,5 +1,5 @@ use coremem::{Driver, Flt, mat, meas}; -use coremem::geom::{Cube, Index, InvertedRegion, Meters, Torus}; +use coremem::geom::{Cube, Index, InvertedRegion, Meters, Torus, Union}; use coremem::stim::{CurlStimulus, Sinusoid1, TimeVarying1 as _}; fn main() { @@ -34,16 +34,23 @@ fn main() { let drive_region = Torus::new_xz(Meters((half_width - ferro_major, half_width, half_depth).into()), wire_major, wire_minor); let sense_region = Torus::new_xz(Meters((half_width + ferro_major, half_width, half_depth).into()), wire_major, wire_minor); - driver.fill_region(&ferro_region, mat::db::minimal_square_ferrite().into()); - driver.fill_region(&drive_region, mat::db::conductor(conductivity).into()); - driver.fill_region(&sense_region, mat::db::conductor(conductivity).into()); - let boundary_xy = half_width - ferro_major - ferro_minor - buffer; let boundary_z = half_depth - wire_major - wire_minor - buffer; let boundary_lower = Meters((boundary_xy, boundary_xy, boundary_z).into()); let boundary_upper = Meters((width - boundary_xy, width - boundary_xy, depth - boundary_z).into()); println!("boundary: {}um; {}um", m_to_um(boundary_xy), m_to_um(boundary_z)); let boundary_region = InvertedRegion::new(Cube::new(boundary_lower, boundary_upper)); + + let vacuum_region = InvertedRegion::new(Union::new() + .with(ferro_region.clone()) + .with(drive_region.clone()) + .with(sense_region.clone()) + .with(boundary_region.clone()) + ); + + driver.fill_region(&ferro_region, mat::db::minimal_square_ferrite().into()); + driver.fill_region(&drive_region, mat::db::conductor(conductivity).into()); + driver.fill_region(&sense_region, mat::db::conductor(conductivity).into()); driver.add_upml_boundary(Meters((boundary_xy, boundary_xy, boundary_z).into())); // J=\sigma E @@ -86,6 +93,7 @@ fn main() { driver.add_measurement(meas::MagneticFlux::new("mem", ferro_region.clone())); driver.add_measurement(meas::Power::new("mem", ferro_region.clone())); driver.add_measurement(meas::Power::new("boundary", boundary_region.clone())); + driver.add_measurement(meas::Power::new("vacuum", vacuum_region.clone())); let prefix = format!("out/{}/{}-flt{}-{}-feat{}um-{}mA-{}ps--radii{}um-{}um-{}um-{}um", base, diff --git a/src/geom/mod.rs b/src/geom/mod.rs index dcef303..bdbb000 100644 --- a/src/geom/mod.rs +++ b/src/geom/mod.rs @@ -3,7 +3,7 @@ mod units; mod vec; mod vecu; -pub use region::{Cube, CylinderZ, InvertedRegion, Region, Sphere, Torus, WorldRegion}; +pub use region::{Cube, CylinderZ, InvertedRegion, Region, Sphere, Torus, Union, WorldRegion}; pub use units::{Coord, Meters, Index}; pub use vec::{Vec2, Vec3}; pub use vecu::Vec3u; diff --git a/src/geom/region.rs b/src/geom/region.rs index 0cec8c8..8cf650f 100644 --- a/src/geom/region.rs +++ b/src/geom/region.rs @@ -162,7 +162,6 @@ impl Region for WorldRegion { } } -/// Region describing the entire simulation space #[derive(Clone, Serialize, Deserialize)] pub struct InvertedRegion(Box); @@ -179,6 +178,29 @@ impl Region for InvertedRegion { } } +#[derive(Clone, Serialize, Deserialize)] +pub struct Union(Vec>); + +impl Union { + pub fn new() -> Self { + Union(Vec::new()) + } + pub fn new_with(r: R) -> Self { + Self::new().with(r) + } + pub fn with(mut self, r: R) -> Self { + self.0.push(Box::new(r)); + self + } +} + +#[typetag::serde] +impl Region for Union { + fn contains(&self, p: Meters) -> bool { + self.0.iter().any(|r| r.contains(p)) + } +} + #[cfg(test)] mod test { use super::*;