diff --git a/opossum/examples/beam_combine_test.rs b/opossum/examples/beam_combine_test.rs index 03389495c4d63e5259ba1cb2fa7ef4dd224fb63b..88c10990385122f848639d48a0383c7bf01e8a99 100644 --- a/opossum/examples/beam_combine_test.rs +++ b/opossum/examples/beam_combine_test.rs @@ -16,19 +16,19 @@ use uom::si::f64::Length; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::new("beam combiner demo"); - let i_s1 = scenery.add_node(Source::new( + let i_s1 = scenery.add_node(&Source::new( "Source 1", &LightData::Energy(DataEnergy { spectrum: create_he_ne_spec(1.0).unwrap(), }), ))?; - let i_s2 = scenery.add_node(Source::new( + let i_s2 = scenery.add_node(&Source::new( "Source 2", &LightData::Energy(DataEnergy { spectrum: create_nd_glass_spec(1.0)?, }), ))?; - let i_bs = scenery.add_node(BeamSplitter::new("bs", &SplittingConfig::Ratio(0.5)).unwrap())?; + let i_bs = scenery.add_node(&BeamSplitter::new("bs", &SplittingConfig::Ratio(0.5)).unwrap())?; let filter_spectrum = generate_filter_spectrum( nanometer!(400.0)..nanometer!(1100.0), nanometer!(1.0), @@ -36,11 +36,11 @@ fn main() -> OpmResult<()> { cut_off: nanometer!(700.0), }, )?; - let i_f = scenery.add_node(IdealFilter::new( + let i_f = scenery.add_node(&IdealFilter::new( "filter", &FilterType::Spectrum(filter_spectrum), )?)?; - let i_d1 = scenery.add_node(Detector::default())?; // Detector 1 + let i_d1 = scenery.add_node(&Detector::default())?; // Detector 1 scenery.connect_nodes(i_s1, "out1", i_bs, "input1", Length::zero())?; scenery.connect_nodes(i_s2, "out1", i_bs, "input2", Length::zero())?; diff --git a/opossum/examples/cylindric_lens_test.rs b/opossum/examples/cylindric_lens_test.rs index 7017b5a83ca708bac50a68ff07151c5f245cc4cb..6cc0bb4fe0c953d615408a1d50eaf00d87a6a4cd 100644 --- a/opossum/examples/cylindric_lens_test.rs +++ b/opossum/examples/cylindric_lens_test.rs @@ -16,7 +16,7 @@ use std::path::Path; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::default(); - let src = scenery.add_node(round_collimated_ray_source( + let src = scenery.add_node(&round_collimated_ray_source( millimeter!(20.0), joule!(1.0), 3, @@ -29,9 +29,9 @@ fn main() -> OpmResult<()> { &RefrIndexConst::new(1.5068)?, )? .with_tilt(degree!(0.0, 0.0, 45.0))?; - let l1 = scenery.add_node(lens)?; - let det = scenery.add_node(RayPropagationVisualizer::default())?; - let det2 = scenery.add_node(SpotDiagram::default())?; + let l1 = scenery.add_node(&lens)?; + let det = scenery.add_node(&RayPropagationVisualizer::default())?; + let det2 = scenery.add_node(&SpotDiagram::default())?; scenery.connect_nodes(src, "out1", l1, "front", millimeter!(50.0))?; scenery.connect_nodes(l1, "rear", det, "in1", millimeter!(100.0))?; scenery.connect_nodes(det, "out1", det2, "in1", millimeter!(0.0))?; diff --git a/opossum/examples/filter_test.rs b/opossum/examples/filter_test.rs index 3971eba70c7c0aa353b441d14bf7a3cd60de001d..fc0e0d22e6288f2bb24c26fe2d14fb54b1f4c644 100644 --- a/opossum/examples/filter_test.rs +++ b/opossum/examples/filter_test.rs @@ -15,24 +15,24 @@ use uom::si::f64::Length; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::new("filter system demo"); - let i_s = scenery.add_node(Source::new( + let i_s = scenery.add_node(&Source::new( "Source", &LightData::Energy(DataEnergy { spectrum: create_he_ne_spec(1.0)?, }), ))?; - let i_bs = scenery.add_node(BeamSplitter::new("bs", &SplittingConfig::Ratio(0.6)).unwrap())?; + let i_bs = scenery.add_node(&BeamSplitter::new("bs", &SplittingConfig::Ratio(0.6)).unwrap())?; let filter_spectrum = Spectrum::from_csv("./opossum/opossum/NE03B.csv")?; - let i_f = scenery.add_node(IdealFilter::new( + let i_f = scenery.add_node(&IdealFilter::new( "filter", &FilterType::Spectrum(filter_spectrum), )?)?; - let i_d1 = scenery.add_node(EnergyMeter::new( + let i_d1 = scenery.add_node(&EnergyMeter::new( "Energy meter 1", opossum::nodes::Metertype::IdealEnergyMeter, ))?; - let i_d2 = scenery.add_node(Spectrometer::default())?; - let i_d3 = scenery.add_node(EnergyMeter::new( + let i_d2 = scenery.add_node(&Spectrometer::default())?; + let i_d3 = scenery.add_node(&EnergyMeter::new( "Energy meter 2", opossum::nodes::Metertype::IdealEnergyMeter, ))?; diff --git a/opossum/examples/folded_telescope.rs b/opossum/examples/folded_telescope.rs index d542253cddfd6d30bce7d012e7d14f830370bb69..4c68f65074251dafaa2f3b448b4108467e30fd56 100644 --- a/opossum/examples/folded_telescope.rs +++ b/opossum/examples/folded_telescope.rs @@ -49,10 +49,10 @@ pub fn main() -> OpmResult<()> { src.set_alignment_wavelength(alignment_wvl)?; src.set_isometry(Isometry::identity()); - let i_src = scenery.add_node(src)?; + let i_src = scenery.add_node(&src)?; // focal length = 996.7 mm (Thorlabs LA1779-B) let lens1 = scenery.add_node( - Lens::new( + &Lens::new( "Lens 1", millimeter!(515.1), millimeter!(f64::INFINITY), @@ -63,12 +63,12 @@ pub fn main() -> OpmResult<()> { )?; let mir_1 = ThinMirror::new("mirr").align_like_node_at_distance(lens1, millimeter!(996.7)); - let mir_1 = scenery.add_node(mir_1)?; + let mir_1 = scenery.add_node(&mir_1)?; let mut lens_1_ref = NodeReference::from_node(&scenery.node(lens1)?); lens_1_ref.set_inverted(true)?; - let lens_1_ref = scenery.add_node(lens_1_ref)?; + let lens_1_ref = scenery.add_node(&lens_1_ref)?; - let i_prop_vis = scenery.add_node(RayPropagationVisualizer::new( + let i_prop_vis = scenery.add_node(&RayPropagationVisualizer::new( "Ray_positions", Some(Vector3::y()), )?)?; diff --git a/opossum/examples/fresnel_coating.rs b/opossum/examples/fresnel_coating.rs index 65e1ae31fd3501e41487b7d361f45a57fe40cac0..21e7862b57b4225a6405fe0c036dd3ebbea38fe5 100644 --- a/opossum/examples/fresnel_coating.rs +++ b/opossum/examples/fresnel_coating.rs @@ -26,8 +26,8 @@ fn main() -> OpmResult<()> { )?; let mut source = Source::new("src", &LightData::Geometric(rays)); source.set_isometry(Isometry::identity()); - let src = scenery.add_node(source)?; - let fd1 = scenery.add_node(FluenceDetector::new("before lens"))?; + let src = scenery.add_node(&source)?; + let fd1 = scenery.add_node(&FluenceDetector::new("before lens"))?; let mut lens1 = Lens::new( "Lens", @@ -37,10 +37,10 @@ fn main() -> OpmResult<()> { &RefrIndexConst::new(1.5)?, )?; lens1.set_coating(&PortType::Input, "front", &CoatingType::Fresnel)?; - let l1 = scenery.add_node(lens1)?; - let fd2 = scenery.add_node(FluenceDetector::new("after lens"))?; - let ed = scenery.add_node(EnergyMeter::default())?; - let det = scenery.add_node(RayPropagationVisualizer::default())?; + let l1 = scenery.add_node(&lens1)?; + let fd2 = scenery.add_node(&FluenceDetector::new("after lens"))?; + let ed = scenery.add_node(&EnergyMeter::default())?; + let det = scenery.add_node(&RayPropagationVisualizer::default())?; scenery.connect_nodes(src, "out1", fd1, "in1", millimeter!(10.0))?; scenery.connect_nodes(fd1, "out1", l1, "front", millimeter!(1.0))?; diff --git a/opossum/examples/ghost_focus.rs b/opossum/examples/ghost_focus.rs index 510cb76b706726a24bd08e02b77ca2b4f76a876a..34ea7df12789992df3158d32d7e835c6f94460a0 100644 --- a/opossum/examples/ghost_focus.rs +++ b/opossum/examples/ghost_focus.rs @@ -1,10 +1,13 @@ use opossum::{ - analyzers::{AnalyzerType, GhostFocusConfig}, + analyzers::{AnalyzerType, GhostFocusConfig, RayTraceConfig}, coatings::CoatingType, degree, error::OpmResult, joule, millimeter, - nodes::{round_collimated_ray_source, Lens, NodeGroup, SpotDiagram, Wedge}, + nodes::{ + collimated_line_ray_source, round_collimated_ray_source, Lens, NodeGroup, SpotDiagram, + Wedge, + }, optic_node::{Alignable, OpticNode}, optic_ports::PortType, refractive_index::RefrIndexConst, @@ -16,15 +19,14 @@ fn main() -> OpmResult<()> { let mut scenery = NodeGroup::default(); let i_src = scenery.add_node( // collimated_line_ray_source(millimeter!(50.), joule!(1.), 100)? - round_collimated_ray_source(millimeter!(50.0), joule!(1.0), 7)?, + &round_collimated_ray_source(millimeter!(50.0), joule!(1.0), 7)?, )?; - let i_sd = scenery.add_node(SpotDiagram::default())?; + let i_sd = scenery.add_node(&SpotDiagram::default())?; let mut lens = Lens::default(); - lens.set_coating(&PortType::Input, "front", &CoatingType::Fresnel)?; lens.set_coating(&PortType::Output, "rear", &CoatingType::Fresnel)?; - let i_l = scenery.add_node(lens)?; + let i_l = scenery.add_node(&lens)?; let mut wedge = Wedge::new( "wedge", @@ -35,9 +37,9 @@ fn main() -> OpmResult<()> { .with_tilt(degree!(5.0, 0.0, 0.0))?; wedge.set_coating(&PortType::Input, "front", &CoatingType::Fresnel)?; wedge.set_coating(&PortType::Output, "rear", &CoatingType::Fresnel)?; - let i_w = scenery.add_node(wedge)?; + let i_w = scenery.add_node(&wedge)?; - let i_sd2 = scenery.add_node(SpotDiagram::default())?; + let i_sd2 = scenery.add_node(&SpotDiagram::default())?; scenery.connect_nodes(i_src, "out1", i_sd, "in1", millimeter!(20.0))?; scenery.connect_nodes(i_sd, "out1", i_l, "front", millimeter!(80.0))?; scenery.connect_nodes(i_l, "rear", i_w, "front", millimeter!(70.0))?; diff --git a/opossum/examples/grating_examples/detector_group.rs b/opossum/examples/grating_examples/detector_group.rs index e1b68ec9552d1fb56b9622486064f27b13038a2e..a6510bf0c2c1d90b0e7c24326cc8cdf1784c9092 100644 --- a/opossum/examples/grating_examples/detector_group.rs +++ b/opossum/examples/grating_examples/detector_group.rs @@ -8,21 +8,21 @@ use opossum::{ pub fn detector_group() -> OpmResult<NodeGroup> { let mut cb = NodeGroup::new("Detector Group"); - let i_prop_vis_top_view = cb.add_node(RayPropagationVisualizer::new( + let i_prop_vis_top_view = cb.add_node(&RayPropagationVisualizer::new( "Ray_positions_top", Some(Vector3::y()), )?)?; - let i_prop_vis_side_view = cb.add_node(RayPropagationVisualizer::new( + let i_prop_vis_side_view = cb.add_node(&RayPropagationVisualizer::new( "Ray_positions_side", Some(Vector3::x()), )?)?; - let paraxial_lens = cb.add_node(ParaxialSurface::new("ideal lens", millimeter!(500.))?)?; + let paraxial_lens = cb.add_node(&ParaxialSurface::new("ideal lens", millimeter!(500.))?)?; let spot_monitor = SpotDiagram::new("spot diagram"); // let rect_config = RectangleConfig::new(millimeter!(150.), millimeter!(150.), micrometer!(0.,0.))?; // let aperture = Aperture::BinaryRectangle(rect_config); // spot_monitor.set_aperture(&PortType::Input, "in1", &aperture)?; // spot_monitor.set_property("plot_aperture", true.into())?; - let spot_diag = cb.add_node(spot_monitor)?; + let spot_diag = cb.add_node(&spot_monitor)?; cb.connect_nodes(paraxial_lens, "rear", spot_diag, "in1", millimeter!(500.0))?; cb.connect_nodes( @@ -40,7 +40,7 @@ pub fn detector_group() -> OpmResult<NodeGroup> { millimeter!(0.0), )?; - cb.add_node(RayPropagationVisualizer::new( + cb.add_node(&RayPropagationVisualizer::new( "stale visualizer", Some(Vector3::x()), )?)?; diff --git a/opossum/examples/grating_examples/folded_martinez.rs b/opossum/examples/grating_examples/folded_martinez.rs index 84cd1b07a349d7618a7b27247e1d540ff73f49bb..0472fb58bc5e275332d88b725dcab13bb9b5e310 100644 --- a/opossum/examples/grating_examples/folded_martinez.rs +++ b/opossum/examples/grating_examples/folded_martinez.rs @@ -20,12 +20,12 @@ pub fn folded_martinez( let mut cb = NodeGroup::new("Martinez stretcher"); let i_g1 = cb.add_node( - ReflectiveGrating::new("grating 1", num_per_mm!(1740.), -1)? + &ReflectiveGrating::new("grating 1", num_per_mm!(1740.), -1)? .with_rot_from_littrow(alignment_wvl, degree!(-4.))?, )?; // focal length = 996.7 mm (Thorlabs LA1779-B) let lens1 = cb.add_node( - Lens::new( + &Lens::new( "Lens 1", millimeter!(515.1), millimeter!(f64::INFINITY), @@ -35,24 +35,25 @@ pub fn folded_martinez( .with_decenter(centimeter!(0., 0., 0.))?, )?; - let mir_1 = cb - .add_node(ThinMirror::new("mirr").align_like_node_at_distance(lens1, telescope_distance))?; - let mir_1_ref = cb.add_node(NodeReference::from_node(&cb.node(mir_1)?))?; + let mir_1 = cb.add_node( + &ThinMirror::new("mirr").align_like_node_at_distance(lens1, telescope_distance), + )?; + let mir_1_ref = cb.add_node(&NodeReference::from_node(&cb.node(mir_1)?))?; let mut lens_1_ref1 = NodeReference::from_node(&cb.node(lens1)?); lens_1_ref1.set_inverted(true)?; - let lens_1_ref1 = cb.add_node(lens_1_ref1)?; - let lens_1_ref2 = cb.add_node(NodeReference::from_node(&cb.node(lens1)?))?; + let lens_1_ref1 = cb.add_node(&lens_1_ref1)?; + let lens_1_ref2 = cb.add_node(&NodeReference::from_node(&cb.node(lens1)?))?; let mut lens_1_ref3 = NodeReference::from_node(&cb.node(lens1)?); lens_1_ref3.set_inverted(true)?; - let lens_1_ref3 = cb.add_node(lens_1_ref3)?; - let g1ref1 = cb.add_node(NodeReference::from_node(&cb.node(i_g1)?))?; - let g1ref2 = cb.add_node(NodeReference::from_node(&cb.node(i_g1)?))?; - let g1ref3 = cb.add_node(NodeReference::from_node(&cb.node(i_g1)?))?; - let retro_mir1 = cb.add_node(ThinMirror::new("retro_mir1"))?; + let lens_1_ref3 = cb.add_node(&lens_1_ref3)?; + let g1ref1 = cb.add_node(&NodeReference::from_node(&cb.node(i_g1)?))?; + let g1ref2 = cb.add_node(&NodeReference::from_node(&cb.node(i_g1)?))?; + let g1ref3 = cb.add_node(&NodeReference::from_node(&cb.node(i_g1)?))?; + let retro_mir1 = cb.add_node(&ThinMirror::new("retro_mir1"))?; // let retro_mir1 = - // cb.add_node(ThinMirror::new("retro_mir1").with_tilt(degree!(-45., 0., 0.))?)?; + // cb.add_node(&ThinMirror::new("retro_mir1").with_tilt(degree!(-45., 0., 0.))?)?; // let retro_mir2 = - // cb.add_node(ThinMirror::new("retro_mir2").with_tilt(degree!(-45., 0., 0.))?)?; + // cb.add_node(&ThinMirror::new("retro_mir2").with_tilt(degree!(-45., 0., 0.))?)?; //first grating pass up to 0° mirror cb.connect_nodes( diff --git a/opossum/examples/grating_examples/folded_martinez_longer_f.rs b/opossum/examples/grating_examples/folded_martinez_longer_f.rs index 2231aa935834bbf518c803f22425f69c32863072..4a557f4fd751ef363a9b6cffe8ab562335301997 100644 --- a/opossum/examples/grating_examples/folded_martinez_longer_f.rs +++ b/opossum/examples/grating_examples/folded_martinez_longer_f.rs @@ -20,12 +20,12 @@ pub fn folded_martinez_longer_f( let mut cb = NodeGroup::new("Martinez stretcher"); let i_g1 = cb.add_node( - ReflectiveGrating::new("grating 1", num_per_mm!(1740.), -1)? + &ReflectiveGrating::new("grating 1", num_per_mm!(1740.), -1)? .with_rot_from_littrow(alignment_wvl, degree!(-4.))?, )?; // focal length = 996.7 mm (Thorlabs LA1779-B) let lens1 = cb.add_node( - Lens::new( + &Lens::new( "Lens 1", millimeter!(1250.), millimeter!(f64::INFINITY), @@ -35,24 +35,25 @@ pub fn folded_martinez_longer_f( .with_decenter(centimeter!(0., 0., 0.))?, )?; - let mir_1 = cb - .add_node(ThinMirror::new("mirr").align_like_node_at_distance(lens1, telescope_distance))?; - let mir_1_ref = cb.add_node(NodeReference::from_node(&cb.node(mir_1)?))?; + let mir_1 = cb.add_node( + &ThinMirror::new("mirr").align_like_node_at_distance(lens1, telescope_distance), + )?; + let mir_1_ref = cb.add_node(&NodeReference::from_node(&cb.node(mir_1)?))?; let mut lens_1_ref1 = NodeReference::from_node(&cb.node(lens1)?); lens_1_ref1.set_inverted(true)?; - let lens_1_ref1 = cb.add_node(lens_1_ref1)?; - let lens_1_ref2 = cb.add_node(NodeReference::from_node(&cb.node(lens1)?))?; + let lens_1_ref1 = cb.add_node(&lens_1_ref1)?; + let lens_1_ref2 = cb.add_node(&NodeReference::from_node(&cb.node(lens1)?))?; let mut lens_1_ref3 = NodeReference::from_node(&cb.node(lens1)?); lens_1_ref3.set_inverted(true)?; - let lens_1_ref3 = cb.add_node(lens_1_ref3)?; - let g1ref1 = cb.add_node(NodeReference::from_node(&cb.node(i_g1)?))?; - let g1ref2 = cb.add_node(NodeReference::from_node(&cb.node(i_g1)?))?; - let g1ref3 = cb.add_node(NodeReference::from_node(&cb.node(i_g1)?))?; - let retro_mir1 = cb.add_node(ThinMirror::new("retro_mir1"))?; + let lens_1_ref3 = cb.add_node(&lens_1_ref3)?; + let g1ref1 = cb.add_node(&NodeReference::from_node(&cb.node(i_g1)?))?; + let g1ref2 = cb.add_node(&NodeReference::from_node(&cb.node(i_g1)?))?; + let g1ref3 = cb.add_node(&NodeReference::from_node(&cb.node(i_g1)?))?; + let retro_mir1 = cb.add_node(&ThinMirror::new("retro_mir1"))?; // let retro_mir1 = - // cb.add_node(ThinMirror::new("retro_mir1").with_tilt(degree!(-45., 0., 0.))?)?; + // cb.add_node(&ThinMirror::new("retro_mir1").with_tilt(degree!(-45., 0., 0.))?)?; // let retro_mir2 = - // cb.add_node(ThinMirror::new("retro_mir2").with_tilt(degree!(-45., 0., 0.))?)?; + // cb.add_node(&ThinMirror::new("retro_mir2").with_tilt(degree!(-45., 0., 0.))?)?; //first grating pass up to 0° mirror cb.connect_nodes( diff --git a/opossum/examples/grating_examples/folded_martinez_paraxial_lens.rs b/opossum/examples/grating_examples/folded_martinez_paraxial_lens.rs index 9856641ac18431f61a90a773a182f32cd6b932a9..341a0389db58a80c6db41216a0aaecdc5cd900c4 100644 --- a/opossum/examples/grating_examples/folded_martinez_paraxial_lens.rs +++ b/opossum/examples/grating_examples/folded_martinez_paraxial_lens.rs @@ -18,32 +18,33 @@ pub fn folded_martinez_paraxial_lens( let mut cb = NodeGroup::new("Martinez stretcher"); let i_g1 = cb.add_node( - ReflectiveGrating::new("grating 1", num_per_mm!(1740.), -1)? + &ReflectiveGrating::new("grating 1", num_per_mm!(1740.), -1)? .with_rot_from_littrow(alignment_wvl, degree!(-4.))?, )?; // focal length = 996.7 mm (Thorlabs LA1779-B) let lens1 = cb.add_node( - ParaxialSurface::new("paraxial lens", telescope_distance)? + &ParaxialSurface::new("paraxial lens", telescope_distance)? .with_decenter(centimeter!(0., 1., 0.))?, )?; - let mir_1 = cb - .add_node(ThinMirror::new("mirr").align_like_node_at_distance(lens1, telescope_distance))?; - let mir_1_ref = cb.add_node(NodeReference::from_node(&cb.node(mir_1)?))?; + let mir_1 = cb.add_node( + &ThinMirror::new("mirr").align_like_node_at_distance(lens1, telescope_distance), + )?; + let mir_1_ref = cb.add_node(&NodeReference::from_node(&cb.node(mir_1)?))?; let mut lens_1_ref1 = NodeReference::from_node(&cb.node(lens1)?); lens_1_ref1.set_inverted(true)?; - let lens_1_ref1 = cb.add_node(lens_1_ref1)?; - let lens_1_ref2 = cb.add_node(NodeReference::from_node(&cb.node(lens1)?))?; + let lens_1_ref1 = cb.add_node(&lens_1_ref1)?; + let lens_1_ref2 = cb.add_node(&NodeReference::from_node(&cb.node(lens1)?))?; let mut lens_1_ref3 = NodeReference::from_node(&cb.node(lens1)?); lens_1_ref3.set_inverted(true)?; - let lens_1_ref3 = cb.add_node(lens_1_ref3)?; - let g1ref1 = cb.add_node(NodeReference::from_node(&cb.node(i_g1)?))?; - let g1ref2 = cb.add_node(NodeReference::from_node(&cb.node(i_g1)?))?; - let g1ref3 = cb.add_node(NodeReference::from_node(&cb.node(i_g1)?))?; + let lens_1_ref3 = cb.add_node(&lens_1_ref3)?; + let g1ref1 = cb.add_node(&NodeReference::from_node(&cb.node(i_g1)?))?; + let g1ref2 = cb.add_node(&NodeReference::from_node(&cb.node(i_g1)?))?; + let g1ref3 = cb.add_node(&NodeReference::from_node(&cb.node(i_g1)?))?; let retro_mir1 = - cb.add_node(ThinMirror::new("retro_mir1").with_tilt(degree!(-45., 0., 0.))?)?; + cb.add_node(&ThinMirror::new("retro_mir1").with_tilt(degree!(-45., 0., 0.))?)?; let retro_mir2 = - cb.add_node(ThinMirror::new("retro_mir2").with_tilt(degree!(-45., 0., 0.))?)?; + cb.add_node(&ThinMirror::new("retro_mir2").with_tilt(degree!(-45., 0., 0.))?)?; //first grating pass up to 0° mirror cb.connect_nodes(i_g1, "diffracted", lens1, "front", millimeter!(800.))?; diff --git a/opossum/examples/grating_examples/grating_examples.rs b/opossum/examples/grating_examples/grating_examples.rs index 053e3d8d3b63ff2440f50d0be4983eb624e93899..0475fc14317e44492d88d4022c2214ceb955dd40 100644 --- a/opossum/examples/grating_examples/grating_examples.rs +++ b/opossum/examples/grating_examples/grating_examples.rs @@ -66,9 +66,9 @@ fn main() -> OpmResult<()> { //////////////////////////////////// let mut scenery = NodeGroup::new("treacy compressor"); - let i_src = scenery.add_node(src.clone())?; - let compressor_node = scenery.add_node(treacy_compressor(alignment_wvl)?)?; - let detectors = scenery.add_node(detector_group()?)?; + let i_src = scenery.add_node(&src.clone())?; + let compressor_node = scenery.add_node(&treacy_compressor(alignment_wvl)?)?; + let detectors = scenery.add_node(&detector_group()?)?; scenery.connect_nodes(i_src, "out1", compressor_node, "input", millimeter!(400.0))?; scenery.connect_nodes( @@ -91,10 +91,10 @@ fn main() -> OpmResult<()> { let telescope_distance = millimeter!(1015.515 * 0.995); let mut scenery = NodeGroup::new("non-ideal folded Martinez stretcher"); - let i_src = scenery.add_node(src.clone())?; + let i_src = scenery.add_node(&src.clone())?; let stretcher_node = - scenery.add_node(folded_martinez(telescope_distance, &nbk7, alignment_wvl)?)?; - let detectors = scenery.add_node(detector_group()?)?; + scenery.add_node(&folded_martinez(telescope_distance, &nbk7, alignment_wvl)?)?; + let detectors = scenery.add_node(&detector_group()?)?; scenery.connect_nodes(i_src, "out1", stretcher_node, "input", millimeter!(400.0))?; scenery.connect_nodes( @@ -119,10 +119,10 @@ fn main() -> OpmResult<()> { let telescope_distance = millimeter!(1017.14885); let mut scenery = NodeGroup::new("ideal folded Martinez stretcher"); - let i_src = scenery.add_node(src.clone())?; + let i_src = scenery.add_node(&src.clone())?; let stretcher_node = - scenery.add_node(folded_martinez(telescope_distance, &nbk7, alignment_wvl)?)?; - let detectors = scenery.add_node(detector_group()?)?; + scenery.add_node(&folded_martinez(telescope_distance, &nbk7, alignment_wvl)?)?; + let detectors = scenery.add_node(&detector_group()?)?; scenery.connect_nodes(i_src, "out1", stretcher_node, "input", millimeter!(400.0))?; scenery.connect_nodes( @@ -145,10 +145,10 @@ fn main() -> OpmResult<()> { let telescope_distance = millimeter!(1015.515); let mut scenery = NodeGroup::new("ideal folded Martinez stretcher circle of least conf"); - let i_src = scenery.add_node(src.clone())?; + let i_src = scenery.add_node(&src.clone())?; let stretcher_node = - scenery.add_node(folded_martinez(telescope_distance, &nbk7, alignment_wvl)?)?; - let detectors = scenery.add_node(detector_group()?)?; + scenery.add_node(&folded_martinez(telescope_distance, &nbk7, alignment_wvl)?)?; + let detectors = scenery.add_node(&detector_group()?)?; scenery.connect_nodes(i_src, "out1", stretcher_node, "input", millimeter!(400.0))?; scenery.connect_nodes( @@ -173,13 +173,13 @@ fn main() -> OpmResult<()> { let telescope_distance = millimeter!(2467.1); let mut scenery = NodeGroup::new("ideal folded Martinez stretcher longer f"); - let i_src = scenery.add_node(src.clone())?; - let stretcher_node = scenery.add_node(folded_martinez_longer_f( + let i_src = scenery.add_node(&src.clone())?; + let stretcher_node = scenery.add_node(&folded_martinez_longer_f( telescope_distance, &nbk7, alignment_wvl, )?)?; - let detectors = scenery.add_node(detector_group()?)?; + let detectors = scenery.add_node(&detector_group()?)?; scenery.connect_nodes(i_src, "out1", stretcher_node, "input", millimeter!(400.0))?; scenery.connect_nodes( @@ -204,13 +204,13 @@ fn main() -> OpmResult<()> { let telescope_distance = millimeter!(1017.14885); let mut scenery = NodeGroup::new("achromatic ideal folded Martinez stretcher"); - let i_src = scenery.add_node(src.clone())?; - let stretcher_node = scenery.add_node(folded_martinez( + let i_src = scenery.add_node(&src.clone())?; + let stretcher_node = scenery.add_node(&folded_martinez( telescope_distance, &RefrIndexConst::new(nbk7.get_refractive_index(nanometer!(1054.))?)?, alignment_wvl, )?)?; - let detectors = scenery.add_node(detector_group()?)?; + let detectors = scenery.add_node(&detector_group()?)?; scenery.connect_nodes(i_src, "out1", stretcher_node, "input", millimeter!(400.0))?; scenery.connect_nodes( @@ -235,12 +235,12 @@ fn main() -> OpmResult<()> { let telescope_distance = millimeter!(1017.14885); let mut scenery = NodeGroup::new("paraxial folded Martinez stretcher"); - let i_src = scenery.add_node(src.clone())?; - let stretcher_node = scenery.add_node(folded_martinez_paraxial_lens( + let i_src = scenery.add_node(&src.clone())?; + let stretcher_node = scenery.add_node(&folded_martinez_paraxial_lens( telescope_distance, alignment_wvl, )?)?; - let detectors = scenery.add_node(detector_group()?)?; + let detectors = scenery.add_node(&detector_group()?)?; scenery.connect_nodes(i_src, "out1", stretcher_node, "input", millimeter!(400.0))?; scenery.connect_nodes( @@ -288,9 +288,9 @@ fn main() -> OpmResult<()> { src.set_alignment_wavelength(alignment_wvl)?; src.set_isometry(Isometry::identity()); - let i_src = scenery.add_node(src)?; + let i_src = scenery.add_node(&src)?; // focal length = 996.7 mm (Thorlabs LA1779-B) - let lens1 = scenery.add_node(Lens::new( + let lens1 = scenery.add_node(&Lens::new( "Lens 1", millimeter!(515.1), millimeter!(f64::INFINITY), @@ -298,14 +298,15 @@ fn main() -> OpmResult<()> { &nbk7, )?)?; let mir_1 = - scenery.add_node(ThinMirror::new("mirr").align_like_node_at_distance(lens1, tel_dist))?; + scenery.add_node(&ThinMirror::new("mirr").align_like_node_at_distance(lens1, tel_dist))?; let mut lens_1_ref1 = NodeReference::from_node(&scenery.node(lens1)?); lens_1_ref1.set_inverted(true)?; - let lens_1_ref1 = scenery.add_node(lens_1_ref1)?; + let lens_1_ref1 = scenery.add_node(&lens_1_ref1)?; - let paraxial_lens = scenery.add_node(ParaxialSurface::new("ideal lens", millimeter!(500.))?)?; - let spot_diag = scenery.add_node(SpotDiagram::new("spot diagram"))?; - let i_prop_vis = scenery.add_node(RayPropagationVisualizer::new( + let paraxial_lens = + scenery.add_node(&ParaxialSurface::new("ideal lens", millimeter!(500.))?)?; + let spot_diag = scenery.add_node(&SpotDiagram::new("spot diagram"))?; + let i_prop_vis = scenery.add_node(&RayPropagationVisualizer::new( "Ray_positions", Some(Vector3::y()), )?)?; diff --git a/opossum/examples/grating_examples/treacy_compressor.rs b/opossum/examples/grating_examples/treacy_compressor.rs index ad1a4c6c22ae628d0f26613f8780e9f709c69b53..9a6eabe56517402bc7a1a3416d49242f6985a869 100644 --- a/opossum/examples/grating_examples/treacy_compressor.rs +++ b/opossum/examples/grating_examples/treacy_compressor.rs @@ -11,22 +11,22 @@ pub fn treacy_compressor(alignment_wvl: Length) -> OpmResult<NodeGroup> { let mut cb = NodeGroup::new("Treacy compressor"); let i_g1 = cb.add_node( - ReflectiveGrating::new("grating 1", num_per_mm!(1740.), -1)? + &ReflectiveGrating::new("grating 1", num_per_mm!(1740.), -1)? .with_rot_from_littrow(alignment_wvl, degree!(-4.))?, )?; let i_g2 = cb.add_node( - ReflectiveGrating::new("grating 2", num_per_mm!(1740.), -1)? + &ReflectiveGrating::new("grating 2", num_per_mm!(1740.), -1)? .to_rot_from_littrow(alignment_wvl, degree!(-4.) + radian!(10e-6))?, )?; let i_g3 = cb.add_node( - ReflectiveGrating::new("grating 3", num_per_mm!(1740.), 1)? + &ReflectiveGrating::new("grating 3", num_per_mm!(1740.), 1)? .with_rot_from_littrow(alignment_wvl, degree!(4.))?, )?; let i_g4 = cb.add_node( - ReflectiveGrating::new("grating 4", num_per_mm!(1740.), 1)? + &ReflectiveGrating::new("grating 4", num_per_mm!(1740.), 1)? .to_rot_from_littrow(alignment_wvl, degree!(4.))?, )?; diff --git a/opossum/examples/group_reverse.rs b/opossum/examples/group_reverse.rs index db4310667fc72c2455863a4f2cbff8a6cffdf371..c50da6bb015fd1261f66115c98c781dbf70aa110 100644 --- a/opossum/examples/group_reverse.rs +++ b/opossum/examples/group_reverse.rs @@ -14,7 +14,7 @@ use uom::si::f64::Length; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::new("Inverse Group test"); - let i_s = scenery.add_node(Source::new( + let i_s = scenery.add_node(&Source::new( "Source", &LightData::Energy(DataEnergy { spectrum: create_he_ne_spec(1.0)?, @@ -23,16 +23,16 @@ fn main() -> OpmResult<()> { let mut group = NodeGroup::default(); group.set_expand_view(true)?; - let g_n1 = group.add_node(Dummy::new("node1"))?; - let g_n2 = group.add_node(Dummy::new("node2"))?; + let g_n1 = group.add_node(&Dummy::new("node1"))?; + let g_n2 = group.add_node(&Dummy::new("node2"))?; group.connect_nodes(g_n1, "rear", g_n2, "front", Length::zero())?; group.map_input_port(g_n1, "front", "in1")?; group.map_output_port(g_n2, "rear", "out1")?; group.set_inverted(true)?; - let i_g = scenery.add_node(group)?; - let i_d = scenery.add_node(EnergyMeter::default())?; + let i_g = scenery.add_node(&group)?; + let i_d = scenery.add_node(&EnergyMeter::default())?; scenery.connect_nodes(i_s, "out1", i_g, "out1", Length::zero())?; scenery.connect_nodes(i_g, "in1", i_d, "in1", Length::zero())?; diff --git a/opossum/examples/group_test.rs b/opossum/examples/group_test.rs index 6521e18def9d0516747a954dd588322697f2937d..b6f6827d6cd6bb9e388cc0c4f573ef9a3fe3834d 100644 --- a/opossum/examples/group_test.rs +++ b/opossum/examples/group_test.rs @@ -14,18 +14,18 @@ use std::path::Path; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::new("group test"); - let i_src = scenery.add_node(collimated_line_ray_source( + let i_src = scenery.add_node(&collimated_line_ray_source( millimeter!(20.0), joule!(1.0), 6, )?)?; let mut group1 = NodeGroup::new("group 1"); group1.set_expand_view(true)?; - let i_g1_l = group1.add_node(Lens::default())?; + let i_g1_l = group1.add_node(&Lens::default())?; group1.map_input_port(i_g1_l, "front", "input")?; - let i_g1_bs = group1.add_node(BeamSplitter::default())?; + let i_g1_bs = group1.add_node(&BeamSplitter::default())?; group1.connect_nodes(i_g1_l, "rear", i_g1_bs, "input1", millimeter!(100.0))?; - let i_g1_m = group1.add_node(ThinMirror::default().with_tilt(degree!(45.0, 0.0, 0.0))?)?; + let i_g1_m = group1.add_node(&ThinMirror::default().with_tilt(degree!(45.0, 0.0, 0.0))?)?; group1.connect_nodes( i_g1_bs, "out1_trans1_refl2", @@ -36,12 +36,12 @@ fn main() -> OpmResult<()> { group1.map_output_port(i_g1_bs, "out2_trans2_refl1", "output1")?; group1.map_output_port(i_g1_m, "reflected", "output2")?; - let scene_g1 = scenery.add_node(group1)?; + let scene_g1 = scenery.add_node(&group1)?; scenery.connect_nodes(i_src, "out1", scene_g1, "input", millimeter!(50.0))?; - let i_prop1 = scenery.add_node(RayPropagationVisualizer::new("direct", None)?)?; - let i_prop2 = scenery.add_node(RayPropagationVisualizer::new("mirrored", None)?)?; + let i_prop1 = scenery.add_node(&RayPropagationVisualizer::new("direct", None)?)?; + let i_prop2 = scenery.add_node(&RayPropagationVisualizer::new("mirrored", None)?)?; scenery.connect_nodes(scene_g1, "output1", i_prop1, "in1", millimeter!(100.0))?; scenery.connect_nodes(scene_g1, "output2", i_prop2, "in1", millimeter!(150.0))?; diff --git a/opossum/examples/hhts/cambox_1w.rs b/opossum/examples/hhts/cambox_1w.rs index 73ab9336898886406e03d3abc496d430e160d7aa..e8c62a27718e0017f0da359d35c6616608f72166 100644 --- a/opossum/examples/hhts/cambox_1w.rs +++ b/opossum/examples/hhts/cambox_1w.rs @@ -14,21 +14,21 @@ pub fn cambox_1w() -> OpmResult<NodeGroup> { let mut cb = NodeGroup::new("CamBox 1w"); - let d1 = cb.add_node(Dummy::new("d1"))?; - let bs1 = cb.add_node(BeamSplitter::new("bs1", &SplittingConfig::Ratio(0.5))?)?; + let d1 = cb.add_node(&Dummy::new("d1"))?; + let bs1 = cb.add_node(&BeamSplitter::new("bs1", &SplittingConfig::Ratio(0.5))?)?; cb.connect_nodes(d1, "rear", bs1, "input1", millimeter!(35.0))?; // FF path - let bs_ff = cb.add_node(BeamSplitter::new("bs_ff", &SplittingConfig::Ratio(0.04))?)?; - let ff_lens = cb.add_node(ParaxialSurface::new("FF lens", millimeter!(100.0))?)?; + let bs_ff = cb.add_node(&BeamSplitter::new("bs_ff", &SplittingConfig::Ratio(0.04))?)?; + let ff_lens = cb.add_node(&ParaxialSurface::new("FF lens", millimeter!(100.0))?)?; let mut node = SpotDiagram::new("FF cam"); node.set_aperture(&PortType::Input, "in1", &cam_aperture)?; - let ff_cam = cb.add_node(node)?; + let ff_cam = cb.add_node(&node)?; let mut ff_fluence = FluenceDetector::new("FF fluence"); ff_fluence.set_aperture(&PortType::Input, "in1", &cam_aperture)?; - let ff_fluence_cam = cb.add_node(ff_fluence)?; + let ff_fluence_cam = cb.add_node(&ff_fluence)?; cb.connect_nodes( bs1, @@ -48,17 +48,17 @@ pub fn cambox_1w() -> OpmResult<NodeGroup> { cb.connect_nodes(ff_cam, "out1", ff_fluence_cam, "in1", millimeter!(0.0))?; // NF path - let nf_lens1 = cb.add_node(ParaxialSurface::new("NF lens1", millimeter!(125.0))?)?; - let nf_lens2 = cb.add_node(ParaxialSurface::new("NF lens2", millimeter!(125.0))?)?; - let nf_bs = cb.add_node(BeamSplitter::new("nf bs", &SplittingConfig::Ratio(0.5))?)?; + let nf_lens1 = cb.add_node(&ParaxialSurface::new("NF lens1", millimeter!(125.0))?)?; + let nf_lens2 = cb.add_node(&ParaxialSurface::new("NF lens2", millimeter!(125.0))?)?; + let nf_bs = cb.add_node(&BeamSplitter::new("nf bs", &SplittingConfig::Ratio(0.5))?)?; let mut node = SpotDiagram::new("NF cam"); node.set_aperture(&PortType::Input, "in1", &cam_aperture)?; node.set_property("plot_aperture", true.into())?; - let nf_cam = cb.add_node(node)?; + let nf_cam = cb.add_node(&node)?; let mut nf_fluence = FluenceDetector::new("NF fluence"); nf_fluence.set_aperture(&PortType::Input, "in1", &cam_aperture)?; - let nf_fluence_cam = cb.add_node(nf_fluence)?; + let nf_fluence_cam = cb.add_node(&nf_fluence)?; cb.connect_nodes( bs1, diff --git a/opossum/examples/hhts/cambox_2w.rs b/opossum/examples/hhts/cambox_2w.rs index 270b1459fe1072745fd698e47f0fa7b6deba3ef3..a68ad3e35bcdaa0c77078f420fec779e47291db6 100644 --- a/opossum/examples/hhts/cambox_2w.rs +++ b/opossum/examples/hhts/cambox_2w.rs @@ -13,22 +13,22 @@ pub fn cambox_2w() -> OpmResult<NodeGroup> { let mut cb = NodeGroup::new("CamBox 2w"); - let d1 = cb.add_node(Dummy::new("d1"))?; - let bs1 = cb.add_node(BeamSplitter::new("bs1", &SplittingConfig::Ratio(0.5))?)?; + let d1 = cb.add_node(&Dummy::new("d1"))?; + let bs1 = cb.add_node(&BeamSplitter::new("bs1", &SplittingConfig::Ratio(0.5))?)?; cb.connect_nodes(d1, "rear", bs1, "input1", millimeter!(35.0))?; // FF path - let bs_ff = cb.add_node(BeamSplitter::new("bs_ff", &SplittingConfig::Ratio(0.04))?)?; - let ff_lens = cb.add_node(ParaxialSurface::new("FF lens", millimeter!(100.0))?)?; + let bs_ff = cb.add_node(&BeamSplitter::new("bs_ff", &SplittingConfig::Ratio(0.04))?)?; + let ff_lens = cb.add_node(&ParaxialSurface::new("FF lens", millimeter!(100.0))?)?; let mut node = SpotDiagram::new("FF cam"); //node.set_aperture(&PortType::Input, "in1", &cam_aperture)?; node.set_property("plot_aperture", true.into())?; - let ff_cam = cb.add_node(node)?; + let ff_cam = cb.add_node(&node)?; let ff_fluence = FluenceDetector::new("FF fluence"); //ff_fluence.set_aperture(&PortType::Input, "in1", &cam_aperture)?; - let ff_fluence_cam = cb.add_node(ff_fluence)?; + let ff_fluence_cam = cb.add_node(&ff_fluence)?; cb.connect_nodes( bs1, @@ -48,16 +48,16 @@ pub fn cambox_2w() -> OpmResult<NodeGroup> { cb.connect_nodes(ff_cam, "out1", ff_fluence_cam, "in1", millimeter!(0.0))?; // NF path - let nf_lens1 = cb.add_node(ParaxialSurface::new("NF lens1", millimeter!(125.0))?)?; - let nf_lens2 = cb.add_node(ParaxialSurface::new("NF lens2", millimeter!(125.0))?)?; - let nf_bs = cb.add_node(BeamSplitter::new("nf bs", &SplittingConfig::Ratio(0.5))?)?; + let nf_lens1 = cb.add_node(&ParaxialSurface::new("NF lens1", millimeter!(125.0))?)?; + let nf_lens2 = cb.add_node(&ParaxialSurface::new("NF lens2", millimeter!(125.0))?)?; + let nf_bs = cb.add_node(&BeamSplitter::new("nf bs", &SplittingConfig::Ratio(0.5))?)?; let node = SpotDiagram::new("NF cam"); //node.set_aperture(&PortType::Input, "in1", &cam_aperture)?; - let nf_cam = cb.add_node(node)?; + let nf_cam = cb.add_node(&node)?; let nf_fluence = FluenceDetector::new("NF fluence"); // nf_fluence.set_aperture(&PortType::Input, "in1", &cam_aperture)?; - let nf_fluence_cam = cb.add_node(nf_fluence)?; + let nf_fluence_cam = cb.add_node(&nf_fluence)?; cb.connect_nodes( bs1, diff --git a/opossum/examples/hhts/hhts.rs b/opossum/examples/hhts/hhts.rs index 0082486c7bf30578959441b83f9631a03a72d197..69865d4809e4818bc9f45d230f8878bf30a9470c 100644 --- a/opossum/examples/hhts/hhts.rs +++ b/opossum/examples/hhts/hhts.rs @@ -140,20 +140,20 @@ fn main() -> OpmResult<()> { let mut scenery = NodeGroup::new("HHT Sensor"); let mut src = Source::new("Source", &LightData::Geometric(rays)); src.set_isometry(Isometry::identity()); - let src = scenery.add_node(src)?; - let input_group = scenery.add_node(hhts_input()?)?; + let src = scenery.add_node(&src)?; + let input_group = scenery.add_node(&hhts_input()?)?; scenery.connect_nodes(src, "out1", input_group, "input", Length::zero())?; // T1 let mut group_t1 = NodeGroup::new("T1"); - let t1_l1a = group_t1.add_node(Lens::new( + let t1_l1a = group_t1.add_node(&Lens::new( "T1 L1a", millimeter!(518.34008), millimeter!(-847.40402), millimeter!(30.0), &refr_index_hk9l, )?)?; - let t1_l1b = group_t1.add_node(Lens::new( + let t1_l1b = group_t1.add_node(&Lens::new( "T1 L1b", millimeter!(-788.45031), millimeter!(-2551.88619), @@ -169,15 +169,15 @@ fn main() -> OpmResult<()> { )?; // node.set_aperture(&PortType::Input, "front", &a_2inch)?; // node.set_aperture(&PortType::Output, "rear", &a_2inch)?; - let t1_l2a = group_t1.add_node(node)?; - let t1_l2b = group_t1.add_node(Lens::new( + let t1_l2a = group_t1.add_node(&node)?; + let t1_l2b = group_t1.add_node(&Lens::new( "T1 L2b", millimeter!(76.76954), millimeter!(-118.59590), millimeter!(14.0), &refr_index_hzf52, )?)?; - let t1_l2c = group_t1.add_node(Lens::new( + let t1_l2c = group_t1.add_node(&Lens::new( "T1 L2c", millimeter!(-63.45837), millimeter!(66.33014), @@ -194,7 +194,7 @@ fn main() -> OpmResult<()> { group_t1.map_output_port(t1_l2c, "rear", "output")?; group_t1.set_expand_view(false)?; - let t1 = scenery.add_node(group_t1)?; + let t1 = scenery.add_node(&group_t1)?; scenery.connect_nodes(input_group, "output", t1, "input", millimeter!(100.0))?; @@ -215,7 +215,7 @@ fn main() -> OpmResult<()> { // real spectrum (Thorlabs HBSY21) //let hbsyx2 = SplittingConfig::Spectrum(Spectrum::from_csv("opossum/examples/hhts/HBSYx2_Reflectivity_45deg_unpol.csv")?); - let bs = group_bs.add_node(BeamSplitter::new("Dichroic BS HBSY21", &short_pass)?)?; + let bs = group_bs.add_node(&BeamSplitter::new("Dichroic BS HBSY21", &short_pass)?)?; // Long pass filter (1w) let felh1000 = FilterType::Spectrum(Spectrum::from_csv( @@ -223,7 +223,7 @@ fn main() -> OpmResult<()> { )?); let mut node = IdealFilter::new("1w Longpass filter", &felh1000)?; node.set_aperture(&PortType::Input, "front", &a_1inch)?; - let filter_1w = group_bs.add_node(node)?; + let filter_1w = group_bs.add_node(&node)?; group_bs.connect_nodes(bs, "out2_trans2_refl1", filter_1w, "front", Length::zero())?; // Long pass filter (2w) @@ -232,35 +232,35 @@ fn main() -> OpmResult<()> { )?); let mut node = IdealFilter::new("2w Shortpass filter", &fesh0700)?; node.set_aperture(&PortType::Input, "front", &a_1inch)?; - let filter_2w = group_bs.add_node(node)?; + let filter_2w = group_bs.add_node(&node)?; group_bs.connect_nodes(bs, "out1_trans1_refl2", filter_2w, "front", Length::zero())?; group_bs.map_input_port(bs, "input1", "input")?; group_bs.map_output_port(filter_1w, "rear", "output_1w")?; group_bs.map_output_port(filter_2w, "rear", "output_2w")?; - let bs_group = scenery.add_node(group_bs)?; + let bs_group = scenery.add_node(&group_bs)?; scenery.connect_nodes(t1, "output", bs_group, "input", millimeter!(100.0))?; // 1w branch // T2_1w let mut group_t2_1w = NodeGroup::new("T2 1w"); - let t2_1w_in = group_t2_1w.add_node(Lens::new( + let t2_1w_in = group_t2_1w.add_node(&Lens::new( "T2 1w In", millimeter!(405.38435), millimeter!(-702.52114), millimeter!(9.5), &refr_index_hk9l, )?)?; - let t2_1w_field = group_t2_1w.add_node(Lens::new( + let t2_1w_field = group_t2_1w.add_node(&Lens::new( "T2 1w Field", millimeter!(179.59020), millimeter!(f64::INFINITY), millimeter!(9.5), &refr_index_hk9l, )?)?; - let t2_1w_exit = group_t2_1w.add_node(Lens::new( + let t2_1w_exit = group_t2_1w.add_node(&Lens::new( "T2 1w Exit", millimeter!(f64::INFINITY), millimeter!(-202.81235), @@ -285,26 +285,26 @@ fn main() -> OpmResult<()> { group_t2_1w.map_input_port(t2_1w_in, "front", "input")?; group_t2_1w.map_output_port(t2_1w_exit, "rear", "output")?; - let t2_1w = scenery.add_node(group_t2_1w)?; + let t2_1w = scenery.add_node(&group_t2_1w)?; // T3_1w let mut group_t3_1w = NodeGroup::new("T3 1w"); - let t3_1w_input = group_t3_1w.add_node(Lens::new( + let t3_1w_input = group_t3_1w.add_node(&Lens::new( "T3 1w Input", millimeter!(f64::INFINITY), millimeter!(-417.35031), millimeter!(9.5), &refr_index_hk9l, )?)?; - let t3_1w_exit = group_t3_1w.add_node(Lens::new( + let t3_1w_exit = group_t3_1w.add_node(&Lens::new( "T3 1w Exit", millimeter!(156.35054), millimeter!(f64::INFINITY), millimeter!(9.5), &refr_index_hk9l, )?)?; - let d_1w_12 = group_t3_1w.add_node(Dummy::new("1w d12"))?; + let d_1w_12 = group_t3_1w.add_node(&Dummy::new("1w d12"))?; group_t3_1w.connect_nodes( t3_1w_input, "rear", @@ -316,18 +316,18 @@ fn main() -> OpmResult<()> { group_t3_1w.map_input_port(t3_1w_input, "front", "input")?; group_t3_1w.map_output_port(d_1w_12, "rear", "output")?; - let t3_1w = scenery.add_node(group_t3_1w)?; + let t3_1w = scenery.add_node(&group_t3_1w)?; scenery.connect_nodes(bs_group, "output_1w", t2_1w, "input", millimeter!(537.5190))?; scenery.connect_nodes(t2_1w, "output", t3_1w, "input", millimeter!(664.58900))?; let mut group_det_1w = NodeGroup::new("Detectors 1w"); - let det_prop = group_det_1w.add_node(RayPropagationVisualizer::new("Propagation", None)?)?; - let det_wavefront_1w = group_det_1w.add_node(WaveFront::new("Wavefront"))?; - let cambox_1w = group_det_1w.add_node(cambox_1w()?)?; + let det_prop = group_det_1w.add_node(&RayPropagationVisualizer::new("Propagation", None)?)?; + let det_wavefront_1w = group_det_1w.add_node(&WaveFront::new("Wavefront"))?; + let cambox_1w = group_det_1w.add_node(&cambox_1w()?)?; let det_energy_1w = - group_det_1w.add_node(EnergyMeter::new("Energy", Metertype::IdealEnergyMeter))?; + group_det_1w.add_node(&EnergyMeter::new("Energy", Metertype::IdealEnergyMeter))?; group_det_1w.connect_nodes(det_prop, "out1", det_wavefront_1w, "in1", Length::zero())?; group_det_1w.connect_nodes( @@ -341,7 +341,7 @@ fn main() -> OpmResult<()> { group_det_1w.map_input_port(det_prop, "in1", "input")?; - let det_1w = scenery.add_node(group_det_1w)?; + let det_1w = scenery.add_node(&group_det_1w)?; scenery.connect_nodes(t3_1w, "output", det_1w, "input", Length::zero())?; // 2w branch @@ -349,21 +349,21 @@ fn main() -> OpmResult<()> { // T2_2w let mut group_t2_2w = NodeGroup::new("T2 2w"); - let t2_2w_in = group_t2_2w.add_node(Lens::new( + let t2_2w_in = group_t2_2w.add_node(&Lens::new( "T2 2w In", millimeter!(536.5733), millimeter!(-677.68238), millimeter!(9.5), &refr_index_hk9l, )?)?; - let t2_2w_field = group_t2_2w.add_node(Lens::new( + let t2_2w_field = group_t2_2w.add_node(&Lens::new( "T2 2w Field", millimeter!(208.48421), millimeter!(f64::INFINITY), millimeter!(9.5), &refr_index_hk9l, )?)?; - let t2_2w_exit = group_t2_2w.add_node(Lens::new( + let t2_2w_exit = group_t2_2w.add_node(&Lens::new( "T2 2w Exit", millimeter!(-767.51217), millimeter!(-178.98988), @@ -387,26 +387,26 @@ fn main() -> OpmResult<()> { group_t2_2w.map_input_port(t2_2w_in, "front", "input")?; group_t2_2w.map_output_port(t2_2w_exit, "rear", "output")?; - let t2_2w = scenery.add_node(group_t2_2w)?; + let t2_2w = scenery.add_node(&group_t2_2w)?; // T3_2w let mut group_t3_2w = NodeGroup::new("T3 2w"); - let t3_2w_input = group_t3_2w.add_node(Lens::new( + let t3_2w_input = group_t3_2w.add_node(&Lens::new( "T3 2w Input", millimeter!(932.92634), millimeter!(-724.14405), millimeter!(9.5), &refr_index_hk9l, )?)?; - let t3_2w_exit = group_t3_2w.add_node(Lens::new( + let t3_2w_exit = group_t3_2w.add_node(&Lens::new( "T3 2w Exit", millimeter!(161.31174), millimeter!(-1069.52277), millimeter!(9.5), &refr_index_hk9l, )?)?; - let d_2w_12 = group_t3_2w.add_node(Dummy::new("2w d12"))?; + let d_2w_12 = group_t3_2w.add_node(&Dummy::new("2w d12"))?; group_t3_2w.connect_nodes( t3_2w_input, "rear", @@ -418,7 +418,7 @@ fn main() -> OpmResult<()> { group_t3_2w.map_input_port(t3_2w_input, "front", "input")?; group_t3_2w.map_output_port(d_2w_12, "rear", "output")?; - let t3_2w = scenery.add_node(group_t3_2w)?; + let t3_2w = scenery.add_node(&group_t3_2w)?; scenery.connect_nodes(bs_group, "output_2w", t2_2w, "input", millimeter!(474.589))?; scenery.connect_nodes(t2_2w, "output", t3_2w, "input", millimeter!(622.09000))?; @@ -426,11 +426,12 @@ fn main() -> OpmResult<()> { // 2w detectors let mut group_det_2w = NodeGroup::new("Detectors 2w"); - let det_prop_2w = group_det_2w.add_node(RayPropagationVisualizer::new("Propagation", None)?)?; - let det_wavefront_2w = group_det_2w.add_node(WaveFront::new("Wavefront"))?; + let det_prop_2w = + group_det_2w.add_node(&RayPropagationVisualizer::new("Propagation", None)?)?; + let det_wavefront_2w = group_det_2w.add_node(&WaveFront::new("Wavefront"))?; let det_energy_2w = - group_det_2w.add_node(EnergyMeter::new("Energy", Metertype::IdealEnergyMeter))?; - let cambox_2w = group_det_2w.add_node(cambox_2w()?)?; + group_det_2w.add_node(&EnergyMeter::new("Energy", Metertype::IdealEnergyMeter))?; + let cambox_2w = group_det_2w.add_node(&cambox_2w()?)?; group_det_2w.connect_nodes(det_prop_2w, "out1", det_wavefront_2w, "in1", Length::zero())?; group_det_2w.connect_nodes( @@ -443,7 +444,7 @@ fn main() -> OpmResult<()> { group_det_2w.connect_nodes(det_energy_2w, "out1", cambox_2w, "input", Length::zero())?; group_det_2w.map_input_port(det_prop_2w, "in1", "input")?; - let det_2w = scenery.add_node(group_det_2w)?; + let det_2w = scenery.add_node(&group_det_2w)?; scenery.connect_nodes(t3_2w, "output", det_2w, "input", Length::zero())?; diff --git a/opossum/examples/hhts/hhts_input.rs b/opossum/examples/hhts/hhts_input.rs index 76623b34cb2e6c7d1075fc872aa0410313258eb4..74ec337c17f700e0f8bf4b0e36317f59d5d1f709 100644 --- a/opossum/examples/hhts/hhts_input.rs +++ b/opossum/examples/hhts/hhts_input.rs @@ -16,14 +16,14 @@ pub fn hhts_input() -> OpmResult<NodeGroup> { "opossum/examples/hhts/HHTS_T1_PM_Transmission.csv", )?); let mut group = NodeGroup::new("HHTS Input"); - let d1 = group.add_node(Dummy::new("d1"))?; - let mm15 = group.add_node(BeamSplitter::new("MM15", &dichroic_mirror)?)?; - let window = group.add_node(IdealFilter::new("window", &window_filter)?)?; - let hhts_t1_cm = group.add_node(BeamSplitter::new("HHTS_T1_CM", &dichroic_mirror)?)?; + let d1 = group.add_node(&Dummy::new("d1"))?; + let mm15 = group.add_node(&BeamSplitter::new("MM15", &dichroic_mirror)?)?; + let window = group.add_node(&IdealFilter::new("window", &window_filter)?)?; + let hhts_t1_cm = group.add_node(&BeamSplitter::new("HHTS_T1_CM", &dichroic_mirror)?)?; let meter = EnergyMeter::new("Beamdump", Metertype::IdealEnergyMeter); - let beam_dump = group.add_node(meter)?; + let beam_dump = group.add_node(&meter)?; - let hhts_t1_pm = group.add_node(BeamSplitter::new("HHTS_T1_PM", &double_mirror)?)?; + let hhts_t1_pm = group.add_node(&BeamSplitter::new("HHTS_T1_PM", &double_mirror)?)?; group.connect_nodes(d1, "rear", mm15, "input1", millimeter!(500.0))?; group.connect_nodes( diff --git a/opossum/examples/inverse_beam_splitter_test.rs b/opossum/examples/inverse_beam_splitter_test.rs index d038034b965b08dc451ebe83868e67925177d268..29a2ecd64379276122fda4ae92c4e98bd5b5db4d 100644 --- a/opossum/examples/inverse_beam_splitter_test.rs +++ b/opossum/examples/inverse_beam_splitter_test.rs @@ -14,7 +14,7 @@ use uom::si::f64::Length; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::new("inverse beam splitter test"); - let i_s = scenery.add_node(Source::new( + let i_s = scenery.add_node(&Source::new( "Source", &LightData::Energy(DataEnergy { spectrum: create_he_ne_spec(1.0)?, @@ -22,12 +22,12 @@ fn main() -> OpmResult<()> { ))?; let mut bs = BeamSplitter::new("bs", &SplittingConfig::Ratio(0.6)).unwrap(); bs.set_inverted(true)?; - let i_bs = scenery.add_node(bs)?; - let i_d1 = scenery.add_node(EnergyMeter::new( + let i_bs = scenery.add_node(&bs)?; + let i_d1 = scenery.add_node(&EnergyMeter::new( "Energy meter 1", opossum::nodes::Metertype::IdealEnergyMeter, ))?; - let i_d2 = scenery.add_node(EnergyMeter::new( + let i_d2 = scenery.add_node(&EnergyMeter::new( "Energy meter 2", opossum::nodes::Metertype::IdealEnergyMeter, ))?; diff --git a/opossum/examples/kepler.rs b/opossum/examples/kepler.rs index 5a480a49f5ef19cbbab0fa670bfd45eef7fbc2ff..34d4713f29db5439e2a38f3ec8605577b73a9494 100644 --- a/opossum/examples/kepler.rs +++ b/opossum/examples/kepler.rs @@ -12,7 +12,7 @@ use std::path::Path; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::default(); - let i_src = scenery.add_node(collimated_line_ray_source( + let i_src = scenery.add_node(&collimated_line_ray_source( millimeter!(20.0), joule!(1.0), 3, @@ -20,9 +20,9 @@ fn main() -> OpmResult<()> { let mut lens1 = ParaxialSurface::new("100 mm lens", millimeter!(100.0))?; let circle = CircleConfig::new(millimeter!(25.), millimeter!(0., 0.))?; lens1.set_aperture(&PortType::Input, "front", &Aperture::BinaryCircle(circle))?; - let i_pl1 = scenery.add_node(lens1)?; - let i_pl2 = scenery.add_node(ParaxialSurface::new("50 mm lens", millimeter!(50.0))?)?; - let i_sd3 = scenery.add_node(RayPropagationVisualizer::new("after telecope", None)?)?; + let i_pl1 = scenery.add_node(&lens1)?; + let i_pl2 = scenery.add_node(&ParaxialSurface::new("50 mm lens", millimeter!(50.0))?)?; + let i_sd3 = scenery.add_node(&RayPropagationVisualizer::new("after telecope", None)?)?; scenery.connect_nodes(i_src, "out1", i_pl1, "front", millimeter!(50.0))?; scenery.connect_nodes(i_pl1, "rear", i_pl2, "front", millimeter!(150.0))?; scenery.connect_nodes(i_pl2, "rear", i_sd3, "in1", millimeter!(50.0))?; diff --git a/opossum/examples/laser_system.rs b/opossum/examples/laser_system.rs index eb23c5b03f2aa21a39e37bdfa7206b0e40d0a20b..162d71926ad9f63fd560954f88a41b35eef84bf5 100644 --- a/opossum/examples/laser_system.rs +++ b/opossum/examples/laser_system.rs @@ -17,19 +17,19 @@ use uom::si::f64::Length; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::new("laser system"); // Main beam line - let i_src = scenery.add_node(round_collimated_ray_source( + let i_src = scenery.add_node(&round_collimated_ray_source( millimeter!(1.0), joule!(1.0), 3, )?)?; - let i_l1 = scenery.add_node(ParaxialSurface::new("f=100", millimeter!(100.0))?)?; - let i_l2 = scenery.add_node(ParaxialSurface::new("f=200", millimeter!(200.0))?)?; - let i_bs = scenery.add_node(BeamSplitter::new("1% BS", &SplittingConfig::Ratio(0.99))?)?; - let i_e1 = scenery.add_node(EnergyMeter::new( + let i_l1 = scenery.add_node(&ParaxialSurface::new("f=100", millimeter!(100.0))?)?; + let i_l2 = scenery.add_node(&ParaxialSurface::new("f=200", millimeter!(200.0))?)?; + let i_bs = scenery.add_node(&BeamSplitter::new("1% BS", &SplittingConfig::Ratio(0.99))?)?; + let i_e1 = scenery.add_node(&EnergyMeter::new( "Energy meter 1", opossum::nodes::Metertype::IdealEnergyMeter, ))?; - let i_sd1 = scenery.add_node(SpotDiagram::new("Output"))?; + let i_sd1 = scenery.add_node(&SpotDiagram::new("Output"))?; scenery.connect_nodes(i_src, "out1", i_l1, "front", Length::zero())?; scenery.connect_nodes(i_l1, "rear", i_l2, "front", millimeter!(300.0))?; @@ -38,7 +38,7 @@ fn main() -> OpmResult<()> { scenery.connect_nodes(i_e1, "out1", i_sd1, "in1", Length::zero())?; // Diagnostic beam line - let i_f = scenery.add_node(IdealFilter::new( + let i_f = scenery.add_node(&IdealFilter::new( "OD1 filter", &opossum::nodes::FilterType::Constant(0.1), )?)?; @@ -47,11 +47,14 @@ fn main() -> OpmResult<()> { // Cam Box let mut cam_box = NodeGroup::new("CamBox"); - let i_cb_bs = cam_box.add_node(BeamSplitter::new("50/50 BS", &SplittingConfig::Ratio(0.5))?)?; - let i_cb_l = cam_box.add_node(ParaxialSurface::new("FF lens", millimeter!(100.0))?)?; - let i_cb_sd1 = cam_box.add_node(SpotDiagram::new("Nearfield"))?; - let i_cb_sd2 = cam_box.add_node(SpotDiagram::new("Farfield"))?; - let i_cb_e = cam_box.add_node(EnergyMeter::new( + let i_cb_bs = cam_box.add_node(&BeamSplitter::new( + "50/50 BS", + &SplittingConfig::Ratio(0.5), + )?)?; + let i_cb_l = cam_box.add_node(&ParaxialSurface::new("FF lens", millimeter!(100.0))?)?; + let i_cb_sd1 = cam_box.add_node(&SpotDiagram::new("Nearfield"))?; + let i_cb_sd2 = cam_box.add_node(&SpotDiagram::new("Farfield"))?; + let i_cb_e = cam_box.add_node(&EnergyMeter::new( "Energy meter", opossum::nodes::Metertype::IdealEnergyMeter, ))?; @@ -75,7 +78,7 @@ fn main() -> OpmResult<()> { cam_box.connect_nodes(i_cb_sd1, "out1", i_cb_e, "in1", Length::zero())?; cam_box.map_input_port(i_cb_bs, "input1", "input")?; - let i_cam_box = scenery.add_node(cam_box)?; + let i_cam_box = scenery.add_node(&cam_box)?; scenery.connect_nodes(i_f, "rear", i_cam_box, "input", Length::zero())?; let mut doc = OpmDocument::new(scenery); diff --git a/opossum/examples/lens_inverse.rs b/opossum/examples/lens_inverse.rs index 01fdc6474aa26b9311a10d74bd705bb45adc6dd5..61e8593d073d2aed23996b10aa2c098730bff947 100644 --- a/opossum/examples/lens_inverse.rs +++ b/opossum/examples/lens_inverse.rs @@ -15,23 +15,23 @@ use std::path::Path; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::default(); - let i_src = scenery.add_node(collimated_line_ray_source( + let i_src = scenery.add_node(&collimated_line_ray_source( millimeter!(20.0), joule!(1.0), 6, )?)?; - let i_l1 = scenery.add_node(Lens::new( + let i_l1 = scenery.add_node(&Lens::new( "lens", millimeter!(100.0), millimeter!(-100.0), millimeter!(10.0), &RefrIndexConst::new(1.5)?, )?)?; - let i_m2 = scenery.add_node(ThinMirror::new("mirror").with_tilt(degree!(5.0, 0.0, 0.0))?)?; + let i_m2 = scenery.add_node(&ThinMirror::new("mirror").with_tilt(degree!(5.0, 0.0, 0.0))?)?; let mut l1_ref = NodeReference::from_node(&scenery.node(i_l1)?); l1_ref.set_inverted(true)?; - let i_l1_ref = scenery.add_node(l1_ref)?; - let i_sd3 = scenery.add_node(RayPropagationVisualizer::default())?; + let i_l1_ref = scenery.add_node(&l1_ref)?; + let i_sd3 = scenery.add_node(&RayPropagationVisualizer::default())?; scenery.connect_nodes(i_src, "out1", i_l1, "front", millimeter!(30.0))?; scenery.connect_nodes(i_l1, "rear", i_m2, "input", millimeter!(90.0))?; scenery.connect_nodes(i_m2, "reflected", i_l1_ref, "rear", millimeter!(0.0))?; diff --git a/opossum/examples/lens_test.rs b/opossum/examples/lens_test.rs index 92916702051514aa1a676dd5621cb3dbdd413f24..b7108ebdb5c2c78358930be5262d4fd504edd4d7 100644 --- a/opossum/examples/lens_test.rs +++ b/opossum/examples/lens_test.rs @@ -12,7 +12,7 @@ use std::path::Path; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::new("Lens Ray-trace test"); - let src = scenery.add_node(collimated_line_ray_source( + let src = scenery.add_node(&collimated_line_ray_source( millimeter!(20.0), joule!(1.0), 6, @@ -24,7 +24,7 @@ fn main() -> OpmResult<()> { &RefrIndexConst::new(1.5068)?, )? .with_tilt(degree!(15.0, 0.0, 0.0))?; - let l1 = scenery.add_node(lens1)?; + let l1 = scenery.add_node(&lens1)?; let lens2 = Lens::new( "Lens 2", millimeter!(205.55), @@ -33,8 +33,8 @@ fn main() -> OpmResult<()> { &RefrIndexConst::new(1.5068).unwrap(), )? .with_tilt(degree!(15.0, 0.0, 0.0))?; - let l2 = scenery.add_node(lens2)?; - let det = scenery.add_node(RayPropagationVisualizer::new("Ray plot", None)?)?; + let l2 = scenery.add_node(&lens2)?; + let det = scenery.add_node(&RayPropagationVisualizer::new("Ray plot", None)?)?; scenery.connect_nodes(src, "out1", l1, "front", millimeter!(50.0))?; scenery.connect_nodes(l1, "rear", l2, "front", millimeter!(50.0))?; scenery.connect_nodes(l2, "rear", det, "in1", millimeter!(50.0))?; diff --git a/opossum/examples/michaelson.rs b/opossum/examples/michaelson.rs index 4ef39f22378a66bad9598eb453b15c4885e512e3..cb8f289140dc807723555f19cf181cdf06207119 100644 --- a/opossum/examples/michaelson.rs +++ b/opossum/examples/michaelson.rs @@ -12,21 +12,21 @@ use uom::si::f64::Length; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::new("Michaelson interferomater"); - let src = scenery.add_node(Source::new( + let src = scenery.add_node(&Source::new( "Source", &LightData::Energy(DataEnergy { spectrum: create_he_ne_spec(1.0)?, }), ))?; - let bs = scenery.add_node(BeamSplitter::default())?; - let sample = scenery.add_node(Dummy::new("Sample"))?; + let bs = scenery.add_node(&BeamSplitter::default())?; + let sample = scenery.add_node(&Dummy::new("Sample"))?; let rf = NodeReference::from_node(&scenery.node(sample)?); - let r_sample = scenery.add_node(rf)?; - let m1 = scenery.add_node(Dummy::new("Mirror"))?; - let m2 = scenery.add_node(Dummy::new("Mirror"))?; + let r_sample = scenery.add_node(&rf)?; + let m1 = scenery.add_node(&Dummy::new("Mirror"))?; + let m2 = scenery.add_node(&Dummy::new("Mirror"))?; let rf = NodeReference::from_node(&scenery.node(bs)?); - let r_bs = scenery.add_node(rf)?; - let det = scenery.add_node(Detector::default())?; + let r_bs = scenery.add_node(&rf)?; + let det = scenery.add_node(&Detector::default())?; scenery.connect_nodes(src, "out1", bs, "input1", Length::zero())?; scenery.connect_nodes(bs, "out1_trans1_refl2", sample, "front", Length::zero())?; diff --git a/opossum/examples/mirror.rs b/opossum/examples/mirror.rs index f33b415060cadadc0eb16c2a3edee5ab482bbf4a..ca155644ca8e37281ca0a0f2bfd2ab8c5cbc207a 100644 --- a/opossum/examples/mirror.rs +++ b/opossum/examples/mirror.rs @@ -16,7 +16,7 @@ use std::path::Path; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::default(); - let i_src = scenery.add_node(round_collimated_ray_source( + let i_src = scenery.add_node(&round_collimated_ray_source( millimeter!(20.0), joule!(1.0), 3, @@ -27,16 +27,16 @@ fn main() -> OpmResult<()> { "input", &CoatingType::ConstantR { reflectivity: 0.5 }, )?; - let i_m1 = scenery.add_node(mirror1)?; + let i_m1 = scenery.add_node(&mirror1)?; let i_m2 = scenery.add_node( - ThinMirror::new("mirror 2") + &ThinMirror::new("mirror 2") .with_curvature(millimeter!(-100.0))? .with_tilt(degree!(22.5, 0.0, 0.0))?, )?; - let i_prop_vis = scenery.add_node(RayPropagationVisualizer::default())?; - let i_sd = scenery.add_node(SpotDiagram::default())?; - let i_wf = scenery.add_node(WaveFront::default())?; - let i_pm = scenery.add_node(EnergyMeter::default())?; + let i_prop_vis = scenery.add_node(&RayPropagationVisualizer::default())?; + let i_sd = scenery.add_node(&SpotDiagram::default())?; + let i_wf = scenery.add_node(&WaveFront::default())?; + let i_pm = scenery.add_node(&EnergyMeter::default())?; scenery.connect_nodes(i_src, "out1", i_m1, "input", millimeter!(100.0))?; scenery.connect_nodes(i_m1, "reflected", i_m2, "input", millimeter!(100.0))?; scenery.connect_nodes(i_m2, "reflected", i_prop_vis, "in1", millimeter!(80.0))?; diff --git a/opossum/examples/mirror_inverse.rs b/opossum/examples/mirror_inverse.rs index 4c02385d041942316b49b371e2ef38d65ca297a5..7fe457ae247ae9710e1d7b397a46ca80c971b34a 100644 --- a/opossum/examples/mirror_inverse.rs +++ b/opossum/examples/mirror_inverse.rs @@ -14,19 +14,20 @@ use std::path::Path; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::default(); - let i_src = scenery.add_node(collimated_line_ray_source( + let i_src = scenery.add_node(&collimated_line_ray_source( millimeter!(20.0), joule!(1.0), 10, )?)?; - let i_m1 = scenery.add_node(ThinMirror::new("mirror 1").with_tilt(degree!(45.0, 0.0, 0.0))?)?; - let i_m2 = scenery.add_node(ThinMirror::new("mirror 2").with_tilt(degree!(2.0, 0.0, 0.0))?)?; + let i_m1 = + scenery.add_node(&ThinMirror::new("mirror 1").with_tilt(degree!(45.0, 0.0, 0.0))?)?; + let i_m2 = scenery.add_node(&ThinMirror::new("mirror 2").with_tilt(degree!(2.0, 0.0, 0.0))?)?; let m1_ref = NodeReference::from_node(&scenery.node(i_m1)?); - let i_m1_ref = scenery.add_node(m1_ref)?; - let i_sd3 = scenery.add_node(RayPropagationVisualizer::default())?; - let i_sd = scenery.add_node(SpotDiagram::default())?; + let i_m1_ref = scenery.add_node(&m1_ref)?; + let i_sd3 = scenery.add_node(&RayPropagationVisualizer::default())?; + let i_sd = scenery.add_node(&SpotDiagram::default())?; let sd_ref = NodeReference::from_node(&scenery.node(i_sd)?); - let i_sd_ref = scenery.add_node(sd_ref)?; + let i_sd_ref = scenery.add_node(&sd_ref)?; scenery.connect_nodes(i_src, "out1", i_sd, "in1", millimeter!(40.0))?; scenery.connect_nodes(i_sd, "out1", i_m1, "input", millimeter!(40.0))?; scenery.connect_nodes(i_m1, "reflected", i_m2, "input", millimeter!(50.0))?; diff --git a/opossum/examples/opticscenery.rs b/opossum/examples/opticscenery.rs index a06ec4d83ee8ae72f5fb0fa78087deedd6c52ed2..9da8d3a22fecf8c2e0ed6d6dbb585d5dae2cc6a3 100644 --- a/opossum/examples/opticscenery.rs +++ b/opossum/examples/opticscenery.rs @@ -10,8 +10,8 @@ use uom::si::f64::Length; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::new("OpticScenery demo"); - let node1 = scenery.add_node(Dummy::new("dummy1"))?; - let node2 = scenery.add_node(Dummy::new("dummy2"))?; + let node1 = scenery.add_node(&Dummy::new("dummy1"))?; + let node2 = scenery.add_node(&Dummy::new("dummy2"))?; scenery.connect_nodes(node1, "rear", node2, "front", Length::zero())?; let mut doc = OpmDocument::new(scenery); diff --git a/opossum/examples/paraxial_lens_wavefront.rs b/opossum/examples/paraxial_lens_wavefront.rs index 78d195f339105706dd0cb113f000128b7fe979ab..7cdc47ad8ceaef8fbb0b3981e82c904cb2bea255 100644 --- a/opossum/examples/paraxial_lens_wavefront.rs +++ b/opossum/examples/paraxial_lens_wavefront.rs @@ -16,10 +16,10 @@ use uom::si::f64::Length; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::new("Lens Ray-trace test"); let src = scenery - .add_node(round_collimated_ray_source(millimeter!(5.0), joule!(1.0), 30).unwrap())?; - let lens = scenery.add_node(ParaxialSurface::new("f=100 mm", millimeter!(100.0))?)?; - let wf = scenery.add_node(WaveFront::default())?; - let det = scenery.add_node(RayPropagationVisualizer::default())?; + .add_node(&round_collimated_ray_source(millimeter!(5.0), joule!(1.0), 30).unwrap())?; + let lens = scenery.add_node(&ParaxialSurface::new("f=100 mm", millimeter!(100.0))?)?; + let wf = scenery.add_node(&WaveFront::default())?; + let det = scenery.add_node(&RayPropagationVisualizer::default())?; scenery.connect_nodes(src, "out1", lens, "front", Length::zero())?; scenery.connect_nodes(lens, "rear", wf, "in1", millimeter!(90.0))?; scenery.connect_nodes(wf, "out1", det, "in1", Length::zero())?; diff --git a/opossum/examples/point_src_wavefront.rs b/opossum/examples/point_src_wavefront.rs index 73730dc5ee5f761527cb2185c11d334a9d910838..75868fbe63de6417145814c04288031c5f5b26d9 100644 --- a/opossum/examples/point_src_wavefront.rs +++ b/opossum/examples/point_src_wavefront.rs @@ -11,8 +11,8 @@ use std::path::Path; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::default(); let source = point_ray_source(degree!(90.0), joule!(1.))?; - let i_s = scenery.add_node(source)?; - let i_wf1 = scenery.add_node(WaveFront::new("wf_monitor 1"))?; + let i_s = scenery.add_node(&source)?; + let i_wf1 = scenery.add_node(&WaveFront::new("wf_monitor 1"))?; scenery.connect_nodes(i_s, "out1", i_wf1, "in1", meter!(0.1))?; diff --git a/opossum/examples/prism_dispersion.rs b/opossum/examples/prism_dispersion.rs index 3f47127c9dff301f4aecf56cebb0a3b7d8e209fe..37d8cdd62b95ca6a21034a5d2f4f01c8bca4df2e 100644 --- a/opossum/examples/prism_dispersion.rs +++ b/opossum/examples/prism_dispersion.rs @@ -49,10 +49,10 @@ fn main() -> OpmResult<()> { let light = LightData::Geometric(rays_1w); let mut light_src = Source::new("collimated ray source", &light); light_src.set_isometry(Isometry::identity()); - let src = scenery.add_node(light_src)?; + let src = scenery.add_node(&light_src)?; let w1 = scenery.add_node( - Wedge::new( + &Wedge::new( "prism 1", millimeter!(20.0), degree!(wedge_angle_in_degree), @@ -67,9 +67,9 @@ fn main() -> OpmResult<()> { &refr_index_hk9l, )? .with_tilt(degree!(wedge_angle_in_degree / 2.0, 0.0, 0.0))?; - let w2 = scenery.add_node(wedge2)?; + let w2 = scenery.add_node(&wedge2)?; let w3 = scenery.add_node( - Wedge::new( + &Wedge::new( "prism 3", millimeter!(20.0), degree!(-1.0 * wedge_angle_in_degree), @@ -78,7 +78,7 @@ fn main() -> OpmResult<()> { .with_tilt(degree!(wedge_angle_in_degree / 2.0, 0.0, 0.0))?, )?; let w4 = scenery.add_node( - Wedge::new( + &Wedge::new( "prism 4", millimeter!(20.0), degree!(wedge_angle_in_degree), @@ -86,8 +86,8 @@ fn main() -> OpmResult<()> { )? .with_tilt(degree!(wedge_angle_in_degree / -2.0, 0.0, 0.0))?, )?; - let det = scenery.add_node(RayPropagationVisualizer::default())?; - let sd = scenery.add_node(SpotDiagram::default())?; + let det = scenery.add_node(&RayPropagationVisualizer::default())?; + let sd = scenery.add_node(&SpotDiagram::default())?; scenery.connect_nodes(src, "out1", w1, "front", millimeter!(50.0))?; scenery.connect_nodes(w1, "rear", w2, "front", millimeter!(100.0))?; scenery.connect_nodes(w2, "rear", w3, "front", millimeter!(150.0))?; diff --git a/opossum/examples/prism_pair.rs b/opossum/examples/prism_pair.rs index 721a1dd166937d1ed21d20f5885f9ddcfac33434..bd3224d81a78ede5595787a976ffd91c3684c6d3 100644 --- a/opossum/examples/prism_pair.rs +++ b/opossum/examples/prism_pair.rs @@ -13,7 +13,7 @@ use std::path::Path; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::new("Prism Pair test"); - let src = scenery.add_node(collimated_line_ray_source( + let src = scenery.add_node(&collimated_line_ray_source( millimeter!(50.0), joule!(1.0), 7, @@ -24,7 +24,7 @@ fn main() -> OpmResult<()> { degree!(30.0), &RefrIndexConst::new(1.5068)?, )?; - let p1 = scenery.add_node(prism1)?; + let p1 = scenery.add_node(&prism1)?; let mut prism2 = Wedge::new( "Prism2", @@ -34,10 +34,10 @@ fn main() -> OpmResult<()> { )?; let iso = Isometry::new(millimeter!(0.0, 20.0, 110.0), degree!(30.0, 0.0, 0.0))?; prism2.set_isometry(iso); - let p2 = scenery.add_node(prism2)?; + let p2 = scenery.add_node(&prism2)?; - let det = scenery.add_node(RayPropagationVisualizer::default())?; - let sd = scenery.add_node(SpotDiagram::default())?; + let det = scenery.add_node(&RayPropagationVisualizer::default())?; + let sd = scenery.add_node(&SpotDiagram::default())?; scenery.connect_nodes(src, "out1", p1, "front", millimeter!(10.0))?; scenery.connect_nodes(p1, "rear", p2, "front", millimeter!(100.0))?; diff --git a/opossum/examples/ray_propagation.rs b/opossum/examples/ray_propagation.rs index 7279b698ba43060bb3a19db917faf942e31f2407..5fa111549b2dd9e002012bdff65bda8f321f66b0 100644 --- a/opossum/examples/ray_propagation.rs +++ b/opossum/examples/ray_propagation.rs @@ -13,12 +13,12 @@ use std::path::Path; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::default(); - let src = scenery.add_node(round_collimated_ray_source( + let src = scenery.add_node(&round_collimated_ray_source( millimeter!(5.0), joule!(1.0), 10, )?)?; - let l1 = scenery.add_node(Lens::new( + let l1 = scenery.add_node(&Lens::new( "l1", millimeter!(200.0), millimeter!(-200.0), @@ -37,8 +37,8 @@ fn main() -> OpmResult<()> { "front", &Aperture::BinaryCircle(CircleConfig::new(millimeter!(3.), millimeter!(0., 0.))?), )?; - let l2 = scenery.add_node(lens2)?; - let det = scenery.add_node(RayPropagationVisualizer::default())?; + let l2 = scenery.add_node(&lens2)?; + let det = scenery.add_node(&RayPropagationVisualizer::default())?; scenery.connect_nodes(src, "out1", l1, "front", millimeter!(30.0))?; scenery.connect_nodes(l1, "rear", l2, "front", millimeter!(197.22992))?; scenery.connect_nodes(l2, "rear", det, "in1", millimeter!(30.0))?; diff --git a/opossum/examples/ray_source.rs b/opossum/examples/ray_source.rs index b48aa6626e52d72a84740c4779f532b3353c6e69..4ec7d510b3476fe46fe9907c6661fc6305d7c0b6 100644 --- a/opossum/examples/ray_source.rs +++ b/opossum/examples/ray_source.rs @@ -18,11 +18,11 @@ fn main() -> OpmResult<()> { let aperture = Aperture::BinaryCircle(CircleConfig::new(millimeter!(1.0), millimeter![0.5, 0.5])?); source.set_aperture(&PortType::Output, "out1", &aperture)?; - let i_s = scenery.add_node(source)?; + let i_s = scenery.add_node(&source)?; let dummy = Dummy::default(); - let i_dummy = scenery.add_node(dummy)?; - let i_d = scenery.add_node(EnergyMeter::default())?; - let i_sd = scenery.add_node(SpotDiagram::default())?; + let i_dummy = scenery.add_node(&dummy)?; + let i_d = scenery.add_node(&EnergyMeter::default())?; + let i_sd = scenery.add_node(&SpotDiagram::default())?; scenery.connect_nodes(i_s, "out1", i_dummy, "front", Length::zero())?; scenery.connect_nodes(i_dummy, "rear", i_d, "in1", Length::zero())?; scenery.connect_nodes(i_d, "out1", i_sd, "in1", Length::zero())?; diff --git a/opossum/examples/reference_test.rs b/opossum/examples/reference_test.rs index 5f6d85b1f1965a9615e949e3f8899017f552adf1..2973a496d74dadf1d6a60991b42468bb8d9f69ff 100644 --- a/opossum/examples/reference_test.rs +++ b/opossum/examples/reference_test.rs @@ -12,18 +12,18 @@ use uom::si::f64::Length; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::new("Reference node demo"); - let src = scenery.add_node(Source::new( + let src = scenery.add_node(&Source::new( "source", &LightData::Energy(DataEnergy { spectrum: create_he_ne_spec(1.0)?, }), ))?; - let filt = scenery.add_node(IdealFilter::new( + let filt = scenery.add_node(&IdealFilter::new( "50 % filter", &opossum::nodes::FilterType::Constant(0.5), )?)?; - let reference = scenery.add_node(NodeReference::from_node(&scenery.node(filt).unwrap()))?; - let detector = scenery.add_node(EnergyMeter::default())?; + let reference = scenery.add_node(&NodeReference::from_node(&scenery.node(filt).unwrap()))?; + let detector = scenery.add_node(&EnergyMeter::default())?; scenery.connect_nodes(src, "out1", filt, "front", Length::zero())?; scenery.connect_nodes(filt, "rear", reference, "front", Length::zero())?; scenery.connect_nodes(reference, "rear", detector, "in1", Length::zero())?; diff --git a/opossum/examples/surface_wavefront.rs b/opossum/examples/surface_wavefront.rs index e63c7dba51e877eba1da6da14481366107f4c05c..03ee0850ffa1b451e404ea3889622e1743543e31 100644 --- a/opossum/examples/surface_wavefront.rs +++ b/opossum/examples/surface_wavefront.rs @@ -18,12 +18,12 @@ use uom::si::f64::Length; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::default(); - let src = scenery.add_node(round_collimated_ray_source( + let src = scenery.add_node(&round_collimated_ray_source( millimeter!(5.0), joule!(1.0), 5, )?)?; - let l1 = scenery.add_node(Lens::new( + let l1 = scenery.add_node(&Lens::new( "l1", millimeter!(200.0), millimeter!(-200.0), @@ -39,10 +39,10 @@ fn main() -> OpmResult<()> { )?; let circle = CircleConfig::new(millimeter!(3.0), millimeter!(0., 0.))?; lens.set_aperture(&PortType::Output, "rear", &Aperture::BinaryCircle(circle))?; - let l2 = scenery.add_node(lens)?; - let det = scenery.add_node(RayPropagationVisualizer::default())?; - let wf = scenery.add_node(WaveFront::default())?; - let sd = scenery.add_node(SpotDiagram::default())?; + let l2 = scenery.add_node(&lens)?; + let det = scenery.add_node(&RayPropagationVisualizer::default())?; + let wf = scenery.add_node(&WaveFront::default())?; + let sd = scenery.add_node(&SpotDiagram::default())?; scenery.connect_nodes(src, "out1", l1, "front", millimeter!(30.0))?; scenery.connect_nodes(l1, "rear", l2, "front", millimeter!(197.22992))?; scenery.connect_nodes(l2, "rear", wf, "in1", millimeter!(30.0))?; diff --git a/opossum/examples/tilted_src.rs b/opossum/examples/tilted_src.rs index 9958bb65482b6ac094f2ebce16e23b5210ca3671..af044ee5f9a14edc46156d4a08778e8e21d2c774 100644 --- a/opossum/examples/tilted_src.rs +++ b/opossum/examples/tilted_src.rs @@ -13,14 +13,15 @@ fn main() -> OpmResult<()> { let mut scenery = NodeGroup::default(); let src = collimated_line_ray_source(millimeter!(20.0), joule!(1.0), 21)? .with_tilt(degree!(20.0, 0.0, 0.0))?; - let i_src = scenery.add_node(src)?; - let i_m1 = scenery.add_node(ThinMirror::new("mirror 1").with_tilt(degree!(45.0, 0.0, 0.0))?)?; + let i_src = scenery.add_node(&src)?; + let i_m1 = + scenery.add_node(&ThinMirror::new("mirror 1").with_tilt(degree!(45.0, 0.0, 0.0))?)?; let i_m2 = scenery.add_node( - ThinMirror::new("mirror 2") + &ThinMirror::new("mirror 2") .with_curvature(millimeter!(-100.0))? .with_tilt(degree!(45.0, 0.0, 0.0))?, )?; - let i_sd3 = scenery.add_node(RayPropagationVisualizer::default())?; + let i_sd3 = scenery.add_node(&RayPropagationVisualizer::default())?; scenery.connect_nodes(i_src, "out1", i_m1, "input", millimeter!(100.0))?; scenery.connect_nodes(i_m1, "reflected", i_m2, "input", millimeter!(100.0))?; diff --git a/opossum/examples/tilted_wavefront_sensor.rs b/opossum/examples/tilted_wavefront_sensor.rs index 4cd9ce3e9a9ecd014217a7052b93cd8ca83512bf..99d0a98976f4dc74e43d8a646f6293a115b72f76 100644 --- a/opossum/examples/tilted_wavefront_sensor.rs +++ b/opossum/examples/tilted_wavefront_sensor.rs @@ -12,11 +12,11 @@ use opossum::{ use std::path::Path; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::default(); - let src = - scenery.add_node(round_collimated_ray_source(millimeter!(5.0), joule!(1.0), 5).unwrap())?; - let wf = scenery.add_node(WaveFront::default().with_tilt(degree!(10.0, 0.0, 0.0))?)?; - let sd = scenery.add_node(SpotDiagram::default().with_tilt(degree!(30.0, 0.0, 0.0))?)?; - let det = scenery.add_node(RayPropagationVisualizer::default())?; + let src = scenery + .add_node(&round_collimated_ray_source(millimeter!(5.0), joule!(1.0), 5).unwrap())?; + let wf = scenery.add_node(&WaveFront::default().with_tilt(degree!(10.0, 0.0, 0.0))?)?; + let sd = scenery.add_node(&SpotDiagram::default().with_tilt(degree!(30.0, 0.0, 0.0))?)?; + let det = scenery.add_node(&RayPropagationVisualizer::default())?; scenery.connect_nodes(src, "out1", wf, "in1", millimeter!(20.0))?; scenery.connect_nodes(wf, "out1", sd, "in1", millimeter!(20.0))?; scenery.connect_nodes(sd, "out1", det, "in1", millimeter!(20.0))?; diff --git a/opossum/examples/two_color_rays.rs b/opossum/examples/two_color_rays.rs index bd2c635d2f43545f922b2c6007f0016609e6fde6..9e3a1a7be25478fc9826c6a368c91a3851b5a581 100644 --- a/opossum/examples/two_color_rays.rs +++ b/opossum/examples/two_color_rays.rs @@ -39,24 +39,24 @@ fn main() -> OpmResult<()> { let mut scenery = NodeGroup::default(); let light = LightData::Geometric(rays_1w); - let src = scenery.add_node(Source::new("collimated ray source", &light))?; - let l1 = scenery.add_node(Lens::new( + let src = scenery.add_node(&Source::new("collimated ray source", &light))?; + let l1 = scenery.add_node(&Lens::new( "l1", millimeter!(200.0), millimeter!(-200.0), millimeter!(10.0), &RefrIndexConst::new(2.0).unwrap(), )?)?; - let l2 = scenery.add_node(Lens::new( + let l2 = scenery.add_node(&Lens::new( "l1", millimeter!(200.0), millimeter!(-200.0), millimeter!(10.0), &RefrIndexConst::new(2.0).unwrap(), )?)?; - let det = scenery.add_node(RayPropagationVisualizer::default())?; - // let wf = scenery.add_node(WaveFront::default()); - let sd = scenery.add_node(SpotDiagram::default())?; + let det = scenery.add_node(&RayPropagationVisualizer::default())?; + // let wf = scenery.add_node(&WaveFront::default()); + let sd = scenery.add_node(&SpotDiagram::default())?; scenery.connect_nodes(src, "out1", l1, "front", millimeter!(30.0))?; scenery.connect_nodes(l1, "rear", l2, "front", millimeter!(197.22992))?; scenery.connect_nodes(l2, "rear", det, "in1", millimeter!(30.0))?; diff --git a/opossum/examples/two_srcs.rs b/opossum/examples/two_srcs.rs index b438a22f146e19b05e51a42f959225f9f12695ad..cd160d672d70542e72a127ef6d070e567f61f23b 100644 --- a/opossum/examples/two_srcs.rs +++ b/opossum/examples/two_srcs.rs @@ -9,18 +9,18 @@ use std::path::Path; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::default(); - let i_src1 = scenery.add_node(collimated_line_ray_source( + let i_src1 = scenery.add_node(&collimated_line_ray_source( millimeter!(20.0), joule!(1.0), 21, )?)?; - let i_src2 = scenery.add_node(collimated_line_ray_source( + let i_src2 = scenery.add_node(&collimated_line_ray_source( millimeter!(20.0), joule!(1.0), 21, )?)?; - let i_bs = scenery.add_node(BeamSplitter::default())?; - let i_sd = scenery.add_node(RayPropagationVisualizer::default())?; + let i_bs = scenery.add_node(&BeamSplitter::default())?; + let i_sd = scenery.add_node(&RayPropagationVisualizer::default())?; scenery.connect_nodes(i_src1, "out1", i_bs, "input1", millimeter!(100.0))?; scenery.connect_nodes(i_src2, "out1", i_bs, "input2", millimeter!(110.0))?; diff --git a/opossum/examples/wavefront.rs b/opossum/examples/wavefront.rs index e0dbe91119085a00fcdcd3649b0a832294f58213..bd0181658da9ac966d3b873bcbba73865599e07c 100644 --- a/opossum/examples/wavefront.rs +++ b/opossum/examples/wavefront.rs @@ -15,16 +15,16 @@ use uom::si::f64::Length; fn main() -> OpmResult<()> { let mut scenery = NodeGroup::new("Wavefont Demo"); let source = round_collimated_ray_source(meter!(5e-3), joule!(1.), 15)?; - let i_s = scenery.add_node(source)?; - let i_wf1 = scenery.add_node(WaveFront::new("wf_monitor 1"))?; - let i_l = scenery.add_node(ParaxialSurface::new("lens", meter!(0.1))?)?; - let i_wf2 = scenery.add_node(WaveFront::new("wf_monitor 2"))?; - let i_sp = scenery.add_node(SpotDiagram::new("spot 3"))?; - let i_l2 = scenery.add_node(ParaxialSurface::new("lens", meter!(0.1))?)?; - let i_wf3 = scenery.add_node(WaveFront::new("wf_mon3"))?; - let i_r1 = scenery.add_node(RayPropagationVisualizer::new("ray_mon1", None)?)?; - let i_s1 = scenery.add_node(Spectrometer::new("spec_mon", SpectrometerType::Ideal))?; - let i_fl1 = scenery.add_node(FluenceDetector::new("fluence monitor"))?; + let i_s = scenery.add_node(&source)?; + let i_wf1 = scenery.add_node(&WaveFront::new("wf_monitor 1"))?; + let i_l = scenery.add_node(&ParaxialSurface::new("lens", meter!(0.1))?)?; + let i_wf2 = scenery.add_node(&WaveFront::new("wf_monitor 2"))?; + let i_sp = scenery.add_node(&SpotDiagram::new("spot 3"))?; + let i_l2 = scenery.add_node(&ParaxialSurface::new("lens", meter!(0.1))?)?; + let i_wf3 = scenery.add_node(&WaveFront::new("wf_mon3"))?; + let i_r1 = scenery.add_node(&RayPropagationVisualizer::new("ray_mon1", None)?)?; + let i_s1 = scenery.add_node(&Spectrometer::new("spec_mon", SpectrometerType::Ideal))?; + let i_fl1 = scenery.add_node(&FluenceDetector::new("fluence monitor"))?; scenery.connect_nodes(i_s, "out1", i_wf1, "in1", meter!(0.1))?; scenery.connect_nodes(i_wf1, "out1", i_l, "front", Length::zero())?; diff --git a/opossum/files_for_testing/opm/optic_ref.opm b/opossum/files_for_testing/opm/optic_ref.opm index eae11320cc186842a6c8fabd823a267679e6dfaa..0c78e26357c055b84e5fc886bad6b504ebfb159d 100644 --- a/opossum/files_for_testing/opm/optic_ref.opm +++ b/opossum/files_for_testing/opm/optic_ref.opm @@ -4,6 +4,7 @@ attributes: alignment: null isometry: null name: test123 + uuid: 587ee70f-6f52-4420-89f6-e1618ff4dbdb ports: inputs: front: diff --git a/opossum/files_for_testing/opm/opticscenery.opm b/opossum/files_for_testing/opm/opticscenery.opm index fe6b67f2de62d1ec5330bb0f29e17cf3ee5e3d1a..9bafe8e8fe51a3a0002dfc199cd6689d45340302 100644 --- a/opossum/files_for_testing/opm/opticscenery.opm +++ b/opossum/files_for_testing/opm/opticscenery.opm @@ -5,6 +5,7 @@ scenery: ports: inputs: {} outputs: {} + uuid: b8cb049b-4eb9-4db8-8842-2fc7c70c27ba props: expand view: !Bool false graph: !OpticGraph @@ -13,6 +14,7 @@ scenery: id: 180328fe-7ad4-4568-b501-183b88c4daee attributes: name: dummy1 + uuid: 180328fe-7ad4-4568-b501-183b88c4daee ports: inputs: front: @@ -28,6 +30,7 @@ scenery: id: 642ce76e-b071-43c0-a77e-1bdbb99b40d8 attributes: name: dummy2 + uuid: 642ce76e-b071-43c0-a77e-1bdbb99b40d8 ports: inputs: front: diff --git a/opossum/src/analyzers/ghostfocus.rs b/opossum/src/analyzers/ghostfocus.rs index 578d0bca951a76674454e486da4317d1f41f707a..8b5d76d89e4d9137f496eee75aee4f73fb02c145 100644 --- a/opossum/src/analyzers/ghostfocus.rs +++ b/opossum/src/analyzers/ghostfocus.rs @@ -1,20 +1,26 @@ //! Analyzer performing a ghost focus analysis using ray tracing +use std::collections::{hash_map::Values, HashMap}; + use chrono::Local; use log::{info, warn}; use nalgebra::{MatrixXx2, MatrixXx3, Vector3}; use plotters::style::RGBAColor; use serde::{Deserialize, Serialize}; -use uom::si::{f64::Length, length::millimeter}; +use uom::si::{f64::Length, length::millimeter, radiant_exposure::joule_per_square_centimeter}; +use uuid::Uuid; use crate::{ error::{OpmResult, OpossumError}, get_version, light_result::{LightRays, LightResult}, millimeter, - nodes::NodeGroup, + nodes::{NodeGroup, OpticGraph}, optic_node::OpticNode, plottable::{PlotArgs, PlotData, PlotParameters, PlotSeries, PlotType, Plottable}, - properties::{Properties, Proptype}, + properties::{ + proptype::{count_str, format_value_with_prefix}, + Properties, Proptype, + }, rays::Rays, reporting::{analysis_report::AnalysisReport, node_report::NodeReport}, }; @@ -98,7 +104,6 @@ impl Analyzer for GhostFocusAnalyzer { scenery.add_to_accumulated_rays(rays, bounce); } } - Ok(()) } fn report(&self, scenery: &NodeGroup) -> OpmResult<AnalysisReport> { @@ -115,14 +120,64 @@ impl Analyzer for GhostFocusAnalyzer { analysis_report.add_node_report(node_report); for node in scenery.graph().nodes() { let node_name = &node.optical_ref.borrow().name(); - let uuid = node.uuid().as_simple().to_string(); - let mut props = Properties::default(); let hit_maps = node.optical_ref.borrow().hit_maps(); for hit_map in &hit_maps { - props.create(hit_map.0, "surface hit map", None, hit_map.1.clone().into())?; + let critical_positions = hit_map.1.critical_fluences(); + if !critical_positions.is_empty() { + for (i, (rays_uuid, (fluence, hist_idx))) in + critical_positions.iter().enumerate() + { + let mut hit_map_props = Properties::default(); + + hit_map_props.create( + "Peak fluence", + "Peak fluence on this surface", + None, + format!( + "{}J/cm²", + format_value_with_prefix( + fluence.get::<joule_per_square_centimeter>() + ) + ) + .into(), + )?; + + let critical_ghost_hist = GhostFocusHistory::from(( + scenery.accumulated_rays(), + *rays_uuid, + *hist_idx, + )); + hit_map_props.create( + "Origin", + "Surface bounces that enabled this fluence", + None, + critical_ghost_hist + .rays_origin_report_str(scenery.graph()) + .into(), + )?; + + hit_map_props.create( + "Ray propagation", + "ray propagation", + None, + Proptype::from(critical_ghost_hist), + )?; + let hit_map_report = NodeReport::new( + "surface", + &format!( + "{} critical fluence on surface '{}' of node '{}'", + count_str(i + 1), + hit_map.0, + node_name + ), + &Uuid::new_v4().as_simple().to_string(), + hit_map_props, + ); + + analysis_report.add_node_report(hit_map_report); + } + } } - let node_report = NodeReport::new("hitmap", node_name, &uuid, props); - analysis_report.add_node_report(node_report); } analysis_report.set_analysis_type("Ghost Focus Analysis"); Ok(analysis_report) @@ -154,13 +209,58 @@ pub trait AnalysisGhostFocus: OpticNode + AnalysisRayTrace { } } +///Struct to store the node origin uuid and parent ray bundle Uuid of a ray bundle +#[derive(Serialize, Deserialize, Clone, Debug, Default)] +pub struct RaysOrigin { + parent_rays: Option<Uuid>, + node_origin: Option<Uuid>, +} +impl RaysOrigin { + ///creates a new [`RaysOrigin`] + #[must_use] + pub const fn new(parent_rays: Option<Uuid>, node_origin: Option<Uuid>) -> Self { + Self { + parent_rays, + node_origin, + } + } +} + +/// Struct to store the correlation between a ray bundle and its parent ray bundle as well as its node origin +#[derive(Serialize, Deserialize, Clone, Debug, Default)] +pub struct RaysNodeCorrelation { + correlation: HashMap<Uuid, RaysOrigin>, +} +impl RaysNodeCorrelation { + ///creates a new [`RaysNodeCorrelation`] + #[must_use] + pub fn new(rays_uuid: &Uuid, rays_origin: &RaysOrigin) -> Self { + let mut correlation = HashMap::<Uuid, RaysOrigin>::new(); + correlation.insert(*rays_uuid, rays_origin.clone()); + Self { correlation } + } + + /// inserts a key value pair in the correlation hashmap + pub fn insert(&mut self, k: &Uuid, v: &RaysOrigin) { + self.correlation.insert(*k, v.clone()); + } + + /// returns the values of the correlation hashmap + #[must_use] + pub fn values(&self) -> Values<'_, Uuid, RaysOrigin> { + self.correlation.values() + } +} + /// struct that holds the history of the ray positions that is needed for report generation #[derive(Serialize, Deserialize, Clone, Debug)] pub struct GhostFocusHistory { /// vector of ray positions for each raybundle at a specifc spectral position pub rays_pos_history: Vec<Vec<Vec<MatrixXx3<Length>>>>, - /// view direction if the rayposition thistory is plotted + /// view direction if the ray position history is plotted pub plot_view_direction: Option<Vector3<f64>>, + ///stores the corrleation between a rays bundle and its parent node as well as parent ray bundle for each bounce in a vector + pub ray_node_correlation: Vec<RaysNodeCorrelation>, } impl GhostFocusHistory { /// Projects the positions o fthie [`GhostFocusHistory`] onto a 2D plane @@ -236,32 +336,125 @@ impl GhostFocusHistory { Ok(projected_history) } + + fn add_specific_ray_history( + &mut self, + accumulated_rays: &Vec<HashMap<Uuid, Rays>>, + rays_uuid: &Uuid, + hist_idx: usize, + ) { + for (bounce, ray_vecs_in_bounce) in accumulated_rays.iter().enumerate() { + if ray_vecs_in_bounce.contains_key(rays_uuid) { + let mut rays_per_bounce_history = + Vec::<Vec<MatrixXx3<Length>>>::with_capacity(ray_vecs_in_bounce.len()); + if let Some(rays) = ray_vecs_in_bounce.get(rays_uuid) { + let mut rays_history = + Vec::<MatrixXx3<Length>>::with_capacity(rays.nr_of_rays(true)); + for ray in rays { + if let Some(ray_hist) = ray.position_history_from_to(0, hist_idx) { + rays_history.push(ray_hist); + } + } + rays_per_bounce_history.push(rays_history); + self.ray_node_correlation[bounce].insert( + rays.uuid(), + &RaysOrigin::new(*rays.parent_id(), *rays.node_origin()), + ); + + self.rays_pos_history[bounce] = rays_per_bounce_history; + if let Some(parent_uuid) = rays.parent_id() { + self.add_specific_ray_history( + accumulated_rays, + parent_uuid, + *rays.parent_pos_split_idx(), + ); + } + } + break; + } + } + } + + ///Returns the report string for the critical ray origin in the ghost focus analysis + #[must_use] + pub fn rays_origin_report_str(&self, graph: &OpticGraph) -> String { + let mut report_str = String::new(); + for (bounce, rays_correlation) in self.ray_node_correlation.iter().enumerate() { + if bounce == 0 { + report_str += "Origin at node '"; + } else { + report_str += format!("bounce {bounce} at node '").as_str(); + } + for rays_origin in rays_correlation.values() { + if let Some(node_uuid) = rays_origin.node_origin { + if let Some(opt_ref) = graph.node_by_uuid(node_uuid) { + report_str += + format!("{}', ", opt_ref.optical_ref.borrow().name()).as_str(); + } + } + } + } + report_str + } } -impl From<Vec<Vec<Rays>>> for GhostFocusHistory { - fn from(value: Vec<Vec<Rays>>) -> Self { +impl From<Vec<HashMap<Uuid, Rays>>> for GhostFocusHistory { + fn from(value: Vec<HashMap<Uuid, Rays>>) -> Self { let mut ghost_focus_history = Vec::<Vec<Vec<MatrixXx3<Length>>>>::with_capacity(value.len()); + let mut ray_node_correlation = Vec::<RaysNodeCorrelation>::with_capacity(value.len()); for ray_vecs_in_bounce in &value { let mut rays_per_bounce_history = Vec::<Vec<MatrixXx3<Length>>>::with_capacity(ray_vecs_in_bounce.len()); - for rays in ray_vecs_in_bounce { + let mut ray_node_bounce_correlation = RaysNodeCorrelation::default(); + for rays in ray_vecs_in_bounce.values() { let mut rays_history = Vec::<MatrixXx3<Length>>::with_capacity(rays.nr_of_rays(false)); for ray in rays { rays_history.push(ray.position_history()); } + ray_node_bounce_correlation.insert( + rays.uuid(), + &RaysOrigin::new(*rays.parent_id(), *rays.node_origin()), + ); rays_per_bounce_history.push(rays_history); } ghost_focus_history.push(rays_per_bounce_history); + ray_node_correlation.push(ray_node_bounce_correlation); } Self { rays_pos_history: ghost_focus_history, plot_view_direction: None, + ray_node_correlation, } } } +impl From<(&Vec<HashMap<Uuid, Rays>>, Uuid, usize)> for GhostFocusHistory { + ///value contains : + /// 0: a vector of Hashmaps that contain Rays. Same structure as the `accumulated_rays` in [`NodeGroup`] + /// 1: the uuid of a ray bundle within field 0 + /// 2: the index of the position in the ray position history up to which it should be displayed + fn from(value: (&Vec<HashMap<Uuid, Rays>>, Uuid, usize)) -> Self { + let (acc_rays, rays_uuid, hist_idx) = value; + let mut ray_pos_history = Vec::<Vec<Vec<MatrixXx3<Length>>>>::with_capacity(acc_rays.len()); + let mut ray_node_correlation = Vec::<RaysNodeCorrelation>::with_capacity(acc_rays.len()); + for _i in 0..acc_rays.len() { + ray_pos_history.push(Vec::<Vec<MatrixXx3<Length>>>::new()); + ray_node_correlation.push(RaysNodeCorrelation::default()); + } + let mut ghost_focus_history = Self { + rays_pos_history: ray_pos_history, + plot_view_direction: None, + ray_node_correlation, + }; + + ghost_focus_history.add_specific_ray_history(acc_rays, &rays_uuid, hist_idx); + + ghost_focus_history + } +} + impl Plottable for GhostFocusHistory { fn add_plot_specific_params(&self, plt_params: &mut PlotParameters) -> OpmResult<()> { plt_params diff --git a/opossum/src/analyzers/raytrace.rs b/opossum/src/analyzers/raytrace.rs index 496cdfd5f8cfe3303f39a6795ace86a302904a7a..9935e5086dcadace61a9961e7e655f85716dbff0 100644 --- a/opossum/src/analyzers/raytrace.rs +++ b/opossum/src/analyzers/raytrace.rs @@ -93,6 +93,7 @@ pub trait AnalysisRayTrace: OpticNode + Surface { backward: bool, port_name: &str, ) -> OpmResult<()> { + let uuid = *self.node_attr().uuid(); if backward { for rays in &mut *rays_bundle { if let Some(aperture) = self.ports().aperture(&PortType::Input, port_name) { @@ -104,7 +105,13 @@ pub trait AnalysisRayTrace: OpticNode + Surface { return Err(OpossumError::OpticPort("output aperture not found".into())); }; let surf = self.get_surface_mut(port_name); - let reflected_rear = rays.refract_on_surface(surf, Some(refri))?; + let mut reflected_rear = rays.refract_on_surface(surf, Some(refri))?; + reflected_rear.set_node_origin_uuid(uuid); + + if let AnalyzerType::GhostFocus(_) = analyzer_type { + surf.evaluate_fluence_of_ray_bundle(rays)?; + } + surf.add_to_forward_rays_cache(reflected_rear); } for rays in self.get_surface_mut(port_name).backwards_rays_cache() { @@ -121,7 +128,11 @@ pub trait AnalysisRayTrace: OpticNode + Surface { return Err(OpossumError::OpticPort("input aperture not found".into())); }; let surf = self.get_surface_mut(port_name); - let reflected_front = rays.refract_on_surface(surf, Some(refri))?; + let mut reflected_front = rays.refract_on_surface(surf, Some(refri))?; + reflected_front.set_node_origin_uuid(uuid); + if let AnalyzerType::GhostFocus(_) = analyzer_type { + surf.evaluate_fluence_of_ray_bundle(rays)?; + } surf.add_to_backward_rays_cache(reflected_front); } for rays in self.get_surface_mut(port_name).forward_rays_cache() { @@ -142,10 +153,17 @@ pub trait AnalysisRayTrace: OpticNode + Surface { backward: bool, port_name: &str, ) -> OpmResult<()> { + let uuid: uuid::Uuid = *self.node_attr().uuid(); let surf = self.get_surface_mut(port_name); if backward { for rays in &mut *rays_bundle { - let reflected_front = rays.refract_on_surface(surf, Some(refri))?; + let mut reflected_front = rays.refract_on_surface(surf, Some(refri))?; + reflected_front.set_node_origin_uuid(uuid); + + if let AnalyzerType::GhostFocus(_) = analyzer_type { + surf.evaluate_fluence_of_ray_bundle(rays)?; + } + surf.add_to_forward_rays_cache(reflected_front); } for rays in surf.backwards_rays_cache() { @@ -163,7 +181,11 @@ pub trait AnalysisRayTrace: OpticNode + Surface { } } else { for rays in &mut *rays_bundle { - let reflected_rear = rays.refract_on_surface(surf, Some(refri))?; + let mut reflected_rear = rays.refract_on_surface(surf, Some(refri))?; + reflected_rear.set_node_origin_uuid(uuid); + if let AnalyzerType::GhostFocus(_) = analyzer_type { + surf.evaluate_fluence_of_ray_bundle(rays)?; + } surf.add_to_backward_rays_cache(reflected_rear); } for rays in surf.forward_rays_cache() { @@ -188,12 +210,19 @@ pub trait AnalysisRayTrace: OpticNode + Surface { /// This functionis used for the propagation through ideal detectors, such as a spot diagram /// # Errors /// This function errors if the effective isometry is not defined - fn pass_through_inert_surface(&mut self, rays_bundle: &mut Vec<Rays>) -> OpmResult<()> { + fn pass_through_inert_surface( + &mut self, + rays_bundle: &mut Vec<Rays>, + analyzer_type: &AnalyzerType, + ) -> OpmResult<()> { if let Some(iso) = self.effective_iso() { let surf = self.get_surface_mut(""); surf.set_isometry(&iso); for rays in &mut *rays_bundle { rays.refract_on_surface(surf, None)?; + if let AnalyzerType::GhostFocus(_) = analyzer_type { + surf.evaluate_fluence_of_ray_bundle(rays)?; + } } } else { return Err(OpossumError::Analysis( @@ -400,10 +429,10 @@ mod test { // simulate simple system for integration test let mut group = NodeGroup::default(); let i_src = group - .add_node(round_collimated_ray_source(millimeter!(10.0), joule!(1.0), 3).unwrap()) + .add_node(&round_collimated_ray_source(millimeter!(10.0), joule!(1.0), 3).unwrap()) .unwrap(); let i_l1 = group - .add_node(ParaxialSurface::new("f=100", millimeter!(100.0)).unwrap()) + .add_node(&ParaxialSurface::new("f=100", millimeter!(100.0)).unwrap()) .unwrap(); group .connect_nodes(i_src, "out1", i_l1, "front", millimeter!(50.0)) diff --git a/opossum/src/dottable.rs b/opossum/src/dottable.rs index 078d01be0ff284f0b40f4d73df9a176d1e908e31..fd1b3e036b3ce0c962f8c775253f3fc6445fc3a0 100644 --- a/opossum/src/dottable.rs +++ b/opossum/src/dottable.rs @@ -365,7 +365,7 @@ mod test { let file_content_lr = get_file_content("./files_for_testing/dot/to_dot_w_node_LR.dot"); let mut scenery = NodeGroup::default(); - scenery.add_node(Dummy::new("Test")).unwrap(); + scenery.add_node(&Dummy::new("Test")).unwrap(); let scenery_dot_str_tb = scenery.toplevel_dot("TB").unwrap(); let scenery_dot_str_lr = scenery.toplevel_dot("LR").unwrap(); @@ -381,19 +381,19 @@ mod test { let mut scenery = NodeGroup::default(); let i_s = scenery - .add_node(Source::new("Source", &LightData::Fourier)) + .add_node(&Source::new("Source", &LightData::Fourier)) .unwrap(); let bs = BeamSplitter::new("test", &SplittingConfig::Ratio(0.6)).unwrap(); // bs.node_attr_mut().set_name("Beam splitter"); - let i_bs = scenery.add_node(bs).unwrap(); + let i_bs = scenery.add_node(&bs).unwrap(); let i_d1 = scenery - .add_node(EnergyMeter::new( + .add_node(&EnergyMeter::new( "Energy meter 1", Metertype::IdealEnergyMeter, )) .unwrap(); let i_d2 = scenery - .add_node(EnergyMeter::new( + .add_node(&EnergyMeter::new( "Energy meter 2", Metertype::IdealEnergyMeter, )) @@ -421,8 +421,8 @@ mod test { let mut scenery = NodeGroup::default(); let mut group1 = NodeGroup::new("group 1"); group1.set_expand_view(true).unwrap(); - let g1_n1 = group1.add_node(Dummy::new("node1")).unwrap(); - let g1_n2 = group1.add_node(BeamSplitter::default()).unwrap(); + let g1_n1 = group1.add_node(&Dummy::new("node1")).unwrap(); + let g1_n2 = group1.add_node(&BeamSplitter::default()).unwrap(); group1 .map_output_port(g1_n2, "out1_trans1_refl2", "out1") .unwrap(); @@ -431,8 +431,8 @@ mod test { .unwrap(); let mut nested_group = NodeGroup::new("group 1_1"); - let nested_g_n1 = nested_group.add_node(Dummy::new("node1_1")).unwrap(); - let nested_g_n2 = nested_group.add_node(Dummy::new("node1_2")).unwrap(); + let nested_g_n1 = nested_group.add_node(&Dummy::new("node1_1")).unwrap(); + let nested_g_n2 = nested_group.add_node(&Dummy::new("node1_2")).unwrap(); nested_group.set_expand_view(true).unwrap(); nested_group @@ -445,23 +445,23 @@ mod test { .map_output_port(nested_g_n2, "rear", "out1") .unwrap(); - let nested_group_index = group1.add_node(nested_group).unwrap(); + let nested_group_index = group1.add_node(&nested_group).unwrap(); group1 .connect_nodes(nested_group_index, "out1", g1_n1, "front", Length::zero()) .unwrap(); let mut group2: NodeGroup = NodeGroup::new("group 2"); group2.set_expand_view(false).unwrap(); - let g2_n1 = group2.add_node(Dummy::new("node2_1")).unwrap(); - let g2_n2 = group2.add_node(Dummy::new("node2_2")).unwrap(); + let g2_n1 = group2.add_node(&Dummy::new("node2_1")).unwrap(); + let g2_n2 = group2.add_node(&Dummy::new("node2_2")).unwrap(); group2.map_input_port(g2_n1, "front", "in1").unwrap(); group2 .connect_nodes(g2_n1, "rear", g2_n2, "front", Length::zero()) .unwrap(); - let scene_g1 = scenery.add_node(group1).unwrap(); - let scene_g2 = scenery.add_node(group2).unwrap(); + let scene_g1 = scenery.add_node(&group1).unwrap(); + let scene_g2 = scenery.add_node(&group2).unwrap(); // set_output_port scenery diff --git a/opossum/src/nodes/beam_splitter.rs b/opossum/src/nodes/beam_splitter.rs index ef1463d0be04ac9acf19b822af80ba0174cf47a3..58a8ae6d3abcbfbb2247c32f28c6ea42bbc894c3 100644 --- a/opossum/src/nodes/beam_splitter.rs +++ b/opossum/src/nodes/beam_splitter.rs @@ -19,7 +19,7 @@ use crate::{ utils::EnumProxy, }; -#[derive(Debug)] +#[derive(Debug, Clone)] /// An ideal beamsplitter node with a given splitting ratio. /// /// ## Optical Ports diff --git a/opossum/src/nodes/cylindric_lens/mod.rs b/opossum/src/nodes/cylindric_lens/mod.rs index f0f0547fd045497212dfaba0be9d77b71841e380..1d96efa4eb55f7c173e1663ce4ab03ec84e22c5e 100644 --- a/opossum/src/nodes/cylindric_lens/mod.rs +++ b/opossum/src/nodes/cylindric_lens/mod.rs @@ -26,7 +26,7 @@ mod analysis_energy; mod analysis_ghostfocus; mod analysis_raytrace; -#[derive(Debug)] +#[derive(Debug, Clone)] /// A real cylindric lens with spherical (or flat) surfaces. By default, the curvature is aligned along the (local) y axis. /// /// diff --git a/opossum/src/nodes/detector.rs b/opossum/src/nodes/detector.rs index 4a0b3b3c002e29f913259ba8964644519c34b4b8..5a3a2123d649fc684c81e9a6cf93eb51276d0303 100644 --- a/opossum/src/nodes/detector.rs +++ b/opossum/src/nodes/detector.rs @@ -34,6 +34,7 @@ use std::fmt::Debug; /// /// During analysis, the output port contains a replica of the input port similar to a [`Dummy`](crate::nodes::Dummy) node. This way, /// different detector nodes can be "stacked" or used somewhere in between arbitrary optic nodes. +#[derive(Clone)] pub struct Detector { light_data: Option<LightData>, node_attr: NodeAttr, @@ -168,6 +169,7 @@ impl AnalysisRayTrace for Detector { self.light_data = Some(ld); } } + impl Surface for Detector { fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface { todo!() diff --git a/opossum/src/nodes/energy_meter.rs b/opossum/src/nodes/energy_meter.rs index 0737cc6f6cd092609c824e05dd4bbb0d11009d4e..13df2d6d6d338be6166c4bfc6ab6db7a91326bfa 100644 --- a/opossum/src/nodes/energy_meter.rs +++ b/opossum/src/nodes/energy_meter.rs @@ -63,6 +63,7 @@ impl From<Metertype> for Proptype { /// /// During analysis, the output port contains a replica of the input port similar to a [`Dummy`](crate::nodes::Dummy) node. This way, /// different dectector nodes can be "stacked" or used somewhere in between arbitrary optic nodes. +#[derive(Clone)] pub struct EnergyMeter { light_data: Option<LightData>, node_attr: NodeAttr, diff --git a/opossum/src/nodes/fluence_detector.rs b/opossum/src/nodes/fluence_detector.rs index 1ba600ca179b02b801068e19171b5cf17086ba67..4048710359fa09c01caf476d7b50c8359a7a510d 100644 --- a/opossum/src/nodes/fluence_detector.rs +++ b/opossum/src/nodes/fluence_detector.rs @@ -10,7 +10,7 @@ use super::node_attr::NodeAttr; use crate::{ analyzers::{ energy::AnalysisEnergy, ghostfocus::AnalysisGhostFocus, raytrace::AnalysisRayTrace, - Analyzable, GhostFocusConfig, RayTraceConfig, + Analyzable, AnalyzerType, GhostFocusConfig, RayTraceConfig, }, dottable::Dottable, error::{OpmResult, OpossumError}, @@ -199,7 +199,10 @@ impl AnalysisGhostFocus for FluenceDetector { return Ok(out_light_rays); }; let mut rays = bouncing_rays.clone(); - self.pass_through_inert_surface(&mut rays)?; + self.pass_through_inert_surface( + &mut rays, + &AnalyzerType::GhostFocus(GhostFocusConfig::default()), + )?; let mut out_light_rays = LightRays::default(); out_light_rays.insert(out_port.to_string(), rays.clone()); diff --git a/opossum/src/nodes/ideal_filter.rs b/opossum/src/nodes/ideal_filter.rs index 15067d1cdad863ff25801e95e3c7d386d40efa77..e4a598f8bfff1c94eba91a551c83c14e5275c780 100644 --- a/opossum/src/nodes/ideal_filter.rs +++ b/opossum/src/nodes/ideal_filter.rs @@ -26,7 +26,7 @@ pub enum FilterType { /// filter based on given transmission spectrum. Spectrum(Spectrum), } -#[derive(Debug)] +#[derive(Debug, Clone)] /// An ideal filter with given transmission or optical density. /// /// ## Optical Ports diff --git a/opossum/src/nodes/lens/analysis_ghostfocus.rs b/opossum/src/nodes/lens/analysis_ghostfocus.rs index b3a42a319bf87959e868622970808993ad773c1c..357c4ba8786e432ed285f607b5bd96c27c1d595b 100644 --- a/opossum/src/nodes/lens/analysis_ghostfocus.rs +++ b/opossum/src/nodes/lens/analysis_ghostfocus.rs @@ -46,7 +46,6 @@ impl AnalysisGhostFocus for Lens { }; let mut rays_bundle = incoming_rays.clone(); - self.enter_through_surface( &mut rays_bundle, &AnalyzerType::GhostFocus(config.clone()), diff --git a/opossum/src/nodes/lens/mod.rs b/opossum/src/nodes/lens/mod.rs index e9f2fd9014fb343d9231a04c4fd97634cd29a2a5..053d75ed213b19865969e8505b875ed2d0bc8cf4 100644 --- a/opossum/src/nodes/lens/mod.rs +++ b/opossum/src/nodes/lens/mod.rs @@ -26,7 +26,7 @@ mod analysis_energy; mod analysis_ghostfocus; mod analysis_raytrace; -#[derive(Debug)] +#[derive(Debug, Clone)] /// A real lens with spherical (or flat) surfaces. /// /// diff --git a/opossum/src/nodes/node_attr.rs b/opossum/src/nodes/node_attr.rs index 843bf66b359ba89c8f269c56d48c669680df48f4..9c6eeef07256e46baa429b5e195ae773a279c74c 100644 --- a/opossum/src/nodes/node_attr.rs +++ b/opossum/src/nodes/node_attr.rs @@ -6,6 +6,7 @@ use std::{cell::RefCell, rc::Rc}; use petgraph::graph::NodeIndex; use serde::{Deserialize, Serialize}; use uom::si::f64::Length; +use uuid::Uuid; use crate::{ error::{OpmResult, OpossumError}, @@ -22,6 +23,7 @@ pub struct NodeAttr { node_type: String, name: String, ports: OpticPorts, + uuid: Uuid, #[serde(default)] props: Properties, #[serde(skip_serializing_if = "Option::is_none")] @@ -68,6 +70,7 @@ impl NodeAttr { inverted: false, alignment: None, align_like_node_at_distance: None, + uuid: Uuid::new_v4(), } } /// Returns the name property of this node. @@ -198,6 +201,16 @@ impl NodeAttr { self.ports = ports; } + /// Returns a reference to the uuid of this [`NodeAttr`]. + #[must_use] + pub const fn uuid(&self) -> &Uuid { + &self.uuid + } + ///Sets the uuid of this [`NodeAttr`]. + pub fn set_uuid(&mut self, uuid: &Uuid) { + self.uuid = *uuid; + } + /// set the nodeindex and distance of the node to which this node should be aligned to pub fn set_align_like_node_at_distance(&mut self, node_idx: NodeIndex, distance: Length) { self.align_like_node_at_distance = Some((node_idx, distance)); diff --git a/opossum/src/nodes/node_group/analysis_ghostfocus.rs b/opossum/src/nodes/node_group/analysis_ghostfocus.rs index cfdc2fb20a157987eb66225de400bdd4cdba2d97..0846be6a5d4224163c84ca21cfb43823ba6a0dd0 100644 --- a/opossum/src/nodes/node_group/analysis_ghostfocus.rs +++ b/opossum/src/nodes/node_group/analysis_ghostfocus.rs @@ -66,10 +66,6 @@ impl AnalysisGhostFocus for NodeGroup { let outgoing_edges = light_rays_to_light_result(outgoing_edges); for outgoing_edge in outgoing_edges { - println!( - "{}", - self.graph.node_by_idx(idx)?.optical_ref.borrow().name() - ); let no_sink = self.graph .set_outgoing_edge_data(idx, &outgoing_edge.0, &outgoing_edge.1); diff --git a/opossum/src/nodes/node_group/mod.rs b/opossum/src/nodes/node_group/mod.rs index c85f126a88c5aefbc26415217282dfc49cf81259..2efdc2c1e90668a91f77b0d18d87a69b9500d204 100644 --- a/opossum/src/nodes/node_group/mod.rs +++ b/opossum/src/nodes/node_group/mod.rs @@ -9,6 +9,7 @@ use crate::{ dottable::Dottable, error::{OpmResult, OpossumError}, get_version, + lightdata::LightData, optic_node::OpticNode, optic_ports::{OpticPorts, PortType}, optic_ref::OpticRef, @@ -16,15 +17,22 @@ use crate::{ rays::Rays, reporting::{analysis_report::AnalysisReport, node_report::NodeReport}, surface::{OpticalSurface, Surface}, + utils::EnumProxy, SceneryResources, }; use chrono::Local; pub use optic_graph::OpticGraph; use petgraph::prelude::NodeIndex; use serde::{Deserialize, Serialize}; -use std::{cell::RefCell, collections::BTreeMap, io::Write, rc::Rc}; +use std::{ + cell::RefCell, + collections::{BTreeMap, HashMap}, + io::Write, + rc::Rc, +}; use tempfile::NamedTempFile; use uom::si::f64::Length; +use uuid::Uuid; #[derive(Debug, Clone, Serialize, Deserialize)] /// The basic building block of an optical system. It represents a group of other optical /// nodes ([`OpticNode`]s) arranged in a (sub)graph. @@ -38,8 +46,8 @@ use uom::si::f64::Length; /// /// fn main() -> OpmResult<()> { /// let mut scenery = NodeGroup::new("OpticScenery demo"); -/// let node1 = scenery.add_node(Dummy::new("dummy1"))?; -/// let node2 = scenery.add_node(Dummy::new("dummy2"))?; +/// let node1 = scenery.add_node(&Dummy::new("dummy1"))?; +/// let node2 = scenery.add_node(&Dummy::new("dummy2"))?; /// scenery.connect_nodes(node1, "rear", node2, "front", millimeter!(100.0))?; /// Ok(()) /// } @@ -71,7 +79,7 @@ pub struct NodeGroup { #[serde(skip)] input_port_distances: BTreeMap<String, Length>, #[serde(skip)] - accumulated_rays: Vec<Vec<Rays>>, + accumulated_rays: Vec<HashMap<Uuid, Rays>>, } impl Default for NodeGroup { fn default() -> Self { @@ -91,7 +99,7 @@ impl Default for NodeGroup { graph: OpticGraph::default(), input_port_distances: BTreeMap::default(), node_attr, - accumulated_rays: Vec::<Vec<Rays>>::new(), + accumulated_rays: Vec::<HashMap<Uuid, Rays>>::new(), } } } @@ -116,12 +124,41 @@ impl NodeGroup { /// /// # Panics /// This function panics if the property "graph" can not be updated. Produces an error of type [`OpossumError::Properties`] - pub fn add_node<T: Analyzable + 'static>(&mut self, node: T) -> OpmResult<NodeIndex> { - let idx = self.graph.add_node(node); + pub fn add_node<T: Analyzable + Clone + 'static>(&mut self, node: &T) -> OpmResult<NodeIndex> { + let idx = self.graph.add_node(node.clone())?; + + // save uuid of node in rays if present + self.store_node_uuid_in_rays_bundle(node, idx)?; + self.node_attr .set_property("graph", self.graph.clone().into()) .unwrap(); - idx + Ok(idx) + } + + fn store_node_uuid_in_rays_bundle<T: Analyzable + Clone + 'static>( + &mut self, + node: &T, + node_idx: NodeIndex, + ) -> OpmResult<()> { + if let Ok(Proptype::LightData(ld)) = node.node_attr().get_property("light data") { + if let Some(LightData::Geometric(rays)) = &ld.value { + let node_from_graph = self.graph_mut().node_by_idx_mut(node_idx)?; + + let mut new_rays = rays.clone(); + new_rays.set_node_origin_uuid(node_from_graph.uuid()); + + let mut node_ref = node_from_graph.optical_ref.borrow_mut(); + node_ref.node_attr_mut().set_property( + "light data", + EnumProxy::<Option<LightData>> { + value: Some(LightData::Geometric(new_rays)), + } + .into(), + )?; + } + } + Ok(()) } /// Return a reference to the optical node specified by its [`NodeIndex`]. /// @@ -372,7 +409,7 @@ impl NodeGroup { /// This function returns a bundle of all rays that propagated in a group after a ghost focus analysis. /// This function is in particular helpful for generating a global ray propagation plot. #[must_use] - pub const fn accumulated_rays(&self) -> &Vec<Vec<Rays>> { + pub const fn accumulated_rays(&self) -> &Vec<HashMap<Uuid, Rays>> { &self.accumulated_rays } @@ -382,9 +419,11 @@ impl NodeGroup { /// - bounce: bouncle level of these rays pub fn add_to_accumulated_rays(&mut self, rays: &Rays, bounce: usize) { if self.accumulated_rays.len() <= bounce { - self.accumulated_rays.push(vec![rays.clone()]); + let mut hashed_rays = HashMap::<Uuid, Rays>::new(); + hashed_rays.insert(*rays.uuid(), rays.clone()); + self.accumulated_rays.push(hashed_rays); } else { - self.accumulated_rays[bounce].push(rays.clone()); + self.accumulated_rays[bounce].insert(*rays.uuid(), rays.clone()); } } @@ -466,7 +505,7 @@ impl OpticNode for NodeGroup { for node in nodes { node.optical_ref.borrow_mut().reset_data(); } - self.accumulated_rays = Vec::<Vec<Rays>>::new(); + self.accumulated_rays = Vec::<HashMap<Uuid, Rays>>::new(); } } @@ -548,8 +587,8 @@ mod test { #[test] fn ports() { let mut og = NodeGroup::default(); - let sn1_i = og.add_node(Dummy::default()).unwrap(); - let sn2_i = og.add_node(Dummy::default()).unwrap(); + let sn1_i = og.add_node(&Dummy::default()).unwrap(); + let sn2_i = og.add_node(&Dummy::default()).unwrap(); og.connect_nodes(sn1_i, "rear", sn2_i, "front", Length::zero()) .unwrap(); assert!(og.ports().names(&PortType::Input).is_empty()); @@ -568,8 +607,8 @@ mod test { #[test] fn ports_inverted() { let mut og = NodeGroup::default(); - let sn1_i = og.add_node(Dummy::default()).unwrap(); - let sn2_i = og.add_node(Dummy::default()).unwrap(); + let sn1_i = og.add_node(&Dummy::default()).unwrap(); + let sn2_i = og.add_node(&Dummy::default()).unwrap(); og.connect_nodes(sn1_i, "rear", sn2_i, "front", Length::zero()) .unwrap(); og.map_input_port(sn1_i, "front", "input").unwrap(); @@ -587,7 +626,7 @@ mod test { #[test] fn report() { let mut scenery = NodeGroup::default(); - scenery.add_node(Detector::default()).unwrap(); + scenery.add_node(&Detector::default()).unwrap(); let report = scenery.toplevel_report().unwrap(); assert!(serde_yaml::to_string(&report).is_ok()); // How shall we further parse the output? @@ -601,8 +640,8 @@ mod test { #[test] fn analyze_dummy() { let mut scenery = NodeGroup::default(); - let node1 = scenery.add_node(Dummy::default()).unwrap(); - let node2 = scenery.add_node(Dummy::default()).unwrap(); + let node1 = scenery.add_node(&Dummy::default()).unwrap(); + let node2 = scenery.add_node(&Dummy::default()).unwrap(); scenery .connect_nodes(node1, "rear", node2, "front", Length::zero()) .unwrap(); @@ -624,11 +663,11 @@ mod test { ); let mut scenery = NodeGroup::default(); let i_s = scenery - .add_node(Source::new("src", &LightData::Geometric(rays))) + .add_node(&Source::new("src", &LightData::Geometric(rays))) .unwrap(); let mut em = EnergyMeter::default(); em.set_isometry(Isometry::identity()); - let i_e = scenery.add_node(em).unwrap(); + let i_e = scenery.add_node(&em).unwrap(); scenery .connect_nodes(i_s, "out1", i_e, "in1", Length::zero()) .unwrap(); diff --git a/opossum/src/nodes/node_group/optic_graph.rs b/opossum/src/nodes/node_group/optic_graph.rs index 332974d4f7eff895c6f4e4dcfa0e1b52d4104b44..6fe528ffe6db6c70705dea288b04643bb3aa1a98 100644 --- a/opossum/src/nodes/node_group/optic_graph.rs +++ b/opossum/src/nodes/node_group/optic_graph.rs @@ -62,11 +62,14 @@ impl OpticGraph { "cannot add nodes if group is set as inverted".into(), )); } + let uuid = *node.node_attr().uuid(); + let idx = self.g.add_node(OpticRef::new( Rc::new(RefCell::new(node)), - None, + Some(uuid), self.global_confg.clone(), )); + Ok(idx) } /// Connect two optical nodes within this [`OpticGraph`]. @@ -348,7 +351,9 @@ impl OpticGraph { .edges_directed(target_node, petgraph::Direction::Incoming) .any(|e| e.weight().target_port() == target_port) } - fn node_by_uuid(&self, uuid: Uuid) -> Option<OpticRef> { + /// Returns Some(`OpticRef`) if the provided uuid is connected with a node in the graph. None, otherwise. + #[must_use] + pub fn node_by_uuid(&self, uuid: Uuid) -> Option<OpticRef> { self.g .node_weights() .find(|node| node.uuid() == uuid) @@ -368,6 +373,21 @@ impl OpticGraph { .ok_or_else(|| OpossumError::OpticScenery("node index does not exist".into()))?; Ok(node.clone()) } + + /// Return a mutable reference to the optical node specified by its node index. + /// + /// This function is mainly useful for setting up a reference node. + /// + /// # Errors + /// + /// This function will return [`OpossumError::OpticScenery`] if the node does not exist. + pub fn node_by_idx_mut(&mut self, node: NodeIndex) -> OpmResult<&mut OpticRef> { + let node = self + .g + .node_weight_mut(node) + .ok_or_else(|| OpossumError::OpticScenery("node index does not exist".into()))?; + Ok(node) + } fn node_idx_by_uuid(&self, uuid: Uuid) -> Option<NodeIndex> { self.g .node_indices() diff --git a/opossum/src/nodes/ray_propagation_visualizer.rs b/opossum/src/nodes/ray_propagation_visualizer.rs index 41f9173de15d0e3c48124e56476ae1187d4e5a5f..cef8299d54bce72726b2e3ce1b9b7f7a9f781d3a 100644 --- a/opossum/src/nodes/ray_propagation_visualizer.rs +++ b/opossum/src/nodes/ray_propagation_visualizer.rs @@ -13,7 +13,7 @@ use super::node_attr::NodeAttr; use crate::{ analyzers::{ energy::AnalysisEnergy, ghostfocus::AnalysisGhostFocus, raytrace::AnalysisRayTrace, - Analyzable, GhostFocusConfig, RayTraceConfig, + Analyzable, AnalyzerType, GhostFocusConfig, RayTraceConfig, }, dottable::Dottable, error::{OpmResult, OpossumError}, @@ -168,7 +168,10 @@ impl AnalysisGhostFocus for RayPropagationVisualizer { return Ok(out_light_rays); }; let mut rays = bouncing_rays.clone(); - self.pass_through_inert_surface(&mut rays)?; + self.pass_through_inert_surface( + &mut rays, + &AnalyzerType::GhostFocus(GhostFocusConfig::default()), + )?; let mut out_light_rays = LightRays::default(); out_light_rays.insert(out_port.to_string(), rays.clone()); diff --git a/opossum/src/nodes/reference.rs b/opossum/src/nodes/reference.rs index 350a5cb489b0c24a987f46b4566ed7eb07390731..5a7b8613139420d0e4f62cadefe4542fd7ca1a30 100644 --- a/opossum/src/nodes/reference.rs +++ b/opossum/src/nodes/reference.rs @@ -21,7 +21,7 @@ use crate::{ use super::node_attr::NodeAttr; -#[derive(Debug)] +#[derive(Debug, Clone)] /// A virtual component referring to another existing component. /// /// This node type is necessary in order to model resonators (loops) or double-pass systems. @@ -199,7 +199,7 @@ mod test { #[test] fn from_node() { let mut scenery = NodeGroup::default(); - let idx = scenery.add_node(Dummy::default()).unwrap(); + let idx = scenery.add_node(&Dummy::default()).unwrap(); let node_ref = scenery.node(idx).unwrap(); let node = NodeReference::from_node(&node_ref); assert!(node.reference.is_some()); @@ -207,7 +207,7 @@ mod test { #[test] fn from_node_name() { let mut scenery = NodeGroup::default(); - let idx = scenery.add_node(Dummy::default()).unwrap(); + let idx = scenery.add_node(&Dummy::default()).unwrap(); let node_ref = scenery.node(idx).unwrap(); let node_name = format!("ref ({})", node_ref.optical_ref.borrow().name()); let node = NodeReference::from_node(&node_ref); @@ -217,7 +217,7 @@ mod test { #[test] fn assign_reference() { let mut scenery = NodeGroup::default(); - let idx = scenery.add_node(Dummy::default()).unwrap(); + let idx = scenery.add_node(&Dummy::default()).unwrap(); let node_ref = scenery.node(idx).unwrap(); let mut node = NodeReference::default(); assert!(node.reference.is_none()); @@ -237,7 +237,7 @@ mod test { #[test] fn ports_non_empty() { let mut scenery = NodeGroup::default(); - let idx = scenery.add_node(Dummy::default()).unwrap(); + let idx = scenery.add_node(&Dummy::default()).unwrap(); let node = NodeReference::from_node(&scenery.node(idx).unwrap()); assert_eq!(node.ports().names(&PortType::Input), vec!["front"]); assert_eq!(node.ports().names(&PortType::Output), vec!["rear"]); @@ -245,7 +245,7 @@ mod test { #[test] fn ports_inverted() { let mut scenery = NodeGroup::default(); - let idx = scenery.add_node(Dummy::default()).unwrap(); + let idx = scenery.add_node(&Dummy::default()).unwrap(); let mut node = NodeReference::from_node(&scenery.node(idx).unwrap()); node.set_inverted(true.into()).unwrap(); assert_eq!(node.ports().names(&PortType::Input), vec!["rear"]); @@ -254,7 +254,7 @@ mod test { #[test] fn analyze_empty() { let mut scenery = NodeGroup::default(); - let idx = scenery.add_node(Dummy::default()).unwrap(); + let idx = scenery.add_node(&Dummy::default()).unwrap(); let mut node = NodeReference::from_node(&scenery.node(idx).unwrap()); let output = AnalysisEnergy::analyze(&mut node, LightResult::default()).unwrap(); assert!(output.is_empty()); @@ -268,7 +268,7 @@ mod test { #[test] fn analyze() { let mut scenery = NodeGroup::default(); - let idx = scenery.add_node(Dummy::default()).unwrap(); + let idx = scenery.add_node(&Dummy::default()).unwrap(); let mut node = NodeReference::from_node(&scenery.node(idx).unwrap()); let mut input = LightResult::default(); @@ -287,7 +287,7 @@ mod test { #[test] fn analyze_inverse() { let mut scenery = NodeGroup::default(); - let idx = scenery.add_node(Dummy::default()).unwrap(); + let idx = scenery.add_node(&Dummy::default()).unwrap(); let mut node = NodeReference::from_node(&scenery.node(idx).unwrap()); node.set_inverted(true).unwrap(); let mut input = LightResult::default(); @@ -307,7 +307,7 @@ mod test { #[test] fn analyze_non_invertible_ref() { let mut scenery = NodeGroup::default(); - let idx = scenery.add_node(Source::default()).unwrap(); + let idx = scenery.add_node(&Source::default()).unwrap(); let mut node = NodeReference::from_node(&scenery.node(idx).unwrap()); node.set_inverted(true).unwrap(); let mut input = LightResult::default(); diff --git a/opossum/src/nodes/source.rs b/opossum/src/nodes/source.rs index 4a0ca6feb5aaa865ad0017bc4eb44677b966909c..af85f8da9c0cece41cb8892595121fc294f6d701 100644 --- a/opossum/src/nodes/source.rs +++ b/opossum/src/nodes/source.rs @@ -303,6 +303,7 @@ impl AnalysisGhostFocus for Source { self.surface.set_isometry(&iso); for r in &mut rays { r.refract_on_surface(&mut self.surface, None)?; + self.surface.evaluate_fluence_of_ray_bundle(r)?; } } else { return Err(OpossumError::Analysis( diff --git a/opossum/src/nodes/spectrometer.rs b/opossum/src/nodes/spectrometer.rs index fee7f36ddab2ba3e287f36256fbb361291aaf7fb..91c8608b0f6e3ca24c219bb7f191df7018201b9a 100644 --- a/opossum/src/nodes/spectrometer.rs +++ b/opossum/src/nodes/spectrometer.rs @@ -214,7 +214,6 @@ impl OpticNode for Spectrometer { self.surface.reset_hit_map(); } } - impl Surface for Spectrometer { fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface { todo!() diff --git a/opossum/src/nodes/spot_diagram.rs b/opossum/src/nodes/spot_diagram.rs index 437473fa96515df49c3babbe376f6c3777307899..398cfaece36b55b4fc39d01a87cadc862f2d0bf6 100644 --- a/opossum/src/nodes/spot_diagram.rs +++ b/opossum/src/nodes/spot_diagram.rs @@ -12,7 +12,7 @@ use super::node_attr::NodeAttr; use crate::{ analyzers::{ energy::AnalysisEnergy, ghostfocus::AnalysisGhostFocus, raytrace::AnalysisRayTrace, - Analyzable, GhostFocusConfig, RayTraceConfig, + Analyzable, AnalyzerType, GhostFocusConfig, RayTraceConfig, }, dottable::Dottable, error::{OpmResult, OpossumError}, @@ -214,7 +214,10 @@ impl AnalysisGhostFocus for SpotDiagram { return Ok(out_light_rays); }; let mut rays = bouncing_rays.clone(); - self.pass_through_inert_surface(&mut rays)?; + self.pass_through_inert_surface( + &mut rays, + &AnalyzerType::GhostFocus(GhostFocusConfig::default()), + )?; let mut out_light_rays = LightRays::default(); out_light_rays.insert(out_port.to_string(), rays); diff --git a/opossum/src/nodes/thin_mirror.rs b/opossum/src/nodes/thin_mirror.rs index 0e8170238c281f7563fdc146d887341ae446151f..f9f42b650ad5b03a461bb56d65bc47d5b8f39583 100644 --- a/opossum/src/nodes/thin_mirror.rs +++ b/opossum/src/nodes/thin_mirror.rs @@ -20,7 +20,7 @@ use crate::{ use num::Zero; use uom::si::f64::Length; -#[derive(Debug)] +#[derive(Debug, Clone)] /// An infinitely thin mirror with a spherical (or flat) surface. /// /// diff --git a/opossum/src/nodes/wedge/mod.rs b/opossum/src/nodes/wedge/mod.rs index 1855e86ea2f9f1c89359688e314d1492661e8068..ac949d8cec60bbecf37051a4d6bea71910cd764a 100644 --- a/opossum/src/nodes/wedge/mod.rs +++ b/opossum/src/nodes/wedge/mod.rs @@ -23,7 +23,7 @@ mod analysis_energy; mod analysis_ghostfocus; mod analysis_raytrace; -#[derive(Debug)] +#[derive(Debug, Clone)] /// An optical element with two flat surfaces, a given thickness and a given wedge angle (= wedged window). /// /// diff --git a/opossum/src/optic_node.rs b/opossum/src/optic_node.rs index 5b5c2558f583ea73244110ca908a3c9c3b7064ef..225492e4605a065de0fbec5de377d3996b7ddbc9 100644 --- a/opossum/src/optic_node.rs +++ b/opossum/src/optic_node.rs @@ -228,6 +228,8 @@ pub trait OpticNode: Dottable { } node_attr_mut.update_properties(node_attributes.properties().clone()); node_attr_mut.set_ports(node_attributes.ports().clone()); + + node_attr_mut.set_uuid(node_attributes.uuid()); } /// Get the node type of this [`OpticNode`] fn node_type(&self) -> String { diff --git a/opossum/src/properties/mod.rs b/opossum/src/properties/mod.rs index 3b42b5014bf83c78a1052d6a80ffa18da140de7a..df11f239f363aaca99c86baba611251f30d8b8e3 100644 --- a/opossum/src/properties/mod.rs +++ b/opossum/src/properties/mod.rs @@ -53,6 +53,11 @@ impl Properties { self.props.insert(name.into(), new_property); Ok(()) } + /// Returns the number of properties that have been set + #[must_use] + pub fn nr_of_props(&self) -> usize { + self.props.len() + } /// Set the value of the property with the given name. /// /// # Errors diff --git a/opossum/src/properties/proptype.rs b/opossum/src/properties/proptype.rs index 0bb7d3d36ed159eb9b8ef281938187942bde9c37..d8e7efd66dc563b0d32e1d9700d85542b49ed2d2 100644 --- a/opossum/src/properties/proptype.rs +++ b/opossum/src/properties/proptype.rs @@ -144,6 +144,7 @@ impl Proptype { Self::WaveFrontData(_) | Self::FluenceDetector(_) => { tt.render("image", &format!("data/{id}_{property_name}.png")) } + Self::NodeReport(report) => { let html_node_report = HtmlNodeReport { node_name: report.name().into(), @@ -231,8 +232,21 @@ impl From<GhostFocusHistory> for Proptype { Self::GhostFocusHistory(value) } } +#[must_use] +pub fn count_str(i: usize) -> String { + if i == 1 { + "1st".to_owned() + } else if i == 2 { + "2nd".to_owned() + } else if i == 3 { + "3rd".to_owned() + } else { + format!("{i}th") + } +} -fn format_value_with_prefix(value: f64) -> String { +#[must_use] +pub fn format_value_with_prefix(value: f64) -> String { if value.is_nan() { return String::from(" nan "); } diff --git a/opossum/src/ray.rs b/opossum/src/ray.rs index 38cf782542c8931431853ea9f5286b360736a94c..5166cd8f5854eb093300b862ce86dda660f8152f 100644 --- a/opossum/src/ray.rs +++ b/opossum/src/ray.rs @@ -10,6 +10,7 @@ use uom::si::{ f64::{Energy, Length}, length::{meter, millimeter, nanometer}, }; +use uuid::Uuid; use crate::{ error::{OpmResult, OpossumError}, @@ -120,6 +121,12 @@ impl Ray { ) -> OpmResult<Self> { Self::new(position, Vector3::z(), wave_length, energy) } + + ///Returns the number of positions in the position history, ergo the length of the history vector + #[must_use] + pub fn ray_history_len(&self) -> usize { + self.pos_hist.len() + } /// Create a ray with a position at the global coordinate origin pointing along the positive z-axis. /// /// # Errors @@ -189,6 +196,48 @@ impl Ray { positions[(nr_of_pos, 2)] = self.pos.z; positions } + + /// Returns the position history of this [`Ray`] starting from and ending at a specific index. + /// + /// This function returns a matrix with all positions (end of propagation and intersection points) of a ray path. + /// **Note**: This function adds to current ray position to the list. + #[must_use] + pub fn position_history_from_to( + &self, + start_idx: usize, + end_idx: usize, + ) -> Option<MatrixXx3<Length>> { + if start_idx >= self.pos_hist.len() { + return None; + } + + let end_idx = if end_idx > self.pos_hist.len() { + self.pos_hist.len() + } else { + end_idx + }; + + let nr_of_pos = end_idx - start_idx; + let mut positions = MatrixXx3::<Length>::zeros(nr_of_pos); + + for (idx, hist_idx) in (start_idx..end_idx - 1).enumerate() { + positions[(idx, 0)] = self.pos_hist[hist_idx].x; + positions[(idx, 1)] = self.pos_hist[hist_idx].y; + positions[(idx, 2)] = self.pos_hist[hist_idx].z; + } + + if end_idx == self.pos_hist.len() { + positions[(nr_of_pos - 1, 0)] = self.pos.x; + positions[(nr_of_pos - 1, 1)] = self.pos.y; + positions[(nr_of_pos - 1, 2)] = self.pos.z; + } else { + positions[(nr_of_pos - 1, 0)] = self.pos_hist[end_idx].x; + positions[(nr_of_pos - 1, 1)] = self.pos_hist[end_idx].y; + positions[(nr_of_pos - 1, 2)] = self.pos_hist[end_idx].z; + } + Some(positions) + } + /// Returns the path length of this [`Ray`]. /// /// Return the geometric path length of the ray. @@ -404,6 +453,7 @@ impl Ray { &mut self, os: &mut OpticalSurface, n2: Option<f64>, + ray_bundle_uuid: &Uuid, ) -> OpmResult<Option<Self>> { let n2 = n2.unwrap_or_else(|| self.refractive_index()); if n2 < 1.0 || !n2.is_finite() { @@ -443,14 +493,17 @@ impl Ray { self.e = input_energy * (1. - reflectivity); let mut reflected_ray = self.clone(); reflected_ray.pos_hist.clear(); - reflected_ray.add_to_pos_hist(reflected_ray.pos); reflected_ray.dir = reflected_dir; reflected_ray.e = input_energy * reflectivity; reflected_ray.number_of_bounces += 1; self.refractive_index = n2; self.number_of_refractions += 1; // save on hit map of surface - os.add_to_hit_map((intersection_point, input_energy), self.number_of_bounces); + os.add_to_hit_map( + (intersection_point, input_energy), + self.number_of_bounces, + ray_bundle_uuid, + ); Ok(Some(reflected_ray)) } else { @@ -988,10 +1041,19 @@ mod test { .unwrap(); let mut s = OpticalSurface::new(Box::new(Plane::new(&isometry))); s.set_coating(CoatingType::ConstantR { reflectivity }); - assert!(ray.refract_on_surface(&mut s, Some(0.9)).is_err()); - assert!(ray.refract_on_surface(&mut s, Some(f64::NAN)).is_err()); - assert!(ray.refract_on_surface(&mut s, Some(f64::INFINITY)).is_err()); - let reflected_ray = ray.refract_on_surface(&mut s, Some(1.5)).unwrap().unwrap(); + assert!(ray + .refract_on_surface(&mut s, Some(0.9), &Uuid::new_v4()) + .is_err()); + assert!(ray + .refract_on_surface(&mut s, Some(f64::NAN), &Uuid::new_v4()) + .is_err()); + assert!(ray + .refract_on_surface(&mut s, Some(f64::INFINITY), &Uuid::new_v4()) + .is_err()); + let reflected_ray = ray + .refract_on_surface(&mut s, Some(1.5), &Uuid::new_v4()) + .unwrap() + .unwrap(); // refracted ray assert_eq!(ray.pos, millimeter!(0., 0., 10.)); @@ -1007,7 +1069,7 @@ mod test { assert_eq!(reflected_ray.pos, millimeter!(0., 0., 10.)); assert_eq!(reflected_ray.refractive_index, 1.0); assert_eq!(reflected_ray.dir, -1.0 * Vector3::z()); - assert_eq!(reflected_ray.pos_hist, vec![millimeter!(0., 0., 10.)]); + assert_eq!(reflected_ray.pos_hist, vec![]); assert_eq!(reflected_ray.path_length(), plane_z_pos); assert_eq!(reflected_ray.number_of_bounces(), 1); assert_eq!(reflected_ray.number_of_refractions(), 0); @@ -1015,7 +1077,8 @@ mod test { let position = millimeter!(0., 1., 0.); let mut ray = Ray::new_collimated(position, wvl, e).unwrap(); - ray.refract_on_surface(&mut s, Some(1.5)).unwrap(); + ray.refract_on_surface(&mut s, Some(1.5), &Uuid::new_v4()) + .unwrap(); assert_eq!(ray.pos, millimeter!(0., 1., 10.)); assert_eq!(ray.dir, Vector3::z()); assert_eq!(ray.path_length, plane_z_pos); @@ -1038,7 +1101,8 @@ mod test { ) .unwrap(); let mut s = OpticalSurface::new(Box::new(Plane::new(&isometry))); - ray.refract_on_surface(&mut s, None).unwrap(); + ray.refract_on_surface(&mut s, None, &Uuid::new_v4()) + .unwrap(); assert_eq!(ray.pos, millimeter!(0., 10., 10.)); assert_eq!(ray.dir[0], 0.0); assert_abs_diff_eq!(ray.dir[1], direction.normalize()[1]); @@ -1061,7 +1125,8 @@ mod test { ) .unwrap(); let mut s = OpticalSurface::new(Box::new(Plane::new(&isometry))); - ray.refract_on_surface(&mut s, Some(1.5)).unwrap(); + ray.refract_on_surface(&mut s, Some(1.5), &Uuid::new_v4()) + .unwrap(); assert_eq!(ray.pos, millimeter!(0., 0., 0.)); assert_eq!(ray.dir, direction); assert_eq!(ray.refractive_index, 1.0); @@ -1083,17 +1148,25 @@ mod test { ) .unwrap(); let mut s = OpticalSurface::new(Box::new(Plane::new(&isometry))); - assert!(ray.refract_on_surface(&mut s, Some(0.9)).is_err()); - assert!(ray.refract_on_surface(&mut s, Some(f64::NAN)).is_err()); - assert!(ray.refract_on_surface(&mut s, Some(f64::INFINITY)).is_err()); - ray.refract_on_surface(&mut s, Some(1.0)).unwrap(); + assert!(ray + .refract_on_surface(&mut s, Some(0.9), &Uuid::new_v4()) + .is_err()); + assert!(ray + .refract_on_surface(&mut s, Some(f64::NAN), &Uuid::new_v4()) + .is_err()); + assert!(ray + .refract_on_surface(&mut s, Some(f64::INFINITY), &Uuid::new_v4()) + .is_err()); + ray.refract_on_surface(&mut s, Some(1.0), &Uuid::new_v4()) + .unwrap(); assert_eq!(ray.pos, millimeter!(0., 10., 10.)); assert_eq!(ray.dir[0], 0.0); assert_abs_diff_eq!(ray.dir[1], direction.normalize()[1]); assert_abs_diff_eq!(ray.dir[2], direction.normalize()[2]); assert_abs_diff_eq!(ray.path_length.value, 2.0_f64.sqrt() * plane_z_pos.value); let mut ray = Ray::new(position, direction, wvl, e).unwrap(); - ray.refract_on_surface(&mut s, Some(1.5)).unwrap(); + ray.refract_on_surface(&mut s, Some(1.5), &Uuid::new_v4()) + .unwrap(); assert_eq!(ray.number_of_bounces(), 0); assert_eq!(ray.number_of_refractions(), 1); assert_eq!(ray.pos, millimeter!(0., 10., 10.)); @@ -1102,7 +1175,8 @@ mod test { assert_abs_diff_eq!(ray.dir[2], 0.8819171036881969); let direction = vector![1.0, 0.0, 1.0]; let mut ray = Ray::new(position, direction, wvl, e).unwrap(); - ray.refract_on_surface(&mut s, Some(1.5)).unwrap(); + ray.refract_on_surface(&mut s, Some(1.5), &Uuid::new_v4()) + .unwrap(); assert_eq!(ray.pos, millimeter!(10., 0., 10.)); assert_eq!(ray.dir[0], 0.4714045207910317); assert_abs_diff_eq!(ray.dir[1], 0.0); @@ -1122,7 +1196,9 @@ mod test { ) .unwrap(); let mut s = OpticalSurface::new(Box::new(Plane::new(&isometry))); - let reflected = ray.refract_on_surface(&mut s, Some(1.0)).unwrap(); + let reflected = ray + .refract_on_surface(&mut s, Some(1.0), &Uuid::new_v4()) + .unwrap(); assert!(reflected.is_none()); assert_eq!(ray.pos, millimeter!(0., 20., 10.)); let test_reflect = vector![0.0, 2.0, -1.0].normalize(); diff --git a/opossum/src/rays.rs b/opossum/src/rays.rs index 7b76e74abb1a81c5e3420f374a59d01ba1fc3c00..a32e998cb18cbc41a98010b5c773bf4734e7dd1f 100644 --- a/opossum/src/rays.rs +++ b/opossum/src/rays.rs @@ -50,11 +50,32 @@ use uom::{ length::{micrometer, millimeter, nanometer}, }, }; +use uuid::Uuid; /// Struct containing all relevant information of a ray bundle -#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] pub struct Rays { /// vector containing the individual rays rays: Vec<Ray>, + /// origin node of this ray bundle + node_origin: Option<Uuid>, + /// id of this ray bundle + uuid: Uuid, + /// parent id of this ray bundle + parent_id: Option<Uuid>, + ///the index of the position history of the parent ray bundle at which this ray bundle was generated + parent_pos_split_idx: usize, +} + +impl Default for Rays { + fn default() -> Self { + Self { + rays: Vec::default(), + node_origin: Option::default(), + uuid: Uuid::new_v4(), + parent_id: Option::default(), + parent_pos_split_idx: usize::default(), + } + } } impl Rays { /// Generate a set of collimated rays (collinear with optical axis) with uniform energy distribution. @@ -84,7 +105,75 @@ impl Rays { let ray = Ray::new_collimated(point, wave_length, energy_per_ray)?; rays.push(ray); } - Ok(Self { rays }) + Ok(Self { + rays, + node_origin: None, + uuid: Uuid::new_v4(), + parent_id: None, + parent_pos_split_idx: 0, + }) + } + ///Returns the uuid of this ray bundle + #[must_use] + pub const fn uuid(&self) -> &Uuid { + &self.uuid + } + ///get the bounce level of this ray bundle + #[must_use] + pub fn bounce_lvl(&self) -> usize { + if self.rays.is_empty() { + 0 + } else { + let valid_rays = self.rays.iter().filter(|r| r.valid()).collect_vec(); + if valid_rays.is_empty() { + 0 + } else { + valid_rays[0].number_of_bounces() + } + } + } + ///returns the length of the position history + #[must_use] + pub fn ray_history_len(&self) -> usize { + if self.rays.is_empty() { + 0 + } else { + let valid_rays = self.rays.iter().filter(|r| r.valid()).collect_vec(); + if valid_rays.is_empty() { + 0 + } else { + valid_rays[0].ray_history_len() + } + } + } + ///Returns the uuid of node at which this ray bundle originated + #[must_use] + pub const fn node_origin(&self) -> &Option<Uuid> { + &self.node_origin + } + ///Returns the uuid of tha parent ray bundle of this ray bundle + #[must_use] + pub const fn parent_id(&self) -> &Option<Uuid> { + &self.parent_id + } + ///Returns the index of the position history of its parent ray bundle + #[must_use] + pub const fn parent_pos_split_idx(&self) -> &usize { + &self.parent_pos_split_idx + } + /// Sets the parent uuid of this ray bundle + pub fn set_parent_uuid(&mut self, parent_uuid: Uuid) { + self.parent_id = Some(parent_uuid); + } + + /// Sets the node origin uuid of this ray bundle + pub fn set_node_origin_uuid(&mut self, node_uuid: Uuid) { + self.node_origin = Some(node_uuid); + } + + /// Sets the parent node split index node origin uuid of this ray bundle + pub fn set_parent_node_split_idx(&mut self, split_idx: usize) { + self.parent_pos_split_idx = split_idx; } /// Generate a set of collimated rays (collinear with optical axis) with specified energy, spectral and position distribution. @@ -124,7 +213,13 @@ impl Rays { rays.push(ray); } } - Ok(Self { rays }) + Ok(Self { + rays, + node_origin: None, + uuid: Uuid::new_v4(), + parent_id: None, + parent_pos_split_idx: 0, + }) } /// Generate a set of collimated rays (collinear with optical axis) with specified energy distribution and position distribution. @@ -162,7 +257,13 @@ impl Rays { rays.push(ray); } } - Ok(Self { rays }) + Ok(Self { + rays, + node_origin: None, + uuid: Uuid::new_v4(), + parent_id: None, + parent_pos_split_idx: 0, + }) } /// Generate a ray cone (= point source) /// @@ -206,7 +307,13 @@ impl Rays { let ray = Ray::new(position, direction, wave_length, energy_per_ray)?; rays.push(ray); } - Ok(Self { rays }) + Ok(Self { + rays, + node_origin: None, + uuid: Uuid::new_v4(), + parent_id: None, + parent_pos_split_idx: 0, + }) } /// Returns the total energy of this [`Rays`]. /// @@ -668,7 +775,7 @@ impl Rays { /// This function refracts all `valid` [`Ray`]s on a given surface. /// /// The refractive index of the surface is given by the `refractive_index` parameter. If this parameter is - /// set to `None`, the refractive index of the incoming individual beam is used. This way it is possibe to model + /// set to `None`, the refractive index of the incoming individual beam is used. This way it is possible to model /// a "passive" surface, which does not change the direction of the [`Ray`]. /// /// # Warnings @@ -695,7 +802,7 @@ impl Rays { } else { None }; - if let Some(reflected) = ray.refract_on_surface(surface, n2)? { + if let Some(reflected) = ray.refract_on_surface(surface, n2, &self.uuid)? { reflected_rays.add_ray(reflected); } else { rays_missed = true; @@ -710,6 +817,8 @@ impl Rays { warn!("ray bundle contains no valid rays - not propagating"); } //surface.set_backwards_rays_cache(reflected_rays.clone()); + reflected_rays.set_parent_uuid(self.uuid); + reflected_rays.set_parent_node_split_idx(self.ray_history_len()); Ok(reflected_rays) } /// Diffract a bundle of [`Rays`] on a periodic surface, e.g., a grating @@ -754,6 +863,7 @@ impl Rays { if !valid_rays_found { warn!("ray bundle contains no valid rays - not propagating"); } + reflected_rays.set_parent_uuid(self.uuid); Ok(reflected_rays) } /// Filter a ray bundle by a given filter. @@ -1114,7 +1224,13 @@ impl Display for Rays { impl From<Vec<Ray>> for Rays { fn from(value: Vec<Ray>) -> Self { - Self { rays: value } + Self { + rays: value, + node_origin: None, + uuid: Uuid::new_v4(), + parent_id: None, + parent_pos_split_idx: 0, + } } } diff --git a/opossum/src/surface/hit_map.rs b/opossum/src/surface/hit_map.rs index da2c1d0c5c2e2a343d4d18c5c0c9f9a4991690ac..e3baf612db4eefcd0e839d808704293d0884549f 100644 --- a/opossum/src/surface/hit_map.rs +++ b/opossum/src/surface/hit_map.rs @@ -1,56 +1,195 @@ //! Data structure for storing intersection points (and energies) of [`Rays`](crate::rays::Rays) hitting an //! [`OpticalSurface`](crate::surface::OpticalSurface). +use std::collections::HashMap; + +use log::warn; use nalgebra::{DVector, MatrixXx2, Point2, Point3}; use plotters::style::RGBAColor; use serde::{Deserialize, Serialize}; -use uom::si::f64::{Energy, Length}; +use uom::si::{ + energy::joule, + f64::{Energy, Length}, + length::centimeter, + radiant_exposure::joule_per_square_centimeter, +}; +use uuid::Uuid; use crate::{ - error::OpmResult, + error::{OpmResult, OpossumError}, + nodes::fluence_detector::Fluence, plottable::{AxLims, PlotArgs, PlotData, PlotParameters, PlotSeries, PlotType, Plottable}, properties::Proptype, - utils::unit_format::{ - get_exponent_for_base_unit_in_e3_steps, get_prefix_for_base_unit, - get_unit_value_as_length_with_format_by_exponent, + utils::{ + griddata::{calc_closed_poly_area, create_voronoi_cells, VoronoiedData}, + unit_format::{ + get_exponent_for_base_unit_in_e3_steps, get_prefix_for_base_unit, + get_unit_value_as_length_with_format_by_exponent, + }, }, + J_per_cm2, }; +#[derive(Default, Debug, Clone, Serialize, Deserialize)] +///Storage struct for `RaysHitMap` on a surface from a single bounce +pub struct BouncedHitMap { + hit_map: HashMap<Uuid, RaysHitMap>, +} + +impl BouncedHitMap { + /// Add intersection point (with energy) to this [`BouncedHitMap`]. + pub fn add_to_hitmap(&mut self, hit_point: (Point3<Length>, Energy), uuid: &Uuid) { + if let Some(rays_hit_map) = self.hit_map.get_mut(uuid) { + rays_hit_map.add_to_hitmap(hit_point); + } else { + self.hit_map.insert(*uuid, RaysHitMap::new(vec![hit_point])); + } + } + + /// creates a new [`BouncedHitMap`] + #[must_use] + pub const fn new(hit_points: HashMap<Uuid, RaysHitMap>) -> Self { + Self { + hit_map: hit_points, + } + } + ///returns a reference to a [`RaysHitMap`] in this [`BouncedHitMap`] + #[must_use] + pub fn get_rays_hit_map(&self, uuid: &Uuid) -> Option<&RaysHitMap> { + self.hit_map.get(uuid) + } +} + +#[derive(Default, Debug, Clone, Serialize, Deserialize)] +///Storage struct for hitpoints on a surface from a single raybundle +pub struct RaysHitMap { + hit_map: Vec<(Point3<Length>, Energy)>, +} + +impl RaysHitMap { + /// Add intersection point (with energy) to this [`HitMap`]. + pub fn add_to_hitmap(&mut self, hit_point: (Point3<Length>, Energy)) { + self.hit_map.push(hit_point); + } + + /// creates a new [`RaysHitMap`] + #[must_use] + pub fn new(hit_points: Vec<(Point3<Length>, Energy)>) -> Self { + Self { + hit_map: hit_points, + } + } + + /// Calculates the fluence of a ray bundle that is stored in this hitmap + /// # Attributes + /// - `max_fluence`: the maximum allowed fluence on this surface + /// # Errors + /// This function errors if no reasonable axlimits can be estimated due to only non-finite values in the positions + #[allow(clippy::type_complexity)] + pub fn calc_fluence( + &self, + max_fluence: Fluence, + ) -> OpmResult<Option<(VoronoiedData, AxLims, AxLims, Fluence, Fluence)>> { + let mut show_hitmap = false; + let max_fluence_jcm2 = max_fluence.get::<joule_per_square_centimeter>(); + let mut pos_in_cm = MatrixXx2::<f64>::zeros(self.hit_map.len()); + let mut energy = DVector::<f64>::zeros(self.hit_map.len()); + let mut energy_in_ray_bundle = 0.; + + for (row, p) in self.hit_map.iter().enumerate() { + pos_in_cm[(row, 0)] = p.0.x.get::<centimeter>(); + pos_in_cm[(row, 1)] = p.0.y.get::<centimeter>(); + energy[row] = p.1.get::<joule>(); + energy_in_ray_bundle += energy[row]; + } + + let proj_ax1_lim = AxLims::finite_from_dvector(&pos_in_cm.column(0)).ok_or_else(|| { + OpossumError::Other( + "cannot construct voronoi cells with non-finite axes bounds!".into(), + ) + })?; + let proj_ax2_lim = AxLims::finite_from_dvector(&pos_in_cm.column(1)).ok_or_else(|| { + OpossumError::Other( + "cannot construct voronoi cells with non-finite axes bounds!".into(), + ) + })?; + let (voronoi, beam_area) = create_voronoi_cells(&pos_in_cm).map_err(|_| { + OpossumError::Other( + "Voronoi diagram for fluence estimation could not be created!".into(), + ) + })?; + + //get the voronoi cells + let v_cells = voronoi.cells(); + let mut fluence_scatter = DVector::from_element(voronoi.sites.len(), f64::NAN); + let mut max_fluence_val = f64::NEG_INFINITY; + for (i, v_cell) in v_cells.iter().enumerate() { + let v_neighbours = v_cell + .points() + .iter() + .map(|p| Point2::new(p.x, p.y)) + .collect::<Vec<Point2<f64>>>(); + if v_neighbours.len() >= 3 { + let poly_area = calc_closed_poly_area(&v_neighbours)?; + fluence_scatter[i] = energy[i] / poly_area; + if fluence_scatter[i] > max_fluence_jcm2 { + if max_fluence_val < fluence_scatter[i] { + max_fluence_val = fluence_scatter[i]; + } + show_hitmap = true; + } + } else { + warn!( + "polygon could not be created. number of neighbors {}", + v_neighbours.len() + ); + } + } + if show_hitmap { + Ok(Some(( + VoronoiedData::combine_data_with_voronoi_diagram(voronoi, fluence_scatter)?, + proj_ax1_lim, + proj_ax2_lim, + J_per_cm2!(energy_in_ray_bundle / beam_area), + J_per_cm2!(max_fluence_val), + ))) + } else { + Ok(None) + } + } +} + /// Data structure for storing intersection points (and energies) of [`Rays`](crate::rays::Rays) hitting an /// [`OpticalSurface`](crate::surface::OpticalSurface). #[derive(Default, Debug, Clone, Serialize, Deserialize)] pub struct HitMap { /// Stores the hitpoints of the rays on this surface, separated by their bounce level and the individual ray bundle - /// First Vec stores a vector of hitmaps from different ray bundles, sorted by their bounce level - /// Second Vec stores the hitmaps of the individual ray bundle. No sorting. - /// Last vec stores the hitpoints of one ray bundle on this surface - #[allow(clippy::type_complexity)] - hit_map: Vec<Vec<Vec<(Point3<Length>, Energy)>>>, + hit_map: Vec<BouncedHitMap>, + /// Stores the fluence and position in the history of the ray bundles that create a critical fluence on this surface. key value is the uuid of the ray bundle + critical_fluence: HashMap<Uuid, (Fluence, usize)>, } impl HitMap { /// Returns a reference to the hit map of this [`HitMap`]. /// /// This function returns a vector of intersection points (with energies) of [`Rays`](crate::rays::Rays) that hit the surface. #[must_use] - #[allow(clippy::type_complexity)] - pub fn hit_map(&self) -> &[Vec<Vec<(Point3<Length>, Energy)>>] { + pub fn hit_map(&self) -> &[BouncedHitMap] { &self.hit_map } /// Add intersection point (with energy) to this [`HitMap`]. /// - pub fn add_to_hitmap(&mut self, hit_point: (Point3<Length>, Energy), bounce: usize) { + pub fn add_to_hitmap( + &mut self, + hit_point: (Point3<Length>, Energy), + bounce: usize, + uuid: &Uuid, + ) { + // make sure that vector is large enough to insert the data if self.hit_map.len() <= bounce { - for _i in 0..=bounce { - if self.hit_map.len() < bounce { - self.hit_map.push(vec![vec![]]); - } - } - self.hit_map.push(vec![vec![hit_point]]); - } else { - let hm_len = self.hit_map[bounce].len(); - if hm_len > 0 { - self.hit_map[bounce][hm_len - 1].push(hit_point); + for _i in 0..bounce + 1 - self.hit_map.len() { + self.hit_map.push(BouncedHitMap::default()); } } + self.hit_map[bounce].add_to_hitmap(hit_point, uuid); } /// Reset this [`HitMap`]. /// @@ -63,6 +202,39 @@ impl HitMap { pub fn is_empty(&self) -> bool { self.hit_map.is_empty() } + + /// returns a reference to the `critical_fluence` field of this [`HitMap`] which contains: + /// - the uuid of the ray bundle that causes this critical fluence on this surface as key + /// - a tuple containing the calculated peak fluence and the index of the position history which can be used to reconstruct the ray-propagation plot later on + #[must_use] + pub fn critical_fluences(&self) -> &HashMap<Uuid, (Fluence, usize)> { + &self.critical_fluence + } + + // pub fn get_critical_fluences(&self) -> OpmResult<Vec<(Uuid, usize, Fluence, Fluence)>>{ + // let max_fluence = J_per_cm2!(0.02); + // let mut critical_positions = Vec::<(Uuid, usize, Fluence, Fluence)>::new(); + // for (bounce, bounced_hit_map) in self.hit_map.iter().enumerate(){ + // for (uuid, rays_hit_map) in &bounced_hit_map.hit_map{ + // if let Some((_vdat, _x_lim, _y_lim, average_fluence, peak_fluence)) = rays_hit_map.calc_fluence(max_fluence)?{ + // critical_positions.push((uuid.clone(), bounce, average_fluence, peak_fluence)); + // } + // } + // } + // Ok(critical_positions) + // } + + ///stores a critical fluence in a hitmap + pub fn add_critical_fluence(&mut self, uuid: &Uuid, rays_hist_pos: usize, fluence: Fluence) { + self.critical_fluence + .insert(*uuid, (fluence, rays_hist_pos)); + } + + ///returns a reference to a [`RaysHitMap`] in this [`HitMap`] + #[must_use] + pub fn get_rays_hit_map(&self, bounce: usize, uuid: &Uuid) -> Option<&RaysHitMap> { + self.hit_map[bounce].get_rays_hit_map(uuid) + } } impl From<HitMap> for Proptype { fn from(value: HitMap) -> Self { @@ -86,18 +258,17 @@ impl Plottable for HitMap { let mut x_min = f64::INFINITY; let mut y_min = f64::INFINITY; - for bounced_ray_bundles in &self.hit_map { - for ray_bundle in bounced_ray_bundles { - let mut xy_pos = Vec::<Point2<Length>>::with_capacity(ray_bundle.len()); - for p in ray_bundle { - xy_pos.push(Point2::new(p.0.x, p.0.y)); + for (i, bounced_ray_bundles) in self.hit_map.iter().enumerate() { + xy_positions.push(Vec::<Point2<Length>>::new()); + for rays_hitmap in bounced_ray_bundles.hit_map.values() { + for p in &rays_hitmap.hit_map { + xy_positions[i].push(Point2::new(p.0.x, p.0.y)); x_max = x_max.max(p.0.x.value); y_max = y_max.max(p.0.y.value); x_min = x_min.min(p.0.x.value); y_min = y_min.min(p.0.y.value); } - xy_positions.push(xy_pos); } } let x_exponent = get_exponent_for_base_unit_in_e3_steps(x_max); @@ -165,8 +336,6 @@ impl Plottable for HitMap { } fn add_plot_specific_params(&self, plt_params: &mut PlotParameters) -> OpmResult<()> { plt_params - // .set(&PlotArgs::XLabel("x position (b)".into()))? - // .set(&PlotArgs::YLabel("y position (b)".into()))? .set(&PlotArgs::AxisEqual(true))? .set(&PlotArgs::PlotAutoSize(true))? .set(&PlotArgs::PlotSize((800, 800)))?; diff --git a/opossum/src/surface/optical_surface.rs b/opossum/src/surface/optical_surface.rs index bb045f3adb0d015078e29efab2d019c237af5f61..55670cedd78771b14f2b376590ca1e1d8040423d 100644 --- a/opossum/src/surface/optical_surface.rs +++ b/opossum/src/surface/optical_surface.rs @@ -1,8 +1,15 @@ use nalgebra::Point3; use uom::si::f64::{Energy, Length}; +use uuid::Uuid; -use super::{hit_map::HitMap, GeoSurface, Plane}; -use crate::{coatings::CoatingType, rays::Rays, utils::geom_transformation::Isometry}; +use super::{ + hit_map::{HitMap, RaysHitMap}, + GeoSurface, Plane, +}; +use crate::{ + coatings::CoatingType, error::OpmResult, nodes::fluence_detector::Fluence, rays::Rays, + utils::geom_transformation::Isometry, J_per_cm2, +}; /// This struct represents an optical surface, which consists of the geometric surface shape ([`GeoSurface`]) and further /// properties such as the [`CoatingType`]. @@ -13,6 +20,7 @@ pub struct OpticalSurface { backward_rays_cache: Vec<Rays>, forward_rays_cache: Vec<Rays>, hit_map: HitMap, + lidt: Fluence, } impl Default for OpticalSurface { fn default() -> Self { @@ -22,6 +30,7 @@ impl Default for OpticalSurface { backward_rays_cache: Vec::<Rays>::new(), forward_rays_cache: Vec::<Rays>::new(), hit_map: HitMap::default(), + lidt: J_per_cm2!(0.1), } } } @@ -33,6 +42,7 @@ impl Clone for OpticalSurface { backward_rays_cache: self.backward_rays_cache.clone(), forward_rays_cache: self.forward_rays_cache.clone(), hit_map: self.hit_map.clone(), + lidt: self.lidt, } } } @@ -46,6 +56,7 @@ impl OpticalSurface { backward_rays_cache: Vec::<Rays>::new(), forward_rays_cache: Vec::<Rays>::new(), hit_map: HitMap::default(), + lidt: J_per_cm2!(0.1), } } /// Returns a reference to the coating of this [`OpticalSurface`]. @@ -99,13 +110,41 @@ impl OpticalSurface { pub const fn hit_map(&self) -> &HitMap { &self.hit_map } + ///stores a critical fluence in a hitmap + pub fn add_critical_fluence(&mut self, uuid: &Uuid, rays_hist_pos: usize, fluence: Fluence) { + self.hit_map + .add_critical_fluence(uuid, rays_hist_pos, fluence); + } + + ///returns a reference to a [`RaysHitMap`] in this [`OpticalSurface`] + #[must_use] + pub fn get_rays_hit_map(&self, bounce: usize, uuid: &Uuid) -> Option<&RaysHitMap> { + self.hit_map.get_rays_hit_map(bounce, uuid) + } /// Add intersection point (with energy) to hit map. /// - pub fn add_to_hit_map(&mut self, hit_point: (Point3<Length>, Energy), bounce: usize) { - self.hit_map.add_to_hitmap(hit_point, bounce); + pub fn add_to_hit_map( + &mut self, + hit_point: (Point3<Length>, Energy), + bounce: usize, + rays_uuid: &Uuid, + ) { + self.hit_map.add_to_hitmap(hit_point, bounce, rays_uuid); } /// Reset hit map of this [`OpticalSurface`]. pub fn reset_hit_map(&mut self) { self.hit_map.reset(); } + + /// Evaluate the fluence of a given ray bundle on this surface. If the fluence surpasses its lidt, store the critical fluence parameters in the hitmap + /// # Errors + /// This function errors on error propagation of `calc_fluence` + pub fn evaluate_fluence_of_ray_bundle(&mut self, rays: &Rays) -> OpmResult<()> { + if let Some(rays_hit_map) = self.get_rays_hit_map(rays.bounce_lvl(), rays.uuid()) { + if let Some((_, _, _, _, peak_fluence)) = rays_hit_map.calc_fluence(self.lidt)? { + self.add_critical_fluence(rays.uuid(), rays.ray_history_len(), peak_fluence); + } + } + Ok(()) + } }