BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
OffSpecularSimulation.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Core/Simulation/OffSpecularSimulation.cpp
6 //! @brief Implements class OffSpecularSimulation.
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 
21 
23  const IDetector& detector)
24  : ISimulation2D(beam, sample, detector)
25 {
26 }
27 
29 {
30  initialize();
31 }
32 
34 {
37 }
38 
40 {
43 }
44 
46 {
47  auto data = std::unique_ptr<OutputData<double>>(m_intensity_map.clone());
49  return SimulationResult(*data, converter);
50 }
51 
52 void OffSpecularSimulation::setBeamParameters(double wavelength, const IAxis& alpha_axis,
53  double phi_i)
54 {
55  m_alpha_i_axis.reset(alpha_axis.clone());
56  if (alpha_axis.size() < 1)
57  throw std::runtime_error("OffSpecularSimulation::prepareSimulation() "
58  "-> Error. Incoming alpha range size < 1.");
59  const double alpha_zero = alpha_axis.lowerBound();
60  instrument().setBeamParameters(wavelength, alpha_zero, phi_i);
62 }
63 
65 {
66  return m_alpha_i_axis.get();
67 }
68 
69 std::unique_ptr<IUnitConverter> OffSpecularSimulation::createUnitConverter() const
70 {
71  const IAxis* axis = beamAxis();
72  if (!axis)
73  throw std::runtime_error("Error in OffSpecularSimulation::createUnitConverter:"
74  " missing inclination angle axis");
75  return std::make_unique<OffSpecularConverter>(detector2D(), beam(), *axis);
76 }
77 
79 {
81  return m_alpha_i_axis->size() * detector().axis(1).size();
82 }
83 
85  : ISimulation2D(other)
86 {
87  if (other.m_alpha_i_axis)
88  m_alpha_i_axis.reset(other.m_alpha_i_axis->clone());
90  initialize();
91 }
92 
94 {
95  m_sim_elements.clear();
96  Beam beam2 = beam();
97  for (size_t i = 0; i < m_alpha_i_axis->size(); ++i) {
98  beam2.setInclination(m_alpha_i_axis->bin(i).center());
99  std::vector<SimulationElement> sim_elements_i = generateSimulationElements(beam2);
100  for (auto ele : sim_elements_i)
101  m_sim_elements.emplace_back(ele);
102  }
103  if (m_cache.empty())
104  m_cache.resize(m_sim_elements.size(), 0.0);
105 }
106 
108 {
109  const bool zero_mean = par_distr.getDistribution()->getMean() == 0.0;
110  if (zero_mean)
111  return;
112 
113  std::unique_ptr<ParameterPool> parameter_pool(createParameterTree());
114  const std::vector<RealParameter*> names =
115  parameter_pool->getMatchedParameters(par_distr.getMainParameterName());
116  for (const auto par : names)
117  if (par->getName().find("InclinationAngle") != std::string::npos && !zero_mean)
118  throw std::runtime_error("Error in OffSpecularSimulation: parameter distribution of "
119  "beam inclination angle should have zero mean.");
120 }
121 
123 {
125  const IAxis& phi_axis = detector().axis(0);
126  size_t phi_f_size = phi_axis.size();
127  if (phi_f_size * m_intensity_map.getAllocatedSize() != m_sim_elements.size())
128  throw std::runtime_error(
129  "OffSpecularSimulation::transferResultsToIntensityMap: "
130  "intensity map size does not conform to number of calculated intensities");
131  for (size_t i = 0; i < m_alpha_i_axis->size(); ++i)
133 }
134 
136 {
138  if (m_alpha_i_axis)
140  size_t detector_dimension = detector().dimension();
141  if (detector_dimension == 2)
142  m_intensity_map.addAxis(detector().axis(1));
144 }
145 
147 {
148  OutputData<double> detector_image;
149  size_t detector_dimension = detector().dimension();
150  for (size_t dim = 0; dim < detector_dimension; ++dim)
151  detector_image.addAxis(detector().axis(dim));
152  size_t detector_size = detector_image.getAllocatedSize();
153  for (size_t i = 0; i < detector_size; ++i)
154  detector_image[i] = m_sim_elements[index * detector_size + i].intensity();
155  detector().applyDetectorResolution(&detector_image);
156  size_t y_axis_size = detector().axis(1).size();
157  for (size_t i = 0; i < detector_size; ++i)
158  m_intensity_map[index * y_axis_size + i % y_axis_size] += detector_image[i];
159 }
160 
162 {
163  if (!m_alpha_i_axis || m_alpha_i_axis->size() < 1)
164  throw std::runtime_error("OffSpecularSimulation::checkInitialization() "
165  "Incoming alpha range not configured.");
166  if (detector().dimension() != 2)
167  throw std::runtime_error(
168  "OffSpecularSimulation::checkInitialization: detector is not two-dimensional");
169 }
170 
172 {
173  setName("OffSpecularSimulation");
174 }
Defines classes representing one-dimensional distributions.
Defines interface ISampleBuilder.
Defines class OffSpecularSimulation.
Defines class ParameterPool.
Defines class RealParameter.
Defines interface UnitConverterSimple and its subclasses.
An incident neutron or x-ray beam.
Definition: Beam.h:27
void setInclination(const double alpha)
Definition: Beam.cpp:96
Interface for one-dimensional axes.
Definition: IAxis.h:25
virtual IAxis * clone() const =0
clone function
virtual size_t size() const =0
retrieve the number of bins
virtual double lowerBound() const =0
Returns value of first point of axis.
Abstract detector interface.
Definition: IDetector.h:36
void applyDetectorResolution(OutputData< double > *p_intensity_map) const
Applies the detector resolution to the given intensity maps.
Definition: IDetector.cpp:118
size_t dimension() const
Returns actual dimensionality of the detector (number of defined axes)
Definition: IDetector.cpp:46
const IAxis & axis(size_t index) const
Definition: IDetector.cpp:56
virtual double getMean() const =0
Returns the distribution-specific mean.
ParameterPool * createParameterTree() const
Creates new parameter pool, with all local parameters and those of its children.
Definition: INode.cpp:126
void setName(const std::string &name)
Abstract base class of OffSpecularSimulation and GISASSimulation.
Definition: ISimulation2D.h:27
size_t numberOfSimulationElements() const override
Gets the number of elements this simulation needs to calculate.
std::vector< SimulationElement > generateSimulationElements(const Beam &beam)
Generate simulation elements for given beam.
IDetector2D & detector2D()
std::vector< SimulationElement > m_sim_elements
Definition: ISimulation2D.h:98
void prepareSimulation() override
Put into a clean state for running a simulation.
std::vector< double > m_cache
Definition: ISimulation2D.h:99
const Instrument & instrument() const
Definition: ISimulation.h:55
IDetector & detector()
Definition: ISimulation.h:63
Beam & beam()
Definition: ISimulation.h:58
void setBeamParameters(double wavelength, double alpha_i, double phi_i)
Sets the beam wavelength and incoming angles.
Definition: Instrument.cpp:76
Our sample model: a stack of layers one below the other.
Definition: MultiLayer.h:41
IUnitConverter class that handles the unit translations for off-specular simulations with a spherical...
Main class to run an off-specular simulation.
size_t intensityMapSize() const override
Returns the total number of the intensity values in the simulation result.
OutputData< double > m_intensity_map
void prepareSimulation() override
Put into a clean state for running a simulation.
size_t numberOfSimulationElements() const override
Gets the number of elements this simulation needs to calculate.
const IAxis * beamAxis() const
Returns axis of the beam.
void validateParametrization(const ParameterDistribution &par_distr) const override
Checks the distribution validity for simulation.
void transferDetectorImage(size_t index)
Normalize, apply detector resolution and transfer detector image corresponding to alpha_i = m_alpha_i...
void initSimulationElementVector() override
Initializes the vector of ISimulation elements.
std::unique_ptr< IAxis > m_alpha_i_axis
void updateIntensityMap() override
Default implementation only adds the detector axes.
SimulationResult result() const override
Returns the results of the simulation in a format that supports unit conversion and export to numpy a...
void transferResultsToIntensityMap() override
Creates the appropriate data structure (e.g.
std::unique_ptr< IUnitConverter > createUnitConverter() const
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 copyFrom(const OutputData< T > &x)
Definition: OutputData.h:267
void setAllTo(const T &value)
Sets content of output data to specific value.
Definition: OutputData.h:476
void addAxis(const IAxis &new_axis)
Definition: OutputData.h:295
size_t getAllocatedSize() const
Returns total size of data buffer (product of bin number in every dimension).
Definition: OutputData.h:59
OutputData * clone() const
Definition: OutputData.h:259
void clear()
Sets object into initial state (no dimensions, data)
Definition: OutputData.h:470
A parametric distribution function, for use with any model parameter.
const IDistribution1D * getDistribution() const
std::string getMainParameterName() const
get the main parameter's name
Wrapper around OutputData<double> that also provides unit conversions.