diff --git a/coretrace/simdata_bridge.cpp b/coretrace/simdata_bridge.cpp index 7dbc3a35..b16f8339 100644 --- a/coretrace/simdata_bridge.cpp +++ b/coretrace/simdata_bridge.cpp @@ -15,30 +15,6 @@ // Private -SolTrace::Data::OpticalProperties make_optics(TOpticalProperties optics_legacy, int interaction_type_int) -{ - // TODO: Not using any transmissivity or reflectivity tables - - // Get interaction type - SolTrace::Data::InteractionType interaction_type = SolTrace::Data::int_to_interaction(interaction_type_int); - - // Get error distribution type - SolTrace::Data::DistributionType dist_type = SolTrace::Data::char_to_distribution(optics_legacy.DistributionType); - - double transmissivity = optics_legacy.Transmissivity; - double reflectivity = optics_legacy.Reflectivity; - double rms_slope = optics_legacy.RMSSlopeError; - double rms_spec = optics_legacy.RMSSpecError; - double refrac_real = optics_legacy.RefractiveIndex[0]; // TODO: verify this is how refractiveindex works (there are 4 values) - double refrac_imag = optics_legacy.RefractiveIndex[1]; - - // Make new optical properties - SolTrace::Data::OpticalProperties optics = SolTrace::Data::OpticalProperties(interaction_type, - dist_type, transmissivity, reflectivity, rms_slope, rms_spec, refrac_real, refrac_imag); - - return optics; -} - void convert_user_sun_data(const std::vector& sun_shape_angle, const std::vector& sun_shape_intensity, std::vector& sun_shape_angle_reduced, std::vector& sun_shape_intensity_reduced) { @@ -283,10 +259,36 @@ int convert_tsystem_to_sim_data(TSystem* sys, const int seed, SolTrace::Data::Si // Set optical properties if (is_virtual == false) { - SolTrace::Data::OpticalProperties optics_front = make_optics(el_legacy->Optics->Front, el_legacy->InteractionType); - SolTrace::Data::OpticalProperties optics_back = make_optics(el_legacy->Optics->Back, el_legacy->InteractionType); - element->set_front_optical_properties(optics_front); - element->set_back_optical_properties(optics_back); + // Convert legacy front/back optics into new OpticalPropertySet + auto &front = el_legacy->Optics->Front; + auto &back = el_legacy->Optics->Back; + + SolTrace::Data::InteractionType interaction_type = SolTrace::Data::int_to_interaction(el_legacy->InteractionType); + double refrac_front = front.RefractiveIndex[0]; + double refrac_back = back.RefractiveIndex[0]; + + SolTrace::Data::OpticalPropertySet optics_set(interaction_type, refrac_front, refrac_back); + + // Front face + SolTrace::Data::DistributionType dist_front = SolTrace::Data::char_to_distribution(front.DistributionType); + optics_set.set_properties(SolTrace::Data::OpticalSide::Front, + dist_front, + front.Transmissivity, + front.Reflectivity, + front.RMSSlopeError, + front.RMSSpecError); + + // Back face + SolTrace::Data::DistributionType dist_back = SolTrace::Data::char_to_distribution(back.DistributionType); + optics_set.set_properties(SolTrace::Data::OpticalSide::Back, + dist_back, + back.Transmissivity, + back.Reflectivity, + back.RMSSlopeError, + back.RMSSpecError); + + auto ref = sd.add_optical_property_set(optics_set); + element->set_optical_property_set(ref); } // Set element name diff --git a/coretrace/simulation_data/composite_element.cpp b/coretrace/simulation_data/composite_element.cpp index 6adcab20..8a48f2e0 100644 --- a/coretrace/simulation_data/composite_element.cpp +++ b/coretrace/simulation_data/composite_element.cpp @@ -4,6 +4,7 @@ #include #include "single_element.hpp" +#include "virtual_element.hpp" namespace SolTrace::Data { @@ -15,9 +16,9 @@ namespace SolTrace::Data return; } - CompositeElement::CompositeElement(const nlohmann::ordered_json &jnode) : ElementBase(jnode), - number_of_elements(0), - my_elements() + CompositeElement::CompositeElement(const nlohmann::ordered_json &jnode, + const OpticalPropertySetResolver& resolve_optics) + : ElementBase(jnode), number_of_elements(0),my_elements() { using json = nlohmann::ordered_json; @@ -29,12 +30,21 @@ namespace SolTrace::Data bool is_single = jelement.at("is_single"); if (is_single) { - element_ptr el = make_element(jelement); - this->add_element(el); + if (jelement.at("virtual_flag") == true) + { + element_ptr el = make_element(jelement, resolve_optics); + this->add_element(el); + } + else + { + element_ptr el = make_element(jelement, resolve_optics); + this->add_element(el); + } + } else { - composite_element_ptr comp = make_element(jelement); + composite_element_ptr comp = make_element(jelement, resolve_optics); this->add_element(comp); } } diff --git a/coretrace/simulation_data/composite_element.hpp b/coretrace/simulation_data/composite_element.hpp index 95a5916f..5c1a1394 100644 --- a/coretrace/simulation_data/composite_element.hpp +++ b/coretrace/simulation_data/composite_element.hpp @@ -29,7 +29,8 @@ namespace SolTrace::Data * @brief Default constructor for composite element */ CompositeElement(); - CompositeElement(const nlohmann::ordered_json& jnode); + CompositeElement(const nlohmann::ordered_json& jnode, + const OpticalPropertySetResolver& resolve_optics); virtual ~CompositeElement(); /** @@ -108,53 +109,31 @@ namespace SolTrace::Data virtual void set_surface(surface_ptr) override {} /** - * @brief Get front optical properties (always null for composite elements) - * @return nullptr (composite elements don't have optical properties) + * @brief Get optical propertiy set id (always undefined for composite elements) + * @return unassigned id (composite elements don't have optical properties) */ - virtual const OpticalProperties *get_front_optical_properties() const override + virtual optics_id get_optical_property_set_id() const override { - return nullptr; + return OPTICS_ID_UNASSIGNED; } /** - * @brief Get front optical properties (always null for composite elements) + * @brief Get optical propertiy set pointer * @return nullptr (composite elements don't have optical properties) */ - virtual OpticalProperties *get_front_optical_properties() override + virtual std::shared_ptr get_optical_property_set() const { return nullptr; } /** - * @brief Set front optical properties (no-op for composite elements) - * @param op Ignored for composite elements + * @brief Set optical propertiy set id (does not apply for composite elements) */ - virtual void set_front_optical_properties(const OpticalProperties &) override {} - - /** - * @brief Get back optical properties (always null for composite elements) - * @return nullptr (composite elements don't have optical properties) - */ - virtual const OpticalProperties *get_back_optical_properties() const override + virtual void set_optical_property_set(const OpticalPropertySetReference&) override { - return nullptr; + assert(false && "CompositeElement does not support optical property sets"); } - /** - * @brief Get back optical properties (always null for composite elements) - * @return nullptr (composite elements don't have optical properties) - */ - virtual OpticalProperties *get_back_optical_properties() override - { - return nullptr; - } - - /** - * @brief Set back optical properties (no-op for composite elements) - * @param op Ignored for composite elements - */ - virtual void set_back_optical_properties(const OpticalProperties &) override {}; - // CompositeElement accessors /** * @brief Add an element to this composite diff --git a/coretrace/simulation_data/container.hpp b/coretrace/simulation_data/container.hpp index bbaa8696..926f31c5 100644 --- a/coretrace/simulation_data/container.hpp +++ b/coretrace/simulation_data/container.hpp @@ -145,11 +145,38 @@ class Container return; } + void reset(K start = 0) + { + this->container.clear(); + this->next_id = start; + } + iterator get_iterator() { return container.begin(); } const_iterator get_const_iterator() const { return container.cbegin(); } bool is_at_end(iterator iter) const { return iter == container.end(); } bool is_at_end(const_iterator citer) const { return citer == container.cend(); } + bool insert_item(K id, value_pointer item) + { + typename std::map::value_type to_insert(id, item); + auto result = this->container.insert(to_insert); + return result.second; + } + + void recompute_next_id(K minimum = 0) + { + K next = minimum; + for (const auto& [id, item] : this->container) + { + if (id >= next) + { + next = id + 1; + } + } + + this->next_id = next; + } + private: std::map container; mutable K next_id; diff --git a/coretrace/simulation_data/cst_templates/heliostat.cpp b/coretrace/simulation_data/cst_templates/heliostat.cpp index dd0a2d6d..900e6635 100644 --- a/coretrace/simulation_data/cst_templates/heliostat.cpp +++ b/coretrace/simulation_data/cst_templates/heliostat.cpp @@ -35,8 +35,6 @@ namespace SolTrace::Data { this->elevation_axis = {1.0, 0.0, 0.0}; this->sun_position = {0.0, 0.0, 1.0}; - this->optics_mirror.set_ideal_reflection(); - this->optics_back.set_ideal_absorption(); return; } @@ -178,8 +176,7 @@ namespace SolTrace::Data 0.0); // TODO: Make back optical properties accessible to user - elem->set_front_optical_properties(this->optics_mirror); - elem->set_back_optical_properties(this->optics_back); + elem->set_optical_property_set(this->facet_optics); elem->enable(); this->heliostat_area += panel_len_x * panel_len_y; @@ -376,24 +373,9 @@ namespace SolTrace::Data return; } - void Heliostat::set_mirror_optics(const OpticalProperties &optics) + void Heliostat::set_optics(OpticalPropertySetReference ref) { - this->optics_mirror = optics; - // TODO: Need to update the subelements! - return; - } - - void Heliostat::set_back_optics(const OpticalProperties& optics) - { - this->optics_back = optics; - // TODO: Need to update the subelements! - return; - } - - void Heliostat::set_optics(const OpticalProperties& mirror_optics, const OpticalProperties& back_optics) - { - this->optics_mirror = mirror_optics; - this->optics_back = back_optics; + this->facet_optics = ref; // TODO: Need to update the subelements! return; } diff --git a/coretrace/simulation_data/cst_templates/heliostat.hpp b/coretrace/simulation_data/cst_templates/heliostat.hpp index 1be30d5a..83809e78 100644 --- a/coretrace/simulation_data/cst_templates/heliostat.hpp +++ b/coretrace/simulation_data/cst_templates/heliostat.hpp @@ -43,9 +43,7 @@ class Heliostat : public CompositeElement void set_focal_length(double fx, double fy); void set_gaps(double gap_x, double gap_y); void set_number_panels(uint_fast64_t num_x, uint_fast64_t num_y); - void set_mirror_optics(const OpticalProperties& optics); - void set_back_optics(const OpticalProperties& optics); - void set_optics(const OpticalProperties& mirror_optics, const OpticalProperties& back_optics); + void set_optics(OpticalPropertySetReference ref); // void set_onaxis_canting_distance(double dist); // void set_offaxis_canting_sun_position(double azimuth, double zenith); void set_canting(CantingType ct, double val1, double val2); @@ -77,8 +75,7 @@ class Heliostat : public CompositeElement uint_fast64_t num_panels_x; uint_fast64_t num_panels_y; - OpticalProperties optics_mirror; - OpticalProperties optics_back; + OpticalPropertySetReference facet_optics; CantingType canting_method; double onaxis_canting_distance; diff --git a/coretrace/simulation_data/cst_templates/linear_fresnel.cpp b/coretrace/simulation_data/cst_templates/linear_fresnel.cpp index e02a2da2..8b8b3467 100644 --- a/coretrace/simulation_data/cst_templates/linear_fresnel.cpp +++ b/coretrace/simulation_data/cst_templates/linear_fresnel.cpp @@ -33,11 +33,6 @@ namespace SolTrace::Data tracking_limit_lower(-180.0), tracking_limit_upper(180.0) { - this->optics_absorber.set_ideal_absorption(); - this->optics_mirror.set_ideal_reflection(); - this->optics_env_out.set_ideal_transmission(); - this->optics_env_in.set_ideal_transmission(); - this->tracking_origin = {1.0, 0.0, 0.0}; this->rotation_axis = {0.0, 1.0, 0.0}; this->neutral_normal = {0.0, 0.0, 1.0}; @@ -176,10 +171,10 @@ namespace SolTrace::Data return; } - void LinearFresnel::set_optics(const OpticalProperties &mirror, - const OpticalProperties &absorber, - const OpticalProperties &envelop_outer, - const OpticalProperties &envelop_inner) + void LinearFresnel::set_optics(const OpticalPropertySetReference mirror, + const OpticalPropertySetReference absorber, + const OpticalPropertySetReference envelop_outer, + const OpticalPropertySetReference envelop_inner) { this->optics_mirror = mirror; this->optics_absorber = absorber; @@ -358,8 +353,7 @@ namespace SolTrace::Data } mirror->set_surface(surf); - mirror->set_front_optical_properties(this->optics_mirror); - mirror->set_back_optical_properties(this->optics_mirror); + mirror->set_optical_property_set(optics_mirror); mirror->enable(); std::stringstream name; @@ -402,8 +396,7 @@ namespace SolTrace::Data abs->set_aperture(make_aperture(this->abs_diameter, this->aperture_size_y)); abs->set_surface(make_surface(0.5 * this->abs_diameter)); - abs->set_front_optical_properties(this->optics_absorber); - abs->set_back_optical_properties(this->optics_absorber); + abs->set_optical_property_set(optics_absorber); abs->enable(); this->absorbers.push_back(abs); @@ -428,8 +421,7 @@ namespace SolTrace::Data envout->set_aperture(make_aperture(this->env_diameter, this->aperture_size_y)); envout->set_surface(make_surface(0.5 * this->env_diameter)); - envout->set_front_optical_properties(this->optics_env_out); - envout->set_back_optical_properties(this->optics_env_out); + envout->set_optical_property_set(optics_env_out); envout->enable(); this->envelope.push_back(envout); @@ -454,8 +446,7 @@ namespace SolTrace::Data double ap_y = this->aperture_size_y; envin->set_aperture(make_aperture(ap_x, ap_y)); envin->set_surface(make_surface(0.5 * ap_x)); - envin->set_front_optical_properties(this->optics_env_in); - envin->set_back_optical_properties(this->optics_env_in); + envin->set_optical_property_set(optics_env_in); envin->enable(); this->envelope.push_back(envin); sts = this->add_element(envin); diff --git a/coretrace/simulation_data/cst_templates/linear_fresnel.hpp b/coretrace/simulation_data/cst_templates/linear_fresnel.hpp index d2a11a6d..9a1a1ac1 100644 --- a/coretrace/simulation_data/cst_templates/linear_fresnel.hpp +++ b/coretrace/simulation_data/cst_templates/linear_fresnel.hpp @@ -35,10 +35,10 @@ class LinearFresnel : public CompositeElement void set_focused_panels(bool focused); void set_gaps(double gap_x, double gap_y, double gap_center); void set_number_panels(int_fast64_t num_x, int_fast64_t num_y); - void set_optics(const OpticalProperties &mirror, - const OpticalProperties &absorber, - const OpticalProperties &envelop_outer, - const OpticalProperties &envelop_inner); + void set_optics(const OpticalPropertySetReference mirror, + const OpticalPropertySetReference absorber, + const OpticalPropertySetReference envelop_outer, + const OpticalPropertySetReference envelop_inner); void set_receiver_height(double height); void set_receiver_dimensions(double absorber_diameter, double envelop_diameter, @@ -90,16 +90,16 @@ class LinearFresnel : public CompositeElement double gap_x; double gap_y; double gap_center; - OpticalProperties optics_mirror; + OpticalPropertySetReference optics_mirror; // Receiver Characteristics double abs_diameter; double env_diameter; double env_thickness; // double receiver_length; - OpticalProperties optics_absorber; - OpticalProperties optics_env_out; - OpticalProperties optics_env_in; + OpticalPropertySetReference optics_absorber; + OpticalPropertySetReference optics_env_out; + OpticalPropertySetReference optics_env_in; // Solar Tracking // double tracking_angle; diff --git a/coretrace/simulation_data/cst_templates/parabolic_dish.cpp b/coretrace/simulation_data/cst_templates/parabolic_dish.cpp index 3dae35e7..12d6b221 100644 --- a/coretrace/simulation_data/cst_templates/parabolic_dish.cpp +++ b/coretrace/simulation_data/cst_templates/parabolic_dish.cpp @@ -100,8 +100,7 @@ void ParabolicDish::create_geometry() mirror->set_aperture(make_aperture(this->aperture_diameter)); mirror->set_surface(make_surface(this->focal_length, this->focal_length)); - mirror->set_front_optical_properties(this->optics_mirror); - mirror->set_back_optical_properties(this->optics_mirror); + mirror->set_optical_property_set(optics_mirror); mirror->enable(); this->mirrors.push_back(mirror); @@ -126,8 +125,7 @@ void ParabolicDish::create_geometry() panel_angle)); mirror->set_surface(make_surface(this->focal_length, this->focal_length)); - mirror->set_front_optical_properties(this->optics_mirror); - mirror->set_back_optical_properties(this->optics_mirror); + mirror->set_optical_property_set(optics_mirror); mirror->set_name("ParabolicMirror"); mirror->enable(); @@ -147,8 +145,7 @@ void ParabolicDish::create_geometry() abs->set_reference_frame_geometry(origin, aim, 0.0); abs->set_aperture(make_aperture(this->abs_diameter)); abs->set_surface(make_surface()); - abs->set_front_optical_properties(this->optics_absorber); - abs->set_back_optical_properties(this->optics_absorber); + abs->set_optical_property_set(optics_absorber); abs->set_name("Absorber"); abs->enable(); @@ -301,8 +298,8 @@ void ParabolicDish::set_number_of_panels(int_fast64_t nradial, return; } -void ParabolicDish::set_optics(const OpticalProperties &mirror, - const OpticalProperties &absorber) +void ParabolicDish::set_optics(const OpticalPropertySetReference &mirror, + const OpticalPropertySetReference &absorber) { this->optics_mirror = mirror; this->optics_absorber = absorber; diff --git a/coretrace/simulation_data/cst_templates/parabolic_dish.hpp b/coretrace/simulation_data/cst_templates/parabolic_dish.hpp index 356a7612..642de314 100644 --- a/coretrace/simulation_data/cst_templates/parabolic_dish.hpp +++ b/coretrace/simulation_data/cst_templates/parabolic_dish.hpp @@ -32,8 +32,8 @@ class ParabolicDish : public CompositeElement void set_focal_length(double flen); void set_gaps(double radial, double angular, double center_radius); void set_number_of_panels(int_fast64_t nradial, int_fast64_t nangular); - void set_optics(const OpticalProperties &mirror, - const OpticalProperties &absorber); + void set_optics(const OpticalPropertySetReference &mirror, + const OpticalPropertySetReference &absorber); void set_receiver_dimensions(double diameter, double distance); void set_tracking_limits(double az_lower, double az_upper, double el_lower, double el_upper); @@ -63,12 +63,12 @@ class ParabolicDish : public CompositeElement double gap_center; int_fast64_t num_panels_r; int_fast64_t num_panels_a; - OpticalProperties optics_mirror; + OpticalPropertySetReference optics_mirror; // Receiver Characteristics double abs_diameter; double abs_distance; - OpticalProperties optics_absorber; + OpticalPropertySetReference optics_absorber; // Follows solar azimuth, elevation convention: // Azimuth is angle clockwise from north (y-axis) in degrees diff --git a/coretrace/simulation_data/cst_templates/parabolic_trough.cpp b/coretrace/simulation_data/cst_templates/parabolic_trough.cpp index 0122f8e5..45bad9b8 100644 --- a/coretrace/simulation_data/cst_templates/parabolic_trough.cpp +++ b/coretrace/simulation_data/cst_templates/parabolic_trough.cpp @@ -119,7 +119,7 @@ void ParabolicTrough::create_geometry() panel->set_aperture(ap); surf = make_surface(this->focal_length, 0.0); panel->set_surface(surf); - panel->set_front_optical_properties(this->optics_mirror); + panel->set_optical_property_set(this->optics_mirror); panel->enable(); this->mirrors.push_back(panel); @@ -147,8 +147,7 @@ void ParabolicTrough::create_geometry() abs->set_aperture(make_aperture(this->absorber_diameter, this->aperture_size_y)); abs->set_surface(make_surface(0.5 * this->absorber_diameter)); - abs->set_front_optical_properties(this->optics_absorber); - abs->set_back_optical_properties(this->optics_absorber); + abs->set_optical_property_set(optics_absorber); abs->enable(); this->absorbers.push_back(abs); auto id = this->add_element(abs); @@ -169,8 +168,7 @@ void ParabolicTrough::create_geometry() envout->set_aperture(make_aperture(this->envelope_diameter, this->aperture_size_y)); envout->set_surface(make_surface(0.5 * this->envelope_diameter)); - envout->set_front_optical_properties(this->optics_envelope_outer); - envout->set_back_optical_properties(this->optics_envelope_outer); + envout->set_optical_property_set(optics_envelope_outer); envout->enable(); this->envelopes.push_back(envout); id = this->add_element(envout); @@ -192,8 +190,7 @@ void ParabolicTrough::create_geometry() double ap_y = this->aperture_size_y; envin->set_aperture(make_aperture(ap_x, ap_y)); envin->set_surface(make_surface(0.5 * ap_x)); - envin->set_front_optical_properties(this->optics_envelope_inner); - envin->set_back_optical_properties(this->optics_envelope_inner); + envin->set_optical_property_set(optics_envelope_inner); envin->enable(); this->envelopes.push_back(envin); id = this->add_element(envin); @@ -458,10 +455,10 @@ void ParabolicTrough::set_number_panels(int_fast64_t num_x, return; } -void ParabolicTrough::set_optics(const OpticalProperties &mirror, - const OpticalProperties &absorber, - const OpticalProperties &envelope_inner, - const OpticalProperties &envelope_outer) +void ParabolicTrough::set_optics(const OpticalPropertySetReference mirror, + const OpticalPropertySetReference absorber, + const OpticalPropertySetReference envelope_inner, + const OpticalPropertySetReference envelope_outer) { this->optics_mirror = mirror; this->optics_absorber = absorber; diff --git a/coretrace/simulation_data/cst_templates/parabolic_trough.hpp b/coretrace/simulation_data/cst_templates/parabolic_trough.hpp index 4178d7fc..ba045e94 100644 --- a/coretrace/simulation_data/cst_templates/parabolic_trough.hpp +++ b/coretrace/simulation_data/cst_templates/parabolic_trough.hpp @@ -51,10 +51,10 @@ class ParabolicTrough : public CompositeElement void set_focal_length(double flen); void set_gaps(double gap_x, double gap_y, double gap_center); void set_number_panels(int_fast64_t num_x, int_fast64_t num_y); - void set_optics(const OpticalProperties &mirror, - const OpticalProperties &absorber, - const OpticalProperties &envelope_inner, - const OpticalProperties &envelope_outer); + void set_optics(const OpticalPropertySetReference mirror, + const OpticalPropertySetReference absorber, + const OpticalPropertySetReference envelope_inner, + const OpticalPropertySetReference envelope_outer); // void set_position(const glm::dvec3 &pos) // { // this->position = pos; @@ -117,16 +117,16 @@ class ParabolicTrough : public CompositeElement double gap_center; int_fast64_t num_panels_x; int_fast64_t num_panels_y; - OpticalProperties optics_mirror; + OpticalPropertySetReference optics_mirror; // Receiver Characteristics double absorber_diameter; double envelope_diameter; double envelope_thickness; // double length; - OpticalProperties optics_absorber; - OpticalProperties optics_envelope_inner; - OpticalProperties optics_envelope_outer; + OpticalPropertySetReference optics_absorber; + OpticalPropertySetReference optics_envelope_inner; + OpticalPropertySetReference optics_envelope_outer; // Solar Tracking double tracking_angle; diff --git a/coretrace/simulation_data/element.hpp b/coretrace/simulation_data/element.hpp index e62c54c8..0304f965 100644 --- a/coretrace/simulation_data/element.hpp +++ b/coretrace/simulation_data/element.hpp @@ -187,13 +187,9 @@ class Element // virtual const OpticalProperties &get_optical_properties() const = 0; // virtual void set_optical_properties(const OpticalProperties &) = 0; - virtual const OpticalProperties *get_front_optical_properties() const = 0; - virtual OpticalProperties *get_front_optical_properties() = 0; - virtual void set_front_optical_properties(const OpticalProperties &) = 0; - - virtual const OpticalProperties *get_back_optical_properties() const = 0; - virtual OpticalProperties *get_back_optical_properties() = 0; - virtual void set_back_optical_properties(const OpticalProperties &) = 0; + virtual optics_id get_optical_property_set_id() const = 0; + virtual std::shared_ptr get_optical_property_set() const = 0; + virtual void set_optical_property_set(const OpticalPropertySetReference& optics) = 0; // Accessors for CompositeElements virtual uint_fast64_t get_number_of_elements() const = 0; diff --git a/coretrace/simulation_data/optical_properties.cpp b/coretrace/simulation_data/optical_properties.cpp index 8bd8d382..5cf4d1e8 100644 --- a/coretrace/simulation_data/optical_properties.cpp +++ b/coretrace/simulation_data/optical_properties.cpp @@ -24,44 +24,96 @@ const std::string interaction_string(InteractionType it) } } -OpticalProperties::OpticalProperties(const nlohmann::ordered_json& jnode) +OpticalPropertySet::OpticalPropertiesFace::OpticalPropertiesFace(const nlohmann::ordered_json& jnode) { - std::string interaction_string = jnode.at("my_type"); - this->my_type = get_enum_from_string(interaction_string, InteractionTypeMap, InteractionType::UNKNOWN); - std::string distribution_string = jnode.at("error_distribution_type"); this->error_distribution_type = get_enum_from_string(distribution_string, DistributionTypeMap, DistributionType::UNKNOWN); - this->transmitivity = jnode.at("transmissivity"); + this->transmissivity = jnode.at("transmissivity"); this->reflectivity = jnode.at("reflectivity"); this->slope_error = jnode.at("slope_error"); this->specularity_error = jnode.at("specularity_error"); - this->refraction_index_front = jnode.at("refraction_index_front"); - this->refraction_index_back = jnode.at("refraction_index_back"); } -void OpticalProperties::write_json(nlohmann::ordered_json& jnode) const +void OpticalPropertySet::OpticalPropertiesFace::write_json(nlohmann::ordered_json& jnode) const { - jnode["my_type"] = InteractionTypeMap.at(this->my_type); jnode["error_distribution_type"] = DistributionTypeMap.at(this->error_distribution_type); - jnode["transmissivity"] = this->transmitivity; + jnode["transmissivity"] = this->transmissivity; jnode["reflectivity"] = this->reflectivity; jnode["slope_error"] = this->slope_error; jnode["specularity_error"] = this->specularity_error; +} + +bool OpticalPropertySet::OpticalPropertiesFace::operator==(const OpticalPropertiesFace& other) const +{ + return this->error_distribution_type == other.error_distribution_type && + this->transmissivity == other.transmissivity && + this->reflectivity == other.reflectivity && + this->slope_error == other.slope_error && + this->specularity_error == other.specularity_error; +} + +bool OpticalPropertySet::OpticalPropertiesFace::operator!=(const OpticalPropertiesFace& other) const +{ + return !(*this == other); +} + +std::ostream &operator<<(std::ostream &os, + const OpticalPropertySet::OpticalPropertiesFace& op) +{ + os << "Transmissivity: " << op.transmissivity + << "\nReflectivity: " << op.reflectivity + << "\nSlope Error: " << op.slope_error + << "\nSpecularity Error: " << op.specularity_error; + return os; +} + +OpticalPropertySet::OpticalPropertySet(const nlohmann::ordered_json& jnode) + : front(jnode.at("front")), back(jnode.at("back")) +{ + std::string interaction_type_string = jnode.at("my_type"); + this->my_type = get_enum_from_string(interaction_type_string, InteractionTypeMap, InteractionType::UNKNOWN); + + this->refraction_index_front = jnode.at("refraction_index_front"); + this->refraction_index_back = jnode.at("refraction_index_back"); + + this->my_name = jnode.at("my_name"); +} + +void OpticalPropertySet::write_json(nlohmann::ordered_json& jnode) const +{ + jnode["my_type"] = InteractionTypeMap.at(this->my_type); jnode["refraction_index_front"] = this->refraction_index_front; jnode["refraction_index_back"] = this->refraction_index_back; + jnode["my_name"] = this->my_name; + + front.write_json(jnode["front"]); + back.write_json(jnode["back"]); } -std::ostream &operator<<(std::ostream &os, - const OpticalProperties &op) +bool OpticalPropertySet::operator==(const OpticalPropertySet& other) const +{ + return this->front == other.front && + this->back == other.back && + this->my_type == other.my_type && + this->refraction_index_front == other.refraction_index_front && + this->refraction_index_back == other.refraction_index_back && + this->my_name == other.my_name; +} + +bool OpticalPropertySet::operator!=(const OpticalPropertySet& other) const +{ + return !(*this == other); +} + +std::ostream& operator<<(std::ostream& os, + const OpticalPropertySet& op) { os << "Type: " << interaction_string(op.my_type) - << "\nTransmitivity: " << op.transmitivity - << "\nReflectivity: " << op.reflectivity - << "\nSlope Error: " << op.slope_error - << "\nSpecularity Error: " << op.specularity_error - << "\nRefraction Index Front: " << op.refraction_index_front - << "\nRefraction Index Back: " << op.refraction_index_back; + << "\nRefraction Index Front: " << op.refraction_index_front + << "\nRefraction Index Back: " << op.refraction_index_back + << "\nFront: " << op.front + << "\nBack: " << op.back; return os; } diff --git a/coretrace/simulation_data/optical_properties.hpp b/coretrace/simulation_data/optical_properties.hpp index 6ec6add7..9d1dda19 100644 --- a/coretrace/simulation_data/optical_properties.hpp +++ b/coretrace/simulation_data/optical_properties.hpp @@ -10,14 +10,34 @@ #ifndef SOLTRACE_OPTICAL_PROPERTIES_H #define SOLTRACE_OPTICAL_PROPERTIES_H +#include +#include +#include #include +#include #include +#include +#include +#include + #include #include "error_distributions.hpp" namespace SolTrace::Data { + using optics_id = std::int_fast64_t; + + enum OPTICS_ID_TYPES + { + OPTICS_ID_VIRTUAL = -3, + OPTICS_ID_UNASSIGNED = -2 + }; + + class OpticalPropertySet; + struct OpticalPropertySetReference; + using OpticalPropertySetContainer = Container; + using OpticalPropertySetResolver = std::function; enum class InteractionType { @@ -33,82 +53,216 @@ namespace SolTrace::Data {InteractionType::UNKNOWN, "UNKNOWN"} }; - struct OpticalProperties + enum class OpticalSide + { + Front, + Back, + Both + }; + + struct OpticalPropertySetReference { + optics_id id = OPTICS_ID_UNASSIGNED; + std::weak_ptr optical_property_set; + }; + + struct OpticalPropertySet + { + private: + + class OpticalPropertiesFace + { + public: + DistributionType error_distribution_type; + double transmissivity; + double reflectivity; + double slope_error; // [mrad] + double specularity_error; // [mrad] + + OpticalPropertiesFace() : error_distribution_type(DistributionType::UNKNOWN), + transmissivity(0.0), + reflectivity(0.0), + slope_error(0.0), + specularity_error(0.0) + { + } + + OpticalPropertiesFace(DistributionType dtype, + double trans, double refl, + double slope_err, double spec_err) + : error_distribution_type(dtype), + transmissivity(trans), + reflectivity(refl), + slope_error(slope_err), + specularity_error(spec_err) + { + } + + OpticalPropertiesFace(const nlohmann::ordered_json& jnode); + + // TODO: What should the error settings be with the below? + void write_json(nlohmann::ordered_json& jnode) const; + + bool operator==(const OpticalPropertiesFace& other) const; + bool operator!=(const OpticalPropertiesFace& other) const; + + + }; + + OpticalPropertiesFace front; + OpticalPropertiesFace back; + InteractionType my_type; - DistributionType error_distribution_type; - double transmitivity; - double reflectivity; - double slope_error; // [mrad] - double specularity_error; // [mrad] + double refraction_index_front; double refraction_index_back; - OpticalProperties() : my_type(InteractionType::REFLECTION), - error_distribution_type(DistributionType::UNKNOWN), - transmitivity(0.0), - reflectivity(0.0), - slope_error(0.0), - specularity_error(0.0), - refraction_index_front(0.0), - refraction_index_back(0.0) + std::string my_name; + + void set_ideal_material(OpticalSide side) { + if (side == OpticalSide::Front || side == OpticalSide::Both) + { + this->front.error_distribution_type = DistributionType::NONE; + this->front.specularity_error = 0.0; + this->front.slope_error = 0.0; + } + + if (side == OpticalSide::Back || side == OpticalSide::Both) + { + this->back.error_distribution_type = DistributionType::NONE; + this->back.specularity_error = 0.0; + this->back.slope_error = 0.0; + } + + return; } - OpticalProperties(InteractionType itype, - DistributionType dtype, - double trans, double refl, - double slope_err, double spec_err, - double ri_front, double ri_back) - : my_type(itype), - error_distribution_type(dtype), - transmitivity(trans), - reflectivity(refl), - slope_error(slope_err), - specularity_error(spec_err), - refraction_index_front(ri_front), - refraction_index_back(ri_back) + public: + + OpticalPropertySet(InteractionType interaction_type, + double refrac_front, double refrac_back, + std::string name = "") + : front(), back(), + my_type(interaction_type), refraction_index_front(refrac_front), + refraction_index_back(refrac_back), + my_name(name) { - } + }; - OpticalProperties(const nlohmann::ordered_json& jnode); + OpticalPropertySet(InteractionType interaction_type, + std::string name = "") + : OpticalPropertySet(interaction_type, 0, 0, name) + { + }; - // TODO: What should the error settings be with the below? + OpticalPropertySet() + : my_type(InteractionType::UNKNOWN), + refraction_index_front(0.0), + refraction_index_back(0.0), + my_name("") + { + }; + + OpticalPropertySet(const nlohmann::ordered_json& jnode); - void set_ideal_material() + void set_properties(const OpticalSide side, + DistributionType dtype, + double trans, double refl, + double slope_err, double spec_err) { - this->error_distribution_type = DistributionType::NONE; - this->specularity_error = 0.0; - this->slope_error = 0.0; + auto set_face_props = [=](OpticalPropertiesFace& face) + { + face.error_distribution_type = dtype; + face.transmissivity = trans; + face.reflectivity = refl; + face.slope_error = slope_err; + face.specularity_error = spec_err; + }; + + if (side == OpticalSide::Front || side == OpticalSide::Both) + set_face_props(this->front); + if (side == OpticalSide::Back || side == OpticalSide::Both) + set_face_props(this->back); + return; } - void set_ideal_absorption() + void set_interaction_type(const InteractionType type) { - this->set_ideal_material(); - this->my_type = InteractionType::REFLECTION; - this->transmitivity = 0.0; - this->reflectivity = 0.0; - return; + this->my_type = type; + } + + void set_refraction_indices(double rfront, double rback) + { + this->refraction_index_front = rfront; + this->refraction_index_back = rback; } - void set_ideal_reflection() + + void set_reflectivity(const OpticalSide side, + double refl) { - this->set_ideal_material(); - this->my_type = InteractionType::REFLECTION; - this->transmitivity = 0.0; - this->reflectivity = 1.0; - return; + if (side == OpticalSide::Front || side == OpticalSide::Both) + { + this->front.reflectivity = refl; + } + + if (side == OpticalSide::Back || side == OpticalSide::Both) + { + this->back.reflectivity = refl; + } + } + + void set_transmissivity(const OpticalSide side, + double trans) + { + if (side == OpticalSide::Front || side == OpticalSide::Both) + { + this->front.transmissivity = trans; + } + + if (side == OpticalSide::Back || side == OpticalSide::Both) + { + this->back.transmissivity = trans; + } + } + + void set_errors(const OpticalSide side, + DistributionType dtype, double slope, + double spec) + { + if (side == OpticalSide::Front || side == OpticalSide::Both) + { + this->front.error_distribution_type = dtype; + this->front.slope_error = slope; + this->front.specularity_error = spec; + } + + if (side == OpticalSide::Back || side == OpticalSide::Both) + { + this->back.error_distribution_type = dtype; + this->back.slope_error = slope; + this->back.specularity_error = spec; + } } + void set_ideal_transmission() { - this->set_ideal_material(); this->my_type = InteractionType::REFRACTION; - this->transmitivity = 1.0; - this->reflectivity = 0.0; + + this->set_ideal_material(OpticalSide::Both); + + this->front.transmissivity = 1.0; + this->front.reflectivity = 0.0; + + this->back.transmissivity = 1.0; + this->back.reflectivity = 0.0; + return; } + void set_ideal_transmission(double refraction_index_front, - double refraction_index_back) + double refraction_index_back) { this->set_ideal_transmission(); this->refraction_index_front = refraction_index_front; @@ -116,22 +270,184 @@ namespace SolTrace::Data return; } + void set_ideal_one_sided_reflector(const OpticalSide side = OpticalSide::Front) + { + if (side == OpticalSide::Both) + { + throw std::invalid_argument("set_ideal_one_sided_reflector requires Front or Back, not Both."); + } + + this->my_type = InteractionType::REFLECTION; + + this->set_ideal_material(OpticalSide::Both); + + this->front.reflectivity = 0.0; + this->front.transmissivity = 0.0; + + this->back.reflectivity = 0.0; + this->back.transmissivity = 0.0; + + if (side == OpticalSide::Front) + { + this->front.reflectivity = 1.0; + } + else + { + this->back.reflectivity = 1.0; + } + } + + void set_ideal_absorption(const OpticalSide side) + { + this->my_type = InteractionType::REFLECTION; + this->set_ideal_material(side); + + if (side == OpticalSide::Front || side == OpticalSide::Both) + { + this->front.transmissivity = 0.0; + this->front.reflectivity = 0.0; + } + + if (side == OpticalSide::Back || side == OpticalSide::Both) + { + this->back.transmissivity = 0.0; + this->back.reflectivity = 0.0; + } + + return; + } + + void set_ideal_reflection(const OpticalSide side) + { + this->my_type = InteractionType::REFLECTION; + + this->set_ideal_material(side); + + if (side == OpticalSide::Front || side == OpticalSide::Both) + { + this->front.transmissivity = 0.0; + this->front.reflectivity = 1.0; + } + + if (side == OpticalSide::Back || side == OpticalSide::Both) + { + this->back.transmissivity = 0.0; + this->back.reflectivity = 1.0; + } + return; + } + + const InteractionType get_interaction_type() const + { + return this->my_type; + } + + const std::string get_name() const + { + return this->my_name; + } + + void get_refraction_indices(double& rfront, double& rback) const + { + rfront = this->refraction_index_front; + rback = this->refraction_index_back; + } + + double get_reflectivity(const OpticalSide side) const + { + switch (side) + { + case(OpticalSide::Front): + return this->front.reflectivity; + case(OpticalSide::Back): + return this->back.reflectivity; + default: + return std::numeric_limits::quiet_NaN(); + } + } + + double get_transmissivity(const OpticalSide side) const + { + switch (side) + { + case(OpticalSide::Front): + return this->front.transmissivity; + case(OpticalSide::Back): + return this->back.transmissivity; + default: + return std::numeric_limits::quiet_NaN(); + } + } + + DistributionType get_error_distribution(const OpticalSide side) const + { + switch (side) + { + case(OpticalSide::Front): + return this->front.error_distribution_type; + case(OpticalSide::Back): + return this->back.error_distribution_type; + default: + return DistributionType::UNKNOWN; + } + } + + double get_slope_error(const OpticalSide side) const + { + switch (side) + { + case(OpticalSide::Front): + return this->front.slope_error; + case(OpticalSide::Back): + return this->back.slope_error; + default: + return std::numeric_limits::quiet_NaN(); + } + } + + double get_specularity_error(const OpticalSide side) const + { + switch (side) + { + case(OpticalSide::Front): + return this->front.specularity_error; + case(OpticalSide::Back): + return this->back.specularity_error; + default: + return std::numeric_limits::quiet_NaN(); + } + } + + void get_errors(const OpticalSide side, + DistributionType& dtype, double& slope, + double& spec) const + { + if (side == OpticalSide::Both) + { + dtype = DistributionType::UNKNOWN; + slope = std::numeric_limits::quiet_NaN(); + spec = std::numeric_limits::quiet_NaN(); + return; + } + + auto& face = side == OpticalSide::Front ? this->front : this->back; + + dtype = face.error_distribution_type; + slope = face.slope_error; + spec = face.specularity_error; + return; + } + void write_json(nlohmann::ordered_json& jnode) const; - // OpticalProperties &operator=(const OpticalProperties &rhs) - // { - // this->my_type = rhs.my_type; - // this->transmitivity = rhs.transmitivity; - // this->reflectivity = rhs.reflectivity; - // this->slope_error = rhs.slope_error; - // this->specularity_error = rhs.specularity_error; - // this->refraction_index_front = rhs.refraction_index_front; - // this->refraction_index_back = rhs.refraction_index_back; - // return *this; - // } - - friend std::ostream &operator<<(std::ostream &os, - const OpticalProperties &op); + bool operator==(const OpticalPropertySet& other) const; + bool operator!=(const OpticalPropertySet& other) const; + + friend std::ostream& operator<<(std::ostream& os, + const OpticalPropertySet& op); + + friend std::ostream& operator<<(std::ostream& os, + const OpticalPropertiesFace& op); }; } // namespace SolTrace::Data diff --git a/coretrace/simulation_data/simdata_io.cpp b/coretrace/simulation_data/simdata_io.cpp index de870e0b..a1f43b65 100644 --- a/coretrace/simulation_data/simdata_io.cpp +++ b/coretrace/simulation_data/simdata_io.cpp @@ -4,13 +4,16 @@ #include #include #include +#include +#include #include #include -#include + #include #include "constants.hpp" #include "basic_sun_position.hpp" +#include "json_helpers.hpp" #include "ray_source.hpp" #include "simulation_data.hpp" #include "single_element.hpp" @@ -18,7 +21,7 @@ #include "sun.hpp" #include "surface.hpp" #include "utilities.hpp" -#include "json_helpers.hpp" +#include "virtual_element.hpp" namespace SolTrace::Data { @@ -277,8 +280,10 @@ bool process_sun(FILE *fp, SimulationData &sd) } bool read_optic_surface(FILE *fp, - OpticalProperties &optics, - int &OpticalSurfaceNumber) + bool is_front, + OpticalPropertySet &optics, + int &OpticalSurfaceNumber, + double &refraction) { if (!fp) return false; @@ -303,8 +308,8 @@ bool read_optic_surface(FILE *fp, double Transmissivity = atof(parts[6].c_str()); double RMSSlope = atof(parts[7].c_str()); double RMSSpecularity = atof(parts[8].c_str()); - double RefractionIndexReal = atof(parts[9].c_str()); - double RefractionIndexImag = atof(parts[10].c_str()); + refraction = atof(parts[9].c_str()); + //double RefractionIndexImag = atof(parts[10].c_str()); // This is not used double GratingCoeffs[4]; GratingCoeffs[0] = atof(parts[11].c_str()); GratingCoeffs[1] = atof(parts[12].c_str()); @@ -356,11 +361,9 @@ bool read_optic_surface(FILE *fp, } // Define optical properties - InteractionType interaction = InteractionType::REFLECTION; DistributionType dist = char_to_distribution(ErrorDistribution); - optics = OpticalProperties(interaction, dist, Transmissivity, - Reflectivity, RMSSlope, RMSSpecularity, - RefractionIndexReal, RefractionIndexImag); + OpticalSide side = is_front ? OpticalSide::Front : OpticalSide::Back; + optics.set_properties(side, dist, Transmissivity, Reflectivity, RMSSlope, RMSSpecularity); if (refl_angles != 0) delete[] refl_angles; @@ -375,7 +378,7 @@ bool read_optic_surface(FILE *fp, bool process_optics( FILE *fp, - std::map> &optics_map) + std::map &optics_map) { char buf[1024]; @@ -394,13 +397,15 @@ bool process_optics( { // int iopt = st_add_optic(cxt, (const char*)(buf + 13)); std::string optics_name = std::string(buf + 13); - OpticalProperties optics_front, optics_back; + double refrac_front, refrac_back; int OpticalSurfaceNumber = 0; - read_optic_surface(fp, optics_front, OpticalSurfaceNumber); - read_optic_surface(fp, optics_back, OpticalSurfaceNumber); - optics_map[optics_name][0] = optics_front; - optics_map[optics_name][1] = optics_back; + OpticalPropertySet optics_set(InteractionType::UNKNOWN, optics_name); + read_optic_surface(fp, true, optics_set, OpticalSurfaceNumber, refrac_front); + read_optic_surface(fp, false, optics_set, OpticalSurfaceNumber, refrac_back); + optics_set.set_refraction_indices(refrac_front, refrac_back); + + optics_map[optics_name] = optics_set; } else return false; @@ -411,8 +416,10 @@ bool process_optics( bool read_element( FILE *fp, - std::map> &optics_map, - element_ptr &el) + std::map &optics_map, + element_ptr &el, + SimulationData &sd, + bool virt) { char buf[1024]; read_line(buf, 1023, fp); @@ -478,7 +485,13 @@ bool read_element( InteractionType interaction = int_to_interaction(atoi(tok[28].c_str())); // Create element - el = make_element(); + if (virt) + el = make_element(); + else + el = make_element(); + + if (!enabled) + el->disable(); // Make aperture ApertureType aperture_type = char_to_aperture(ShapeIndex); @@ -539,22 +552,30 @@ bool read_element( zrot); // Set optical properties - OpticalProperties optics_front = optics_map[optics_name][0]; - OpticalProperties optics_back = optics_map[optics_name][1]; - el->set_front_optical_properties(optics_front); - el->set_back_optical_properties(optics_back); + if (!virt) + { + auto optics_iter = optics_map.find(optics_name); + if (optics_iter == optics_map.end()) + { + std::stringstream ss; + ss << "Element references unknown optical property set: " << optics_name; + throw std::runtime_error(ss.str()); + } - // Set optical interaction type - el->get_front_optical_properties()->my_type = interaction; - el->get_back_optical_properties()->my_type = interaction; + OpticalPropertySet optics_set = optics_iter->second; + optics_set.set_interaction_type(interaction); + auto optics_ref = sd.find_or_add_optical_property_set(optics_set); + el->set_optical_property_set(optics_ref); + } + return true; } bool process_stages( FILE *fp, SimulationData &sd, - std::map> &optics_map) + std::map &optics_map) { char buf[1024]; @@ -599,7 +620,7 @@ bool process_stages( for (int i_element = 0; i_element < count_element; i_element++) { element_ptr el; - read_element(fp, optics_map, el); + read_element(fp, optics_map, el, sd, virt); el->set_name(std::to_string(i_element)); // TODO make virtual if stage is virtual? @@ -687,7 +708,7 @@ bool load_stinput_file(SimulationData &sd, std::string filename) process_sun(fp, sd); // Read in Optics - std::map> optics_map; + std::map optics_map; process_optics(fp, optics_map); // Read in Stages @@ -717,16 +738,7 @@ void write_json_file(SimulationData& sd, std::string filename) // Write parameters { json jpar; - SolTrace::Data::SimulationParameters sim_par = sd.get_simulation_parameters(); - jpar["include_sun_shape_errors"] = sim_par.include_sun_shape_errors; // bool - jpar["include_optical_errors"] = sim_par.include_optical_errors; // bool - jpar["number_of_rays"] = sim_par.number_of_rays; // int - jpar["max_number_of_rays"] = sim_par.max_number_of_rays; // int - jpar["tolerance"] = sim_par.tolerance; // double - jpar["latitude"] = sim_par.latitude; // double - jpar["longitude"] = sim_par.longitude; // double - jpar["seed"] = sim_par.seed; // int - + sd.get_simulation_parameters().write_json(jpar); root["simulation_parameters"] = jpar; } @@ -757,6 +769,23 @@ void write_json_file(SimulationData& sd, std::string filename) root["ray_sources"] = jsources; } + // Write optical properties + { + json joptics_top; + for (auto it = sd.get_optics_iterator(); !sd.is_optics_at_end(it); ++it) + { + json joptics; + + SolTrace::Data::optics_id id = it->first; + auto optics_set = it->second; + + optics_set->write_json(joptics); + + joptics_top[std::to_string(id)] = joptics; + } + root["optical_properties"] = joptics_top; + } + // Write Elements { json jelements_top; @@ -813,14 +842,7 @@ void load_json_file(SimulationData& sd, std::string filename) // Simulation parameters SolTrace::Data::SimulationParameters& sim_par = sd.get_simulation_parameters(); json jpar = root["simulation_parameters"]; - sim_par.include_sun_shape_errors = jpar.at("include_sun_shape_errors"); - sim_par.include_optical_errors = jpar.at("include_optical_errors"); - sim_par.number_of_rays = jpar.at("number_of_rays"); - sim_par.max_number_of_rays = jpar.at("max_number_of_rays"); - sim_par.tolerance = jpar.at("tolerance"); - sim_par.latitude = jpar.at("latitude"); - sim_par.longitude = jpar.at("longitude"); - sim_par.seed = jpar.at("seed"); + sim_par = SolTrace::Data::SimulationParameters(jpar); // Ray sources json jsources = root["ray_sources"]; @@ -838,8 +860,51 @@ void load_json_file(SimulationData& sd, std::string filename) sd.add_ray_source(sun); } + // Optical properties + json joptics = root.at("optical_properties"); + for (auto& [key, joptic] : joptics.items()) + { + optics_id opt_id = static_cast(std::stoll(key)); + OpticalPropertySet opt_set(joptic); + + // Check for pre-existing optical property sets + const OpticalPropertySet* existing = sd.get_optical_property_set(opt_id); + if (existing != nullptr) + { + // This should be a built in optical property set + if (opt_id >= 0) + throw std::runtime_error("Custom optical property set already exists"); + + // Ensure loaded built in matches + if (*existing != opt_set) + { + std::stringstream ss; + ss << "Built-in optical property set mismatch for id " << opt_id; + throw std::runtime_error(ss.str()); + } + } + else // Insert new optical property set + { + auto ptr = std::make_shared(opt_set); + bool flag = sd.my_optical_property_sets.insert_item(opt_id, ptr); + if (!flag) + { + std::stringstream ss; + ss << "Failed to insert optical property set id from JSON: " << opt_id; + throw std::runtime_error(ss.str()); + } + } + } + // Set optical property set next id + sd.my_optical_property_sets.recompute_next_id(0); + // Elements json jelements = root["elements"]; + auto resolve_optics = [&sd](const optics_id id) + { + auto ptr = sd.my_optical_property_sets.get_item(id); + return OpticalPropertySetReference{ id, ptr }; + }; for (auto& [key, jelement] : jelements.items()) { // Check if stage @@ -847,19 +912,19 @@ void load_json_file(SimulationData& sd, std::string filename) if (jelement.contains("is_stage") && jelement.at("is_stage") == true) { // Make stage - stage_ptr stage = make_stage(jelement); + stage_ptr stage = make_stage(jelement, resolve_optics); sd.add_stage(stage); } // Composite else if (jelement.contains("is_composite") && jelement.at("is_composite") == true) { - composite_element_ptr comp = make_element(jelement); + composite_element_ptr comp = make_element(jelement, resolve_optics); sd.add_element(comp); } // Single Element else { - single_element_ptr single = make_element(jelement); + single_element_ptr single = make_element(jelement, resolve_optics); sd.add_element(single); } } diff --git a/coretrace/simulation_data/simulation_data.cpp b/coretrace/simulation_data/simulation_data.cpp index 64a17e70..200bc239 100644 --- a/coretrace/simulation_data/simulation_data.cpp +++ b/coretrace/simulation_data/simulation_data.cpp @@ -1,6 +1,7 @@ #include "simulation_data.hpp" #include +#include #include "composite_element.hpp" #include "simdata_io.hpp" @@ -9,7 +10,8 @@ namespace SolTrace::Data { SimulationData::SimulationData() : number_of_elements(0), my_elements(1), - my_sources(0) + my_sources(0), + my_optical_property_sets(0) { return; } @@ -232,6 +234,54 @@ uint_fast64_t SimulationData::remove_subelements(element_ptr el) return retval; } +OpticalPropertySetReference SimulationData::add_optical_property_set(const OpticalPropertySet& opt_set) +{ + std::shared_ptr ptr = std::make_shared(opt_set); + const optics_id id = this->my_optical_property_sets.add_item(ptr); + return { id, ptr }; +} + +OpticalPropertySetReference SimulationData::find_or_add_optical_property_set(const OpticalPropertySet& opt_set) +{ + // Check if set already exists + for (auto it = this->get_optics_iterator(); !this->is_optics_at_end(it); ++it) + { + const OpticalPropertySet& existing = *it->second; + if (existing == opt_set) + { + const optics_id id = it->first; + auto ptr = it->second; + return { id, ptr }; + + } + } + + // Add if it doesn't exist + return add_optical_property_set(opt_set); +} + +const OpticalPropertySet* SimulationData::get_optical_property_set(const Element& el) const +{ + return get_optical_property_set(el.get_optical_property_set_id()); +} + +OpticalPropertySet* SimulationData::get_mutable_optical_property_set(const Element& el) +{ + return this->get_optical_property_set(el.get_optical_property_set_id()); +} + +const OpticalPropertySet* SimulationData::get_optical_property_set(optics_id id) const +{ + auto ptr = this->my_optical_property_sets.get_item(id); + return ptr == nullptr ? nullptr : ptr.get(); +} + +OpticalPropertySet* SimulationData::get_optical_property_set(optics_id id) +{ + auto ptr = this->my_optical_property_sets.get_item(id); + return ptr == nullptr ? nullptr : ptr.get(); +} + int SimulationData::update_simulation_positions() { int sts = 0; @@ -283,6 +333,8 @@ void SimulationData::clear(bool reset_parameters) this->my_sources.clear(); this->number_of_elements = 0; + this->my_optical_property_sets.reset(0); + if (reset_parameters) this->my_parameters = SimulationParameters(); // Reset } diff --git a/coretrace/simulation_data/simulation_data.hpp b/coretrace/simulation_data/simulation_data.hpp index d3ceecbe..4f3b7b84 100644 --- a/coretrace/simulation_data/simulation_data.hpp +++ b/coretrace/simulation_data/simulation_data.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include "container.hpp" #include "element.hpp" @@ -27,6 +28,8 @@ namespace SolTrace::Data { class SimulationData { + friend void load_json_file(SimulationData& sd, std::string filename); + public: SimulationData(); virtual ~SimulationData(); @@ -159,6 +162,28 @@ class SimulationData // return citer == this->my_elements.end(); } + OpticalPropertySetReference add_optical_property_set(const OpticalPropertySet& opt_set); + OpticalPropertySetReference find_or_add_optical_property_set(const OpticalPropertySet& opt_set); + + const OpticalPropertySet* get_optical_property_set(const Element& el) const; + OpticalPropertySet* get_mutable_optical_property_set(const Element& el); + + /// @brief Get an iterator that can be used to access all + /// optical property sets owned by this SimulationData object. + /// @return iterator + OpticalPropertySetContainer::iterator get_optics_iterator() + { + return this->my_optical_property_sets.get_iterator(); + } + + /// @brief Tests whether the given iterator is at the end + /// @param iter iterator to test + /// @return true if at end, false otherwise + bool is_optics_at_end(OpticalPropertySetContainer::iterator it) + { + return this->my_optical_property_sets.is_at_end(it); + } + /// @brief Set the number of rays to trace /// @param nrays number of rays to trace void set_number_of_rays(uint_fast64_t nrays) @@ -289,7 +314,8 @@ class SimulationData /// Serializes the current simulation data and writes it to the specified JSON file. void export_json_file(const std::string file_name); - /// @brief Clear elements and ray sources. Designed for use by the file stinput and json file readers when there is an error. + /// @brief Clear elements, ray sources, and optical property sets. + /// Designed for use by the file stinput and json file readers when there is an error. /// @param reset_parameters Optional bool to reset simulation parameters void clear(bool reset_parameters = false); @@ -301,6 +327,7 @@ class SimulationData ElementContainer my_elements; RaySourceContainer my_sources; SimulationParameters my_parameters; + OpticalPropertySetContainer my_optical_property_sets; // void add_single_element(element_id key, element_ptr el); // void add_composite_element(element_id key, element_ptr el); @@ -308,6 +335,9 @@ class SimulationData // uint_fast64_t remove_composite_element(element_ptr el); uint_fast64_t add_subelements(element_ptr el); uint_fast64_t remove_subelements(element_ptr el); + + const OpticalPropertySet* get_optical_property_set(optics_id id) const; + OpticalPropertySet* get_optical_property_set(optics_id id); }; } // namespace SolTrace::Data diff --git a/coretrace/simulation_data/simulation_data_export.hpp b/coretrace/simulation_data/simulation_data_export.hpp index a25e0498..3091d286 100644 --- a/coretrace/simulation_data/simulation_data_export.hpp +++ b/coretrace/simulation_data/simulation_data_export.hpp @@ -18,7 +18,10 @@ using SolTrace::Data::Hexagon; using SolTrace::Data::InteractionType; using SolTrace::Data::IrregularQuadrilateral; using SolTrace::Data::IrregularTriangle; -using SolTrace::Data::OpticalProperties; +using SolTrace::Data::optics_id; +using SolTrace::Data::OpticalPropertySet; +using SolTrace::Data::OpticalPropertySetReference; +using SolTrace::Data::OpticalSide; using SolTrace::Data::Parabola; using SolTrace::Data::Rectangle; using SolTrace::Data::SimulationData; diff --git a/coretrace/simulation_data/simulation_parameters.hpp b/coretrace/simulation_data/simulation_parameters.hpp index 6fb66717..dafeced0 100644 --- a/coretrace/simulation_data/simulation_parameters.hpp +++ b/coretrace/simulation_data/simulation_parameters.hpp @@ -12,6 +12,7 @@ #define SOLTRACE_SIMULATION_PARAMETERS_H #include +#include namespace SolTrace::Data { @@ -43,7 +44,30 @@ struct SimulationParameters include_optical_errors(false) { } + SimulationParameters(const nlohmann::ordered_json& jnode) + { + this->include_sun_shape_errors = jnode.at("include_sun_shape_errors"); + this->include_optical_errors = jnode.at("include_optical_errors"); + this->number_of_rays = jnode.at("number_of_rays"); + this->max_number_of_rays = jnode.at("max_number_of_rays"); + this->tolerance = jnode.at("tolerance"); + this->latitude = jnode.at("latitude"); + this->longitude = jnode.at("longitude"); + this->seed = jnode.at("seed"); + } ~SimulationParameters() {} + + void write_json(nlohmann::ordered_json& jnode) const + { + jnode["include_sun_shape_errors"] = this->include_sun_shape_errors; // bool + jnode["include_optical_errors"] = this->include_optical_errors; // bool + jnode["number_of_rays"] = this->number_of_rays; // int + jnode["max_number_of_rays"] = this->max_number_of_rays; // int + jnode["tolerance"] = this->tolerance; // double + jnode["latitude"] = this->latitude; // double + jnode["longitude"] = this->longitude; // double + jnode["seed"] = this->seed; // int + } }; // TODO: Implement the output stream operator. diff --git a/coretrace/simulation_data/single_element.cpp b/coretrace/simulation_data/single_element.cpp index 7afba808..f4baaf23 100644 --- a/coretrace/simulation_data/single_element.cpp +++ b/coretrace/simulation_data/single_element.cpp @@ -13,24 +13,22 @@ namespace SolTrace::Data { SingleElement::SingleElement() : ElementBase(), aperture(nullptr), surface(nullptr), - optics_front(), - optics_back() + opt_id(OPTICS_ID_UNASSIGNED) { - this->optics_front.set_ideal_absorption(); - this->optics_back.set_ideal_absorption(); return; } -SingleElement::SingleElement(const nlohmann::ordered_json& jnode) : ElementBase(jnode), +SingleElement::SingleElement(const nlohmann::ordered_json& jnode, + const OpticalPropertySetResolver& resolve_optics) : ElementBase(jnode), aperture(nullptr), surface(nullptr), - optics_front(), - optics_back() + opt_id(OPTICS_ID_UNASSIGNED) { this->set_aperture(Aperture::make_aperture_from_json(jnode.at("aperture"))); this->set_surface(make_surface_from_json(jnode.at("surface"))); - this->set_front_optical_properties(OpticalProperties(jnode.at("optics_front"))); - this->set_back_optical_properties(OpticalProperties(jnode.at("optics_back"))); + + const optics_id opt_id = jnode.at("opt_id").get(); + this->set_optical_property_set(resolve_optics(opt_id)); } SingleElement::~SingleElement() @@ -62,6 +60,16 @@ void SingleElement::enforce_user_fields_set() const throw std::invalid_argument(ss.str()); } + if (this->opt_id == OPTICS_ID_UNASSIGNED || + this->get_optical_property_set() == nullptr) + { + std::stringstream ss; + ss << "Element (Name: " << this->get_name() + << ", UUID: " << this->get_id() + << ") has no valid optical property set assigned."; + throw std::invalid_argument(ss.str()); + } + return; } @@ -73,11 +81,7 @@ void SingleElement::write_json(nlohmann::ordered_json& jnode) const this->write_common_json(jnode); // Optical Properties - json joptics_front, joptics_back; - this->optics_front.write_json(joptics_front); - this->optics_back.write_json(joptics_back); - jnode["optics_front"] = joptics_front; - jnode["optics_back"] = joptics_back; + jnode["opt_id"] = this->opt_id; // Aperture json japerture; diff --git a/coretrace/simulation_data/single_element.hpp b/coretrace/simulation_data/single_element.hpp index a8260602..ca80c544 100644 --- a/coretrace/simulation_data/single_element.hpp +++ b/coretrace/simulation_data/single_element.hpp @@ -27,7 +27,8 @@ class SingleElement : public ElementBase { public: SingleElement(); - SingleElement(const nlohmann::ordered_json& jnode); + SingleElement(const nlohmann::ordered_json& jnode, + const OpticalPropertySetResolver& resolve_optics); virtual ~SingleElement(); virtual bool is_single() const override { return true; } @@ -60,21 +61,30 @@ class SingleElement : public ElementBase return; } - const OpticalProperties *get_front_optical_properties() const override + + + optics_id get_optical_property_set_id() const override { - return &(this->optics_front); + return this->opt_id; } - OpticalProperties *get_front_optical_properties() override + + std::shared_ptr get_optical_property_set() const override { - return &(this->optics_front); + return this->optical_property_set.lock(); } - void set_front_optical_properties(const OpticalProperties &op) override + + /*OpticalProperties *get_front_optical_properties() override + { + return &(this->optics_front); + }*/ + void set_optical_property_set(const OpticalPropertySetReference& optics) override { - this->optics_front = op; + this->opt_id = optics.id; + this->optical_property_set = optics.optical_property_set; return; } - const OpticalProperties *get_back_optical_properties() const override + /*const OpticalProperties *get_back_optical_properties() const override { return &(this->optics_back); } @@ -85,7 +95,7 @@ class SingleElement : public ElementBase void set_back_optical_properties(const OpticalProperties &op) override { this->optics_back = op; - } + }*/ virtual void enforce_user_fields_set() const override; @@ -95,8 +105,8 @@ class SingleElement : public ElementBase aperture_ptr aperture; surface_ptr surface; - OpticalProperties optics_front; - OpticalProperties optics_back; + optics_id opt_id = OPTICS_ID_UNASSIGNED; + std::weak_ptr optical_property_set; }; using single_element_ptr = typename std::shared_ptr; diff --git a/coretrace/simulation_data/stage_element.cpp b/coretrace/simulation_data/stage_element.cpp index a64bf120..5e94f3b9 100644 --- a/coretrace/simulation_data/stage_element.cpp +++ b/coretrace/simulation_data/stage_element.cpp @@ -14,7 +14,9 @@ StageElement::StageElement(int_fast64_t stage) : CompositeElement() return; } -StageElement::StageElement(const nlohmann::ordered_json& jnode) : CompositeElement(jnode) +StageElement::StageElement(const nlohmann::ordered_json& jnode, + const OpticalPropertySetResolver& resolve_optics) + : CompositeElement(jnode, resolve_optics) { // Check that it is a stage if (jnode.contains("is_stage") == false || jnode.at("is_stage").get() == false) diff --git a/coretrace/simulation_data/stage_element.hpp b/coretrace/simulation_data/stage_element.hpp index 4f17447c..25c47c6c 100644 --- a/coretrace/simulation_data/stage_element.hpp +++ b/coretrace/simulation_data/stage_element.hpp @@ -21,7 +21,8 @@ class StageElement: public CompositeElement { public: StageElement(int_fast64_t stage); - StageElement(const nlohmann::ordered_json& jnode); + StageElement(const nlohmann::ordered_json& jnode, + const OpticalPropertySetResolver& resolve_optics); ~StageElement(); virtual bool is_stage() const override { return true; } virtual element_id add_element(element_ptr el); diff --git a/coretrace/simulation_data/virtual_element.cpp b/coretrace/simulation_data/virtual_element.cpp index a478efd3..b54bc1de 100644 --- a/coretrace/simulation_data/virtual_element.cpp +++ b/coretrace/simulation_data/virtual_element.cpp @@ -3,22 +3,53 @@ namespace SolTrace::Data { -void VirtualElement::set_virtual_optics(OpticalProperties &op) + +VirtualElement::VirtualElement() + : SingleElement() { - op.my_type = InteractionType::REFRACTION; - op.reflectivity = 0.0; - op.slope_error = 0.0; - op.specularity_error = 0.0; - op.transmitivity = 1.0; - op.refraction_index_front = 1.0; - op.refraction_index_back = 1.0; - return; + auto optics = std::make_shared( + InteractionType::REFRACTION, + 1.0, + 1.0, + "VirtualProp"); + + optics->set_properties( + OpticalSide::Both, + DistributionType::NONE, + 1.0, + 0.0, + 0.0, + 0.0); + + this->owned_optical_property_set = optics; + OpticalPropertySetReference optics_ref = { OPTICS_ID_VIRTUAL, + this->owned_optical_property_set }; + + this->set_optical_property_set(optics_ref); } -VirtualElement::VirtualElement() : SingleElement() +VirtualElement::VirtualElement(const nlohmann::ordered_json& jnode, + const OpticalPropertySetResolver& resolve_optics) : SingleElement(jnode, resolve_optics) { - set_virtual_optics(this->optics_front); - set_virtual_optics(this->optics_back); + auto optics = std::make_shared( + InteractionType::REFRACTION, + 1.0, + 1.0, + "VirtualProp"); + + optics->set_properties( + OpticalSide::Both, + DistributionType::NONE, + 1.0, + 0.0, + 0.0, + 0.0); + + this->owned_optical_property_set = optics; + OpticalPropertySetReference optics_ref = { OPTICS_ID_VIRTUAL, + this->owned_optical_property_set }; + + this->set_optical_property_set(optics_ref); } VirtualElement::~VirtualElement() diff --git a/coretrace/simulation_data/virtual_element.hpp b/coretrace/simulation_data/virtual_element.hpp index 4da0adb6..94982af7 100644 --- a/coretrace/simulation_data/virtual_element.hpp +++ b/coretrace/simulation_data/virtual_element.hpp @@ -18,17 +18,20 @@ namespace SolTrace::Data { class VirtualElement : public SingleElement { public: - static void set_virtual_optics(OpticalProperties &op); - VirtualElement(); + VirtualElement(const nlohmann::ordered_json& jnode, + const OpticalPropertySetResolver& resolve_optics); virtual ~VirtualElement(); virtual bool is_virtual() const override { return true; } - void set_front_optical_properties(const OpticalProperties &op) override {} - void set_back_optical_properties(const OpticalProperties &op) override {} - + //virtual void set_optical_property_set_id(optics_id) override {} + //virtual optics_id get_optical_property_set_id() const override + //{ + // return opt_id; // TODO: return identifier saying it's permanent/virtual + //} private: + std::shared_ptr owned_optical_property_set; }; class VirtualPlane : public VirtualElement diff --git a/coretrace/simulation_runner/embree_runner/trace_embree.cpp b/coretrace/simulation_runner/embree_runner/trace_embree.cpp index d3720dfe..1cb6bc48 100644 --- a/coretrace/simulation_runner/embree_runner/trace_embree.cpp +++ b/coretrace/simulation_runner/embree_runner/trace_embree.cpp @@ -429,7 +429,7 @@ namespace SolTrace::EmbreeRunner } // Get optics and check for absorption - const OpticalProperties *optics = 0; + decltype(&Stage->ElementList[0]->Optics) optics_set = nullptr; RayEvent rev = RayEvent::VIRTUAL; if (Stage->Virtual) { @@ -441,10 +441,7 @@ namespace SolTrace::EmbreeRunner { telement_ptr const& optelm = Stage->ElementList[LastElementNumber - 1]; - if (LastHitBackSide) - optics = &optelm->Optics.Back; - else - optics = &optelm->Optics.Front; + optics_set = &optelm->Optics; bool good; { @@ -454,9 +451,10 @@ namespace SolTrace::EmbreeRunner i, thread_id, myrng, - optics, + optics_set, LastDFXYZ, LastCosRaySurfElement, + LastHitBackSide, rev); // t_determine_interaction += std::chrono::duration_cast( // Clock::now() - _t0).count(); @@ -484,7 +482,8 @@ namespace SolTrace::EmbreeRunner System, myrng, IncludeSunShape, - optics, + optics_set, + LastHitBackSide, IncludeErrors, i, Stage, diff --git a/coretrace/simulation_runner/native_runner/determine_interaction_type.cpp b/coretrace/simulation_runner/native_runner/determine_interaction_type.cpp index 39ce2b6c..0202ae37 100644 --- a/coretrace/simulation_runner/native_runner/determine_interaction_type.cpp +++ b/coretrace/simulation_runner/native_runner/determine_interaction_type.cpp @@ -16,10 +16,10 @@ namespace SolTrace::NativeRunner int_fast64_t stage, unsigned thread_id, MTRand &myrng, - const OpticalProperties *optics, + const OpticalPropertySet *optics, const glm::dvec3 &LastDFXYZ, const glm::dvec3 &LastCosRaySurfElement, - // bool LastHitBackSide, + bool LastHitBackSide, RayEvent &rev) { bool good = true; @@ -28,8 +28,11 @@ namespace SolTrace::NativeRunner double TestValue; auto UnitLastDFXYZ = glm::dvec3{0.0}; double IncidentAngle = 0; + + const OpticalSide side = LastHitBackSide == false ? OpticalSide::Front : OpticalSide::Back; + // TODO: Implement tables... - switch (optics->my_type) + switch (optics->get_interaction_type()) { case InteractionType::REFRACTION: // if (optics->UseTransmissivityTable) @@ -61,7 +64,7 @@ namespace SolTrace::NativeRunner // TestValue = optics->transmitivity; // rev = RayEvent::TRANSMIT; // } - TestValue = optics->transmitivity; + TestValue = optics->get_transmissivity(side); rev = RayEvent::TRANSMIT; break; case InteractionType::REFLECTION: @@ -93,19 +96,19 @@ namespace SolTrace::NativeRunner // TestValue = optics->reflectivity; // rev = RayEvent::REFLECT; // } - TestValue = optics->reflectivity; + TestValue = optics->get_reflectivity(side); rev = RayEvent::REFLECT; break; default: good = false; std::stringstream ss; ss << "Bad optical interaction." - << " Type: " << static_cast(optics->my_type) + << " Type: " << static_cast(optics->get_interaction_type()) << " Stage: " << stage << " Thread: " << thread_id << "\n"; logger->error_log(ss.str()); - break; + return false; } // Apply MonteCarlo probability of absorption. Limited diff --git a/coretrace/simulation_runner/native_runner/determine_interaction_type.hpp b/coretrace/simulation_runner/native_runner/determine_interaction_type.hpp index 95a6e309..692099ac 100644 --- a/coretrace/simulation_runner/native_runner/determine_interaction_type.hpp +++ b/coretrace/simulation_runner/native_runner/determine_interaction_type.hpp @@ -16,10 +16,10 @@ namespace SolTrace::NativeRunner int_fast64_t stage, unsigned thread_id, MTRand &myrng, - const SolTrace::Data::OpticalProperties *optics, + const SolTrace::Data::OpticalPropertySet *optics, glm::dvec3 const& LastDFXYZ, glm::dvec3 const& LastCosRaySurfElement, - // bool LastHitBackSide, + bool LastHitBackSide, SolTrace::Result::RayEvent &rev); } // namespace SolTrace::NativeRunner diff --git a/coretrace/simulation_runner/native_runner/native_runner.cpp b/coretrace/simulation_runner/native_runner/native_runner.cpp index ca6341aa..ad321552 100644 --- a/coretrace/simulation_runner/native_runner/native_runner.cpp +++ b/coretrace/simulation_runner/native_runner/native_runner.cpp @@ -211,9 +211,13 @@ namespace SolTrace::NativeRunner "Element does not match current stage"); } + const auto optics = el->get_optical_property_set(); + if (optics == nullptr) + throw std::runtime_error("Element has invalid optical property set."); telement_ptr elem = make_telement(iter->second, current_stage, - this->eparams); + this->eparams, + *optics); // ++element_number; // current_stage->ElementList.push_back(elem); current_stage->add_element(elem); @@ -244,9 +248,13 @@ namespace SolTrace::NativeRunner element_ptr el = iter->second; if (el->is_enabled() && el->is_single()) { + const auto optics = el->get_optical_property_set(); + if (optics == nullptr) + throw std::runtime_error("Element has invalid optical property set."); telement_ptr tel = make_telement(el, stage, - this->eparams); + this->eparams, + *optics); // stage->ElementList.push_back(tel); // ++element_number; this->check_supported_options(tel); @@ -501,9 +509,9 @@ namespace SolTrace::NativeRunner void NativeRunner::check_supported_options(telement_ptr telem) { check_supported_optical_distribution( - telem->Optics.Front.error_distribution_type); + telem->Optics.get_error_distribution(OpticalSide::Front)); check_supported_optical_distribution( - telem->Optics.Back.error_distribution_type); + telem->Optics.get_error_distribution(OpticalSide::Back)); // TODO: Put other checks here diff --git a/coretrace/simulation_runner/native_runner/native_runner_types.cpp b/coretrace/simulation_runner/native_runner/native_runner_types.cpp index 4d950cfb..5017a0e4 100644 --- a/coretrace/simulation_runner/native_runner/native_runner_types.cpp +++ b/coretrace/simulation_runner/native_runner/native_runner_types.cpp @@ -466,7 +466,8 @@ namespace SolTrace::NativeRunner telement_ptr make_telement(element_ptr el, tstage_ptr my_stage, - const ElementParameters &eparams) + const ElementParameters &eparams, + const SolTrace::Data::OpticalPropertySet& optics) { // std::cout << "Name: " << el->get_name() // << "\nSDID: " << el->get_id() @@ -490,8 +491,7 @@ namespace SolTrace::NativeRunner eparams); // How to handle optical properties? - telem->Optics.Front = *el->get_front_optical_properties(); - telem->Optics.Back = *el->get_back_optical_properties(); + telem->Optics = optics; telem->sim_data_id = el->get_id(); telem->element_number = my_stage->next_element_number(); diff --git a/coretrace/simulation_runner/native_runner/native_runner_types.hpp b/coretrace/simulation_runner/native_runner/native_runner_types.hpp index f5e2d74d..ce315659 100644 --- a/coretrace/simulation_runner/native_runner/native_runner_types.hpp +++ b/coretrace/simulation_runner/native_runner/native_runner_types.hpp @@ -140,15 +140,6 @@ namespace SolTrace::NativeRunner uint_fast64_t newton_max_iters; }; - struct TOpticalPropertySet - { - std::string Name; - // TOpticalProperties Front; - // TOpticalProperties Back; - SolTrace::Data::OpticalProperties Front; - SolTrace::Data::OpticalProperties Back; - }; - // Forward declaration so TElement can have a stage pointer struct TStage; using tstage_ptr = typename std::shared_ptr; @@ -186,7 +177,7 @@ namespace SolTrace::NativeRunner // double CurvOfRev; /////////// OPTICAL PARAMETERS /////////////// - TOpticalPropertySet Optics; + SolTrace::Data::OpticalPropertySet Optics; std::string Comment; // mjw element number in the stage - unique ID in order @@ -199,7 +190,8 @@ namespace SolTrace::NativeRunner using telement_ptr = typename std::shared_ptr; telement_ptr make_telement(SolTrace::Data::element_ptr el, tstage_ptr my_stage, - const ElementParameters &eparams); + const ElementParameters &eparams, + const SolTrace::Data::OpticalPropertySet& optics); struct TSun { diff --git a/coretrace/simulation_runner/native_runner/process_interaction.cpp b/coretrace/simulation_runner/native_runner/process_interaction.cpp index bfd15ee6..bdcfb06c 100644 --- a/coretrace/simulation_runner/native_runner/process_interaction.cpp +++ b/coretrace/simulation_runner/native_runner/process_interaction.cpp @@ -9,103 +9,106 @@ namespace SolTrace::NativeRunner { -void ProcessInteraction( - // system info - TSystem *System, - MTRand &myrng, - const bool IncludeSunShape, - const SolTrace::Data::OpticalProperties *optics, - const bool IncludeErrors, - // stage info - const int i, - // const TStage *Stage, - const tstage_ptr Stage, - // const telement_ptr Elem, - // const int k, - // ray info - const uint_fast64_t MultipleHitCount, - glm::dvec3 &LastDFXYZ, - // Outputs - glm::dvec3 &LastCosRaySurfElement, - int &ErrorFlag, - glm::dvec3 &CosRayOutElement, - glm::dvec3 &LastPosRaySurfElement, - glm::dvec3 &PosRayOutElement) -{ - // Initialize - glm::dvec3 CosIn(0.0, 0.0, 0.0); - glm::dvec3 CosOut(0.0, 0.0, 0.0); - - if (!Stage->Virtual) { - // change to account for first hit only in primary stage 8-11-31 - if (IncludeSunShape && i == 0 && MultipleHitCount == 1) { - // Apply sunshape to UNPERTURBED ray at intersection point - // only apply sunshape error once for primary stage - CosIn = LastCosRaySurfElement; - // sun shape - Errors(myrng, CosIn, 1, &System->Sun, optics, CosOut, LastDFXYZ); - LastCosRaySurfElement = CosOut; - } + void ProcessInteraction( + // system info + TSystem* System, + MTRand& myrng, + const bool IncludeSunShape, + const SolTrace::Data::OpticalPropertySet* optics, + const bool LastHitBackSide, + const bool IncludeErrors, + // stage info + const int i, + // const TStage *Stage, + const tstage_ptr Stage, + // const telement_ptr Elem, + // const int k, + // ray info + const uint_fast64_t MultipleHitCount, + glm::dvec3& LastDFXYZ, + // Outputs + glm::dvec3& LastCosRaySurfElement, + int& ErrorFlag, + glm::dvec3& CosRayOutElement, + glm::dvec3& LastPosRaySurfElement, + glm::dvec3& PosRayOutElement) + { + // Initialize + glm::dvec3 CosIn(0.0, 0.0, 0.0); + glm::dvec3 CosOut(0.0, 0.0, 0.0); + + if (!Stage->Virtual) { + // change to account for first hit only in primary stage 8-11-31 + if (IncludeSunShape && i == 0 && MultipleHitCount == 1) { + // Apply sunshape to UNPERTURBED ray at intersection point + // only apply sunshape error once for primary stage + CosIn = LastCosRaySurfElement; + // sun shape + Errors(myrng, CosIn, 1, &System->Sun, optics, LastHitBackSide, CosOut, LastDFXYZ); + LastCosRaySurfElement = CosOut; + } - //{Determine interaction at surface and direction of perturbed ray} - ErrorFlag = 0; + //{Determine interaction at surface and direction of perturbed ray} + ErrorFlag = 0; + + // {Apply surface normal errors to surface normal before interaction + // ray at intersection point - Wendelin 11-23-09} + if (IncludeErrors) { + CosIn = CosRayOutElement; + // surface normal errors + SurfaceNormalErrors(myrng, LastDFXYZ, optics, LastHitBackSide, CosOut); + // myrng_counter++; + LastDFXYZ = CosOut; + } - // {Apply surface normal errors to surface normal before interaction - // ray at intersection point - Wendelin 11-23-09} - if (IncludeErrors) { - CosIn = CosRayOutElement; - // surface normal errors - SurfaceNormalErrors(myrng, LastDFXYZ, optics, CosOut); + Interaction(myrng, + LastPosRaySurfElement, + LastCosRaySurfElement, + LastDFXYZ, // Stage->ElementList[k]->InteractionType, + optics, + LastHitBackSide, + 630.0, + PosRayOutElement, + CosRayOutElement, + &ErrorFlag); // myrng_counter++; - LastDFXYZ = CosOut; - } - Interaction(myrng, - LastPosRaySurfElement, - LastCosRaySurfElement, - LastDFXYZ, // Stage->ElementList[k]->InteractionType, + // {Apply specularity optical error to PERTURBED (i.e. after + // interaction) ray at intersection point} + if (IncludeErrors) { + // if (optics->error_distribution_type == 'F' || + // optics->error_distribution_type == 'f') + // { + // // Apply diffuse errors relative to surface normal + // CopyVec3(CosIn, LastDFXYZ); + // } + // else + // { + // // Apply all other errors relative to the specularly-reflected + // // direction + // CopyVec3(CosIn, CosRayOutElement); + // } + + // TODO: Not sure what error distribution type 'F' is? + // Do we need to implement it? For now just use the 'else' + // clause from the above. + CosIn = CosRayOutElement; + + // optical errors + Errors(myrng, + CosIn, + 2, + &System->Sun, + // Stage->ElementList[k].get(), optics, - 630.0, - PosRayOutElement, - CosRayOutElement, - &ErrorFlag); - // myrng_counter++; - - // {Apply specularity optical error to PERTURBED (i.e. after - // interaction) ray at intersection point} - if (IncludeErrors) { - // if (optics->error_distribution_type == 'F' || - // optics->error_distribution_type == 'f') - // { - // // Apply diffuse errors relative to surface normal - // CopyVec3(CosIn, LastDFXYZ); - // } - // else - // { - // // Apply all other errors relative to the specularly-reflected - // // direction - // CopyVec3(CosIn, CosRayOutElement); - // } - - // TODO: Not sure what error distribution type 'F' is? - // Do we need to implement it? For now just use the 'else' - // clause from the above. - CosIn = CosRayOutElement; - - // optical errors - Errors(myrng, - CosIn, - 2, - &System->Sun, - // Stage->ElementList[k].get(), - optics, - CosOut, - LastDFXYZ); - // myrng_counter++; - CosRayOutElement = CosOut; + LastHitBackSide, + CosOut, + LastDFXYZ); + // myrng_counter++; + CosRayOutElement = CosOut; + } } } - } inline double sqr(double x) { return (x) * (x); } @@ -113,7 +116,8 @@ void ProcessInteraction( const glm::dvec3 &PosXYZ, const glm::dvec3 &CosKLM, const glm::dvec3 &DFXYZ, - const SolTrace::Data::OpticalProperties *Opticl, + const SolTrace::Data::OpticalPropertySet *Opticl, + const bool LastHitBackSide, double Wavelength, glm::dvec3 &PosOut, glm::dvec3 &CosOut, @@ -185,7 +189,7 @@ void ProcessInteraction( PosOut = PosXYZ; - switch (Opticl->my_type) + switch (Opticl->get_interaction_type()) { /*{ InteractionType = 1, Refraction @@ -196,8 +200,21 @@ void ProcessInteraction( // as the commented out bit immediately below. // Refr1 = Opticl->RefractiveIndex[0]; // Refr2 = Opticl->RefractiveIndex[2]; - Refr1 = Opticl->refraction_index_front; - Refr2 = Opticl->refraction_index_back; + + double refrac_front, refrac_back; + Opticl->get_refraction_indices(refrac_front, refrac_back); + + if (!LastHitBackSide) + { + Refr1 = refrac_front; + Refr2 = refrac_back; + } + else + { + Refr1 = refrac_back; + Refr2 = refrac_front; + } + RMU = Refr1 / Refr2; D2 = glm::dot(DFXYZ, DFXYZ); B = (RMU * RMU - 1.0) / D2; diff --git a/coretrace/simulation_runner/native_runner/process_interaction.hpp b/coretrace/simulation_runner/native_runner/process_interaction.hpp index c1625998..076b95f1 100644 --- a/coretrace/simulation_runner/native_runner/process_interaction.hpp +++ b/coretrace/simulation_runner/native_runner/process_interaction.hpp @@ -15,7 +15,8 @@ void ProcessInteraction( TSystem* System, MTRand& myrng, const bool IncludeSunShape, - const SolTrace::Data::OpticalProperties* optics, + const SolTrace::Data::OpticalPropertySet* optics, + const bool LastHitBackSide, const bool IncludeErrors, // stage info const int i, @@ -37,7 +38,8 @@ void Interaction(MTRand& myrng, const glm::dvec3& PosXYZ, const glm::dvec3& CosKLM, const glm::dvec3& DFXYZ, - const SolTrace::Data::OpticalProperties* Opticl, + const SolTrace::Data::OpticalPropertySet* Opticl, + const bool LastHitBackSide, double Wavelength, glm::dvec3& PosOut, glm::dvec3& CosOut, diff --git a/coretrace/simulation_runner/native_runner/trace.cpp b/coretrace/simulation_runner/native_runner/trace.cpp index dc1775ad..214b58b1 100644 --- a/coretrace/simulation_runner/native_runner/trace.cpp +++ b/coretrace/simulation_runner/native_runner/trace.cpp @@ -377,7 +377,7 @@ namespace SolTrace::NativeRunner } // Get optics and check for absorption - const OpticalProperties *optics = 0; + const OpticalPropertySet *optics_set = 0; RayEvent rev = RayEvent::VIRTUAL; if (Stage->Virtual) { @@ -391,19 +391,17 @@ namespace SolTrace::NativeRunner telement_ptr optelm = Stage->ElementList[LastElementNumber - 1]; - if (LastHitBackSide) - optics = &optelm->Optics.Back; - else - optics = &optelm->Optics.Front; + optics_set = &optelm->Optics; bool good = determine_interaction_type( logger, i, 0, myrng, - optics, + optics_set, LastDFXYZ, LastCosRaySurfElement, + LastHitBackSide, rev); if (!good) @@ -423,7 +421,8 @@ namespace SolTrace::NativeRunner ProcessInteraction(System, myrng, IncludeSunShape, - optics, + optics_set, + LastHitBackSide, IncludeErrors, i, Stage, diff --git a/coretrace/simulation_runner/native_runner/tracing_errors.cpp b/coretrace/simulation_runner/native_runner/tracing_errors.cpp index 485620d2..62c5eb3e 100644 --- a/coretrace/simulation_runner/native_runner/tracing_errors.cpp +++ b/coretrace/simulation_runner/native_runner/tracing_errors.cpp @@ -20,7 +20,8 @@ namespace SolTrace::NativeRunner { void SurfaceNormalErrors(MTRand &myrng, glm::dvec3 &CosIn, - const SolTrace::Data::OpticalProperties *OptProperties, + const SolTrace::Data::OpticalPropertySet* OptProperties, + const bool LastHitBackSide, glm::dvec3 &CosOut) noexcept(false) // throw(nanexcept) { @@ -36,6 +37,8 @@ void SurfaceNormalErrors(MTRand &myrng, int i = 0; + const OpticalSide side = LastHitBackSide == false ? OpticalSide::Front : OpticalSide::Back; + glm::dvec3 Origin(0.0, 0.0, 0.0); glm::dvec3 Euler(0.0, 0.0, 0.0); @@ -68,9 +71,9 @@ void SurfaceNormalErrors(MTRand &myrng, // TODO: Add distribution type to optical properties // dist = OptProperties->DistributionType; - dist = OptProperties->error_distribution_type; + dist = OptProperties->get_error_distribution(side); // delop = OptProperties->RMSSlopeError / 1000.0; - delop = OptProperties->slope_error / 1000.0; + delop = OptProperties->get_slope_error(side) / 1000.0; switch (dist) { @@ -125,7 +128,8 @@ void Errors( TSun* Sun, // TElement *Element, // TOpticalProperties *OptProperties, - const SolTrace::Data::OpticalProperties* OptProperties, + const SolTrace::Data::OpticalPropertySet* OptProperties, + const bool LastHitBackSide, glm::dvec3& CosOut, glm::dvec3& DFXYZ) { @@ -152,6 +156,8 @@ void Errors( glm::dvec3 PosIn(0.0, 0.0, 0.0); glm::dvec3 PosOut(0.0, 0.0, 0.0); + const OpticalSide side = LastHitBackSide == false ? OpticalSide::Front : OpticalSide::Back; + // char dist = 'g'; double delop = 0.0, thetax = 0.0, thetay = 0.0, theta2 = 0.0, phi = 0.0, theta = 0.0, stest = 0.0; uint_fast64_t i; @@ -264,10 +270,10 @@ void Errors( { // dist = OptProperties->DistributionType; // errors // // delop = sqrt(4.0*sqr(OptProperties->RMSSlopeError)+sqr(OptProperties->RMSSpecError))/1000.0; - delop = OptProperties->specularity_error; + delop = OptProperties->get_specularity_error(side); Label_50: - switch (OptProperties->error_distribution_type) + switch (OptProperties->get_error_distribution(side)) { case DistributionType::GAUSSIAN: // case 'g': thetax = myrng.randNorm(0., delop); @@ -324,7 +330,7 @@ void Errors( /*{If reflection error application and new ray direction (after errors) physically goes through opaque surface, then go back and get new perturbation 06-12-07}*/ if ((Source == 2) && - (OptProperties->my_type == InteractionType::REFLECTION) && + (OptProperties->get_interaction_type() == InteractionType::REFLECTION) && (glm::dot(CosOut, DFXYZ) < 0) && maxcall++ < 50000) { diff --git a/coretrace/simulation_runner/native_runner/tracing_errors.hpp b/coretrace/simulation_runner/native_runner/tracing_errors.hpp index cdb2ee42..5c426668 100644 --- a/coretrace/simulation_runner/native_runner/tracing_errors.hpp +++ b/coretrace/simulation_runner/native_runner/tracing_errors.hpp @@ -14,13 +14,15 @@ void Errors(MTRand& myrng, TSun* Sun, // TElement *Element, // TOpticalProperties *OptProperties, - const SolTrace::Data::OpticalProperties* OptProperties, + const SolTrace::Data::OpticalPropertySet* OptProperties, + const bool LastHitBackSide, glm::dvec3& CosOut, glm::dvec3& DFXYZ); void SurfaceNormalErrors(MTRand& myrng, glm::dvec3& CosIn, - const SolTrace::Data::OpticalProperties* OptProperties, + const SolTrace::Data::OpticalPropertySet* OptProperties, + const bool LastHitBackSide, glm::dvec3& CosOut) noexcept(false); // throw(nanexcept); diff --git a/coretrace/simulation_runner/optix_runner/optix_runner.cpp b/coretrace/simulation_runner/optix_runner/optix_runner.cpp index 532638a6..61136def 100644 --- a/coretrace/simulation_runner/optix_runner/optix_runner.cpp +++ b/coretrace/simulation_runner/optix_runner/optix_runner.cpp @@ -2,6 +2,7 @@ #include "simulation_data/simulation_data_export.hpp" #include +#include #include #include @@ -10,6 +11,8 @@ using SolTrace::Runner::SimulationRunner; using SolTrace::Result::SimulationResult; +using SolTrace::Data::optics_id; + OptixRunner::OptixRunner() : SimulationRunner(), m_simdata(nullptr), m_sys() {} @@ -188,15 +191,28 @@ RunnerStatus OptixRunner::setup_elements(const SimulationData *data) optix_el->set_id(static_cast(id)); // Add optical properties - OpticalProperties *opt_front = el->get_front_optical_properties(); - OptixCSP::OpticalDistribution od = this->to_optical_distribution(opt_front->error_distribution_type); - optix_el->set_optics_front(opt_front->my_type == InteractionType::REFRACTION, opt_front->reflectivity, - opt_front->transmitivity, opt_front->slope_error, opt_front->specularity_error, od); - - OpticalProperties *opt_back = el->get_back_optical_properties(); - od = this->to_optical_distribution(opt_back->error_distribution_type); - optix_el->set_optics_back(opt_back->my_type == InteractionType::REFRACTION, opt_back->reflectivity, - opt_back->transmitivity, opt_back->slope_error, opt_back->specularity_error, od); + auto opt_set = el->get_optical_property_set(); + + if (opt_set == nullptr) + throw std::runtime_error("Element has invalid optical property set."); + + DistributionType front_dist; + double front_slope, front_spec; + opt_set->get_errors(OpticalSide::Front, front_dist, front_slope, front_spec); + + OptixCSP::OpticalDistribution front_dist_optix = this->to_optical_distribution(front_dist); + optix_el->set_optics_front(opt_set->get_interaction_type() == InteractionType::REFRACTION, + opt_set->get_reflectivity(OpticalSide::Front), opt_set->get_transmissivity(OpticalSide::Front), + front_slope, front_spec, front_dist_optix); + + DistributionType back_dist; + double back_slope, back_spec; + opt_set->get_errors(OpticalSide::Back, back_dist, back_slope, back_spec); + + OptixCSP::OpticalDistribution back_dist_optix = this->to_optical_distribution(back_dist); + optix_el->set_optics_back(opt_set->get_interaction_type() == InteractionType::REFRACTION, + opt_set->get_reflectivity(OpticalSide::Back), opt_set->get_transmissivity(OpticalSide::Back), + back_slope, back_spec, back_dist_optix); if (m_sys.is_verbose()) { diff --git a/google-tests/regression-tests/native_runner_multithreading_performance_test.cpp b/google-tests/regression-tests/native_runner_multithreading_performance_test.cpp index 03a0f1bf..9edb2bc9 100644 --- a/google-tests/regression-tests/native_runner_multithreading_performance_test.cpp +++ b/google-tests/regression-tests/native_runner_multithreading_performance_test.cpp @@ -1,5 +1,6 @@ #include +#include #include #include @@ -10,6 +11,8 @@ #include "common.hpp" +using SolTrace::Result::RayEvent; + TEST(NativeRunner, Multithreading) { const uint_fast64_t NRAYS = 50000; diff --git a/google-tests/regression-tests/native_runner_performance_test.cpp b/google-tests/regression-tests/native_runner_performance_test.cpp index 6d5e5e1e..bf7134f0 100644 --- a/google-tests/regression-tests/native_runner_performance_test.cpp +++ b/google-tests/regression-tests/native_runner_performance_test.cpp @@ -55,8 +55,15 @@ TEST(NativeRunner, PerformanceTest) my_runner.enable_power_tower(); my_runner.enable_point_focus(); - OpticalProperties mirror; - mirror.set_ideal_reflection(); + SolTrace::Data::OpticalPropertySet mirror_optics(SolTrace::Data::InteractionType::REFLECTION, "Mirror"); + mirror_optics.set_ideal_reflection(SolTrace::Data::OpticalSide::Front); + mirror_optics.set_ideal_absorption(SolTrace::Data::OpticalSide::Back); + mirror_optics.set_errors(SolTrace::Data::OpticalSide::Front, SolTrace::Data::DistributionType::NONE, 0.0, 0.0); + auto mirror_optics_ref = sdata.add_optical_property_set(mirror_optics); + + SolTrace::Data::OpticalPropertySet absorber_optics(SolTrace::Data::InteractionType::REFLECTION, "Absorber"); + absorber_optics.set_ideal_absorption(SolTrace::Data::OpticalSide::Both); + auto absorber_optics_ref = sdata.add_optical_property_set(absorber_optics); stage_ptr st1 = make_stage(1); st1->set_reference_frame_geometry(zero, khat, 0.0); @@ -90,7 +97,7 @@ TEST(NativeRunner, PerformanceTest) // vector_add(1.0, hs_origin, 1.0, aim, aim_point); auto hs = make_element(); - hs->set_mirror_optics(mirror); + hs->set_optics(mirror_optics_ref); // hs->set_reference_frame_geometry(hs_origin, aim, 0.0); hs->set_origin(hs_origin); hs->set_aperture_size(2.0 * dx, 2.0 * dy); @@ -119,8 +126,7 @@ TEST(NativeRunner, PerformanceTest) } auto absorb = make_element(); - absorb->get_front_optical_properties()->set_ideal_absorption(); - absorb->get_back_optical_properties()->set_ideal_absorption(); + absorb->set_optical_property_set(absorber_optics_ref); absorb->set_aperture(make_aperture(2.0 * ABS_RADIUS)); absorb->set_surface(make_surface(1.0 / ABS_RADIUS)); // absorb->set_surface(make_surface()); diff --git a/google-tests/unit-tests/common/common.cpp b/google-tests/unit-tests/common/common.cpp index efa53391..b5d6f66c 100644 --- a/google-tests/unit-tests/common/common.cpp +++ b/google-tests/unit-tests/common/common.cpp @@ -3,6 +3,7 @@ #include +#include #include #include #include @@ -50,11 +51,18 @@ bool is_identical(const glm::dmat3 &A, const glm::dmat3 &B) return check; } -element_ptr make_configured_element() +element_ptr make_configured_element(SimulationData& sd) { + OpticalPropertySet opt_set(InteractionType::REFLECTION, "test_optics"); + opt_set.set_ideal_reflection(OpticalSide::Both); + opt_set.set_errors(OpticalSide::Both, DistributionType::NONE, 0.0, 0.0); + auto optics_ref = sd.find_or_add_optical_property_set(opt_set); + element_ptr el = SolTrace::Data::make_element(); el->set_aperture(SolTrace::Data::make_aperture(2.0)); el->set_surface(SolTrace::Data::make_surface()); + el->set_optical_property_set(optics_ref); + return el; } diff --git a/google-tests/unit-tests/common/common.hpp b/google-tests/unit-tests/common/common.hpp index b7155644..0f1632a0 100644 --- a/google-tests/unit-tests/common/common.hpp +++ b/google-tests/unit-tests/common/common.hpp @@ -18,7 +18,7 @@ bool is_identical(const glm::dmat3 &A, // Convenience function for making element with all // required fields are set. Used when the test does not // care about the specifics of the element. -SolTrace::Data::element_ptr make_configured_element(); +SolTrace::Data::element_ptr make_configured_element(SimulationData& sd); // Helper functions to create surfaces inline std::shared_ptr create_cylinder_surface(double radius = 1.0) diff --git a/google-tests/unit-tests/simulation_data/CMakeLists.txt b/google-tests/unit-tests/simulation_data/CMakeLists.txt index 2b972c37..995c85a3 100644 --- a/google-tests/unit-tests/simulation_data/CMakeLists.txt +++ b/google-tests/unit-tests/simulation_data/CMakeLists.txt @@ -17,16 +17,17 @@ add_subdirectory(cst-templates) # Add test files for simulation_data set(SIMULATION_DATA_TEST_SRC ../common/common.cpp - linear_algebra_test.cpp - utilities_test.cpp aperture_test.cpp surface_test.cpp container_test.cpp element_test.cpp + file_io_test.cpp + linear_algebra_test.cpp + optical_properties_test.cpp simulation_data_test.cpp sun_position_test.cpp sun_test.cpp - file_io_test.cpp + utilities_test.cpp ) add_executable(SimulationDataUnitTests diff --git a/google-tests/unit-tests/simulation_data/cst-templates/heliostat_field_test_template.hpp b/google-tests/unit-tests/simulation_data/cst-templates/heliostat_field_test_template.hpp index fb44af0c..e100ed9e 100644 --- a/google-tests/unit-tests/simulation_data/cst-templates/heliostat_field_test_template.hpp +++ b/google-tests/unit-tests/simulation_data/cst-templates/heliostat_field_test_template.hpp @@ -144,8 +144,11 @@ class HeliostatFieldSimulationHelper { // Initial setup of receiver receiver = SolTrace::Data::make_element(); - receiver->get_front_optical_properties()->set_ideal_absorption(); - receiver->get_back_optical_properties()->set_ideal_reflection(); + SolTrace::Data::OpticalPropertySet receiver_opt_set(SolTrace::Data::InteractionType::REFLECTION, "ReceiverOptics"); + receiver_opt_set.set_ideal_absorption(SolTrace::Data::OpticalSide::Front); + receiver_opt_set.set_ideal_reflection(SolTrace::Data::OpticalSide::Back); + auto receiver_ref = simData.add_optical_property_set(receiver_opt_set); + receiver->set_optical_property_set(receiver_ref); receiver->set_aperture(SolTrace::Data::make_aperture(rec_radius * 2.0, rec_height)); receiver->set_surface(SolTrace::Data::make_surface(rec_radius)); glm::dvec3 offset = {0.0, 0.0, 0.0}; @@ -157,8 +160,11 @@ class HeliostatFieldSimulationHelper { receiver->enable(); top_heat_shield = SolTrace::Data::make_element(); - top_heat_shield->get_front_optical_properties()->set_ideal_absorption(); - top_heat_shield->get_back_optical_properties()->set_ideal_reflection(); + SolTrace::Data::OpticalPropertySet top_heat_shield_opt_set(SolTrace::Data::InteractionType::REFLECTION, "TopHeatShieldOptics"); + top_heat_shield_opt_set.set_ideal_absorption(SolTrace::Data::OpticalSide::Front); + top_heat_shield_opt_set.set_ideal_reflection(SolTrace::Data::OpticalSide::Back); + auto top_heat_shield_ref = simData.add_optical_property_set(top_heat_shield_opt_set); + top_heat_shield->set_optical_property_set(top_heat_shield_ref); top_heat_shield->set_aperture(SolTrace::Data::make_aperture(rec_radius * 2.0, rec_heat_shield_height)); top_heat_shield->set_surface(SolTrace::Data::make_surface(rec_radius)); offset = { 0.0, 0.0, (rec_height + rec_heat_shield_height)/2.}; @@ -169,8 +175,11 @@ class HeliostatFieldSimulationHelper { top_heat_shield->enable(); bottom_heat_shield = SolTrace::Data::make_element(); - bottom_heat_shield->get_front_optical_properties()->set_ideal_absorption(); - bottom_heat_shield->get_back_optical_properties()->set_ideal_reflection(); + SolTrace::Data::OpticalPropertySet bottom_heat_shield_opt_set(SolTrace::Data::InteractionType::REFLECTION, "BottomHeatShieldOptics"); + bottom_heat_shield_opt_set.set_ideal_absorption(SolTrace::Data::OpticalSide::Front); + bottom_heat_shield_opt_set.set_ideal_reflection(SolTrace::Data::OpticalSide::Back); + auto bottom_heat_shield_ref = simData.add_optical_property_set(bottom_heat_shield_opt_set); + bottom_heat_shield->set_optical_property_set(bottom_heat_shield_ref); bottom_heat_shield->set_aperture(SolTrace::Data::make_aperture(rec_radius * 2.0, rec_heat_shield_height)); bottom_heat_shield->set_surface(SolTrace::Data::make_surface(rec_radius)); offset = { 0.0, 0.0, -(rec_height + rec_heat_shield_height) / 2. }; @@ -200,15 +209,12 @@ class HeliostatFieldSimulationHelper { void create_heliostat_field() { // Define mirror optical properties - OpticalProperties mirror; - mirror.set_ideal_reflection(); - mirror.reflectivity = 0.9; - mirror.slope_error = 2.0; // mrad - mirror.specularity_error = 0.0; // mrad - mirror.error_distribution_type = DistributionType::GAUSSIAN; - // Backside is absorbing - OpticalProperties mirror_back; - mirror_back.set_ideal_absorption(); + SolTrace::Data::OpticalPropertySet mirror_opt_set(SolTrace::Data::InteractionType::REFLECTION, "HeliostatMirrorOptics"); + mirror_opt_set.set_reflectivity(SolTrace::Data::OpticalSide::Front, 0.9); + mirror_opt_set.set_ideal_absorption(SolTrace::Data::OpticalSide::Back); + mirror_opt_set.set_errors(SolTrace::Data::OpticalSide::Front, SolTrace::Data::DistributionType::GAUSSIAN, 2.0, 0.0); + mirror_opt_set.set_errors(SolTrace::Data::OpticalSide::Back, SolTrace::Data::DistributionType::NONE, 0.0, 0.0); + auto mirror_ref = simData.add_optical_property_set(mirror_opt_set); // Reading in field layout and aimpoints std::vector x_coords; @@ -246,7 +252,7 @@ class HeliostatFieldSimulationHelper { for (size_t i = 0; i < x_coords.size(); i++) { glm::dvec3 heliostat_origin(x_coords[i], y_coords[i], 4.49); auto heliostat = SolTrace::Data::make_element(); - heliostat->set_optics(mirror, mirror_back); + heliostat->set_optics(mirror_ref); heliostat->set_reference_frame_geometry(heliostat_origin, khat, 0.0); heliostat->set_aperture_size(10.38, 9.73); // Width, Height heliostat->set_number_panels(1, 1); diff --git a/google-tests/unit-tests/simulation_data/cst-templates/heliostat_test.cpp b/google-tests/unit-tests/simulation_data/cst-templates/heliostat_test.cpp index 807a2af3..166001b8 100644 --- a/google-tests/unit-tests/simulation_data/cst-templates/heliostat_test.cpp +++ b/google-tests/unit-tests/simulation_data/cst-templates/heliostat_test.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -117,7 +118,12 @@ TEST(Heliostat, ErrorChecking_SetCanting) TEST(Heliostat, ErrorChecking_CreateGeometryWithoutParameters) { + SimulationData sd; + auto optics = OpticalPropertySet(); + auto optics_ref = sd.add_optical_property_set(optics); + auto hs = SolTrace::Data::make_element(); + hs->set_optics(optics_ref); // Test create_geometry without setting required parameters EXPECT_THROW(hs->create_geometry(), std::invalid_argument); @@ -147,11 +153,12 @@ TEST(Heliostat, ErrorChecking_CreateGeometryWithoutParameters) TEST(Heliostat, BuildParabolaNone) { - OpticalProperties mirror; - mirror.set_ideal_reflection(); + SimulationData sd; + auto optics = OpticalPropertySet(); + auto optics_ref = sd.add_optical_property_set(optics); auto hs = SolTrace::Data::make_element(); - hs->set_mirror_optics(mirror); + hs->set_optics(optics_ref); hs->set_origin(1.0, 1.0, 0.0); hs->set_aim_vector(0.0, 0.0, 100.0); hs->set_aperture_size(12.0, 12.0); @@ -168,11 +175,12 @@ TEST(Heliostat, BuildParabolaNone) TEST(Heliostat, BuildFlatOnAxis) { - OpticalProperties mirror; - mirror.set_ideal_reflection(); + SimulationData sd; + auto optics = OpticalPropertySet(); + auto optics_ref = sd.add_optical_property_set(optics); auto hs = SolTrace::Data::make_element(); - hs->set_mirror_optics(mirror); + hs->set_optics(optics_ref); hs->set_origin(1.0, 1.0, 0.0); hs->set_aim_vector(0.0, 0.0, 100.0); hs->set_aperture_size(12.0, 12.0); @@ -207,8 +215,10 @@ TEST(Heliostat, Trace) my_runner.disable_power_tower(); my_runner.enable_point_focus(); - OpticalProperties mirror; - mirror.set_ideal_reflection(); + SolTrace::Data::OpticalPropertySet hs_opt_set(InteractionType::REFLECTION, "HeliostatMirror"); + hs_opt_set.set_ideal_reflection(SolTrace::Data::OpticalSide::Both); + hs_opt_set.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::GAUSSIAN, 0.0, 0.0); + auto hs_ref = my_sim.add_optical_property_set(hs_opt_set); stage_ptr st1 = SolTrace::Data::make_stage(1); st1->set_reference_frame_geometry(zero, khat, 0.0); @@ -225,7 +235,8 @@ TEST(Heliostat, Trace) glm::dvec3 aim_point = hs_origin + aim; auto hs = SolTrace::Data::make_element(); - hs->set_mirror_optics(mirror); + hs->set_optics(hs_ref); + // hs->set_origin(hs_origin); // hs->set_aim_vector(0.0, 0.0, 2.0); // hs->set_zrot(0.0); @@ -245,9 +256,12 @@ TEST(Heliostat, Trace) auto ret = st1->add_element(hs); EXPECT_TRUE(SolTrace::Data::Element::is_success(ret)); + SolTrace::Data::OpticalPropertySet ab_opt_set(InteractionType::REFLECTION, "Absorber"); + ab_opt_set.set_ideal_absorption(SolTrace::Data::OpticalSide::Both); + auto ab_ref = my_sim.add_optical_property_set(ab_opt_set); + auto absorb = SolTrace::Data::make_element(); - absorb->get_front_optical_properties()->set_ideal_absorption(); - absorb->get_back_optical_properties()->set_ideal_absorption(); + absorb->set_optical_property_set(ab_ref); absorb->set_aperture(SolTrace::Data::make_aperture(5.0, 5.0)); absorb->set_surface(SolTrace::Data::make_surface()); // absorb->set_origin(abs_origin); @@ -349,8 +363,10 @@ TEST(Heliostat, TraceOffAxisCanting) my_runner.disable_power_tower(); my_runner.disable_point_focus(); - OpticalProperties mirror; - mirror.set_ideal_reflection(); + SolTrace::Data::OpticalPropertySet hs_opt_set(SolTrace::Data::InteractionType::REFLECTION, "HeliostatMirror"); + hs_opt_set.set_ideal_reflection(SolTrace::Data::OpticalSide::Both); + hs_opt_set.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::GAUSSIAN, 0.0, 0.0); + auto hs_ref = my_sim.add_optical_property_set(hs_opt_set); stage_ptr st1 = SolTrace::Data::make_stage(1); st1->set_reference_frame_geometry(zero, khat, 0.0); @@ -363,7 +379,7 @@ TEST(Heliostat, TraceOffAxisCanting) double canting_zenith = 90.0; auto hs = SolTrace::Data::make_element(); - hs->set_mirror_optics(mirror); + hs->set_optics(hs_ref); hs->set_reference_frame_geometry(hs_origin, khat, 0.0); hs->set_aperture_size(12.0, 8.0); hs->set_number_panels(5, 5); @@ -379,9 +395,12 @@ TEST(Heliostat, TraceOffAxisCanting) auto ret = st1->add_element(hs); EXPECT_TRUE(SolTrace::Data::Element::is_success(ret)); + SolTrace::Data::OpticalPropertySet ab_opt_set(SolTrace::Data::InteractionType::REFLECTION, "Absorber"); + ab_opt_set.set_ideal_absorption(SolTrace::Data::OpticalSide::Both); + auto ab_ref = my_sim.add_optical_property_set(ab_opt_set); + auto absorb = SolTrace::Data::make_element(); - absorb->get_front_optical_properties()->set_ideal_absorption(); - absorb->get_back_optical_properties()->set_ideal_absorption(); + absorb->set_optical_property_set(ab_ref); absorb->set_aperture(SolTrace::Data::make_aperture(10.0, 10.0)); // TODO: Set a tight aperture (2.35, 1.55) absorb->set_surface(SolTrace::Data::make_surface()); glm::dvec3 v1 = {0.0, 1.0, 0.0}; @@ -462,8 +481,9 @@ TEST(Heliostat, TraceOffAxisCanting) TEST(Heliostat, ErrorChecking_UpdateGeometry) { - OpticalProperties mirror; - mirror.set_ideal_reflection(); + SimulationData sd; + auto optics = OpticalPropertySet(); + auto optics_ref = sd.add_optical_property_set(optics); glm::dvec3 sun_pos(0.0, 0.0, 1000.0); glm::dvec3 hs_origin(1.0, 1.0, 0.0); @@ -474,7 +494,8 @@ TEST(Heliostat, ErrorChecking_UpdateGeometry) glm::dvec3 aim_point = hs_origin + aim; auto hs = SolTrace::Data::make_element(); - hs->set_mirror_optics(mirror); + //hs->set_optics_id(SolTrace::Data::OPTICS_ID_VIRTUAL); + //hs->set_mirror_optics(mirror); // hs->set_origin(hs_origin); // hs->set_aim_vector(0.0, 0.0, 2.0); // hs->set_zrot(0.0); @@ -487,6 +508,7 @@ TEST(Heliostat, ErrorChecking_UpdateGeometry) hs->set_focal_length(0.0); hs->set_canting(Heliostat::NONE, 0.0, 0.0); hs->set_target_position(abs_origin); + hs->set_optics(optics_ref); EXPECT_THROW(hs->update_geometry(10.0, -10.0), std::invalid_argument); EXPECT_THROW(hs->update_geometry(10.0, 100.0), std::invalid_argument); @@ -523,8 +545,9 @@ TEST(Heliostat, UpdateGeometry) my_runner.disable_power_tower(); my_runner.enable_point_focus(); - OpticalProperties mirror; - mirror.set_ideal_reflection(); + SolTrace::Data::OpticalPropertySet hs_opt_set(InteractionType::REFLECTION, 0, 0); + hs_opt_set.set_properties(OpticalSide::Both, DistributionType::GAUSSIAN, 0, 1, 0, 0); + auto hs_ref = my_sim.add_optical_property_set(hs_opt_set); glm::dvec3 sun_pos; SolTrace::Data::sun_position_vector_degrees(sun_pos, sun_az, sun_el); @@ -532,7 +555,7 @@ TEST(Heliostat, UpdateGeometry) glm::dvec3 abs_origin(0.0, 0.0, 2.0); auto hs = SolTrace::Data::make_element(); - hs->set_mirror_optics(mirror); + hs->set_optics(hs_ref); hs->set_origin(1.0, 1.0, 0.0); hs->set_aperture_size(12.0, 12.0); hs->set_number_panels(3, 4); @@ -560,8 +583,11 @@ TEST(Heliostat, UpdateGeometry) // TODO: Test for correct z-rotation... auto absorb = SolTrace::Data::make_element(); - absorb->get_front_optical_properties()->set_ideal_absorption(); - absorb->get_back_optical_properties()->set_ideal_absorption(); + SolTrace::Data::OpticalPropertySet ab_opt_set(InteractionType::REFLECTION); + ab_opt_set.set_ideal_absorption(OpticalSide::Both); + auto ab_ref = my_sim.add_optical_property_set(ab_opt_set); + + absorb->set_optical_property_set(ab_ref); absorb->set_aperture(SolTrace::Data::make_aperture(5.0, 5.0)); absorb->set_surface(SolTrace::Data::make_surface()); // absorb->set_origin(abs_origin); diff --git a/google-tests/unit-tests/simulation_data/cst-templates/linear_fresnel_test.cpp b/google-tests/unit-tests/simulation_data/cst-templates/linear_fresnel_test.cpp index a8a7cf39..2d79da0c 100644 --- a/google-tests/unit-tests/simulation_data/cst-templates/linear_fresnel_test.cpp +++ b/google-tests/unit-tests/simulation_data/cst-templates/linear_fresnel_test.cpp @@ -2,7 +2,9 @@ #include #include +#include #include +#include #include #include #include @@ -125,7 +127,12 @@ TEST(LinearFresnel, ErrorChecking_SetReceiverDimensions) TEST(LinearFresnel, ErrorChecking_CreateGeometryWithoutParameters) { + SimulationData sd; + auto optics = OpticalPropertySet(); + auto optics_ref = sd.add_optical_property_set(optics); + auto lf = SolTrace::Data::make_element(); + lf->set_optics(optics_ref, optics_ref, optics_ref, optics_ref); // Test create_geometry without setting required parameters EXPECT_THROW(lf->create_geometry(), std::invalid_argument); @@ -149,24 +156,28 @@ TEST(LinearFresnel, ErrorChecking_CreateGeometryWithoutParameters) TEST(LinearFresnel, Build) { - OpticalProperties mirror; - mirror.set_ideal_reflection(); + SimulationData my_sim; + + SolTrace::Data::OpticalPropertySet mirror_optics(SolTrace::Data::InteractionType::REFLECTION, + 0, 0, "Mirror"); + mirror_optics.set_ideal_one_sided_reflector(OpticalSide::Front); + + auto mirror_opt_ref = my_sim.add_optical_property_set(mirror_optics); - OpticalProperties absorber; - absorber.set_ideal_absorption(); + auto absorber_optics = SolTrace::Data::OpticalPropertySet(InteractionType::REFLECTION, "Absorber"); + absorber_optics.set_ideal_absorption(OpticalSide::Both); + auto abs_opt_ref = my_sim.add_optical_property_set(absorber_optics); - OpticalProperties envelop_out; - envelop_out.set_ideal_transmission(); - envelop_out.refraction_index_front = 1.46; - envelop_out.refraction_index_back = 1.0; + auto envelop_outer_optics = SolTrace::Data::OpticalPropertySet(InteractionType::REFRACTION, "EnvelopeOuter"); + envelop_outer_optics.set_ideal_transmission(1.46, 1.0); + auto env_out_opt_ref = my_sim.add_optical_property_set(envelop_outer_optics); - OpticalProperties envelop_in; - envelop_in.set_ideal_transmission(); - envelop_in.refraction_index_front = 1.0; - envelop_in.refraction_index_back = 1.46; + auto envelop_inner_optics = SolTrace::Data::OpticalPropertySet(InteractionType::REFRACTION, "EnvelopeInner"); + envelop_inner_optics.set_ideal_transmission(1.0, 1.46); + auto env_in_opt_ref = my_sim.add_optical_property_set(envelop_inner_optics); auto lf = SolTrace::Data::make_element(); - lf->set_optics(mirror, absorber, envelop_out, envelop_in); + lf->set_optics(mirror_opt_ref, abs_opt_ref, env_out_opt_ref, env_in_opt_ref); lf->set_origin(10.0, -10.0, 0.0); lf->set_aperture_size(6.0, 12.0); lf->set_number_panels(10, 4); @@ -178,7 +189,7 @@ TEST(LinearFresnel, Build) lf->create_geometry(); lf = SolTrace::Data::make_element(); - lf->set_optics(mirror, absorber, envelop_out, envelop_in); + lf->set_optics(mirror_opt_ref, abs_opt_ref, env_out_opt_ref, env_in_opt_ref); lf->set_origin(10.0, -10.0, 0.0); lf->set_aperture_size(6.0, 12.0); lf->set_number_panels(1, 1); @@ -210,34 +221,30 @@ TEST(LinearFresnel, Tracing) my_runner.disable_power_tower(); my_runner.disable_point_focus(); - OpticalProperties mirror; - mirror.set_ideal_reflection(); - mirror.slope_error = 1.5; - mirror.specularity_error = 0.5; - - OpticalProperties absorber; - absorber.set_ideal_absorption(); - absorber.slope_error = 1e-5; - absorber.specularity_error = 1e-5; - - OpticalProperties envelop_out; - envelop_out.set_ideal_transmission(); - // envelop_out.refraction_index_front = 1.46; - envelop_out.refraction_index_front = 1.0; - envelop_out.refraction_index_back = 1.0; - envelop_out.slope_error = 1e-4; - envelop_out.specularity_error = 1e-4; - - OpticalProperties envelop_in; - envelop_in.set_ideal_transmission(); - envelop_in.refraction_index_front = 1.0; - // envelop_in.refraction_index_back = 1.46; - envelop_in.refraction_index_back = 1.0; - envelop_in.slope_error = 1e-4; - envelop_in.specularity_error = 1e-4; + SolTrace::Data::OpticalPropertySet mirror_optics(SolTrace::Data::InteractionType::REFLECTION, + 0.0, 0.0, "Mirror"); + mirror_optics.set_ideal_one_sided_reflector(OpticalSide::Front); + mirror_optics.set_errors(OpticalSide::Front, DistributionType::NONE, 1.5, 0.5); + mirror_optics.set_errors(OpticalSide::Back, DistributionType::NONE, 1e-5, 1e-5); + auto mirror_opt_ref = my_sim.add_optical_property_set(mirror_optics); + + auto absorber_optics = SolTrace::Data::OpticalPropertySet(InteractionType::REFLECTION, "Absorber"); + absorber_optics.set_ideal_absorption(OpticalSide::Both); + absorber_optics.set_errors(OpticalSide::Both, DistributionType::NONE, 1e-5, 1e-5); + auto abs_opt_ref = my_sim.add_optical_property_set(absorber_optics); + + auto envelop_outer_optics = SolTrace::Data::OpticalPropertySet(InteractionType::REFRACTION, "EnvelopeOuter"); + envelop_outer_optics.set_ideal_transmission(1.0, 1.0); + envelop_outer_optics.set_errors(OpticalSide::Both, DistributionType::NONE, 1e-4, 1e-4); + auto env_out_opt_ref = my_sim.add_optical_property_set(envelop_outer_optics); + + auto envelop_inner_optics = SolTrace::Data::OpticalPropertySet(InteractionType::REFRACTION, "EnvelopeInner"); + envelop_inner_optics.set_ideal_transmission(1.0, 1.0); + envelop_inner_optics.set_errors(OpticalSide::Both, DistributionType::NONE, 1e-4, 1e-4); + auto env_in_opt_ref = my_sim.add_optical_property_set(envelop_inner_optics); auto lf = SolTrace::Data::make_element(); - lf->set_optics(mirror, absorber, envelop_out, envelop_in); + lf->set_optics(mirror_opt_ref, abs_opt_ref, env_out_opt_ref, env_in_opt_ref); lf->set_origin(0.0, 0.0, 0.0); lf->set_aperture_size(6.0, 12.0); lf->set_number_panels(2, 2); @@ -358,29 +365,27 @@ TEST(LinearFresnel, UpdateGeometry) my_runner.disable_power_tower(); my_runner.disable_point_focus(); - OpticalProperties mirror; - mirror.set_ideal_reflection(); - mirror.slope_error = 1.5; - mirror.specularity_error = 0.5; - - OpticalProperties absorber; - absorber.set_ideal_absorption(); - absorber.slope_error = 1e-5; - absorber.specularity_error = 1e-5; - - OpticalProperties envelop_out; - envelop_out.set_ideal_transmission(); - envelop_out.refraction_index_front = 1.46; - envelop_out.refraction_index_back = 1.0; - envelop_out.slope_error = 1e-4; - envelop_out.specularity_error = 1e-4; - - OpticalProperties envelop_in; - envelop_in.set_ideal_transmission(); - envelop_in.refraction_index_front = 1.0; - envelop_in.refraction_index_back = 1.46; - envelop_in.slope_error = 1e-4; - envelop_in.specularity_error = 1e-4; + SolTrace::Data::OpticalPropertySet mirror_optics(SolTrace::Data::InteractionType::REFLECTION, + 0.0, 0.0, "Mirror"); + mirror_optics.set_ideal_one_sided_reflector(OpticalSide::Front); + mirror_optics.set_errors(OpticalSide::Front, DistributionType::NONE, 1.5, 0.5); + mirror_optics.set_errors(OpticalSide::Back, DistributionType::NONE, 1e-5, 1e-5); + auto mirror_opt_ref = my_sim.add_optical_property_set(mirror_optics); + + auto absorber_optics = SolTrace::Data::OpticalPropertySet(InteractionType::REFLECTION, "Absorber"); + absorber_optics.set_ideal_absorption(OpticalSide::Both); + absorber_optics.set_errors(OpticalSide::Both, DistributionType::NONE, 1e-5, 1e-5); + auto abs_opt_ref = my_sim.add_optical_property_set(absorber_optics); + + auto envelop_outer_optics = SolTrace::Data::OpticalPropertySet(InteractionType::REFRACTION, "EnvelopeOuter"); + envelop_outer_optics.set_ideal_transmission(1.46, 1.0); + envelop_outer_optics.set_errors(OpticalSide::Both, DistributionType::NONE, 1e-4, 1e-4); + auto env_out_opt_ref = my_sim.add_optical_property_set(envelop_outer_optics); + + auto envelop_inner_optics = SolTrace::Data::OpticalPropertySet(InteractionType::REFRACTION, "EnvelopeInner"); + envelop_inner_optics.set_ideal_transmission(1.0, 1.46); + envelop_inner_optics.set_errors(OpticalSide::Both, DistributionType::NONE, 1e-4, 1e-4); + auto env_in_opt_ref = my_sim.add_optical_property_set(envelop_inner_optics); auto sun = SolTrace::Data::make_ray_source(); glm::dvec3 sun_pos; @@ -391,7 +396,7 @@ TEST(LinearFresnel, UpdateGeometry) my_sim.add_ray_source(sun); auto lf = SolTrace::Data::make_element(); - lf->set_optics(mirror, absorber, envelop_out, envelop_in); + lf->set_optics(mirror_opt_ref, abs_opt_ref, env_out_opt_ref, env_in_opt_ref); lf->set_origin(10.0, 0.0, 0.0); // lf->set_origin(0.0, 0.0, 0.0); lf->set_aperture_size(6.0, 12.0); @@ -494,6 +499,12 @@ TEST(LinearFresnel, UpdateGeometry_TrackingLimits) const double TOL = 1e-12; auto lf = SolTrace::Data::make_element(); + + SimulationData sd; + auto optics = OpticalPropertySet(); + auto optics_ref = sd.add_optical_property_set(optics); + lf->set_optics(optics_ref, optics_ref, optics_ref, optics_ref); + lf->set_origin(0.0, 0.0, 0.0); lf->set_aperture_size(4.0, 8.0); lf->set_number_panels(2, 1); @@ -560,6 +571,12 @@ TEST(LinearFresnel, ErrorChecking_SetTrackingLimits) TEST(LinearFresnel, ErrorChecking_UpdateGeometryInvalidArgs) { auto lf = SolTrace::Data::make_element(); + + SimulationData sd; + auto optics = OpticalPropertySet(); + auto optics_ref = sd.add_optical_property_set(optics); + lf->set_optics(optics_ref, optics_ref, optics_ref, optics_ref); + lf->set_aperture_size(5.0, 10.0); lf->set_number_panels(2, 2); lf->set_receiver_height(3.0); diff --git a/google-tests/unit-tests/simulation_data/cst-templates/parabolic_dish_test.cpp b/google-tests/unit-tests/simulation_data/cst-templates/parabolic_dish_test.cpp index 4a58b432..02b1aa3b 100644 --- a/google-tests/unit-tests/simulation_data/cst-templates/parabolic_dish_test.cpp +++ b/google-tests/unit-tests/simulation_data/cst-templates/parabolic_dish_test.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -40,14 +41,12 @@ TEST(ParabolicDish, ArcLength) TEST(ParabolicDish, Build) { - OpticalProperties mirror; - mirror.set_ideal_reflection(); - - OpticalProperties absorber; - absorber.set_ideal_absorption(); - auto dish = SolTrace::Data::make_element(); - dish->set_optics(mirror, absorber); + SimulationData sd; + auto optics = OpticalPropertySet(); + auto optics_ref = sd.add_optical_property_set(optics); + dish->set_optics(optics_ref, optics_ref); + dish->set_origin(20.0, -20.0, 30.0); dish->set_aperture_size(10.0); dish->set_number_of_panels(2, 2); @@ -57,7 +56,7 @@ TEST(ParabolicDish, Build) dish->create_geometry(); dish = SolTrace::Data::make_element(); - dish->set_optics(mirror, absorber); + dish->set_optics(optics_ref, optics_ref); dish->set_origin(20.0, -20.0, 30.0); dish->set_aperture_size(10.0); dish->set_number_of_panels(1, 1); @@ -86,18 +85,19 @@ TEST(ParabolicDish, Tracing) my_runner.disable_power_tower(); my_runner.disable_point_focus(); - OpticalProperties mirror; - mirror.set_ideal_reflection(); - mirror.slope_error = 1.5; - mirror.specularity_error = 0.5; + SolTrace::Data::OpticalPropertySet mirror_optics(SolTrace::Data::InteractionType::REFLECTION, "Mirror"); + mirror_optics.set_ideal_one_sided_reflector(SolTrace::Data::OpticalSide::Front); + mirror_optics.set_errors(SolTrace::Data::OpticalSide::Front, SolTrace::Data::DistributionType::NONE, 1.5, 0.5); + mirror_optics.set_errors(SolTrace::Data::OpticalSide::Back, SolTrace::Data::DistributionType::NONE, 1e-5, 1e-5); + auto mirror_opt_ref = my_sim.add_optical_property_set(mirror_optics); - OpticalProperties absorber; - absorber.set_ideal_absorption(); - absorber.slope_error = 1e-5; - absorber.specularity_error = 1e-5; + SolTrace::Data::OpticalPropertySet absorber_optics(SolTrace::Data::InteractionType::REFLECTION, "Absorber"); + absorber_optics.set_ideal_absorption(SolTrace::Data::OpticalSide::Both); + absorber_optics.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 1e-5, 1e-5); + auto abs_opt_ref = my_sim.add_optical_property_set(absorber_optics); auto dish = SolTrace::Data::make_element(); - dish->set_optics(mirror, absorber); + dish->set_optics(mirror_opt_ref, abs_opt_ref); dish->set_origin(2.0, -2.0, 0.0); dish->set_aperture_size(10.0); dish->set_number_of_panels(2, 2); @@ -187,18 +187,19 @@ TEST(ParabolicDish, UpdateGeometry) my_runner.disable_power_tower(); my_runner.disable_point_focus(); - OpticalProperties mirror; - mirror.set_ideal_reflection(); - mirror.slope_error = 1.5; - mirror.specularity_error = 0.5; + SolTrace::Data::OpticalPropertySet mirror_optics(SolTrace::Data::InteractionType::REFLECTION, "Mirror"); + mirror_optics.set_ideal_one_sided_reflector(SolTrace::Data::OpticalSide::Front); + mirror_optics.set_errors(SolTrace::Data::OpticalSide::Front, SolTrace::Data::DistributionType::NONE, 1.5, 0.5); + mirror_optics.set_errors(SolTrace::Data::OpticalSide::Back, SolTrace::Data::DistributionType::NONE, 1e-5, 1e-5); + auto mirror_opt_ref = my_sim.add_optical_property_set(mirror_optics); - OpticalProperties absorber; - absorber.set_ideal_absorption(); - absorber.slope_error = 1e-5; - absorber.specularity_error = 1e-5; + SolTrace::Data::OpticalPropertySet absorber_optics(SolTrace::Data::InteractionType::REFLECTION, "Absorber"); + absorber_optics.set_ideal_absorption(SolTrace::Data::OpticalSide::Both); + absorber_optics.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 1e-5, 1e-5); + auto abs_opt_ref = my_sim.add_optical_property_set(absorber_optics); auto dish = SolTrace::Data::make_element(); - dish->set_optics(mirror, absorber); + dish->set_optics(mirror_opt_ref, abs_opt_ref); dish->set_origin(10.0, 2.0, 0.0); dish->set_aperture_size(10.0); dish->set_number_of_panels(2, 2); @@ -375,6 +376,11 @@ TEST(ParabolicDish, ErrorChecking_CreateGeometryWithoutParameters) { auto dish = SolTrace::Data::make_element(); + SimulationData sd; + auto optics = OpticalPropertySet(); + auto optics_ref = sd.add_optical_property_set(optics); + dish->set_optics(optics_ref, optics_ref); + // Test create_geometry without setting required parameters EXPECT_THROW(dish->create_geometry(), std::invalid_argument); @@ -398,6 +404,12 @@ TEST(ParabolicDish, ErrorChecking_CreateGeometryWithoutParameters) TEST(ParabolicDish, ErrorChecking_UpdateGeometry) { auto dish = SolTrace::Data::make_element(); + + SimulationData sd; + auto optics = OpticalPropertySet(); + auto optics_ref = sd.add_optical_property_set(optics); + dish->set_optics(optics_ref, optics_ref); + dish->set_aperture_size(10.0); dish->set_number_of_panels(2, 2); dish->set_gaps(0.02, 0.01, 0.5); diff --git a/google-tests/unit-tests/simulation_data/cst-templates/parabolic_trough_test.cpp b/google-tests/unit-tests/simulation_data/cst-templates/parabolic_trough_test.cpp index 467f8886..2f872612 100644 --- a/google-tests/unit-tests/simulation_data/cst-templates/parabolic_trough_test.cpp +++ b/google-tests/unit-tests/simulation_data/cst-templates/parabolic_trough_test.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -136,6 +137,11 @@ TEST(ParabolicTrough, ErrorChecking_CreateGeometryWithoutParameters) { auto pt = SolTrace::Data::make_element(); + SimulationData sd; + auto optics = OpticalPropertySet(); + auto optics_ref = sd.add_optical_property_set(optics); + pt->set_optics(optics_ref, optics_ref, optics_ref, optics_ref); + // Test create_geometry without setting required parameters EXPECT_THROW(pt->create_geometry(), std::invalid_argument); @@ -158,24 +164,12 @@ TEST(ParabolicTrough, ErrorChecking_CreateGeometryWithoutParameters) TEST(ParabolicTrough, Build) { - OpticalProperties mirror; - mirror.set_ideal_reflection(); - - OpticalProperties absorber; - absorber.set_ideal_absorption(); - - OpticalProperties envelop_out; - envelop_out.set_ideal_transmission(); - envelop_out.refraction_index_front = 1.46; - envelop_out.refraction_index_back = 1.0; - - OpticalProperties envelop_in; - envelop_in.set_ideal_transmission(); - envelop_in.refraction_index_front = 1.0; - envelop_in.refraction_index_back = 1.46; - + SimulationData sd; + auto optics = OpticalPropertySet(); + auto optics_ref = sd.add_optical_property_set(optics); + auto pt = SolTrace::Data::make_element(); - pt->set_optics(mirror, absorber, envelop_out, envelop_in); + pt->set_optics(optics_ref, optics_ref, optics_ref, optics_ref); pt->set_origin(20.0, -20.0, 30.0); pt->set_aperture_size(5.774, 11.96); pt->set_number_panels(4, 7); @@ -186,7 +180,7 @@ TEST(ParabolicTrough, Build) pt->create_geometry(); pt = SolTrace::Data::make_element(); - pt->set_optics(mirror, absorber, envelop_out, envelop_in); + pt->set_optics(optics_ref, optics_ref, optics_ref, optics_ref); pt->set_origin(20.0, -20.0, 30.0); pt->set_aperture_size(5.774, 11.96); pt->set_number_panels(1, 7); @@ -217,32 +211,30 @@ TEST(ParabolicTrough, Tracing) my_runner.disable_power_tower(); my_runner.disable_point_focus(); - OpticalProperties mirror; - mirror.set_ideal_reflection(); - mirror.slope_error = 1.5; - mirror.specularity_error = 0.5; - - OpticalProperties absorber; - absorber.set_ideal_absorption(); - absorber.slope_error = 1e-5; - absorber.specularity_error = 1e-5; - - OpticalProperties envelop_out; - envelop_out.set_ideal_transmission(); - envelop_out.refraction_index_front = 1.46; - envelop_out.refraction_index_back = 1.0; - envelop_out.slope_error = 1e-4; - envelop_out.specularity_error = 1e-4; - - OpticalProperties envelop_in; - envelop_in.set_ideal_transmission(); - envelop_in.refraction_index_front = 1.0; - envelop_in.refraction_index_back = 1.46; - envelop_in.slope_error = 1e-4; - envelop_in.specularity_error = 1e-4; + SolTrace::Data::OpticalPropertySet mirror_optics(SolTrace::Data::InteractionType::REFLECTION, + 0.0, 0.0, "Mirror"); + mirror_optics.set_ideal_one_sided_reflector(SolTrace::Data::OpticalSide::Front); + mirror_optics.set_errors(SolTrace::Data::OpticalSide::Front, SolTrace::Data::DistributionType::NONE, 1.5, 0.5); + mirror_optics.set_errors(SolTrace::Data::OpticalSide::Back, SolTrace::Data::DistributionType::NONE, 1e-5, 1e-5); + auto mirror_opt_ref = my_sim.add_optical_property_set(mirror_optics); + + auto absorber_optics = SolTrace::Data::OpticalPropertySet(SolTrace::Data::InteractionType::REFLECTION, "Absorber"); + absorber_optics.set_ideal_absorption(SolTrace::Data::OpticalSide::Both); + absorber_optics.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 1e-5, 1e-5); + auto abs_opt_ref = my_sim.add_optical_property_set(absorber_optics); + + auto envelop_outer_optics = SolTrace::Data::OpticalPropertySet(SolTrace::Data::InteractionType::REFRACTION, "EnvelopeOuter"); + envelop_outer_optics.set_ideal_transmission(1.46, 1.0); + envelop_outer_optics.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 1e-4, 1e-4); + auto env_out_opt_ref = my_sim.add_optical_property_set(envelop_outer_optics); + + auto envelop_inner_optics = SolTrace::Data::OpticalPropertySet(SolTrace::Data::InteractionType::REFRACTION, "EnvelopeInner"); + envelop_inner_optics.set_ideal_transmission(1.0, 1.46); + envelop_inner_optics.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 1e-4, 1e-4); + auto env_in_opt_ref = my_sim.add_optical_property_set(envelop_inner_optics); auto pt = SolTrace::Data::make_element(); - pt->set_optics(mirror, absorber, envelop_out, envelop_in); + pt->set_optics(mirror_opt_ref, abs_opt_ref, env_out_opt_ref, env_in_opt_ref); pt->set_origin(20.0, -20.0, 30.0); pt->set_angles(0.0, 0.0); pt->set_aperture_size(6.0, 12.0); @@ -342,32 +334,34 @@ TEST(ParabolicTrough, UpdateGeometry) my_runner.disable_power_tower(); my_runner.disable_point_focus(); - OpticalProperties mirror; - mirror.set_ideal_reflection(); - mirror.slope_error = 1.5; - mirror.specularity_error = 0.5; - - OpticalProperties absorber; - absorber.set_ideal_absorption(); - absorber.slope_error = 1e-5; - absorber.specularity_error = 1e-5; - - OpticalProperties envelop_out; - envelop_out.set_ideal_transmission(); - envelop_out.refraction_index_front = 1.46; - envelop_out.refraction_index_back = 1.0; - envelop_out.slope_error = 1e-4; - envelop_out.specularity_error = 1e-4; - - OpticalProperties envelop_in; - envelop_in.set_ideal_transmission(); - envelop_in.refraction_index_front = 1.0; - envelop_in.refraction_index_back = 1.46; - envelop_in.slope_error = 1e-4; - envelop_in.specularity_error = 1e-4; + SolTrace::Data::OpticalPropertySet mirror_optics(SolTrace::Data::InteractionType::REFLECTION, + 0.0, 0.0, "Mirror"); + mirror_optics.set_ideal_one_sided_reflector(SolTrace::Data::OpticalSide::Front); + mirror_optics.set_errors(SolTrace::Data::OpticalSide::Front, SolTrace::Data::DistributionType::NONE, 1.5, 0.5); + mirror_optics.set_errors(SolTrace::Data::OpticalSide::Back, SolTrace::Data::DistributionType::NONE, 1e-5, 1e-5); + + auto mirror_opt_ref = my_sim.add_optical_property_set(mirror_optics); + + auto absorber_optics = SolTrace::Data::OpticalPropertySet(SolTrace::Data::InteractionType::REFLECTION, "Absorber"); + absorber_optics.set_ideal_absorption(SolTrace::Data::OpticalSide::Both); + absorber_optics.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 1e-5, 1e-5); + + auto abs_opt_ref = my_sim.add_optical_property_set(absorber_optics); + + auto envelop_outer_optics = SolTrace::Data::OpticalPropertySet(SolTrace::Data::InteractionType::REFRACTION, "EnvelopeOuter"); + envelop_outer_optics.set_ideal_transmission(1.46, 1.0); + envelop_outer_optics.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 1e-4, 1e-4); + + auto env_out_opt_ref = my_sim.add_optical_property_set(envelop_outer_optics); + + auto envelop_inner_optics = SolTrace::Data::OpticalPropertySet(SolTrace::Data::InteractionType::REFRACTION, "EnvelopeInner"); + envelop_inner_optics.set_ideal_transmission(1.0, 1.46); + envelop_inner_optics.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 1e-4, 1e-4); + + auto env_in_opt_ref = my_sim.add_optical_property_set(envelop_inner_optics); auto pt = SolTrace::Data::make_element(); - pt->set_optics(mirror, absorber, envelop_out, envelop_in); + pt->set_optics(mirror_opt_ref, abs_opt_ref, env_out_opt_ref, env_in_opt_ref); pt->set_origin(10.0, 0.0, 0.0); // pt->set_origin(0.0, 0.0, 0.0); pt->set_angles(30.0, 10.0); @@ -496,6 +490,12 @@ TEST(ParabolicTrough, UpdateGeometry_TrackingLimits) const double UPPER = 10.0; auto pt = SolTrace::Data::make_element(); + + SimulationData sd; + auto optics = OpticalPropertySet(); + auto optics_ref = sd.add_optical_property_set(optics); + pt->set_optics(optics_ref, optics_ref, optics_ref, optics_ref); + pt->set_origin(0.0, 0.0, 0.0); pt->set_angles(0.0, 0.0); pt->set_tracking_limits(LOWER, UPPER); @@ -547,6 +547,12 @@ TEST(ParabolicTrough, UpdateGeometry_TrackingLimits) TEST(ParabolicTrough, ErrorChecking_UpdateGeometry) { auto pt = SolTrace::Data::make_element(); + + SimulationData sd; + auto optics = OpticalPropertySet(); + auto optics_ref = sd.add_optical_property_set(optics); + pt->set_optics(optics_ref, optics_ref, optics_ref, optics_ref); + pt->set_origin(10.0, 0.0, 0.0); pt->set_angles(30.0, 10.0); pt->set_tracking_limits(-90.0, 90.0); diff --git a/google-tests/unit-tests/simulation_data/cst-templates/single_heliostat_test_template.hpp b/google-tests/unit-tests/simulation_data/cst-templates/single_heliostat_test_template.hpp index c7746abb..e0f74d9b 100644 --- a/google-tests/unit-tests/simulation_data/cst-templates/single_heliostat_test_template.hpp +++ b/google-tests/unit-tests/simulation_data/cst-templates/single_heliostat_test_template.hpp @@ -113,21 +113,19 @@ class SingleHeliostatSimulationHelper { //runner.disable_point_focus(); // Define mirror optical properties - OpticalProperties mirror; - mirror.set_ideal_reflection(); - mirror.reflectivity = 0.9; - mirror.slope_error = this->slope_error; // mrad - mirror.specularity_error = this->spec_error; // mrad - mirror.error_distribution_type = this->error_dist; - // Backside is absorbing - OpticalProperties mirror_back; - mirror_back.set_ideal_absorption(); + SolTrace::Data::OpticalPropertySet mirror_opt_set(SolTrace::Data::InteractionType::REFLECTION, "HeliostatMirror"); + // Front reflectivity less than 1.0, back is absorbing + mirror_opt_set.set_reflectivity(SolTrace::Data::OpticalSide::Front, 0.9); + mirror_opt_set.set_ideal_absorption(SolTrace::Data::OpticalSide::Back); + mirror_opt_set.set_errors(SolTrace::Data::OpticalSide::Front, this->error_dist, this->slope_error, this->spec_error); + mirror_opt_set.set_errors(SolTrace::Data::OpticalSide::Back, SolTrace::Data::DistributionType::NONE, 0.0, 0.0); // Initial setup of heliostat glm::dvec3 heliostat_origin(0.0, 500.0, 5.65); glm::dvec3 rec_origin(0.0, 0.0, 169.0); heliostat = SolTrace::Data::make_element(); - heliostat->set_optics(mirror, mirror_back); + auto mirror_ref = simData.add_optical_property_set(mirror_opt_set); + heliostat->set_optics(mirror_ref); heliostat->set_reference_frame_geometry(heliostat_origin, khat, 0.0); heliostat->set_aperture_size(11.415, 10.42); // Width, Height heliostat->set_number_panels(1, 1); @@ -140,9 +138,12 @@ class SingleHeliostatSimulationHelper { heliostat->enable(); // Initial setup of receiver + SolTrace::Data::OpticalPropertySet rec_opt_set(SolTrace::Data::InteractionType::REFLECTION, "Receiver"); + rec_opt_set.set_ideal_absorption(SolTrace::Data::OpticalSide::Both); + auto rec_ref = simData.add_optical_property_set(rec_opt_set); + receiver = SolTrace::Data::make_element(); - receiver->get_front_optical_properties()->set_ideal_absorption(); - receiver->get_back_optical_properties()->set_ideal_reflection(); + receiver->set_optical_property_set(rec_ref); receiver->set_aperture(SolTrace::Data::make_aperture(rec_width, rec_height)); receiver->set_surface(SolTrace::Data::make_surface()); glm::dvec3 v1 = {0.0, 1.0, 0.0}; // Pointing North TODO: change to point towards heliostat diff --git a/google-tests/unit-tests/simulation_data/element_test.cpp b/google-tests/unit-tests/simulation_data/element_test.cpp index 19e4cb52..794d507d 100644 --- a/google-tests/unit-tests/simulation_data/element_test.cpp +++ b/google-tests/unit-tests/simulation_data/element_test.cpp @@ -12,8 +12,8 @@ TEST(OpticalProperties, OutputOperator) { std::stringstream ss; - OpticalProperties op; - op.set_ideal_reflection(); + OpticalPropertySet op; + op.set_ideal_reflection(OpticalSide::Both); ss << op; EXPECT_GE(ss.str().length(), 0); } @@ -87,29 +87,6 @@ TEST(Element, SingleElementAccessors) auto rsp = std::dynamic_pointer_cast(ref.get_surface()); EXPECT_NE(rsp, nullptr); EXPECT_EQ(rsp->half_angle, HA); - - auto opf = ref.get_front_optical_properties(); - auto opb = ref.get_back_optical_properties(); - EXPECT_EQ(opf->transmitivity, opb->transmitivity); - EXPECT_EQ(opf->reflectivity, opb->reflectivity); - EXPECT_EQ(opf->slope_error, opb->slope_error); - EXPECT_EQ(opf->specularity_error, opb->specularity_error); - - OpticalProperties op(InteractionType::REFLECTION, - DistributionType::GAUSSIAN, - 0.75, 0.25, 0.1, 0.001, 1.0, 1.0); - ref.set_front_optical_properties(op); - // EXPECT_EQ(*opf, op); - EXPECT_EQ(opf->transmitivity, op.transmitivity); - EXPECT_EQ(opf->reflectivity, op.reflectivity); - EXPECT_EQ(opf->slope_error, op.slope_error); - EXPECT_EQ(opf->specularity_error, op.specularity_error); - - ref.set_back_optical_properties(op); - EXPECT_EQ(opb->transmitivity, op.transmitivity); - EXPECT_EQ(opb->reflectivity, op.reflectivity); - EXPECT_EQ(opb->slope_error, op.slope_error); - EXPECT_EQ(opb->specularity_error, op.specularity_error); } TEST(Element, VirtualElement) @@ -141,23 +118,6 @@ TEST(Element, VirtualElement) EXPECT_TRUE(ve.is_single()); EXPECT_FALSE(ve.is_composite()); - // These functions should have no effects - OpticalProperties op(InteractionType::REFLECTION, - DistributionType::GAUSSIAN, - 0.75, 0.25, 0.1, 0.001, 1.0, 1.0); - ve.set_front_optical_properties(op); - auto opf = ve.get_front_optical_properties(); - EXPECT_EQ(opf->reflectivity, 0.0); - EXPECT_EQ(opf->slope_error, 0.0); - EXPECT_EQ(opf->specularity_error, 0.0); - EXPECT_EQ(opf->transmitivity, 1.0); - ve.set_back_optical_properties(op); - auto opb = ve.get_back_optical_properties(); - EXPECT_EQ(opb->reflectivity, 0.0); - EXPECT_EQ(opb->slope_error, 0.0); - EXPECT_EQ(opb->specularity_error, 0.0); - EXPECT_EQ(opb->transmitivity, 1.0); - return; } @@ -190,32 +150,25 @@ TEST(Element, VirtualPlane) TEST(Element, CompositeElementAccessors) { + SimulationData sd; auto cmp = SolTrace::Data::make_element(); EXPECT_TRUE(cmp->is_composite()); // Things that should be empty... EXPECT_EQ(cmp->get_aperture(), nullptr); EXPECT_EQ(cmp->get_surface(), nullptr); - EXPECT_EQ(cmp->get_front_optical_properties(), nullptr); - EXPECT_EQ(cmp->get_back_optical_properties(), nullptr); + EXPECT_EQ(cmp->get_optical_property_set_id(), SolTrace::Data::OPTICS_ID_UNASSIGNED); + EXPECT_EQ(cmp->get_optical_property_set(), nullptr); const aperture_ptr ap = cmp->get_aperture(); EXPECT_EQ(ap, nullptr); const surface_ptr sp = cmp->get_surface(); EXPECT_EQ(sp, nullptr); - const OpticalProperties *op = cmp->get_back_optical_properties(); - EXPECT_EQ(op, nullptr); - op = cmp->get_front_optical_properties(); - EXPECT_EQ(op, nullptr); - - // These should do nothing... - cmp->set_front_optical_properties(OpticalProperties()); - cmp->set_back_optical_properties(OpticalProperties()); // Add/remove/change elements const int NUM_ELEMENTS = 4; for (int i = 0; i < NUM_ELEMENTS; ++i) { - auto elem = make_configured_element(); + auto elem = make_configured_element(sd); cmp->add_element(elem); // EXPECT_EQ(elem->get_stage(), STAGE); } @@ -224,11 +177,11 @@ TEST(Element, CompositeElementAccessors) cmp->remove_element(0); EXPECT_EQ(cmp->get_number_of_elements(), NUM_ELEMENTS - 1); EXPECT_EQ(cmp->get_element(0), nullptr); - auto elem = make_configured_element(); + auto elem = make_configured_element(sd); auto id = cmp->add_element(elem); EXPECT_EQ(cmp->get_element(id).get(), elem.get()); - auto elem2 = make_configured_element(); + auto elem2 = make_configured_element(sd); EXPECT_NE(elem.get(), elem2.get()); cmp->replace_element(id, elem2); EXPECT_EQ(cmp->get_element(id).get(), elem2.get()); @@ -258,7 +211,7 @@ TEST(Element, CompositeElementAccessors) EXPECT_FALSE(elem2->is_virtual()); cmp->mark_virtual(); - auto elem3 = make_configured_element(); + auto elem3 = make_configured_element(sd); EXPECT_FALSE(elem3->is_virtual()); cmp->add_element(elem3); EXPECT_TRUE(elem3->is_virtual()); @@ -283,15 +236,16 @@ TEST(Element, CompositeElementAccessors) TEST(Element, StageElementAccessors) { + SimulationData sd; const int_fast64_t STAGE = 10; const int_fast64_t RESET_STAGE = 20; auto st1 = SolTrace::Data::make_stage(10); - auto el1 = make_configured_element(); + auto el1 = make_configured_element(sd); auto cmp1 = SolTrace::Data::make_element(); - auto sub1 = make_configured_element(); - auto sub2 = make_configured_element(); - auto sub3 = make_configured_element(); + auto sub1 = make_configured_element(sd); + auto sub2 = make_configured_element(sd); + auto sub3 = make_configured_element(sd); EXPECT_TRUE(SolTrace::Data::Element::is_success(cmp1->add_element(sub1))); EXPECT_TRUE(SolTrace::Data::Element::is_success(cmp1->add_element(sub2))); EXPECT_TRUE(SolTrace::Data::Element::is_success(cmp1->add_element(sub3))); @@ -314,7 +268,8 @@ TEST(Element, StageElementAccessors) TEST(Element, CoordinateComputationsIdentity) { - auto el = make_configured_element(); + SimulationData sd; + auto el = make_configured_element(sd); auto st = SolTrace::Data::make_stage(0); glm::dvec3 origin(0.0, 0.0, 0.0); glm::dvec3 aim(0.0, 0.0, 1.0); @@ -396,6 +351,7 @@ TEST(Element, CoordinateComputationsIdentity) TEST(Element, CoordinateComputationsRotations) { + SimulationData sd; using SolTrace::Data::PI; // **** Setup Answers **** // @@ -447,7 +403,7 @@ TEST(Element, CoordinateComputationsRotations) const double zrot2 = 60.0; // **** Setup Elements **** // - auto el = make_configured_element(); + auto el = make_configured_element(sd); el->set_reference_frame_geometry(Origin, aim1, zrot1); auto st = SolTrace::Data::make_stage(0); @@ -506,6 +462,7 @@ TEST(Element, CoordinateComputationsRotations) TEST(Element, CoordinateComputationsTranslations) { + SimulationData sd; // **** Setup Answers **** // // Origin glm::dvec3 Origin1(1.0, 2.0, 3.0); @@ -528,7 +485,7 @@ TEST(Element, CoordinateComputationsTranslations) aim2 = 1.0 * Origin2 + 1.0 * aim2; // **** Setup Elements **** // - auto el = make_configured_element(); + auto el = make_configured_element(sd); el->set_reference_frame_geometry(Origin1, aim1, zrot); auto st = SolTrace::Data::make_stage(0); @@ -588,6 +545,7 @@ TEST(Element, CoordinateComputationsTranslations) TEST(Element, CoordinateComputations) { + SimulationData sd; using SolTrace::Data::MatrixTranspose; using SolTrace::Data::PI; @@ -647,7 +605,7 @@ TEST(Element, CoordinateComputations) const double zrot2 = 60.0; // **** Setup Elements **** // - auto el = make_configured_element(); + auto el = make_configured_element(sd); el->set_reference_frame_geometry(Origin1, aim1, zrot1); auto st = SolTrace::Data::make_stage(0); @@ -735,6 +693,7 @@ TEST(Element, CoordinateComputations) TEST(Element, VectorCoordinateComputations) { + SimulationData sd; using SolTrace::Data::MatrixTranspose; using SolTrace::Data::PI; @@ -793,7 +752,7 @@ TEST(Element, VectorCoordinateComputations) const double zrot2 = 60.0; // **** Setup Elements **** // - auto el = make_configured_element(); + auto el = make_configured_element(sd); el->set_reference_frame_geometry(Origin1, aim1, zrot1); auto st = SolTrace::Data::make_stage(0); @@ -865,7 +824,14 @@ TEST(Element, VectorCoordinateComputations) TEST(Element, SingleElementEnforceUserFieldsSet) { + SimulationData sd; + OpticalPropertySet opt_set(InteractionType::REFLECTION, 1, 1); + opt_set.set_properties(OpticalSide::Both, DistributionType::GAUSSIAN, + 0.75, 0.25, 0.1, 0.001); + auto optics_ref = sd.add_optical_property_set(opt_set); + auto elem = SolTrace::Data::make_element(); + elem->set_optical_property_set(optics_ref); // SingleElement requires aperture and surface to be set // Test that it throws when aperture is missing @@ -878,20 +844,11 @@ TEST(Element, SingleElementEnforceUserFieldsSet) // Set both aperture and surface - should not throw elem->set_surface(SolTrace::Data::make_surface()); EXPECT_NO_THROW(elem->enforce_user_fields_set()); - - // Test with optical properties set as well - OpticalProperties op(InteractionType::REFLECTION, - DistributionType::GAUSSIAN, - 0.75, 0.25, 0.1, 0.001, 1.0, 1.0); - elem->set_front_optical_properties(op); - elem->set_back_optical_properties(op); - - // Should still not throw - EXPECT_NO_THROW(elem->enforce_user_fields_set()); } TEST(Element, CompositeElementEnforceUserFieldsSet) { + SimulationData sd; auto comp = SolTrace::Data::make_element(); // CompositeElement requires at least one subelement @@ -903,7 +860,7 @@ TEST(Element, CompositeElementEnforceUserFieldsSet) EXPECT_THROW(comp->add_element(elem1), std::invalid_argument); // Add properly configured child elements - auto elem2 = SolTrace::Data::make_element(); + auto elem2 = make_configured_element(sd); elem2->set_aperture(SolTrace::Data::make_aperture(2.0, 3.0)); elem2->set_surface(SolTrace::Data::make_surface(1.0, 2.0)); EXPECT_NO_THROW(comp->add_element(elem2)); diff --git a/google-tests/unit-tests/simulation_data/file_io_test.cpp b/google-tests/unit-tests/simulation_data/file_io_test.cpp index 770fae61..fbc4374b 100644 --- a/google-tests/unit-tests/simulation_data/file_io_test.cpp +++ b/google-tests/unit-tests/simulation_data/file_io_test.cpp @@ -760,6 +760,6 @@ TEST(io_json, stage_read_fail) jstage["elements"] = json::object(); // Empty node // Try to make stage - EXPECT_THROW(make_stage(jstage), std::invalid_argument); + EXPECT_THROW(make_stage(jstage, nullptr), std::invalid_argument); } diff --git a/google-tests/unit-tests/simulation_data/optical_properties_test.cpp b/google-tests/unit-tests/simulation_data/optical_properties_test.cpp new file mode 100644 index 00000000..fde2a2ba --- /dev/null +++ b/google-tests/unit-tests/simulation_data/optical_properties_test.cpp @@ -0,0 +1,241 @@ +#include + +#include +#include +#include +#include + +#include "common.hpp" + +TEST(OpticalProperties, DangleOpticalPointer) +{ + SimulationData sd; + + // Make optical property set + auto opt_set = OpticalPropertySet(); + opt_set.set_ideal_reflection(OpticalSide::Both); + + // Add to simulation data + auto opt_ref = sd.add_optical_property_set(opt_set); + + // Make element + auto test_element = make_element(); + test_element->set_aperture(make_aperture(1)); + test_element->set_surface(make_surface()); + + // Attach optical property reference to element + test_element->set_optical_property_set(opt_ref); + + // Add element to simulation data + ASSERT_NO_THROW(sd.add_element(test_element)); + + sd.clear(); + + EXPECT_EQ(sd.get_optical_property_set(*test_element), nullptr); +} + +TEST(OpticalProperties, MissingOptical) +{ + SimulationData sd; + + // Make element + auto test_element = make_element(); + test_element->set_aperture(make_aperture(1)); + test_element->set_surface(make_surface()); + + // Add element to simulation data + EXPECT_THROW(sd.add_element(test_element), std::invalid_argument); +} + +TEST(OpticalProperties, MutateOptics) +{ + SimulationData sd; + + // Make optical property set + auto opt_set = OpticalPropertySet(); + opt_set.set_ideal_reflection(OpticalSide::Both); + + // Add to simulation data + auto opt_ref = sd.add_optical_property_set(opt_set); + + // Make element 1 + auto test_element_1 = make_element(); + test_element_1->set_aperture(make_aperture(1)); + test_element_1->set_surface(make_surface()); + + // Attach optical property reference to element 1 + test_element_1->set_optical_property_set(opt_ref); + + // Make element 2 + auto test_element_2 = make_element(); + test_element_2->set_aperture(make_aperture(1)); + test_element_2->set_surface(make_surface()); + + // Attach same optical properties to elemetn 2 + test_element_2->set_optical_property_set(opt_ref); + + // Modify optical properties directly from simulation data + auto* optics_ptr = sd.get_mutable_optical_property_set(*test_element_1); + optics_ptr->set_reflectivity(OpticalSide::Front, 0.5); + + // Confirm reflectivity is modified for both + EXPECT_EQ(test_element_1->get_optical_property_set()->get_reflectivity(OpticalSide::Front), + 0.5); + EXPECT_EQ(test_element_2->get_optical_property_set()->get_reflectivity(OpticalSide::Front), + 0.5); + + EXPECT_EQ(test_element_1->get_optical_property_set(), + test_element_2->get_optical_property_set()); +} + +TEST(OpticalProperties, NullPointer) +{ + // Make optics + OpticalPropertySet opt_set = OpticalPropertySet(); + opt_set.set_ideal_reflection(OpticalSide::Both); + auto opt_ptr = std::make_shared(opt_set); + + // Make optics reference + OpticalPropertySetReference ref = { 0, opt_ptr }; + + // Make element + auto test_element = make_element(); + test_element->set_aperture(make_aperture(1)); + test_element->set_surface(make_surface()); + test_element->set_optical_property_set(ref); + + // Add element to simulation data + SimulationData sd; + sd.add_element(test_element); + + // Delete optics pointer + opt_ptr.reset(); + + // Try to get pointer + EXPECT_EQ(test_element->get_optical_property_set(), nullptr); + +} + +TEST(OpticalProperties, ElementCanAccessSimulationOwnedOptics) +{ + SimulationData sd; + + OpticalPropertySet opt_set; + opt_set.set_ideal_reflection(OpticalSide::Both); + + auto opt_ref = sd.add_optical_property_set(opt_set); + + auto test_element = make_element(); + test_element->set_aperture(make_aperture(1)); + test_element->set_surface(make_surface()); + test_element->set_optical_property_set(opt_ref); + + EXPECT_NE(test_element->get_optical_property_set(), nullptr); + EXPECT_EQ(test_element->get_optical_property_set()->get_reflectivity(OpticalSide::Front), 1.0); +} + +TEST(OpticalProperties, RemovingElementDoesNotRemoveOptics) +{ + SimulationData sd; + + OpticalPropertySet opt_set; + opt_set.set_ideal_reflection(OpticalSide::Both); + + auto opt_ref = sd.add_optical_property_set(opt_set); + + auto test_element = make_element(); + test_element->set_aperture(make_aperture(1)); + test_element->set_surface(make_surface()); + test_element->set_optical_property_set(opt_ref); + + auto id = sd.add_element(test_element); + ASSERT_TRUE(SolTrace::Data::Element::is_success(id)); + + sd.remove_element(id); + + EXPECT_NE(sd.get_optical_property_set(*test_element), nullptr); +} + +TEST(OpticalProperties, FindOrAddDeduplicatesEquivalentOptics) +{ + SimulationData sd; + + OpticalPropertySet opt_set_1; + opt_set_1.set_ideal_reflection(OpticalSide::Both); + + OpticalPropertySet opt_set_2; + opt_set_2.set_ideal_reflection(OpticalSide::Both); + + auto ref_1 = sd.find_or_add_optical_property_set(opt_set_1); + auto ref_2 = sd.find_or_add_optical_property_set(opt_set_2); + + EXPECT_EQ(ref_1.id, ref_2.id); + EXPECT_EQ(ref_1.optical_property_set.lock(), ref_2.optical_property_set.lock()); +} + +TEST(OpticalProperties, FindOrAddKeepsDifferentOpticsSeparate) +{ + SimulationData sd; + + OpticalPropertySet opt_set_1; + opt_set_1.set_ideal_reflection(OpticalSide::Both); + + OpticalPropertySet opt_set_2; + opt_set_2.set_ideal_reflection(OpticalSide::Both); + opt_set_2.set_reflectivity(OpticalSide::Front, 0.5); + + auto ref_1 = sd.find_or_add_optical_property_set(opt_set_1); + auto ref_2 = sd.find_or_add_optical_property_set(opt_set_2); + + EXPECT_NE(ref_1.id, ref_2.id); + EXPECT_NE(ref_1.optical_property_set.lock(), ref_2.optical_property_set.lock()); +} + +TEST(OpticalProperties, AddElementWithExpiredOpticsThrows) +{ + auto test_element = make_element(); + test_element->set_aperture(make_aperture(1)); + test_element->set_surface(make_surface()); + + { + SimulationData temporary_sd; + + OpticalPropertySet opt_set; + opt_set.set_ideal_reflection(OpticalSide::Both); + + auto opt_ref = temporary_sd.add_optical_property_set(opt_set); + test_element->set_optical_property_set(opt_ref); + } + + SimulationData sd; + + EXPECT_THROW(sd.add_element(test_element), std::invalid_argument); +} + +TEST(OpticalProperties, ReplaceElementDoesNotInvalidateOptics) +{ + SimulationData sd; + + OpticalPropertySet opt_set; + opt_set.set_ideal_reflection(OpticalSide::Both); + + auto opt_ref = sd.add_optical_property_set(opt_set); + + auto old_element = make_element(); + old_element->set_aperture(make_aperture(1)); + old_element->set_surface(make_surface()); + old_element->set_optical_property_set(opt_ref); + + auto id = sd.add_element(old_element); + ASSERT_TRUE(SolTrace::Data::Element::is_success(id)); + + auto new_element = make_element(); + new_element->set_aperture(make_aperture(2)); + new_element->set_surface(make_surface()); + new_element->set_optical_property_set(opt_ref); + + EXPECT_TRUE(sd.replace_element(id, new_element)); + + EXPECT_NE(new_element->get_optical_property_set(), nullptr); + EXPECT_NE(sd.get_optical_property_set(*new_element), nullptr); +} \ No newline at end of file diff --git a/google-tests/unit-tests/simulation_data/simulation_data_test.cpp b/google-tests/unit-tests/simulation_data/simulation_data_test.cpp index 191f60db..e46e3683 100644 --- a/google-tests/unit-tests/simulation_data/simulation_data_test.cpp +++ b/google-tests/unit-tests/simulation_data/simulation_data_test.cpp @@ -64,12 +64,17 @@ TEST(SimulationData, AddProperlyConfiguredElementsSucceeds) { SimulationData my_sim; + // Make dummy optical properties + OpticalPropertySet dummy_optics; + auto optics_ref = my_sim.add_optical_property_set(dummy_optics); + // Create a properly configured SingleElement auto configured_single = SolTrace::Data::make_element(); auto aperture = SolTrace::Data::make_aperture(1.0, 1.0); auto surface = SolTrace::Data::make_surface(); configured_single->set_aperture(aperture); configured_single->set_surface(surface); + configured_single->set_optical_property_set(optics_ref); // Adding a properly configured element should succeed EXPECT_NO_THROW(my_sim.add_element(configured_single)); @@ -83,6 +88,7 @@ TEST(SimulationData, AddProperlyConfiguredElementsSucceeds) auto surface2 = SolTrace::Data::make_surface(); configured_sub1->set_aperture(aperture2); configured_sub1->set_surface(surface2); + configured_sub1->set_optical_property_set(optics_ref); configured_composite->add_element(configured_sub1); // Adding a properly configured composite should succeed @@ -97,7 +103,7 @@ TEST(SimulationData, ValidationErrorPreservesSimulationState) SimulationData my_sim; // Add a properly configured element first - auto good_element = make_configured_element(); + auto good_element = make_configured_element(my_sim); my_sim.add_element(good_element); EXPECT_EQ(my_sim.get_number_of_elements(), 1); @@ -119,14 +125,14 @@ TEST(SimulationData, AddRemoveGetElements) { SimulationData my_sim; - auto my_reflector = make_configured_element(); + auto my_reflector = make_configured_element(my_sim); auto id1 = my_sim.add_element(my_reflector); EXPECT_EQ(id1, my_reflector->get_id()); EXPECT_EQ(my_sim.get_number_of_elements(), 1); auto my_comp = SolTrace::Data::make_element(); - auto sub1 = make_configured_element(); - auto sub2 = make_configured_element(); + auto sub1 = make_configured_element(my_sim); + auto sub2 = make_configured_element(my_sim); my_comp->add_element(sub1); my_comp->add_element(sub2); EXPECT_EQ(my_comp->get_number_of_elements(), 2); @@ -166,22 +172,23 @@ TEST(SimulationData, AddRemoveGetElements) TEST(SimulationData, ReplaceElement) { - auto el1 = make_configured_element(); - auto el2 = make_configured_element(); + SimulationData my_sim; + + auto el1 = make_configured_element(my_sim); + auto el2 = make_configured_element(my_sim); auto cmp1 = SolTrace::Data::make_element(); - auto sub1 = make_configured_element(); - auto sub2 = make_configured_element(); + auto sub1 = make_configured_element(my_sim); + auto sub2 = make_configured_element(my_sim); cmp1->add_element(sub1); cmp1->add_element(sub2); auto cmp2 = SolTrace::Data::make_element(); - auto sub3 = make_configured_element(); - auto sub4 = make_configured_element(); - auto sub5 = make_configured_element(); + auto sub3 = make_configured_element(my_sim); + auto sub4 = make_configured_element(my_sim); + auto sub5 = make_configured_element(my_sim); cmp2->add_element(sub3); cmp2->add_element(sub4); cmp2->add_element(sub5); - SimulationData my_sim; auto id1 = my_sim.add_element(el1); auto id2 = my_sim.add_element(cmp1); EXPECT_EQ(my_sim.get_number_of_elements(), 3); @@ -226,22 +233,23 @@ TEST(SimulationData, ReplaceElement) TEST(SimulationData, IteratorElement) { - auto el1 = make_configured_element(); - auto el2 = make_configured_element(); + SimulationData my_sim; + + auto el1 = make_configured_element(my_sim); + auto el2 = make_configured_element(my_sim); auto cmp1 = SolTrace::Data::make_element(); - auto sub1 = make_configured_element(); - auto sub2 = make_configured_element(); + auto sub1 = make_configured_element(my_sim); + auto sub2 = make_configured_element(my_sim); cmp1->add_element(sub1); cmp1->add_element(sub2); auto cmp2 = SolTrace::Data::make_element(); - auto sub3 = make_configured_element(); - auto sub4 = make_configured_element(); - auto sub5 = make_configured_element(); + auto sub3 = make_configured_element(my_sim); + auto sub4 = make_configured_element(my_sim); + auto sub5 = make_configured_element(my_sim); cmp2->add_element(sub3); cmp2->add_element(sub4); cmp2->add_element(sub5); - SimulationData my_sim; my_sim.add_element(el1); my_sim.add_element(el2); my_sim.add_element(cmp1); diff --git a/google-tests/unit-tests/simulation_runner/embree_runner/embree_runner_test.cpp b/google-tests/unit-tests/simulation_runner/embree_runner/embree_runner_test.cpp index cd03262f..2c293e41 100644 --- a/google-tests/unit-tests/simulation_runner/embree_runner/embree_runner_test.cpp +++ b/google-tests/unit-tests/simulation_runner/embree_runner/embree_runner_test.cpp @@ -60,8 +60,11 @@ TEST(EmbreeRunner, SingleRayValidationTest) sph->set_reference_frame_geometry(origin, aim, zrot); sph->set_aperture(SolTrace::Data::make_aperture(20.0)); sph->set_surface(SolTrace::Data::make_surface(c)); - sph->get_front_optical_properties()->set_ideal_reflection(); - sph->get_back_optical_properties()->set_ideal_reflection(); + SolTrace::Data::OpticalPropertySet sphere_optics(SolTrace::Data::InteractionType::REFLECTION, "Sphere"); + sphere_optics.set_ideal_reflection(SolTrace::Data::OpticalSide::Both); + sphere_optics.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 0.0, 0.0); + auto sphere_optics_ref = sd.add_optical_property_set(sphere_optics); + sph->set_optical_property_set(sphere_optics_ref); sph->set_name("Sphere"); sd.add_element(sph); @@ -72,6 +75,11 @@ TEST(EmbreeRunner, SingleRayValidationTest) para->set_reference_frame_geometry(origin, aim, zrot); para->set_aperture(SolTrace::Data::make_aperture(31.0, 31.0)); para->set_surface(SolTrace::Data::make_surface(0.5 / 0.03, 0.5 / 0.03)); + SolTrace::Data::OpticalPropertySet parabola_optics(SolTrace::Data::InteractionType::REFLECTION, "Parabola"); + parabola_optics.set_ideal_absorption(SolTrace::Data::OpticalSide::Both); + parabola_optics.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 0.0, 0.0); + auto parabola_optics_ref = sd.add_optical_property_set(parabola_optics); + para->set_optical_property_set(parabola_optics_ref); para->set_name("Parabola"); sd.add_element(para); @@ -145,9 +153,11 @@ TEST(EmbreeRunner, PowerTowerSmokeTest) absorber->compute_coordinate_rotations(); absorber->set_surface(SolTrace::Data::make_surface()); // surface(nullptr) absorber->set_aperture(SolTrace::Data::make_aperture(2.0, 2.0)); - OpticalProperties *foptics = absorber->get_front_optical_properties(); - foptics->my_type = InteractionType::REFLECTION; - foptics->reflectivity = 0.0; + SolTrace::Data::OpticalPropertySet absorber_optics(SolTrace::Data::InteractionType::REFLECTION, "Absorber"); + absorber_optics.set_ideal_absorption(SolTrace::Data::OpticalSide::Both); + absorber_optics.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 0.0, 0.0); + auto absorber_optics_ref = sd.add_optical_property_set(absorber_optics); + absorber->set_optical_property_set(absorber_optics_ref); // Make stage 1 -- second stage -- these can be added to SimulationData // in any order but should be numbered in the desired order @@ -175,8 +185,12 @@ TEST(EmbreeRunner, PowerTowerSmokeTest) for (int k = 0; k < NUM_ELEMENTS; ++k) { auto el = SolTrace::Data::make_element(); - foptics = el->get_front_optical_properties(); - foptics->reflectivity = 1.0; + SolTrace::Data::OpticalPropertySet mirror_optics(SolTrace::Data::InteractionType::REFLECTION, "Mirror"); + mirror_optics.set_ideal_reflection(SolTrace::Data::OpticalSide::Front); + mirror_optics.set_ideal_absorption(SolTrace::Data::OpticalSide::Back); + mirror_optics.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 0.0, 0.0); + auto mirror_optics_ref = sd.add_optical_property_set(mirror_optics); + el->set_optical_property_set(mirror_optics_ref); pos = { 5 * sin(k * PI * 2.0 / NUM_ELEMENTS), diff --git a/google-tests/unit-tests/simulation_runner/native_runner/native_runner_multithreading_test.cpp b/google-tests/unit-tests/simulation_runner/native_runner/native_runner_multithreading_test.cpp index 1cd0ff41..70321ba5 100644 --- a/google-tests/unit-tests/simulation_runner/native_runner/native_runner_multithreading_test.cpp +++ b/google-tests/unit-tests/simulation_runner/native_runner/native_runner_multithreading_test.cpp @@ -42,8 +42,13 @@ namespace mirror->set_reference_frame_geometry(glm::dvec3(0.0, 0.0, 0.0), glm::dvec3(0.0, 0.0, 1.0), 0.0); - mirror->get_front_optical_properties()->set_ideal_reflection(); - mirror->get_back_optical_properties()->set_ideal_reflection(); + + SolTrace::Data::OpticalPropertySet mirror_optics_set(SolTrace::Data::InteractionType::REFLECTION, "Mirror"); + mirror_optics_set.set_ideal_reflection(SolTrace::Data::OpticalSide::Both); + mirror_optics_set.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 0.0, 0.0); + auto ref = sd.add_optical_property_set(mirror_optics_set); + mirror->set_optical_property_set(ref); + stage->add_element(mirror); sd.add_stage(stage); diff --git a/google-tests/unit-tests/simulation_runner/native_runner/native_runner_test.cpp b/google-tests/unit-tests/simulation_runner/native_runner/native_runner_test.cpp index c23f0e9b..2eaa1532 100644 --- a/google-tests/unit-tests/simulation_runner/native_runner/native_runner_test.cpp +++ b/google-tests/unit-tests/simulation_runner/native_runner/native_runner_test.cpp @@ -133,9 +133,11 @@ TEST(NativeRunner, ErrorOnUnsupportedOptions) auto mirror = SolTrace::Data::make_element(); mirror->set_aperture(make_aperture(10.0, 10.0)); mirror->set_surface(make_surface()); - auto opf = mirror->get_front_optical_properties(); - opf->set_ideal_reflection(); - opf->error_distribution_type = DistributionType::UNKNOWN; + SolTrace::Data::OpticalPropertySet mirror_optics(SolTrace::Data::InteractionType::REFLECTION, "Mirror"); + mirror_optics.set_ideal_one_sided_reflector(SolTrace::Data::OpticalSide::Front); + mirror_optics.set_errors(SolTrace::Data::OpticalSide::Front, SolTrace::Data::DistributionType::UNKNOWN, 0.0, 0.0); + auto mirror_optics_ref = my_sim.add_optical_property_set(mirror_optics); + mirror->set_optical_property_set(mirror_optics_ref); RunnerStatus sts; sts = runner.initialize(); @@ -168,9 +170,13 @@ TEST(NativeRunner, SmokeTest) const int NUM_ELEMENTS = 4; double x[NUM_ELEMENTS] = {1.0, 0.0, -1.0, 0.0}; double y[NUM_ELEMENTS] = {0.0, 1.0, 0.0, -1.0}; - OpticalProperties optics(SolTrace::Data::InteractionType::REFLECTION, - SolTrace::Data::DistributionType::GAUSSIAN, - 0.0, 1.0, 0.0, 0.0, 1.0, 1.0); + SolTrace::Data::OpticalPropertySet mirror_optics_set(SolTrace::Data::InteractionType::REFLECTION, "SmokeTestOptics"); + mirror_optics_set.set_ideal_reflection(SolTrace::Data::OpticalSide::Both); + mirror_optics_set.set_reflectivity(SolTrace::Data::OpticalSide::Front, 1.0); + mirror_optics_set.set_reflectivity(SolTrace::Data::OpticalSide::Back, 1.0); + mirror_optics_set.set_errors(SolTrace::Data::OpticalSide::Front, SolTrace::Data::DistributionType::GAUSSIAN, 0.0, 0.0); + mirror_optics_set.set_errors(SolTrace::Data::OpticalSide::Back, SolTrace::Data::DistributionType::GAUSSIAN, 0.0, 0.0); + auto optics_ref = my_sim.add_optical_property_set(mirror_optics_set); for (int k = 0; k < NUM_ELEMENTS; ++k) { @@ -180,8 +186,7 @@ TEST(NativeRunner, SmokeTest) el->set_reference_frame_geometry(glm::dvec3(x[k], y[k], 0.0), glm::dvec3(-x[k], -y[k], 1.0), 0.0); - el->set_front_optical_properties(optics); - el->set_back_optical_properties(optics); + el->set_optical_property_set(optics_ref); my_st->add_element(el); } @@ -257,9 +262,13 @@ TEST(NativeRunner, RaysLaunchedEqualsRequestedAfterRun) const int NUM_ELEMENTS = 4; double x[NUM_ELEMENTS] = {1.0, 0.0, -1.0, 0.0}; double y[NUM_ELEMENTS] = {0.0, 1.0, 0.0, -1.0}; - OpticalProperties optics(SolTrace::Data::InteractionType::REFLECTION, - SolTrace::Data::DistributionType::GAUSSIAN, - 0.0, 1.0, 0.0, 0.0, 1.0, 1.0); + SolTrace::Data::OpticalPropertySet mirror_optics_set(SolTrace::Data::InteractionType::REFLECTION, "RaysLaunchedOptics"); + mirror_optics_set.set_ideal_reflection(SolTrace::Data::OpticalSide::Both); + mirror_optics_set.set_reflectivity(SolTrace::Data::OpticalSide::Front, 1.0); + mirror_optics_set.set_reflectivity(SolTrace::Data::OpticalSide::Back, 1.0); + mirror_optics_set.set_errors(SolTrace::Data::OpticalSide::Front, SolTrace::Data::DistributionType::GAUSSIAN, 0.0, 0.0); + mirror_optics_set.set_errors(SolTrace::Data::OpticalSide::Back, SolTrace::Data::DistributionType::GAUSSIAN, 0.0, 0.0); + auto optics_ref = my_sim.add_optical_property_set(mirror_optics_set); for (int k = 0; k < NUM_ELEMENTS; ++k) { element_ptr el = SolTrace::Data::make_element(); @@ -268,8 +277,7 @@ TEST(NativeRunner, RaysLaunchedEqualsRequestedAfterRun) el->set_reference_frame_geometry(glm::dvec3(x[k], y[k], 0.0), glm::dvec3(-x[k], -y[k], 1.0), 0.0); - el->set_front_optical_properties(optics); - el->set_back_optical_properties(optics); + el->set_optical_property_set(optics_ref); my_st->add_element(el); } my_sim.add_stage(my_st); @@ -306,9 +314,10 @@ TEST(NativeRunner, PowerTowerSmokeTest) absorber->compute_coordinate_rotations(); absorber->set_surface(SolTrace::Data::make_surface()); // surface(nullptr) absorber->set_aperture(SolTrace::Data::make_aperture(2.0, 2.0)); - OpticalProperties *foptics = absorber->get_front_optical_properties(); - foptics->my_type = InteractionType::REFLECTION; - foptics->reflectivity = 0.0; + SolTrace::Data::OpticalPropertySet absorber_optics(SolTrace::Data::InteractionType::REFLECTION, "Absorber"); + absorber_optics.set_ideal_absorption(SolTrace::Data::OpticalSide::Both); + auto absorber_optics_ref = sd.add_optical_property_set(absorber_optics); + absorber->set_optical_property_set(absorber_optics_ref); // Make stage 1 -- second stage -- these can be added to SimulationData // in any order but should be numbered in the desired order @@ -336,8 +345,11 @@ TEST(NativeRunner, PowerTowerSmokeTest) for (int k = 0; k < NUM_ELEMENTS; ++k) { auto el = SolTrace::Data::make_element(); - foptics = el->get_front_optical_properties(); - foptics->reflectivity = 1.0; + SolTrace::Data::OpticalPropertySet mirror_optics(SolTrace::Data::InteractionType::REFLECTION, "Mirror"); + mirror_optics.set_ideal_one_sided_reflector(SolTrace::Data::OpticalSide::Front); + mirror_optics.set_ideal_absorption(SolTrace::Data::OpticalSide::Back); + auto mirror_optics_ref = sd.add_optical_property_set(mirror_optics); + el->set_optical_property_set(mirror_optics_ref); pos = {5 * sin(k * PI * 2.0 / NUM_ELEMENTS), 5 * cos(k * PI * 2.0 / NUM_ELEMENTS), 0.0}; rvec = glm::normalize(absorber->get_origin_global() - pos); @@ -460,8 +472,11 @@ TEST(NativeRunner, SingleRayValidationTest) sph->set_reference_frame_geometry(origin, aim, zrot); sph->set_aperture(SolTrace::Data::make_aperture(20.0)); sph->set_surface(SolTrace::Data::make_surface(c)); - sph->get_front_optical_properties()->set_ideal_reflection(); - sph->get_back_optical_properties()->set_ideal_reflection(); + SolTrace::Data::OpticalPropertySet sphere_optics(SolTrace::Data::InteractionType::REFLECTION, "Sphere"); + sphere_optics.set_ideal_reflection(SolTrace::Data::OpticalSide::Both); + sphere_optics.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 0.0, 0.0); + auto sphere_optics_ref = sd.add_optical_property_set(sphere_optics); + sph->set_optical_property_set(sphere_optics_ref); sph->set_name("Sphere"); sd.add_element(sph); @@ -472,6 +487,11 @@ TEST(NativeRunner, SingleRayValidationTest) para->set_reference_frame_geometry(origin, aim, zrot); para->set_aperture(SolTrace::Data::make_aperture(31.0, 31.0)); para->set_surface(SolTrace::Data::make_surface(0.5 / 0.03, 0.5 / 0.03)); + SolTrace::Data::OpticalPropertySet parabola_optics(SolTrace::Data::InteractionType::REFLECTION, "Parabola"); + parabola_optics.set_ideal_absorption(SolTrace::Data::OpticalSide::Both); + parabola_optics.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 0.0, 0.0); + auto parabola_optics_ref = sd.add_optical_property_set(parabola_optics); + para->set_optical_property_set(parabola_optics_ref); para->set_name("Parabola"); sd.add_element(para); diff --git a/google-tests/unit-tests/simulation_runner/native_runner/optical_error_test.cpp b/google-tests/unit-tests/simulation_runner/native_runner/optical_error_test.cpp index 0e0ea186..10a595e6 100644 --- a/google-tests/unit-tests/simulation_runner/native_runner/optical_error_test.cpp +++ b/google-tests/unit-tests/simulation_runner/native_runner/optical_error_test.cpp @@ -1,5 +1,6 @@ #include +#include #include #include @@ -36,13 +37,12 @@ TEST(OpticalErrors, Gaussian) plate->set_aperture(make_aperture(5, 5)); plate->set_name("plate"); - auto foptics = plate->get_front_optical_properties(); - foptics->set_ideal_reflection(); - foptics->slope_error = 1.0; - foptics->specularity_error = 1e-3; - foptics->error_distribution_type = DistributionType::GAUSSIAN; - - plate->get_back_optical_properties()->set_ideal_reflection(); + SolTrace::Data::OpticalPropertySet plate_optics(SolTrace::Data::InteractionType::REFLECTION, "plate_optics_gaussian"); + plate_optics.set_ideal_reflection(SolTrace::Data::OpticalSide::Both); + plate_optics.set_errors(SolTrace::Data::OpticalSide::Front, SolTrace::Data::DistributionType::GAUSSIAN, 1.0, 1e-3); + plate_optics.set_errors(SolTrace::Data::OpticalSide::Back, SolTrace::Data::DistributionType::NONE, 0.0, 0.0); + auto plate_optics_ref = sd.add_optical_property_set(plate_optics); + plate->set_optical_property_set(plate_optics_ref); // Add element to stage stage->add_element(plate); @@ -139,13 +139,12 @@ TEST(OpticalErrors, Uniform) plate->set_aperture(make_aperture(5, 5)); plate->set_name("plate"); - auto foptics = plate->get_front_optical_properties(); - foptics->set_ideal_reflection(); - foptics->slope_error = 1.0; - foptics->specularity_error = 1e-3; - foptics->error_distribution_type = DistributionType::PILLBOX; - - plate->get_back_optical_properties()->set_ideal_reflection(); + SolTrace::Data::OpticalPropertySet plate_optics(SolTrace::Data::InteractionType::REFLECTION, "plate_optics_uniform"); + plate_optics.set_ideal_reflection(SolTrace::Data::OpticalSide::Both); + plate_optics.set_errors(SolTrace::Data::OpticalSide::Front, SolTrace::Data::DistributionType::PILLBOX, 1.0, 1e-3); + plate_optics.set_errors(SolTrace::Data::OpticalSide::Back, SolTrace::Data::DistributionType::NONE, 0.0, 0.0); + auto plate_optics_ref = sd.add_optical_property_set(plate_optics); + plate->set_optical_property_set(plate_optics_ref); // Add element to stage stage->add_element(plate); diff --git a/google-tests/unit-tests/simulation_runner/native_runner/stage_test.cpp b/google-tests/unit-tests/simulation_runner/native_runner/stage_test.cpp index cbd9b778..ca3a4076 100644 --- a/google-tests/unit-tests/simulation_runner/native_runner/stage_test.cpp +++ b/google-tests/unit-tests/simulation_runner/native_runner/stage_test.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -21,6 +22,15 @@ static SimulationData create_two_flat_elements_simulation(const bool separateSta { SimulationData sd; + SolTrace::Data::OpticalPropertySet reflective_optics(SolTrace::Data::InteractionType::REFLECTION, "reflective_plate_optics"); + reflective_optics.set_ideal_reflection(SolTrace::Data::OpticalSide::Both); + reflective_optics.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 0.0, 0.0); + auto reflective_optics_ref = sd.add_optical_property_set(reflective_optics); + + SolTrace::Data::OpticalPropertySet absorber_optics(SolTrace::Data::InteractionType::REFLECTION, "absorbing_plate_optics"); + absorber_optics.set_ideal_absorption(SolTrace::Data::OpticalSide::Both); + auto absorber_optics_ref = sd.add_optical_property_set(absorber_optics); + // Sun auto sun = make_ray_source(); sun->set_position(0.0, 0.0, 100.0); @@ -33,8 +43,7 @@ static SimulationData create_two_flat_elements_simulation(const bool separateSta plate1->set_aim_vector(0, 50, 100); // Tilted 45 degrees toward +Y plate1->set_surface(make_surface()); plate1->set_aperture(make_aperture(10, 10)); - plate1->get_front_optical_properties()->set_ideal_reflection(); - plate1->get_back_optical_properties()->set_ideal_reflection(); + plate1->set_optical_property_set(reflective_optics_ref); plate1->set_name("plate1"); // Plate 2: Positioned to receive reflected rays from plate 1 @@ -44,8 +53,7 @@ static SimulationData create_two_flat_elements_simulation(const bool separateSta plate2->set_aim_vector(0, 0, 100); // Tilted 45 degrees toward -Y (facing plate 1) plate2->set_surface(make_surface()); plate2->set_aperture(make_aperture(5, 5)); // Smaller to absorb rays - plate2->get_front_optical_properties()->set_ideal_absorption(); - plate2->get_back_optical_properties()->set_ideal_absorption(); + plate2->set_optical_property_set(absorber_optics_ref); plate2->set_name("plate2"); if (separateStages) @@ -304,6 +312,12 @@ TEST(StageTest, DuplicateStageNumbersThrows) elA->set_aim_vector(0, 0, 100); elA->set_surface(make_surface()); elA->set_aperture(make_aperture(1, 1)); + { + SolTrace::Data::OpticalPropertySet optics(SolTrace::Data::InteractionType::REFLECTION, "duplicate_stage_A_optics"); + optics.set_ideal_reflection(SolTrace::Data::OpticalSide::Both); + optics.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 0.0, 0.0); + elA->set_optical_property_set(sd.add_optical_property_set(optics)); + } st0a->add_element(elA); auto elB = make_element(); @@ -311,6 +325,12 @@ TEST(StageTest, DuplicateStageNumbersThrows) elB->set_aim_vector(0, 0, 100); elB->set_surface(make_surface()); elB->set_aperture(make_aperture(1, 1)); + { + SolTrace::Data::OpticalPropertySet optics(SolTrace::Data::InteractionType::REFLECTION, "duplicate_stage_B_optics"); + optics.set_ideal_reflection(SolTrace::Data::OpticalSide::Both); + optics.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 0.0, 0.0); + elB->set_optical_property_set(sd.add_optical_property_set(optics)); + } st0b->add_element(elB); sd.add_stage(st0a); @@ -334,6 +354,12 @@ TEST(StageTest, ElementBeforeStageThrowsWhenStagesEnabled) el->set_aim_vector(0,0,100); el->set_surface(make_surface()); el->set_aperture(make_aperture(1,1)); + { + SolTrace::Data::OpticalPropertySet optics(SolTrace::Data::InteractionType::REFLECTION, "element_before_stage_optics"); + optics.set_ideal_reflection(SolTrace::Data::OpticalSide::Both); + optics.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 0.0, 0.0); + el->set_optical_property_set(sd.add_optical_property_set(optics)); + } sd.add_element(el); auto st0 = make_stage(0); @@ -343,6 +369,12 @@ TEST(StageTest, ElementBeforeStageThrowsWhenStagesEnabled) elB->set_aim_vector(0, 0, 100); elB->set_surface(make_surface()); elB->set_aperture(make_aperture(1, 1)); + { + SolTrace::Data::OpticalPropertySet optics(SolTrace::Data::InteractionType::REFLECTION, "element_before_stage_B_optics"); + optics.set_ideal_reflection(SolTrace::Data::OpticalSide::Both); + optics.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 0.0, 0.0); + elB->set_optical_property_set(sd.add_optical_property_set(optics)); + } st0->add_element(elB); sd.add_stage(st0); @@ -365,6 +397,12 @@ TEST(StageTest, ElementBeforeStageSucceedsWhenStagesDisabled) el->set_aim_vector(0,0,100); el->set_surface(make_surface()); el->set_aperture(make_aperture(1,1)); + { + SolTrace::Data::OpticalPropertySet optics(SolTrace::Data::InteractionType::REFLECTION, "element_before_stage_disabled_optics"); + optics.set_ideal_reflection(SolTrace::Data::OpticalSide::Both); + optics.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 0.0, 0.0); + el->set_optical_property_set(sd.add_optical_property_set(optics)); + } sd.add_element(el); auto st0 = make_stage(0); @@ -374,6 +412,12 @@ TEST(StageTest, ElementBeforeStageSucceedsWhenStagesDisabled) elB->set_aim_vector(0, 0, 100); elB->set_surface(make_surface()); elB->set_aperture(make_aperture(1, 1)); + { + SolTrace::Data::OpticalPropertySet optics(SolTrace::Data::InteractionType::REFLECTION, "element_before_stage_disabled_B_optics"); + optics.set_ideal_reflection(SolTrace::Data::OpticalSide::Both); + optics.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 0.0, 0.0); + elB->set_optical_property_set(sd.add_optical_property_set(optics)); + } st0->add_element(elB); sd.add_stage(st0); @@ -403,6 +447,12 @@ TEST(StageTest, NoStagesCreatesSingleInternalStage) el->set_aim_vector(0,0,100); el->set_surface(make_surface()); el->set_aperture(make_aperture(2,2)); + { + SolTrace::Data::OpticalPropertySet optics(SolTrace::Data::InteractionType::REFLECTION, "no_stage_internal_optics"); + optics.set_ideal_reflection(SolTrace::Data::OpticalSide::Both); + optics.set_errors(SolTrace::Data::OpticalSide::Both, SolTrace::Data::DistributionType::NONE, 0.0, 0.0); + el->set_optical_property_set(sd.add_optical_property_set(optics)); + } sd.add_element(el); NativeRunner runner; diff --git a/google-tests/unit-tests/simulation_runner/native_runner/tower_demo.cpp b/google-tests/unit-tests/simulation_runner/native_runner/tower_demo.cpp index f1f51106..91268e4d 100644 --- a/google-tests/unit-tests/simulation_runner/native_runner/tower_demo.cpp +++ b/google-tests/unit-tests/simulation_runner/native_runner/tower_demo.cpp @@ -40,9 +40,12 @@ SimulationData create_tower_demo_simulation_data(bool create_stages) absorber->compute_coordinate_rotations(); absorber->set_surface(make_surface()); // surface(nullptr) absorber->set_aperture(make_aperture(2.0, 2.0)); - OpticalProperties *foptics = absorber->get_front_optical_properties(); - foptics->my_type = InteractionType::REFLECTION; - foptics->reflectivity = 0.0; + + SolTrace::Data::OpticalPropertySet abs_optics(SolTrace::Data::InteractionType::REFLECTION, "Absorber"); + abs_optics.set_ideal_absorption(SolTrace::Data::OpticalSide::Both); + auto abs_ref = sd.add_optical_property_set(abs_optics); + absorber->set_optical_property_set(abs_ref); + absorber->set_name("Absorber"); stage_ptr st0, st1; @@ -76,11 +79,14 @@ SimulationData create_tower_demo_simulation_data(bool create_stages) glm::dvec3 rvec, svec, avec; glm::dvec3 aim, pos; + SolTrace::Data::OpticalPropertySet mirror_optics_set(SolTrace::Data::InteractionType::REFLECTION, "Mirror"); + mirror_optics_set.set_ideal_reflection(SolTrace::Data::OpticalSide::Both); + auto mirror_optics_ref = sd.add_optical_property_set(mirror_optics_set); + for (int i = -1; i < 2; ++i) { auto el = make_element(); - foptics = el->get_front_optical_properties(); - foptics->reflectivity = 1.0; + el->set_optical_property_set(mirror_optics_ref); pos = {5 * sin(i * PI / 2.0), 5 * cos(i * PI / 2.0), 0.0}; el->set_origin(pos); diff --git a/google-tests/unit-tests/simulation_runner/optix_runner/flat_optical_test.cpp b/google-tests/unit-tests/simulation_runner/optix_runner/flat_optical_test.cpp index 212b9066..5fa83588 100644 --- a/google-tests/unit-tests/simulation_runner/optix_runner/flat_optical_test.cpp +++ b/google-tests/unit-tests/simulation_runner/optix_runner/flat_optical_test.cpp @@ -1,12 +1,15 @@ #include #include +#include #include #include #include using SolTrace::Runner::RunnerStatus; +using SolTrace::Data::OpticalPropertySet; + void make_default_sd(SimulationData& sd, element_ptr& plate) { sd.clear(); @@ -36,10 +39,13 @@ void make_default_sd(SimulationData& sd, element_ptr& plate) double spec_err = 0; double ri_front = 0; // Refraction not supported double ri_back = 0; - OpticalProperties plate_optics = OpticalProperties(itype, dtype, transmissivity, - reflectivity, slope_err, spec_err, ri_front, ri_back); - plate->set_front_optical_properties(plate_optics); - plate->set_back_optical_properties(plate_optics); + + OpticalPropertySet plate_opt(itype, ri_front, ri_back, "PlateOptics"); + plate_opt.set_properties(OpticalSide::Both, dtype, transmissivity, reflectivity, + slope_err, spec_err); + auto plate_opt_ref = sd.add_optical_property_set(plate_opt); + plate->set_optical_property_set(plate_opt_ref); + plate->set_name("plate"); // Add element to stage @@ -96,10 +102,10 @@ TEST(FlatOptixOptical, Transmissivity) // Set plate properties (transmissive) double transmissivity = 0.8; - plate->get_front_optical_properties()->my_type = InteractionType::REFRACTION; - plate->get_front_optical_properties()->transmitivity = transmissivity; - plate->get_back_optical_properties()->my_type = InteractionType::REFRACTION; - plate->get_back_optical_properties()->transmitivity = transmissivity; + OpticalPropertySet* plate_opt_set = sd.get_mutable_optical_property_set(*plate); + ASSERT_NE(plate_opt_set, nullptr); + plate_opt_set->set_interaction_type(InteractionType::REFRACTION); + plate_opt_set->set_transmissivity(OpticalSide::Both, transmissivity); // Run simulation OptixRunner runner; @@ -133,10 +139,10 @@ TEST(FlatOptixOptical, Reflectivity) // Set plate properties (reflective) double reflectivity = 0.6; - plate->get_front_optical_properties()->my_type = InteractionType::REFLECTION; - plate->get_front_optical_properties()->reflectivity = reflectivity; - plate->get_back_optical_properties()->my_type = InteractionType::REFLECTION; - plate->get_back_optical_properties()->reflectivity = reflectivity; + OpticalPropertySet* plate_opt_set = sd.get_mutable_optical_property_set(*plate); + ASSERT_NE(plate_opt_set, nullptr); + plate_opt_set->set_interaction_type(InteractionType::REFLECTION); + plate_opt_set->set_reflectivity(OpticalSide::Both, reflectivity); // Run simulation OptixRunner runner; @@ -169,10 +175,10 @@ TEST(FlatOptixOptical, SimResults) // Set plate properties (reflective) double reflectivity = 0.6; - plate->get_front_optical_properties()->my_type = InteractionType::REFLECTION; - plate->get_front_optical_properties()->reflectivity = reflectivity; - plate->get_back_optical_properties()->my_type = InteractionType::REFLECTION; - plate->get_back_optical_properties()->reflectivity = reflectivity; + OpticalPropertySet* plate_opt_set = sd.get_mutable_optical_property_set(*plate); + ASSERT_NE(plate_opt_set, nullptr); + plate_opt_set->set_interaction_type(InteractionType::REFLECTION); + plate_opt_set->set_reflectivity(OpticalSide::Both, reflectivity); // Run simulation OptixRunner runner; @@ -231,8 +237,9 @@ TEST(FlatOptixOptical, Absorption) make_default_sd(sd, plate); // Set plate properties (absorptive - no reflection, no transmission) - plate->get_front_optical_properties()->set_ideal_absorption(); - plate->get_back_optical_properties()->set_ideal_absorption(); + OpticalPropertySet* plate_opt_set = sd.get_mutable_optical_property_set(*plate); + ASSERT_NE(plate_opt_set, nullptr); + plate_opt_set->set_ideal_absorption(OpticalSide::Both); // Run simulation OptixRunner runner; @@ -264,8 +271,9 @@ TEST(FlatOptixOptical, IdealReflection) make_default_sd(sd, plate); // Set plate properties (ideal reflection) - plate->get_front_optical_properties()->set_ideal_reflection(); - plate->get_back_optical_properties()->set_ideal_reflection(); + OpticalPropertySet* plate_opt_set = sd.get_mutable_optical_property_set(*plate); + ASSERT_NE(plate_opt_set, nullptr); + plate_opt_set->set_ideal_reflection(OpticalSide::Both); // Run simulation OptixRunner runner; @@ -303,10 +311,10 @@ TEST(FlatOptixOptical, SeedReproducibility) // Set plate properties double reflectivity = 0.5; - plate->get_front_optical_properties()->my_type = InteractionType::REFLECTION; - plate->get_front_optical_properties()->reflectivity = reflectivity; - plate->get_back_optical_properties()->my_type = InteractionType::REFLECTION; - plate->get_back_optical_properties()->reflectivity = reflectivity; + OpticalPropertySet* plate_opt_set = sd.get_mutable_optical_property_set(*plate); + EXPECT_NE(plate_opt_set, nullptr); + plate_opt_set->set_interaction_type(InteractionType::REFLECTION); + plate_opt_set->set_reflectivity(OpticalSide::Both, reflectivity); OptixRunner runner; runner.initialize(); @@ -342,10 +350,10 @@ TEST(FlatOptixOptical, RayCountScaling) params.number_of_rays = num_rays; params.max_number_of_rays = num_rays * 100; - plate->get_front_optical_properties()->my_type = InteractionType::REFLECTION; - plate->get_front_optical_properties()->reflectivity = reflectivity; - plate->get_back_optical_properties()->my_type = InteractionType::REFLECTION; - plate->get_back_optical_properties()->reflectivity = reflectivity; + OpticalPropertySet* plate_opt_set = sd.get_mutable_optical_property_set(*plate); + EXPECT_NE(plate_opt_set, nullptr); + plate_opt_set->set_interaction_type(InteractionType::REFLECTION); + plate_opt_set->set_reflectivity(OpticalSide::Both, reflectivity); OptixRunner runner; runner.initialize(); @@ -380,10 +388,10 @@ TEST(FlatOptixOptical, MixedReflectionAbsorption) // Set plate properties with partial reflection and absorption double reflectivity = 0.4; - plate->get_front_optical_properties()->my_type = InteractionType::REFLECTION; - plate->get_front_optical_properties()->reflectivity = reflectivity; - plate->get_back_optical_properties()->my_type = InteractionType::REFLECTION; - plate->get_back_optical_properties()->reflectivity = reflectivity; + OpticalPropertySet* plate_opt_set = sd.get_mutable_optical_property_set(*plate); + ASSERT_NE(plate_opt_set, nullptr); + plate_opt_set->set_interaction_type(InteractionType::REFLECTION); + plate_opt_set->set_reflectivity(OpticalSide::Both, reflectivity); // Run simulation OptixRunner runner; diff --git a/google-tests/unit-tests/simulation_runner/optix_runner/geometry_intersection_test.cpp b/google-tests/unit-tests/simulation_runner/optix_runner/geometry_intersection_test.cpp index b1dd3f36..b3f065d8 100644 --- a/google-tests/unit-tests/simulation_runner/optix_runner/geometry_intersection_test.cpp +++ b/google-tests/unit-tests/simulation_runner/optix_runner/geometry_intersection_test.cpp @@ -30,10 +30,11 @@ element_id set_default_sd(SimulationData &sd, el->set_surface(surf); el->set_aperture(ap); - OpticalProperties el_optics; - el_optics.set_ideal_absorption(); - el->set_front_optical_properties(el_optics); - el->set_back_optical_properties(el_optics); + OpticalPropertySet optics(InteractionType::REFLECTION, 0, 0); + optics.set_ideal_absorption(OpticalSide::Both); + auto opt_ref = sd.add_optical_property_set(optics); + el->set_optical_property_set(opt_ref); + el->set_name("el"); // Add element to stage @@ -50,6 +51,7 @@ element_id set_default_sd(SimulationData &sd, stop->set_aim_vector(0, 0, 100); stop->set_surface(make_surface()); stop->set_aperture(make_aperture(sx, sy)); + stop->set_optical_property_set(opt_ref); sd.add_element(stop); // Set parameters diff --git a/google-tests/unit-tests/simulation_runner/optix_runner/gpu_tower_demo.cpp b/google-tests/unit-tests/simulation_runner/optix_runner/gpu_tower_demo.cpp index f99fb8e8..095a2459 100644 --- a/google-tests/unit-tests/simulation_runner/optix_runner/gpu_tower_demo.cpp +++ b/google-tests/unit-tests/simulation_runner/optix_runner/gpu_tower_demo.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -31,9 +32,15 @@ TEST(GpuTowerDemo, OptixRunnerWithStages) absorber->set_aim_vector(0.0, 5.0, 0.0); absorber->set_surface(make_surface()); absorber->set_aperture(make_aperture(2.0, 2.0)); - OpticalProperties *foptics = absorber->get_front_optical_properties(); - foptics->my_type = InteractionType::REFLECTION; - foptics->reflectivity = 0.0; + + SolTrace::Data::OpticalPropertySet absorber_optics( + InteractionType::REFLECTION, + 0.0, + 0.0, + "absorber_optics"); + absorber_optics.set_ideal_absorption(OpticalSide::Both); + auto absorber_optics_ref = sd.add_optical_property_set(absorber_optics); + absorber->set_optical_property_set(absorber_optics_ref); absorber->set_name("Absorber"); // // Absorber -- Cylindrical -- MAY NOT WORK DUE TO UNIMPLEMENTED CODE! @@ -71,11 +78,18 @@ TEST(GpuTowerDemo, OptixRunnerWithStages) double spacing = PI / 4.0; + SolTrace::Data::OpticalPropertySet reflector_optics( + InteractionType::REFLECTION, + 0.0, + 0.0, + "reflector_optics"); + reflector_optics.set_ideal_one_sided_reflector(); + auto reflector_optics_ref = sd.add_optical_property_set(reflector_optics); + for (int i = -1; i < 4; ++i) { auto el = make_element(); - foptics = el->get_front_optical_properties(); - foptics->reflectivity = 1.0; + el->set_optical_property_set(reflector_optics_ref); pos = {5 * sin(i * spacing), 5 * cos(i * spacing), @@ -171,7 +185,14 @@ static void setup_tower_sd(SimulationData &sd, uint_fast64_t nrays) absorber->set_aim_vector(0.0, 5.0, 0.0); absorber->set_surface(make_surface()); absorber->set_aperture(make_aperture(2.0, 2.0)); - absorber->get_front_optical_properties()->set_ideal_absorption(); + SolTrace::Data::OpticalPropertySet absorber_optics( + InteractionType::REFLECTION, + 0.0, + 0.0, + "tower_absorber_optics"); + absorber_optics.set_ideal_absorption(OpticalSide::Both); + auto absorber_optics_ref = sd.add_optical_property_set(absorber_optics); + absorber->set_optical_property_set(absorber_optics_ref); auto st1 = make_stage(1); st1->set_origin(0.0, 0.0, 0.0); @@ -183,10 +204,17 @@ static void setup_tower_sd(SimulationData &sd, uint_fast64_t nrays) st0->set_aim_vector(0.0, 0.0, 1.0); const double spacing = PI / 4.0; + SolTrace::Data::OpticalPropertySet reflector_optics( + InteractionType::REFLECTION, + 0.0, + 0.0, + "tower_reflector_optics"); + reflector_optics.set_ideal_one_sided_reflector(); + auto reflector_optics_ref = sd.add_optical_property_set(reflector_optics); for (int i = -1; i < 4; ++i) { auto el = make_element(); - el->get_front_optical_properties()->reflectivity = 1.0; + el->set_optical_property_set(reflector_optics_ref); glm::dvec3 pos = {5 * sin(i * spacing), 5 * cos(i * spacing), 0.0}; el->set_origin(pos); diff --git a/google-tests/unit-tests/simulation_runner/optix_runner/max_ray_depth_test.cpp b/google-tests/unit-tests/simulation_runner/optix_runner/max_ray_depth_test.cpp index 59702454..f4d97eed 100644 --- a/google-tests/unit-tests/simulation_runner/optix_runner/max_ray_depth_test.cpp +++ b/google-tests/unit-tests/simulation_runner/optix_runner/max_ray_depth_test.cpp @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -209,8 +210,14 @@ TEST(OptixRunnerMaxRayDepth, DepthExceededCounterCountsTerminatedReflectedRays) make_two_plate_sd(sd, plate1, plate2); // Override plate 2 to be reflective so hitting it at max_depth triggers the counter. - plate2->get_front_optical_properties()->set_ideal_reflection(); - plate2->get_back_optical_properties()->set_ideal_reflection(); + SolTrace::Data::OpticalPropertySet reflective_optics( + SolTrace::Data::InteractionType::REFLECTION, + 0.0, + 0.0, + "max_depth_reflective_override"); + reflective_optics.set_ideal_reflection(OpticalSide::Both); + auto reflective_optics_ref = sd.add_optical_property_set(reflective_optics); + plate2->set_optical_property_set(reflective_optics_ref); OptixRunner runner; runner.set_max_ray_depth(2); // max interactions per ray = 1 (plate 1 only) diff --git a/google-tests/unit-tests/simulation_runner/optix_runner/ray_position_sampling_test.cpp b/google-tests/unit-tests/simulation_runner/optix_runner/ray_position_sampling_test.cpp index 244a9687..a67c519e 100644 --- a/google-tests/unit-tests/simulation_runner/optix_runner/ray_position_sampling_test.cpp +++ b/google-tests/unit-tests/simulation_runner/optix_runner/ray_position_sampling_test.cpp @@ -8,6 +8,7 @@ #include +#include #include #include #include @@ -111,11 +112,14 @@ namespace plate->set_aim_vector(0, 0, 100); plate->set_surface(make_surface()); plate->set_aperture(make_aperture(200, 200)); - OpticalProperties op(InteractionType::REFLECTION, - DistributionType::NONE, - 0, 1, 0, 0, 0, 0); - plate->set_front_optical_properties(op); - plate->set_back_optical_properties(op); + SolTrace::Data::OpticalPropertySet plate_optics( + SolTrace::Data::InteractionType::REFLECTION, + 0.0, + 0.0, + "ray_position_sampling_plate_optics"); + plate_optics.set_ideal_reflection(OpticalSide::Both); + auto plate_optics_ref = sd.add_optical_property_set(plate_optics); + plate->set_optical_property_set(plate_optics_ref); plate->set_name("plate"); stage->add_element(plate); diff --git a/google-tests/unit-tests/simulation_runner/optix_runner/sun_test.cpp b/google-tests/unit-tests/simulation_runner/optix_runner/sun_test.cpp index 5db70cdf..5b564f66 100644 --- a/google-tests/unit-tests/simulation_runner/optix_runner/sun_test.cpp +++ b/google-tests/unit-tests/simulation_runner/optix_runner/sun_test.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include #include @@ -9,6 +10,7 @@ #include using SolTrace::Runner::RunnerStatus; +using SolTrace::Data::OpticalPropertySet; namespace { @@ -329,10 +331,14 @@ namespace double spec_err = 0; double ri_front = 0; // Refraction not supported double ri_back = 0; - OpticalProperties plate_optics(itype, dtype, transmissivity, - reflectivity, slope_err, spec_err, ri_front, ri_back); - plate->set_front_optical_properties(plate_optics); - plate->set_back_optical_properties(plate_optics); + + OpticalPropertySet plate_optics(itype, ri_front, ri_back, + "PlateOptics"); + plate_optics.set_properties(OpticalSide::Both, dtype, transmissivity, + reflectivity, slope_err, spec_err); + auto optics_ref = sd.add_optical_property_set(plate_optics); + plate->set_optical_property_set(optics_ref); + plate->set_name("plate"); // Add element to stage diff --git a/google-tests/unit-tests/simulation_runner/optix_runner/two_plate_test.cpp b/google-tests/unit-tests/simulation_runner/optix_runner/two_plate_test.cpp index b88f5916..cf883d6a 100644 --- a/google-tests/unit-tests/simulation_runner/optix_runner/two_plate_test.cpp +++ b/google-tests/unit-tests/simulation_runner/optix_runner/two_plate_test.cpp @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -29,8 +30,14 @@ void make_two_plate_sd(SimulationData& sd, element_ptr& plate1, element_ptr& pla plate1->set_aim_vector(0, 50, 100); // Tilted 45 degrees toward +Y plate1->set_surface(make_surface()); plate1->set_aperture(make_aperture(5, 5)); - plate1->get_front_optical_properties()->set_ideal_reflection(); - plate1->get_back_optical_properties()->set_ideal_reflection(); + SolTrace::Data::OpticalPropertySet reflective_optics( + SolTrace::Data::InteractionType::REFLECTION, + 0.0, + 0.0, + "two_plate_reflector_optics"); + reflective_optics.set_ideal_reflection(OpticalSide::Both); + auto reflective_optics_ref = sd.add_optical_property_set(reflective_optics); + plate1->set_optical_property_set(reflective_optics_ref); plate1->set_name("plate1"); // Plate 2: Positioned to receive reflected rays from plate 1 @@ -40,8 +47,14 @@ void make_two_plate_sd(SimulationData& sd, element_ptr& plate1, element_ptr& pla plate2->set_aim_vector(0, 0, 100); // Tilted 45 degrees toward -Y (facing plate 1) plate2->set_surface(make_surface()); plate2->set_aperture(make_aperture(10, 10)); // Larger to catch reflected rays - plate2->get_front_optical_properties()->set_ideal_absorption(); - plate2->get_back_optical_properties()->set_ideal_absorption(); + SolTrace::Data::OpticalPropertySet absorbing_optics( + SolTrace::Data::InteractionType::REFLECTION, + 0.0, + 0.0, + "two_plate_absorber_optics"); + absorbing_optics.set_ideal_absorption(OpticalSide::Both); + auto absorbing_optics_ref = sd.add_optical_property_set(absorbing_optics); + plate2->set_optical_property_set(absorbing_optics_ref); plate2->set_name("plate2"); // Add elements to stage diff --git a/google-tests/unit-tests/simulation_runner/optix_runner/vector_error_test.cpp b/google-tests/unit-tests/simulation_runner/optix_runner/vector_error_test.cpp index c1fb698c..5ccebc50 100644 --- a/google-tests/unit-tests/simulation_runner/optix_runner/vector_error_test.cpp +++ b/google-tests/unit-tests/simulation_runner/optix_runner/vector_error_test.cpp @@ -1,10 +1,22 @@ #include +#include #include #include #include +static OpticalPropertySetReference add_plate_optics(SimulationData& sd, + SolTrace::Data::DistributionType distribution) +{ + SolTrace::Data::OpticalPropertySet plate_optics(SolTrace::Data::InteractionType::REFLECTION, + "plate_optics"); + plate_optics.set_ideal_reflection(OpticalSide::Both); + plate_optics.set_errors(OpticalSide::Front, distribution, 1, 1e-3); + + return sd.add_optical_property_set(plate_optics); +} + TEST(OpticalErrors, Disabled) { const uint_fast64_t NRAYS = 10000; @@ -35,14 +47,7 @@ TEST(OpticalErrors, Disabled) plate->set_surface(make_surface()); plate->set_aperture(make_aperture(5, 5)); plate->set_name("plate"); - - auto foptics = plate->get_front_optical_properties(); - foptics->set_ideal_reflection(); - foptics->slope_error = 1.0; - foptics->specularity_error = 1e-3; - foptics->error_distribution_type = DistributionType::GAUSSIAN; - - plate->get_back_optical_properties()->set_ideal_reflection(); + plate->set_optical_property_set(add_plate_optics(sd, SolTrace::Data::DistributionType::GAUSSIAN)); // Add element to stage stage->add_element(plate); @@ -141,14 +146,7 @@ TEST(OpticalErrors, None) plate->set_surface(make_surface()); plate->set_aperture(make_aperture(5, 5)); plate->set_name("plate"); - - auto foptics = plate->get_front_optical_properties(); - foptics->set_ideal_reflection(); - foptics->slope_error = 1.0; - foptics->specularity_error = 1e-3; - foptics->error_distribution_type = DistributionType::NONE; - - plate->get_back_optical_properties()->set_ideal_reflection(); + plate->set_optical_property_set(add_plate_optics(sd, SolTrace::Data::DistributionType::NONE)); // Add element to stage stage->add_element(plate); @@ -247,14 +245,7 @@ TEST(OpticalErrors, Gaussian) plate->set_surface(make_surface()); plate->set_aperture(make_aperture(5, 5)); plate->set_name("plate"); - - auto foptics = plate->get_front_optical_properties(); - foptics->set_ideal_reflection(); - foptics->slope_error = 1.0; - foptics->specularity_error = 1e-3; - foptics->error_distribution_type = DistributionType::GAUSSIAN; - - plate->get_back_optical_properties()->set_ideal_reflection(); + plate->set_optical_property_set(add_plate_optics(sd, SolTrace::Data::DistributionType::GAUSSIAN)); // Add element to stage stage->add_element(plate); @@ -352,14 +343,7 @@ TEST(OpticalErrors, PILLBOX) plate->set_surface(make_surface()); plate->set_aperture(make_aperture(5, 5)); plate->set_name("plate"); - - auto foptics = plate->get_front_optical_properties(); - foptics->set_ideal_reflection(); - foptics->slope_error = 1.0; - foptics->specularity_error = 1e-3; - foptics->error_distribution_type = DistributionType::PILLBOX; - - plate->get_back_optical_properties()->set_ideal_reflection(); + plate->set_optical_property_set(add_plate_optics(sd, SolTrace::Data::DistributionType::PILLBOX)); // Add element to stage stage->add_element(plate);