BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
ISimulation2D.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Core/Simulation/ISimulation2D.cpp
6 //! @brief Implements interface ISimulation2D.
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
17 #include "Base/Utils/Assert.h"
21 
22 ISimulation2D::ISimulation2D(const Beam& beam, const MultiLayer& sample, const IDetector& detector)
23  : ISimulation(beam, sample, detector)
24 {
25 }
26 
27 #ifndef SWIG
28 ISimulation2D::ISimulation2D(const Beam& beam, const IDetector& detector)
29  : ISimulation(beam, detector)
30 {
31 }
32 #endif // SWIG
33 
35 
37 
39 {
41  IDetector2D* p = dynamic_cast<IDetector2D*>(getDetector());
42  ASSERT(p);
43  return *p;
44 }
45 
47 {
49  const IDetector2D* p = dynamic_cast<const IDetector2D*>(getDetector());
50  ASSERT(p);
51  return *p;
52 }
53 
55 {
58 }
59 
60 void ISimulation2D::addMask(const IShape2D& shape, bool mask_value)
61 {
62  detector2D().addMask(shape, mask_value);
63 }
64 
66 {
67  detector2D().maskAll();
68 }
69 
70 void ISimulation2D::setRegionOfInterest(double xlow, double ylow, double xup, double yup)
71 {
72  detector2D().setRegionOfInterest(xlow, ylow, xup, yup);
73 }
74 
76  : ISimulation(other), m_sim_elements(other.m_sim_elements), m_cache(other.m_cache)
77 {
78 }
79 
81 {
82  if (!m_detector_context)
83  throw std::runtime_error("Error in numberOfSimulationElements(): no detector context");
84  return m_detector_context->numberOfSimulationElements();
85 }
86 
87 void ISimulation2D::setDetectorParameters(size_t n_x, double x_min, double x_max, size_t n_y,
88  double y_min, double y_max)
89 {
90  detector2D().setDetectorParameters(n_x, x_min, x_max, n_y, y_min, y_max);
92 }
93 
95 {
98 }
99 
100 std::unique_ptr<IComputation> ISimulation2D::generateSingleThreadedComputation(size_t start,
101  size_t n_elements)
102 {
103  ASSERT(start < m_sim_elements.size() && start + n_elements <= m_sim_elements.size());
104  const auto& begin = m_sim_elements.begin() + static_cast<long>(start);
105  const auto polarized =
107  return std::make_unique<DWBAComputation>(*sample(), options(), progress(), begin,
108  begin + static_cast<long>(n_elements), polarized);
109 }
110 
111 std::vector<SimulationElement> ISimulation2D::generateSimulationElements(const Beam& beam)
112 {
113  const double wavelength = beam.wavelength();
114  const double alpha_i = -beam.direction().alpha(); // Defined to be always positive in Beam
115  const double phi_i = beam.direction().phi();
116  const Eigen::Matrix2cd beam_polarization = beam.getPolarization();
117 
118  const IDetector2D& detector = detector2D();
119  const Eigen::Matrix2cd analyzer_operator = detector.detectionProperties().analyzerOperator();
120  const size_t spec_index = detector.indexOfSpecular(beam);
121 
122  const size_t N = m_detector_context->numberOfSimulationElements();
123 
124  std::vector<SimulationElement> result;
125  result.reserve(N);
126  for (size_t element_index = 0; element_index < N; ++element_index) {
127  SimulationElement element(wavelength, alpha_i, phi_i,
128  m_detector_context->createPixel(element_index), beam_polarization,
129  analyzer_operator,
130  m_detector_context->detectorIndex(element_index) == spec_index);
131  result.emplace_back(std::move(element));
132  }
133  return result;
134 }
135 
136 void ISimulation2D::normalize(size_t start_ind, size_t n_elements)
137 {
138  const double beam_intensity = beam().intensity();
139  for (size_t i = start_ind, stop_point = start_ind + n_elements; i < stop_point; ++i) {
140  SimulationElement& element = m_sim_elements[i];
141  double sin_alpha_i = std::abs(std::sin(element.getAlphaI()));
142  if (sin_alpha_i == 0.0) {
143  element.setIntensity(0);
144  continue;
145  }
146  const double solid_angle = element.solidAngle();
147  element.setIntensity(element.intensity() * beam_intensity * solid_angle / sin_alpha_i);
148  }
149 }
150 
151 void ISimulation2D::addBackgroundIntensity(size_t start_ind, size_t n_elements)
152 {
153  if (!background())
154  return;
155  for (size_t i = start_ind, stop_point = start_ind + n_elements; i < stop_point; ++i) {
156  SimulationElement& element = m_sim_elements[i];
157  element.setIntensity(background()->addBackground(element.intensity()));
158  }
159 }
160 
161 void ISimulation2D::addDataToCache(double weight)
162 {
163  if (m_sim_elements.size() != m_cache.size())
164  throw std::runtime_error("Error in ISimulation2D::addDataToCache(double): cache size"
165  " not the same as element size");
166  for (unsigned i = 0; i < m_sim_elements.size(); i++)
167  m_cache[i] += m_sim_elements[i].intensity() * weight;
168 }
169 
171 {
172  ASSERT(!m_cache.empty());
173  if (!m_cache.empty()) {
174  for (unsigned i = 0; i < m_sim_elements.size(); i++)
175  m_sim_elements[i].setIntensity(m_cache[i]);
176  m_cache.clear();
177  }
178 }
179 
180 std::vector<double> ISimulation2D::rawResults() const
181 {
182  std::vector<double> result;
183  result.resize(m_sim_elements.size());
184  for (unsigned i = 0; i < m_sim_elements.size(); ++i)
185  result[i] = m_sim_elements[i].intensity();
186  return result;
187 }
188 
189 void ISimulation2D::setRawResults(const std::vector<double>& raw_data)
190 {
192  if (raw_data.size() != m_sim_elements.size())
193  throw std::runtime_error("ISimulation2D::setRawResults: size of vector passed as "
194  "argument doesn't match number of elements in this simulation");
195  for (unsigned i = 0; i < raw_data.size(); i++)
196  m_sim_elements[i].setIntensity(raw_data[i]);
198 }
Defines the macro ASSERT.
#define ASSERT(condition)
Definition: Assert.h:31
Defines class DWBAComputation.
Define DetectorContext class.
Defines interface IBackground.
Defines interface ISimulation2D.
Defines class SimulationElement.
An incident neutron or x-ray beam.
Definition: Beam.h:27
Direction direction() const
Definition: Beam.h:45
Eigen::Matrix2cd getPolarization() const
Returns the polarization density matrix (in spin basis along z-axis)
Definition: Beam.cpp:127
double intensity() const
Returns the beam intensity in neutrons/sec.
Definition: Beam.h:42
double wavelength() const
Definition: Beam.h:43
kvector_t analyzerDirection() const
Retrieve the analyzer characteristics.
Eigen::Matrix2cd analyzerOperator() const
Return the polarization density matrix (in spin basis along z-axis)
double phi() const
Definition: Direction.h:30
double alpha() const
Definition: Direction.h:29
Abstract 2D detector interface.
Definition: IDetector2D.h:31
std::unique_ptr< DetectorContext > createContext() const
Definition: IDetector2D.cpp:69
void setRegionOfInterest(double xlow, double ylow, double xup, double yup)
Sets rectangular region of interest with lower left and upper right corners defined.
Definition: IDetector2D.cpp:48
void addMask(const IShape2D &shape, bool mask_value=true)
Adds mask of given shape to the stack of detector masks.
Definition: IDetector2D.cpp:74
void setDetectorParameters(size_t n_x, double x_min, double x_max, size_t n_y, double y_min, double y_max)
Sets detector parameters using angle ranges.
Definition: IDetector2D.cpp:35
void maskAll()
Put the mask for all detector channels (i.e. exclude whole detector from the analysis)
Definition: IDetector2D.cpp:80
Abstract detector interface.
Definition: IDetector.h:36
const DetectionProperties & detectionProperties() const
Returns detection properties.
Definition: IDetector.h:82
Basic class for all shapes in 2D.
Definition: IShape2D.h:27
Abstract base class of OffSpecularSimulation and GISASSimulation.
Definition: ISimulation2D.h:27
std::unique_ptr< DetectorContext > m_detector_context
void setDetector(const IDetector2D &detector)
Sets the detector (axes can be overwritten later)
std::unique_ptr< IComputation > generateSingleThreadedComputation(size_t start, size_t n_elements) override
Generate a single threaded computation for a given range of simulation elements.
size_t numberOfSimulationElements() const override
Gets the number of elements this simulation needs to calculate.
void setRawResults(const std::vector< double > &raw_data) override
void moveDataFromCache() override
void setDetectorParameters(size_t n_phi, double phi_min, double phi_max, size_t n_alpha, double alpha_min, double alpha_max)
Sets spherical detector parameters using angle ranges.
void normalize(size_t start_ind, size_t n_elements) override
Normalize the detector counts to beam intensity, to solid angle, and to exposure angle.
std::vector< SimulationElement > generateSimulationElements(const Beam &beam)
Generate simulation elements for given beam.
std::vector< double > rawResults() const override
void setRegionOfInterest(double xlow, double ylow, double xup, double yup)
Sets rectangular region of interest with lower left and upper right corners defined.
IDetector2D & detector2D()
std::vector< SimulationElement > m_sim_elements
Definition: ISimulation2D.h:98
~ISimulation2D() override
virtual void initUnitConverter()
Definition: ISimulation2D.h:73
void maskAll()
Put the mask for all detector channels (i.e. exclude whole detector from the analysis)
void prepareSimulation() override
Put into a clean state for running a simulation.
std::vector< double > m_cache
Definition: ISimulation2D.h:99
void addBackgroundIntensity(size_t start_ind, size_t n_elements) override
void addDataToCache(double weight) override
void addMask(const IShape2D &shape, bool mask_value=true)
Adds mask of given shape to the stack of detector masks.
Abstract base class of OffSpecularSimulation, GISASSimulation and SpecularSimulation.
Definition: ISimulation.h:38
virtual void updateIntensityMap()
Definition: ISimulation.h:119
const IBackground * background() const
Definition: ISimulation.h:74
const MultiLayer * sample() const
const Instrument & instrument() const
Definition: ISimulation.h:55
ProgressHandler & progress()
Definition: ISimulation.h:125
virtual void initSimulationElementVector()=0
Initializes the vector of ISimulation elements.
const SimulationOptions & options() const
Definition: ISimulation.h:124
virtual void prepareSimulation()
Put into a clean state for running a simulation.
virtual SimulationResult result() const =0
Returns the results of the simulation in a format that supports unit conversion and export to numpy a...
IDetector & detector()
Definition: ISimulation.h:63
IDetector * getDetector()
Definition: ISimulation.h:61
virtual void transferResultsToIntensityMap()
Creates the appropriate data structure (e.g.
Definition: ISimulation.h:114
Beam & beam()
Definition: ISimulation.h:58
void setDetector(const IDetector &detector)
Sets the detector (axes can be overwritten later)
Definition: Instrument.cpp:52
Our sample model: a stack of layers one below the other.
Definition: MultiLayer.h:41
Data stucture containing both input and output of a single detector cell.
double solidAngle() const
double intensity() const
double getAlphaI() const
void setIntensity(double intensity)
matrixFFVector_t polarized(const SimulationElement &sim_element, const std::vector< FormFactorCoherentSum > &ff_wrappers)