From 4557fe7902924db2971296da52760dbe649443c1 Mon Sep 17 00:00:00 2001 From: "y.zobus" <y.zobus@gsi.de> Date: Fri, 21 Jul 2023 16:04:33 +0200 Subject: [PATCH] added lens node --- examples/lens_test.rs | 25 +++++++ src/nodes/node_lens.rs | 153 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 examples/lens_test.rs create mode 100644 src/nodes/node_lens.rs diff --git a/examples/lens_test.rs b/examples/lens_test.rs new file mode 100644 index 00000000..a8c6571c --- /dev/null +++ b/examples/lens_test.rs @@ -0,0 +1,25 @@ +use opossum::{ + nodes::{RealLens, Source, Detector}, + optic_scenery::OpticScenery, error::OpossumError, +}; +use std::fs::File; +use std::io::Write; + +fn main() -> Result<(), OpossumError> { + let mut scenery = OpticScenery::new(); + scenery.set_description("Lens Ray-trace test".into()); + let src = scenery.add_element("Source", Source::default()); + let l1 = scenery.add_element("Lens 1", RealLens::default()); + let l2 = scenery.add_element("Lens 2", RealLens::default()); + let det=scenery.add_element("Detector", Detector::default()); + + scenery.connect_nodes(src, "out1", l1, "in1")?; + scenery.connect_nodes(l1, "out1", l2, "in1")?; + scenery.connect_nodes(l2, "out1", det, "in1")?; + + + let path = "lens_system.dot"; + let mut output = File::create(path).unwrap(); + write!(output, "{}", scenery.to_dot()).unwrap(); + Ok(()) +} diff --git a/src/nodes/node_lens.rs b/src/nodes/node_lens.rs new file mode 100644 index 00000000..8be6263b --- /dev/null +++ b/src/nodes/node_lens.rs @@ -0,0 +1,153 @@ +use std::collections::HashMap; +use uom::{si::f64::{Energy, Length}, si::length::meter, num_traits::Zero}; +use ndarray::{Array1, Array2, array}; + +type Result<T> = std::result::Result<T, OpossumError>; + + +use crate::{ + analyzer::AnalyzerType, + error::OpossumError, + lightdata::{LightData, DataEnergy, RayDataParaxial}, + optic_node::{Dottable, LightResult, Optical}, + optic_ports::OpticPorts, +}; + +pub struct IdealLens { + focal_length: f64, + aperture: f64 +} +#[derive(Debug)] +pub struct RealLens { + aperture: Length, + curvatures: Array1<Length>, + center_thickness: Length, + z_pos: Length, + refractive_index: f64, +} + + +impl RealLens { + pub fn new(aperture: Length, front_curvature: Length, rear_curvature: Length, center_thickness: Length, z_pos: Length, refractive_index: f64) -> Self { + Self{ aperture: aperture, + curvatures: array![front_curvature,rear_curvature], + center_thickness: center_thickness, + z_pos: z_pos, + refractive_index: refractive_index, + } + } + + pub fn get_aperture(&self) -> Length{ + self.aperture + } + + pub fn set_aperture(&mut self, aperture: f64) { + self.aperture = Length::new::<meter>(aperture); + } + + pub fn get_curvatures(&self) -> &Array1<Length>{ + &self.curvatures + } + + pub fn set_curvatures(&mut self, curvature_1: f64, curvature_2: f64) { + self.curvatures = array![Length::new::<meter>(curvature_1),Length::new::<meter>(curvature_2)]; + } + + pub fn get_thickness(&self) -> Length{ + self.center_thickness + } + + pub fn set_thickness(&mut self, thickness: f64) { + self.center_thickness = Length::new::<meter>(thickness); + } + + pub fn get_position(&self) -> Length{ + self.z_pos + } + + pub fn set_position(&mut self, position: f64) { + self.z_pos = Length::new::<meter>(position); + } + + pub fn get_refractve_index(&self) -> f64{ + self.refractive_index + } + + pub fn set_refractve_index(&mut self, refractive_index: f64) { + self.refractive_index = refractive_index; + } + + fn analyze_ray_trace(&mut self, incoming_data: LightResult) -> Result<LightResult> { + let in1: Option<&Option<LightData>> = incoming_data.get("in1"); + Ok(incoming_data) + + // let mut in_rays: Vec<RayDataParaxial> = Vec::new(); + // if let Some(Some(in1)) = in1 { + // match in1 { + // LightData::ParAxialRayTrace(rays) => in_rays = rays.rays, + // _ => return Err(OpossumError::Analysis("expected set of rays".into())), + // } + // }; + + // let out1_energy = Some(LightData::Energy(DataEnergy { + // energy: in1_energy * self.ratio + in2_energy * (1.0 - self.ratio), + // })); + // Ok(HashMap::from([ + // ("out1_trans1_refl2".into(), out1_energy), + // ("out2_trans2_refl1".into(), out2_energy), + // ])) + } + + // fn ray_propagate(&mut self, rays: &mut Vec<RayDataParaxial>){ + // for ray in rays.into_iter(){ + // if ray.pos + // }; + // } + + // pub struct RayDataParaxial { + // // ray: Array1<f64>, + // ray: Array1<f64>, + // pos: Vec<[f64;3]>, + // index: usize, + // bounce_lvl: usize, + // max_bounces: usize, + // } + +} + +impl Default for RealLens { + /// Create a 100mm focal lengths lens. LA1251-B from thorlabs. refractive inde hardcoded for n-bk7 at 1054 nm + fn default() -> Self { + Self { aperture: Length::new::<meter>(25e-3), + curvatures: array![Length::new::<meter>(51.5e-3),Length::new::<meter>(f64::INFINITY)], + center_thickness: Length::new::<meter>(3.6e-3), + z_pos: Length::new::<meter>(0.0), + refractive_index: 1.5068} + } +} + +impl Optical for RealLens { + fn node_type(&self) -> &str { + "real lens" + } + fn ports(&self) -> OpticPorts { + let mut ports = OpticPorts::new(); + ports.add_input("in1").unwrap(); + ports.add_output("out1").unwrap(); + ports + } + + fn analyze(&mut self, incoming_data: LightResult, analyzer_type: &AnalyzerType) -> Result<LightResult> { + match analyzer_type { + AnalyzerType::Energy => Err(OpossumError::Analysis("Energy Analysis is not yet implemented for Lens Nodes".into())), + AnalyzerType::ParAxialRayTrace => self.analyze_ray_trace(incoming_data), + } + } +} + + +impl Dottable for RealLens { + fn node_color(&self) -> &str { + "blue" + } +} -- GitLab