BornAgain  1.19.79
Open-source research software to simulate and fit neutron and x-ray reflectometry and grazing-incidence small-angle scattering
OffspecSimulation.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Sim/Simulation/OffspecSimulation.cpp
6 //! @brief Implements class OffspecSimulation.
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 
16 #include "Base/Axis/Bin.h"
17 #include "Base/Axis/IAxis.h"
19 #include "Base/Util/Assert.h"
20 #include "Device/Beam/Beam.h"
22 #include "Device/Data/Datafield.h"
28 
30  const IDetector& detector)
31  : ISimulation2D(beam, sample, detector)
32 {
33 }
34 
36  : ISimulation2D(sample)
37 {
38 }
39 
41 {
44 }
45 
47 {
50 }
51 
53 {
55  const IAxis& phi_axis = detector().axis(0);
56  size_t phi_f_size = phi_axis.size();
57  ASSERT(phi_f_size * m_intensity_map->size() == m_eles.size());
58  for (size_t i = 0; i < m_alpha_i_axis->size(); ++i)
60 
61  auto data = std::unique_ptr<Datafield>(m_intensity_map->clone());
62  std::unique_ptr<ICoordSystem> coordsSystem(createCoordSystem());
63  return {*data, *coordsSystem};
64 }
65 
66 void OffspecSimulation::setBeamParameters(double wavelength, const IAxis& alpha_axis, double phi_i)
67 {
68  m_alpha_i_axis.reset(alpha_axis.clone());
69  if (alpha_axis.size() < 1)
70  throw std::runtime_error("OffspecSimulation::prepareSimulation() "
71  "-> Error. Incoming alpha range size < 1.");
72  const double alpha_zero = alpha_axis.min();
73  beam().setWavelength(wavelength);
74  beam().setDirection({alpha_zero, phi_i});
76 }
77 
79 {
80  return m_alpha_i_axis.get();
81 }
82 
83 #ifndef SWIG
85 {
86  ASSERT(beamAxis());
87  return detector().offspecCoords(beamAxis()->clone(), beam().direction());
88 }
89 #endif
90 
92 {
94  return m_alpha_i_axis->size() * detector().axis(1).size();
95 }
96 
98 {
99  m_eles.clear();
100  Beam beam2 = beam();
101  for (size_t i = 0; i < m_alpha_i_axis->size(); ++i) {
102  beam2.setInclination(m_alpha_i_axis->bin(i).center());
103  std::vector<std::unique_ptr<DiffuseElement>> eles_i = generateElements(beam2);
104  for (auto&& ele : eles_i)
105  m_eles.emplace_back(std::move(ele));
106  }
107  if (m_cache.empty())
108  m_cache.resize(m_eles.size(), 0.0);
109 }
110 
112 {
113  const bool zero_mean = par_distr.getDistribution()->mean() == 0.0;
114  if (zero_mean)
115  return;
116  /* TODO come back to this after refactoring of distribution handling
117  if (par_distr.whichParameter() == ParameterDistribution::BeamInclinationAngle)
118  throw std::runtime_error("Error in OffspecSimulation: parameter distribution of "
119  "beam inclination angle should have zero mean.");
120  */
121 }
122 
124 {
126  if (detector().rank() == 1)
127  m_intensity_map.reset(new Datafield({m_alpha_i_axis->clone()}));
128  else if (detector().rank() == 2)
129  m_intensity_map.reset(new Datafield({m_alpha_i_axis->clone(), detector().axis(1).clone()}));
130  else
131  ASSERT(0);
132  m_intensity_map->setAllTo(0.);
133 }
134 
136 {
137  std::unique_ptr<Datafield> detector_image;
138  if (detector().rank() == 1)
139  detector_image.reset(new Datafield({detector().axis(0).clone()}));
140  else if (detector().rank() == 2)
141  detector_image.reset(new Datafield(
142  {detector().axis(0).clone(), detector().axis(1).clone()}));
143  else
144  ASSERT(0);
145 
146  size_t N = detector_image->size();
147  for (size_t i = 0; i < N; ++i)
148  (*detector_image)[i] = m_eles[index * N + i]->intensity();
149  detector().applyDetectorResolution(detector_image.get());
150  size_t y_axis_size = detector().axis(1).size();
151  for (size_t i = 0; i < N; ++i)
152  (*m_intensity_map)[index * y_axis_size + i % y_axis_size] += (*detector_image)[i];
153 }
154 
156 {
158  ASSERT(m_alpha_i_axis->size() >= 1);
159  ASSERT(detector().rank() == 2);
160 }
Defines the macro ASSERT.
#define ASSERT(condition)
Definition: Assert.h:45
Defines class Beam.
Defines structs Bin1D, Bin1DCVector.
Defines interface CoordSystem2D and its subclasses.
Defines and implements templated class Datafield.
Defines class DiffuseElement.
Defines classes representing one-dimensional distributions.
Defines interface IAxis.
Defines class OffspecSimulation.
Defines class RectangularDetector.
Defines class RectangularPixel.
Defines class SimulationResult.
Defines class SphericalDetector.
An incident neutron or x-ray beam.
Definition: Beam.h:28
void setDirection(const Direction &direction)
Definition: Beam.cpp:92
void setInclination(double alpha)
Definition: Beam.cpp:102
void setWavelength(double wavelength)
Definition: Beam.cpp:85
Stores radiation power per bin.
Definition: Datafield.h:30
Abstract base class for one-dimensional axes.
Definition: IAxis.h:27
virtual IAxis * clone() const =0
virtual double min() const =0
Returns value of first point of axis.
virtual size_t size() const =0
Returns the number of bins.
Interface to provide axis translations to different units for simulation output.
Definition: ICoordSystem.h:40
Abstract detector interface.
Definition: IDetector.h:57
const IAxis & axis(size_t index) const
One axis of the complete detector. Any region of interest is not taken into account.
Definition: IDetector.cpp:74
size_t rank() const
Returns number of defined axes.
Definition: IDetector.cpp:64
void applyDetectorResolution(Datafield *p_intensity_map) const
Applies the detector resolution to the given intensity maps.
Definition: IDetector.cpp:169
virtual ICoordSystem * offspecCoords(IAxis *beamAxis, const Direction &beamDirection) const =0
virtual double mean() const =0
Returns the distribution-specific mean.
Abstract base class of simulations that generate 2D patterns.
Definition: ISimulation2D.h:34
IDetector & detector()
Definition: ISimulation2D.h:58
std::vector< std::unique_ptr< DiffuseElement > > generateElements(const Beam &beam)
Generate simulation elements for given beam.
Beam & beam()
Definition: ISimulation2D.h:57
void prepareSimulation() override
Put into a clean state for running a simulation.
std::vector< double > m_cache
size_t numberOfElements() const override
Gets the number of elements this simulation needs to calculate.
std::vector< std::unique_ptr< DiffuseElement > > m_eles
Our sample model: a stack of layers one below the other.
Definition: MultiLayer.h:43
const IAxis * beamAxis() const
Returns axis of the beam.
std::unique_ptr< Datafield > m_intensity_map
void updateIntensityMap() override
Default implementation only adds the detector axes.
void transferDetectorImage(size_t index)
Normalize, apply detector resolution and transfer detector image corresponding to alpha_i = m_alpha_i...
OffspecSimulation(const Beam &beam, const MultiLayer &sample, const IDetector &detector)
size_t numberOfElements() const override
Gets the number of elements this simulation needs to calculate.
size_t intensityMapSize() const override
Returns the total number of the intensity values in the simulation result.
SimulationResult pack_result() override
Sets m_result.
void prepareSimulation() override
Put into a clean state for running a simulation.
ICoordSystem * createCoordSystem() const override
void validateParametrization(const ParameterDistribution &par_distr) const override
Checks the distribution validity for simulation.
std::unique_ptr< IAxis > m_alpha_i_axis
void setBeamParameters(double wavelength, const IAxis &alpha_axis, double phi_i)
Sets beam parameters from here (forwarded to Instrument)
void checkInitialization() const
Check correct number of axes.
void initElementVector() override
Initializes the vector of ISimulation elements.
A parametric distribution function, for use with any model parameter.
const IDistribution1D * getDistribution() const
Wrapper around Datafield that also provides unit conversions.
#define N
Definition: mixmax.h:31