BornAgain  1.18.0
Simulate and fit neutron and x-ray scattering at grazing incidence
OffSpecSimulation.cpp
Go to the documentation of this file.
1 // ************************************************************************** //
2 //
3 // BornAgain: simulate and fit scattering at grazing incidence
4 //
5 //! @file Core/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 
24 
26 {
27  initialize();
28 }
29 
31 {
34 }
35 
37 {
40 }
41 
43 {
44  auto data = std::unique_ptr<OutputData<double>>(m_intensity_map.clone());
45  OffSpecularConverter converter(instrument().detector2D(), instrument().getBeam(),
47  return SimulationResult(*data, converter);
48 }
49 
50 void OffSpecSimulation::setBeamParameters(double wavelength, const IAxis& alpha_axis, double phi_i)
51 {
52  mP_alpha_i_axis.reset(alpha_axis.clone());
53  if (alpha_axis.size() < 1)
54  throw Exceptions::ClassInitializationException("OffSpecSimulation::prepareSimulation() "
55  "-> Error. Incoming alpha range size < 1.");
56  const double alpha_zero = alpha_axis.getMin();
57  instrument().setBeamParameters(wavelength, alpha_zero, phi_i);
59 }
60 
62 {
63  return mP_alpha_i_axis.get();
64 }
65 
66 std::unique_ptr<IUnitConverter> OffSpecSimulation::createUnitConverter() const
67 {
68  const IAxis* axis = beamAxis();
69  if (!axis)
70  throw std::runtime_error("Error in OffSpecSimulation::createUnitConverter:"
71  " missing inclination angle axis");
72  return std::make_unique<OffSpecularConverter>(instrument().detector2D(), instrument().getBeam(),
73  *axis);
74 }
75 
77 {
79  return mP_alpha_i_axis->size() * instrument().getDetectorAxis(1).size();
80 }
81 
83 {
84  if (other.mP_alpha_i_axis)
85  mP_alpha_i_axis.reset(other.mP_alpha_i_axis->clone());
87  initialize();
88 }
89 
91 {
92  m_sim_elements.clear();
93  Beam beam = instrument().getBeam();
94  const double wavelength = beam.getWavelength();
95  const double phi_i = beam.getPhi();
96 
97  for (size_t i = 0; i < mP_alpha_i_axis->size(); ++i) {
98  // Incoming angle by convention defined as positive:
99  double alpha_i = mP_alpha_i_axis->getBin(i).getMidPoint();
100  double total_alpha = alpha_i;
101  beam.setCentralK(wavelength, total_alpha, phi_i);
102  auto sim_elements_i = generateSimulationElements(beam);
103  m_sim_elements.insert(m_sim_elements.end(), std::make_move_iterator(sim_elements_i.begin()),
104  std::make_move_iterator(sim_elements_i.end()));
105  }
106  if (m_cache.empty())
107  m_cache.resize(m_sim_elements.size(), 0.0);
108 }
109 
111 {
112  const bool zero_mean = par_distr.getDistribution()->getMean() == 0.0;
113  if (zero_mean)
114  return;
115 
116  std::unique_ptr<ParameterPool> parameter_pool(createParameterTree());
117  const std::vector<RealParameter*> names =
118  parameter_pool->getMatchedParameters(par_distr.getMainParameterName());
119  for (const auto par : names)
120  if (par->getName().find("InclinationAngle") != std::string::npos && !zero_mean)
121  throw std::runtime_error("Error in OffSpecSimulation: parameter distribution of "
122  "beam inclination angle should have zero mean.");
123 }
124 
126 {
128  const IAxis& phi_axis = instrument().getDetectorAxis(0);
129  size_t phi_f_size = phi_axis.size();
130  if (phi_f_size * m_intensity_map.getAllocatedSize() != m_sim_elements.size())
132  "OffSpecSimulation::transferResultsToIntensityMap: "
133  "intensity map size does not conform to number of calculated intensities");
134  for (size_t i = 0; i < mP_alpha_i_axis->size(); ++i)
136 }
137 
139 {
141  if (mP_alpha_i_axis)
143  size_t detector_dimension = instrument().getDetectorDimension();
144  if (detector_dimension == 2)
145  m_intensity_map.addAxis(instrument().getDetectorAxis(1));
147 }
148 
150 {
151  OutputData<double> detector_image;
152  size_t detector_dimension = instrument().getDetectorDimension();
153  for (size_t dim = 0; dim < detector_dimension; ++dim)
154  detector_image.addAxis(instrument().getDetectorAxis(dim));
155  size_t detector_size = detector_image.getAllocatedSize();
156  for (size_t i = 0; i < detector_size; ++i)
157  detector_image[i] = m_sim_elements[index * detector_size + i].getIntensity();
158  instrument().applyDetectorResolution(&detector_image);
159  size_t y_axis_size = instrument().getDetectorAxis(1).size();
160  for (size_t i = 0; i < detector_size; ++i)
161  m_intensity_map[index * y_axis_size + i % y_axis_size] += detector_image[i];
162 }
163 
165 {
166  if (!mP_alpha_i_axis || mP_alpha_i_axis->size() < 1)
167  throw Exceptions::ClassInitializationException("OffSpecSimulation::checkInitialization() "
168  "Incoming alpha range not configured.");
169  if (instrument().getDetectorDimension() != 2)
171  "OffSpecSimulation::checkInitialization: detector is not two-dimensional");
172 }
173 
175 {
176  setName("OffSpecSimulation");
177 }
Defines class DWBAComputation.
Defines classes representing one-dimensional distributions.
Defines class Histogram2D.
Defines pure virtual base class ISampleBuilder.
Defines class MultiLayer.
Defines class OffSpecSimulation.
Defines class ParameterPool.
Defines class RealParameter.
Defines interface UnitConverterSimple and its subclasses.
Beam defined by wavelength, direction and intensity.
Definition: Beam.h:27
double getWavelength() const
Definition: Beam.h:69
void setCentralK(double wavelength, double alpha_i, double phi_i)
Sets the wavevector in terms of wavelength and incoming angles.
Definition: Beam.cpp:76
double getPhi() const
Definition: Beam.h:71
Interface for one-dimensional axes.
Definition: IAxis.h:25
virtual IAxis * clone() const =0
clone function
virtual double getMin() const =0
Returns value of first point of axis.
virtual size_t size() const =0
retrieve the number of bins
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:116
void setName(const std::string &name)
Beam & getBeam()
Definition: Instrument.h:44
void applyDetectorResolution(OutputData< double > *p_intensity_map) const
apply the detector resolution to the given intensity map
Definition: Instrument.cpp:82
const IAxis & getDetectorAxis(size_t index) const
Definition: Instrument.cpp:157
void setBeamParameters(double wavelength, double alpha_i, double phi_i)
Sets the beam wavelength and incoming angles.
Definition: Instrument.cpp:87
size_t getDetectorDimension() const
Definition: Instrument.cpp:162
Main class to run an off-specular simulation.
void transferResultsToIntensityMap() override
Creates the appropriate data structure (e.g.
SimulationResult result() const override
Returns the results of the simulation in a format that supports unit conversion and export to numpy a...
void updateIntensityMap() override
Default implementation only adds the detector axes.
void initSimulationElementVector() override
Initializes the vector of Simulation elements.
const IAxis * beamAxis() const
Returns axis of the beam.
size_t numberOfSimulationElements() const final
Gets the number of elements this simulation needs to calculate.
void transferDetectorImage(size_t index)
Normalize, apply detector resolution and transfer detector image corresponding to alpha_i = mp_alpha_...
std::unique_ptr< IAxis > mP_alpha_i_axis
size_t intensityMapSize() const override
Returns the total number of the intensity values in the simulation result.
void prepareSimulation() final
Put into a clean state for running a simulation.
void validateParametrization(const ParameterDistribution &par_distr) const override
Checks the distribution validity for simulation.
std::unique_ptr< IUnitConverter > createUnitConverter() const
void checkInitialization() const
Check correct number of axes.
OutputData< double > m_intensity_map
void setBeamParameters(double wavelength, const IAxis &alpha_axis, double phi_i)
Sets beam parameters from here (forwarded to Instrument)
IUnitConverter class that handles the unit translations for off-specular simulations with a spherical...
void copyFrom(const OutputData< T > &x)
Definition: OutputData.h:261
void setAllTo(const T &value)
Sets content of output data to specific value.
Definition: OutputData.h:479
void addAxis(const IAxis &new_axis)
Definition: OutputData.h:289
size_t getAllocatedSize() const
Returns total size of data buffer (product of bin number in every dimension).
Definition: OutputData.h:62
OutputData * clone() const
Definition: OutputData.h:253
void clear()
Sets object into initial state (no dimensions, data)
Definition: OutputData.h:473
A parametric distribution function, for use with any model parameter.
const IDistribution1D * getDistribution() const
std::string getMainParameterName() const
get the main parameter's name
Pure virtual base class of OffSpecularSimulation and GISASSimulation.
Definition: Simulation2D.h:27
size_t numberOfSimulationElements() const override
Gets the number of elements this simulation needs to calculate.
std::vector< double > m_cache
Definition: Simulation2D.h:95
std::vector< SimulationElement > m_sim_elements
Definition: Simulation2D.h:94
std::vector< SimulationElement > generateSimulationElements(const Beam &beam)
Generate simulation elements for given beam.
void prepareSimulation() override
Put into a clean state for running a simulation.
Wrapper around OutputData<double> that also provides unit conversions.
const Instrument & instrument() const
Definition: Simulation.h:55