diff --git a/Core/Binning/SimulationElement.cpp b/Core/Binning/SimulationElement.cpp index 307c4f012f74f335ebaf624633686852b59aa4d7..8aef522613003862b6d46313304e3aed235b9af4 100644 --- a/Core/Binning/SimulationElement.cpp +++ b/Core/Binning/SimulationElement.cpp @@ -25,25 +25,28 @@ SimulationElement::SimulationElement(double wavelength, double alpha_i, double p , m_phi_i(phi_i) , m_intensity(0.0) , mP_pixel(std::move(pixel)) - , m_contains_specular(false) { initPolarization(); } SimulationElement::SimulationElement(const SimulationElement& other) : m_wavelength(other.m_wavelength), m_alpha_i(other.m_alpha_i), m_phi_i(other.m_phi_i) - , m_intensity(other.m_intensity), m_contains_specular(other.m_contains_specular) + , m_intensity(other.m_intensity) { mP_pixel.reset(other.mP_pixel->clone()); + if (other.m_specular_data) + m_specular_data.reset(new SpecularData(*other.m_specular_data)); m_polarization = other.m_polarization; m_analyzer_operator = other.m_analyzer_operator; } SimulationElement::SimulationElement(const SimulationElement& other, double x, double y) : m_wavelength(other.m_wavelength), m_alpha_i(other.m_alpha_i), m_phi_i(other.m_phi_i) - , m_intensity(other.m_intensity), m_contains_specular(other.m_contains_specular) + , m_intensity(other.m_intensity) { mP_pixel.reset(other.mP_pixel->createZeroSizePixel(x, y)); + if (other.m_specular_data) + m_specular_data.reset(new SpecularData(*other.m_specular_data)); m_polarization = other.m_polarization; m_analyzer_operator = other.m_analyzer_operator; } @@ -56,7 +59,7 @@ SimulationElement::SimulationElement(SimulationElement&& other) noexcept , m_polarization(std::move(other.m_polarization)) , m_analyzer_operator(std::move(other.m_analyzer_operator)) , mP_pixel(std::move(other.mP_pixel)) - , m_contains_specular(other.m_contains_specular) + , m_specular_data(std::move(other.m_specular_data)) { } @@ -108,7 +111,7 @@ void SimulationElement::swapContent(SimulationElement &other) std::swap(m_polarization, other.m_polarization); std::swap(m_analyzer_operator, other.m_analyzer_operator); std::swap(mP_pixel, other.mP_pixel); - std::swap(m_contains_specular, other.m_contains_specular); + std::swap(m_specular_data, other.m_specular_data); } void SimulationElement::initPolarization() @@ -127,14 +130,14 @@ double SimulationElement::getPhi(double x, double y) const return getKf(x,y).phi(); } -bool SimulationElement::containsSpecularWavevector() const +void SimulationElement::setSpecular() { - return m_contains_specular; + m_specular_data.reset(new SpecularData); } -void SimulationElement::setSpecular(bool contains_specular) +void SimulationElement::setSpecular(std::unique_ptr<SpecularData> specular_data) { - m_contains_specular = contains_specular; + m_specular_data = std::move(specular_data); } double SimulationElement::getIntegrationFactor(double x, double y) const { @@ -152,3 +155,26 @@ void addElementsWithWeight(std::vector<SimulationElement>::const_iterator first, for (std::vector<SimulationElement>::const_iterator it = first; it != last; ++it, ++result) result->addIntensity(it->getIntensity() * weight); } + +SpecularData::SpecularData() : data_type_used(DATA_TYPE::Invalid) {} + +SpecularData::SpecularData(MatrixVector coefficients) + : data(std::move(coefficients)) + , data_type_used(DATA_TYPE::Matrix) +{} + +SpecularData::SpecularData(ScalarVector coefficients) + : data(std::move(coefficients)) + , data_type_used(DATA_TYPE::Scalar) +{} + +const ILayerRTCoefficients& SpecularData::operator[](size_t index) const +{ + if (data_type_used == DATA_TYPE::Invalid) + throw std::runtime_error( + "Error in SpecularData::operator[]: attempt to access uninitialized data"); + if (data_type_used == DATA_TYPE::Scalar) + return (*boost::get<ScalarVector>(&data))[index]; + else + return (*boost::get<MatrixVector>(&data))[index]; +} diff --git a/Core/Binning/SimulationElement.h b/Core/Binning/SimulationElement.h index 09017df9ad2540da692fa095b9aed4eb660e87a9..a2c965dc4cea2be6707ee3145870affb3ba3a6ae 100644 --- a/Core/Binning/SimulationElement.h +++ b/Core/Binning/SimulationElement.h @@ -20,10 +20,14 @@ #include "EigenCore.h" #include "Vectors3D.h" #include "IPixel.h" +#include "MatrixRTCoefficients.h" +#include "ScalarRTCoefficients.h" +#include <boost/variant.hpp> #include <memory> #include <vector> class IPixel; +class SpecularData; //! Data stucture containing both input and output of a single detector cell. //! @ingroup simulation @@ -80,11 +84,12 @@ public: double getAlpha(double x, double y) const; double getPhi(double x, double y) const; - //! check if element contains given wavevector - bool containsSpecularWavevector() const; + //! check if element corresponds to specular peak + SpecularData* specularData() const {return m_specular_data.get();} - //! indicate that this element contains the specular wavevector - void setSpecular(bool contains_specular); + //! Turn on specular data + void setSpecular(); + void setSpecular(std::unique_ptr<SpecularData> specular_data); private: void swapContent(SimulationElement &other); @@ -99,7 +104,7 @@ private: Eigen::Matrix2cd m_analyzer_operator; //!< polarization analyzer operator #endif std::unique_ptr<IPixel> mP_pixel; - bool m_contains_specular; + std::unique_ptr<SpecularData> m_specular_data; }; @@ -109,4 +114,29 @@ void addElementsWithWeight(std::vector<SimulationElement>::const_iterator first, std::vector<SimulationElement>::iterator result, double weight); +//! Helper class for SimulationElement to carry specular information +//! @ingroup simulation + +class SpecularData +{ + // FIXME: find a better way to carry the specular data in SimulationElement + using ScalarVector = std::vector<ScalarRTCoefficients>; + using MatrixVector = std::vector<MatrixRTCoefficients>; +public: + SpecularData(); + + SpecularData(MatrixVector coefficients); + + SpecularData(ScalarVector coefficients); + + const ILayerRTCoefficients& operator[](size_t index) const; + + bool isInited() const {return data_type_used != DATA_TYPE::Invalid;} + +private: + enum class DATA_TYPE { Invalid = -1, Scalar, Matrix }; + boost::variant<ScalarVector, MatrixVector> data; + DATA_TYPE data_type_used; +}; + #endif // SIMULATIONELEMENT_H diff --git a/Core/Computation/SpecularComputationTerm.cpp b/Core/Computation/SpecularComputationTerm.cpp index b7dc91548a7aaa5f781a0d5e22701a8b1185c6ea..954e51680477c30c66fd18e89a00290db2a720d1 100644 --- a/Core/Computation/SpecularComputationTerm.cpp +++ b/Core/Computation/SpecularComputationTerm.cpp @@ -17,12 +17,13 @@ void SpecularComputationTerm::eval(ProgressHandler*, return; for (auto it = begin_it; it != end_it; ++it) - if (it->containsSpecularWavevector()) + if (it->specularData()) evalSingle(it); } void SpecularComputationTerm::evalSingle(const std::vector<SimulationElement>::iterator& iter) const { - complex_t R = mp_fresnel_map->getInCoefficients(*iter, 0)->getScalarR(); - iter->setIntensity(std::norm(R)); + mp_fresnel_map->fillSpecularData(*iter); + const ILayerRTCoefficients& layer_data = (*iter->specularData())[0]; + iter->setIntensity(std::norm(layer_data.getScalarR())); } diff --git a/Core/Instrument/IDetector2D.cpp b/Core/Instrument/IDetector2D.cpp index d4e807e8b1f53fddc96152f8ce2f6e57e3697793..7f933e97896b54bca6aa310d5fcfddb349fa47e8 100644 --- a/Core/Instrument/IDetector2D.cpp +++ b/Core/Instrument/IDetector2D.cpp @@ -111,7 +111,7 @@ std::vector<SimulationElement> IDetector2D::createSimulationElements(const Beam sim_element.setPolarization(beam_polarization); sim_element.setAnalyzerOperator(analyzer_operator); if (it.index()==spec_index) { - sim_element.setSpecular(true); + sim_element.setSpecular(); } result.push_back(std::move(sim_element)); } diff --git a/Core/Instrument/SpecularDetector1D.cpp b/Core/Instrument/SpecularDetector1D.cpp index bb6013eaa643ec12a7b048dbf1577e530eb1821e..5aa6d7bd47c051a8a9322a4e28d626a190a00efc 100644 --- a/Core/Instrument/SpecularDetector1D.cpp +++ b/Core/Instrument/SpecularDetector1D.cpp @@ -80,7 +80,7 @@ std::vector<SimulationElement> SpecularDetector1D::createSimulationElements(cons std::make_unique<SpecularPixel>(alpha_i)); sim_element.setPolarization(beam_polarization); sim_element.setAnalyzerOperator(analyzer_operator); - sim_element.setSpecular(true); + sim_element.setSpecular(); result.push_back(std::move(sim_element)); } diff --git a/Core/Multilayer/IFresnelMap.h b/Core/Multilayer/IFresnelMap.h index ab72fc3cf60fca0955c3367ab96c0fd1494a9a7c..5f274abb9fba872ffe75ec1063f843fd00fa6ba2 100644 --- a/Core/Multilayer/IFresnelMap.h +++ b/Core/Multilayer/IFresnelMap.h @@ -23,6 +23,7 @@ class ILayerRTCoefficients; class MultiLayer; class SimulationElement; +struct SpecularData; //! Holds the necessary information to calculate the radiation wavefunction in every layer //! for different incoming (outgoing) angles of the beam in the top layer @@ -43,6 +44,9 @@ public: virtual const ILayerRTCoefficients* getInCoefficients( const SimulationElement& sim_element, size_t layer_index) const =0; + //! Fills simulation element specular data + virtual void fillSpecularData(SimulationElement& sim_element) const = 0; + //! Sets the multilayer to be used for the Fresnel calculations. virtual void setMultilayer(const MultiLayer& multilayer); diff --git a/Core/Multilayer/MatrixFresnelMap.cpp b/Core/Multilayer/MatrixFresnelMap.cpp index f0459a02f0885466b4b466558870cd40d987117f..546bebf2d4cbc2e61d86e202d4a648247f58258c 100644 --- a/Core/Multilayer/MatrixFresnelMap.cpp +++ b/Core/Multilayer/MatrixFresnelMap.cpp @@ -46,6 +46,17 @@ MatrixFresnelMap::getInCoefficients(const SimulationElement& sim_element, size_t return getCoefficients(sim_element.getKi(), layer_index, *mP_multilayer, m_hash_table_in); } +void MatrixFresnelMap::fillSpecularData(SimulationElement& sim_element) const +{ + const auto& kvec = sim_element.getKi(); + std::vector<MatrixRTCoefficients> coef_vector; + if (m_use_cache) + coef_vector = getCoefficientsFromCache(kvec, *mP_multilayer, m_hash_table_in); + else + coef_vector = calculateCoefficients(*mP_multilayer, kvec); + sim_element.setSpecular(std::make_unique<SpecularData>(std::move(coef_vector))); +} + const ILayerRTCoefficients* MatrixFresnelMap::getCoefficients(kvector_t kvec, size_t layer_index, const MultiLayer& multilayer, CoefficientHash& hash_table) const diff --git a/Core/Multilayer/MatrixFresnelMap.h b/Core/Multilayer/MatrixFresnelMap.h index 2076f7e046962c2ffa05eb0453090ece3420b43e..bbbb5cd6520f4e09c02d5abd9a91e6a5fe7deb6f 100644 --- a/Core/Multilayer/MatrixFresnelMap.h +++ b/Core/Multilayer/MatrixFresnelMap.h @@ -44,6 +44,9 @@ public: void setMultilayer(const MultiLayer& multilayer) final override; + //! Fills simulation element specular data + virtual void fillSpecularData(SimulationElement& sim_element) const override; + typedef std::unordered_map<kvector_t, std::vector<MatrixRTCoefficients>, HashKVector> CoefficientHash; diff --git a/Core/Multilayer/ScalarFresnelMap.cpp b/Core/Multilayer/ScalarFresnelMap.cpp index f64371cf963a6be7afd4e97282dfb512b59d0225..1276f51cf72a1ae22bd5bcf6238159e7657f22c8 100644 --- a/Core/Multilayer/ScalarFresnelMap.cpp +++ b/Core/Multilayer/ScalarFresnelMap.cpp @@ -42,6 +42,17 @@ const ILayerRTCoefficients* ScalarFresnelMap::getInCoefficients( return getCoefficients(sim_element.getKi(), layer_index); } +void ScalarFresnelMap::fillSpecularData(SimulationElement& sim_element) const +{ + const auto& kvec = sim_element.getKi(); + std::vector<ScalarRTCoefficients> coef_vector; + if (m_use_cache) + coef_vector = getCoefficientsFromCache(kvec); + else + coef_vector = calculateCoefficients(*mP_multilayer, kvec); + sim_element.setSpecular(std::make_unique<SpecularData>(std::move(coef_vector))); +} + const ScalarRTCoefficients* ScalarFresnelMap::getCoefficients( kvector_t kvec, size_t layer_index) const { diff --git a/Core/Multilayer/ScalarFresnelMap.h b/Core/Multilayer/ScalarFresnelMap.h index 60fb90fa80ff206b73a18671c5a2d116b1b2812b..9f258660425cca80f530b5df5f5b6d3d4ee2e0e8 100644 --- a/Core/Multilayer/ScalarFresnelMap.h +++ b/Core/Multilayer/ScalarFresnelMap.h @@ -44,6 +44,9 @@ public: virtual const ILayerRTCoefficients* getInCoefficients( const SimulationElement& sim_element, size_t layer_index) const final override; + //! Fills simulation element specular data + virtual void fillSpecularData(SimulationElement& sim_element) const override; + private: const ScalarRTCoefficients* getCoefficients(kvector_t kvec, size_t layer_index) const; const std::vector<ScalarRTCoefficients>& getCoefficientsFromCache(kvector_t kvec) const;