diff --git a/opossum/src/nodes/beam_splitter/mod.rs b/opossum/src/nodes/beam_splitter/mod.rs index a77bb672cf5ecc3133fbb9436093d1db2ab80dcc..5feca1812ed03ecedbbb2fec26ff5c4881673460 100644 --- a/opossum/src/nodes/beam_splitter/mod.rs +++ b/opossum/src/nodes/beam_splitter/mod.rs @@ -9,7 +9,7 @@ use crate::{ dottable::Dottable, error::{OpmResult, OpossumError}, lightdata::{DataEnergy, LightData}, - optic_node::OpticNode, + optic_node::{Alignable, OpticNode}, optic_ports::{OpticPorts, PortType}, properties::Proptype, ray::SplittingConfig, @@ -316,6 +316,7 @@ impl Dottable for BeamSplitter { impl Analyzable for BeamSplitter {} impl AnalysisGhostFocus for BeamSplitter {} +impl Alignable for BeamSplitter {} #[cfg(test)] mod test { use super::*; diff --git a/opossum/src/nodes/detector.rs b/opossum/src/nodes/detector.rs index ba0b86de9381ebad6d2a43b2edd762b66be8f9ea..c7f3245d13f2c4eeb27979a3c2000c2c4aa7909f 100644 --- a/opossum/src/nodes/detector.rs +++ b/opossum/src/nodes/detector.rs @@ -9,7 +9,7 @@ use crate::{ error::{OpmResult, OpossumError}, light_result::LightResult, lightdata::LightData, - optic_node::{OpticNode, LIDT}, + optic_node::{Alignable, OpticNode, LIDT}, optic_ports::{OpticPorts, PortType}, surface::{OpticalSurface, Plane}, utils::geom_transformation::Isometry, @@ -174,6 +174,7 @@ impl AnalysisRayTrace for Detector { self.light_data = Some(ld); } } +impl Alignable for Detector {} #[cfg(test)] mod test { diff --git a/opossum/src/nodes/dummy.rs b/opossum/src/nodes/dummy.rs index ef53480d23e479a0314f1ab78ea9fa0af0cda7e3..3e4b17f62c9f4e59395a4f50316e5d963ff832f8 100644 --- a/opossum/src/nodes/dummy.rs +++ b/opossum/src/nodes/dummy.rs @@ -83,6 +83,7 @@ impl AnalysisEnergy for Dummy { ) } } +impl Alignable for Dummy {} impl AnalysisRayTrace for Dummy { fn analyze( @@ -129,6 +130,219 @@ impl AnalysisRayTrace for Dummy { Ok(LightResult::from([(outport.into(), data.clone())])) } } + + fn calc_node_position( + &mut self, + incoming_data: LightResult, + config: &RayTraceConfig, + ) -> OpmResult<LightResult> { + AnalysisRayTrace::analyze(self, incoming_data, config) + } + + fn enter_through_surface( + &mut self, + rays_bundle: &mut Vec<crate::rays::Rays>, + analyzer_type: &crate::analyzers::AnalyzerType, + refri: &crate::refractive_index::RefractiveIndexType, + backward: bool, + port_name: &str, + ) -> OpmResult<()> { + let uuid = *self.node_attr().uuid(); + let Some(iso) = &self.effective_iso() else { + return Err(OpossumError::Analysis( + "surface has no isometry defined".into(), + )); + }; + if backward { + for rays in &mut *rays_bundle { + if let Some(aperture) = self.ports().aperture(&PortType::Input, port_name) { + rays.apodize(aperture, iso)?; + if let crate::analyzers::AnalyzerType::RayTrace(ref config) = analyzer_type { + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } + } else { + return Err(OpossumError::OpticPort("output aperture not found".into())); + }; + let surf = self.get_surface_mut(port_name); + let mut reflected_rear = rays.refract_on_surface(surf, Some(refri))?; + reflected_rear.set_node_origin_uuid(uuid); + + if let crate::analyzers::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() { + rays_bundle.push(rays.clone()); + } + } else { + for rays in &mut *rays_bundle { + if let Some(aperture) = self.ports().aperture(&PortType::Input, port_name) { + rays.apodize(aperture, &self.effective_iso().unwrap())?; + if let crate::analyzers::AnalyzerType::RayTrace(ref config) = analyzer_type { + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } + } else { + return Err(OpossumError::OpticPort("input aperture not found".into())); + }; + let surf = self.get_surface_mut(port_name); + let mut reflected_front = rays.refract_on_surface(surf, Some(refri))?; + reflected_front.set_node_origin_uuid(uuid); + if let crate::analyzers::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() { + rays_bundle.push(rays.clone()); + } + } + Ok(()) + } + + fn exit_through_surface( + &mut self, + rays_bundle: &mut Vec<crate::rays::Rays>, + analyzer_type: &crate::analyzers::AnalyzerType, + refri: &crate::refractive_index::RefractiveIndexType, + backward: bool, + port_name: &str, + ) -> OpmResult<()> { + let uuid: uuid::Uuid = *self.node_attr().uuid(); + let Some(iso) = &self.effective_iso() else { + return Err(OpossumError::Analysis( + "surface has no isometry defined".into(), + )); + }; + let surf = self.get_surface_mut(port_name); + if backward { + for rays in &mut *rays_bundle { + let mut reflected_front = rays.refract_on_surface(surf, Some(refri))?; + reflected_front.set_node_origin_uuid(uuid); + + if let crate::analyzers::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() { + rays_bundle.push(rays.clone()); + } + for rays in &mut *rays_bundle { + if let Some(aperture) = self.ports().aperture(&PortType::Output, port_name) { + rays.apodize(aperture, iso)?; + if let crate::analyzers::AnalyzerType::RayTrace(config) = analyzer_type { + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } + } else { + return Err(OpossumError::OpticPort("input aperture not found".into())); + }; + } + } else { + for rays in &mut *rays_bundle { + let mut reflected_rear = rays.refract_on_surface(surf, Some(refri))?; + reflected_rear.set_node_origin_uuid(uuid); + if let crate::analyzers::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() { + rays_bundle.push(rays.clone()); + } + for rays in &mut *rays_bundle { + if let Some(aperture) = self.ports().aperture(&PortType::Output, port_name) { + rays.apodize(aperture, iso)?; + if let crate::analyzers::AnalyzerType::RayTrace(config) = analyzer_type { + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } + } else { + return Err(OpossumError::OpticPort("output aperture not found".into())); + }; + } + } + Ok(()) + } + + fn pass_through_inert_surface( + &mut self, + rays_bundle: &mut Vec<crate::rays::Rays>, + analyzer_type: &crate::analyzers::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 crate::analyzers::AnalyzerType::GhostFocus(_) = analyzer_type { + surf.evaluate_fluence_of_ray_bundle(rays)?; + } + } + } else { + return Err(OpossumError::Analysis( + "no location for surface defined. Aborting".into(), + )); + } + // merge all rays + if let Some(ld) = self.get_light_data_mut() { + if let LightData::GhostFocus(rays) = ld { + for r in rays_bundle { + rays.push(r.clone()); + } + } + } else { + self.set_light_data(LightData::GhostFocus(rays_bundle.clone())); + } + Ok(()) + } + + fn get_light_data_mut(&mut self) -> Option<&mut LightData> { + None + } + + fn set_light_data(&mut self, _ld: LightData) {} + + fn get_node_attributes_ray_trace( + &self, + node_attr: &NodeAttr, + ) -> OpmResult<( + Isometry, + crate::refractive_index::RefractiveIndexType, + uom::si::f64::Length, + uom::si::f64::Angle, + )> { + let Some(eff_iso) = self.effective_iso() else { + return Err(OpossumError::Analysis( + "no location for surface defined".into(), + )); + }; + let Ok(crate::properties::Proptype::RefractiveIndex(index_model)) = + node_attr.get_property("refractive index") + else { + return Err(OpossumError::Analysis( + "cannot read refractive index".into(), + )); + }; + let Ok(crate::properties::Proptype::Length(center_thickness)) = + node_attr.get_property("center thickness") + else { + return Err(OpossumError::Analysis( + "cannot read center thickness".into(), + )); + }; + + let angle = if let Ok(crate::properties::Proptype::Angle(wedge)) = + node_attr.get_property("wedge") + { + *wedge + } else { + crate::degree!(0.) + }; + + Ok((eff_iso, index_model.value.clone(), *center_thickness, angle)) + } } impl OpticNode for Dummy { @@ -145,8 +359,6 @@ impl OpticNode for Dummy { &mut self.surface } } - -impl Alignable for Dummy {} impl Dottable for Dummy {} #[cfg(test)] diff --git a/opossum/src/nodes/energy_meter.rs b/opossum/src/nodes/energy_meter.rs index 65e163f0393ed80e1a2922d4e6c5d3e596db2718..9ef3ad5f3da8d4ca40bdd3d1f4dfe97e09986d58 100644 --- a/opossum/src/nodes/energy_meter.rs +++ b/opossum/src/nodes/energy_meter.rs @@ -9,7 +9,7 @@ use crate::{ joule, light_result::LightResult, lightdata::LightData, - optic_node::{OpticNode, LIDT}, + optic_node::{Alignable, OpticNode, LIDT}, optic_ports::{OpticPorts, PortType}, properties::{Properties, Proptype}, reporting::node_report::NodeReport, @@ -289,6 +289,7 @@ impl AnalysisRayTrace for EnergyMeter { self.light_data = Some(ld); } } +impl Alignable for EnergyMeter {} #[cfg(test)] mod test { use super::*; diff --git a/opossum/src/nodes/fluence_detector.rs b/opossum/src/nodes/fluence_detector.rs index b6f06d95965e08b63dacad2c7c5c4d55fbf35ee4..22044b0e4dc73fcedb3ee9d34bef08be4b10d868 100644 --- a/opossum/src/nodes/fluence_detector.rs +++ b/opossum/src/nodes/fluence_detector.rs @@ -16,7 +16,7 @@ use crate::{ error::{OpmResult, OpossumError}, light_result::{LightRays, LightResult}, lightdata::LightData, - optic_node::{OpticNode, LIDT}, + optic_node::{Alignable, OpticNode, LIDT}, optic_ports::{OpticPorts, PortType}, plottable::{PlotArgs, PlotData, PlotParameters, PlotSeries, PlotType, Plottable}, properties::{Properties, Proptype}, @@ -146,6 +146,7 @@ impl OpticNode for FluenceDetector { } } +impl Alignable for FluenceDetector {} impl Dottable for FluenceDetector { fn node_color(&self) -> &str { "hotpink" diff --git a/opossum/src/nodes/ideal_filter.rs b/opossum/src/nodes/ideal_filter.rs index 24c29fd15114fc66482379aa92251658b0ca0d71..a96dd838592f411464d56579c36f4d03da1e2f36 100644 --- a/opossum/src/nodes/ideal_filter.rs +++ b/opossum/src/nodes/ideal_filter.rs @@ -9,7 +9,7 @@ use crate::{ error::{OpmResult, OpossumError}, light_result::LightResult, lightdata::LightData, - optic_node::{OpticNode, LIDT}, + optic_node::{Alignable, OpticNode, LIDT}, optic_ports::{OpticPorts, PortType}, properties::Proptype, spectrum::Spectrum, @@ -185,7 +185,7 @@ impl OpticNode for IdealFilter { &mut self.surface } } - +impl Alignable for IdealFilter {} impl Dottable for IdealFilter { fn node_color(&self) -> &str { "darkgray" diff --git a/opossum/src/nodes/ray_propagation_visualizer.rs b/opossum/src/nodes/ray_propagation_visualizer.rs index 779f8943c74acef82952aec613094b27db4ffd64..eee0419e714acd89444d0f36fdcc12b5e60036b7 100644 --- a/opossum/src/nodes/ray_propagation_visualizer.rs +++ b/opossum/src/nodes/ray_propagation_visualizer.rs @@ -20,7 +20,7 @@ use crate::{ light_result::{LightRays, LightResult}, lightdata::LightData, millimeter, - optic_node::{OpticNode, LIDT}, + optic_node::{Alignable, OpticNode, LIDT}, optic_ports::{OpticPorts, PortType}, plottable::{PlotArgs, PlotData, PlotParameters, PlotSeries, PlotType, Plottable}, properties::{Properties, Proptype}, @@ -253,6 +253,7 @@ impl AnalysisRayTrace for RayPropagationVisualizer { self.light_data = Some(ld); } } +impl Alignable for RayPropagationVisualizer {} /// struct that holds the history of the rays' positions for rays of a specific wavelength #[derive(Serialize, Deserialize, Clone, Debug)] diff --git a/opossum/src/nodes/spectrometer.rs b/opossum/src/nodes/spectrometer.rs index 08071af3b2f3cbfa445477751e1f05716ee9e0bc..070104bb386228e997c8a08ed554787f6d0d27eb 100644 --- a/opossum/src/nodes/spectrometer.rs +++ b/opossum/src/nodes/spectrometer.rs @@ -14,7 +14,7 @@ use crate::{ light_result::LightResult, lightdata::LightData, nanometer, - optic_node::{OpticNode, LIDT}, + optic_node::{Alignable, OpticNode, LIDT}, optic_ports::{OpticPorts, PortType}, plottable::{PlotArgs, PlotParameters, PlotSeries, PlotType, Plottable}, properties::{Properties, Proptype}, @@ -217,7 +217,7 @@ impl OpticNode for Spectrometer { &mut self.surface } } - +impl Alignable for Spectrometer {} impl Debug for Spectrometer { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match &self.light_data {