BornAgain  1.19.79
Open-source research software to simulate and fit neutron and x-ray reflectometry and grazing-incidence small-angle scattering
SpecularSimulation.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Sim/Simulation/SpecularSimulation.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 
17 #include "Base/Util/Assert.h"
20 #include "Device/Data/Datafield.h"
27 #include "Sim/Scan/AlphaScan.h"
28 
29 // ************************************************************************************************
30 // class SpecularSimulation
31 // ************************************************************************************************
32 
34  : ISimulation(sample)
35  , m_scan(scan.clone())
36 {
37  // TODO: move inside AlphaScan when pointwise resolution is implemented
38  if (scan.coordinateAxis()->min() < 0.0)
39  throw std::runtime_error("Invalid scan: minimum value on coordinate axis is negative");
40 }
41 
43 
45 
47 {
48  return m_scan->numberOfElements();
49 }
50 
52 {
53  ASSERT(!m_eles.empty());
54  Datafield data({m_scan->coordinateAxis()->clone()}, m_scan->createIntensities(m_eles));
55  return {data, createCoordSystem()};
56 }
57 
59 {
60  return m_scan->coordinateAxis()->size();
61 }
62 
63 #ifndef SWIG
65 {
66  return m_scan->createCoordSystem();
67 }
68 #endif
69 
71 {
72  m_eles = m_scan->generateElements();
73 
74  if (!m_cache.empty())
75  return;
76  m_cache.resize(m_eles.size(), 0);
77 }
78 
79 std::unique_ptr<IComputation> SpecularSimulation::createComputation(const reSample& re_sample,
80  size_t start, size_t n_elements)
81 {
82  ASSERT(start < m_eles.size() && start + n_elements <= m_eles.size());
83  const auto& begin = m_eles.begin() + static_cast<long>(start);
84  return std::make_unique<SpecularComputation>(re_sample, options(), progress(), begin,
85  begin + static_cast<long>(n_elements));
86 }
87 
89 {
90  ASSERT(m_eles.size() == m_cache.size());
91 }
92 
94 {
95  const bool zero_mean = par_distr.getDistribution()->mean() == 0.0;
96  if (zero_mean)
97  return;
98  /* TODO come back to this after refactoring of distribution handling
99  if (par_distr.whichParameter() == ParameterDistribution::BeamInclinationAngle)
100  throw std::runtime_error("Error in SpecularSimulation: parameter distribution of "
101  "beam inclination angle should have zero mean.");
102  */
103 }
104 
105 void SpecularSimulation::normalize(size_t start_ind, size_t n_elements)
106 {
107  std::vector<double> footprints = m_scan->footprint(start_ind, n_elements);
108 
109  for (size_t i = start_ind, k = 0; i < start_ind + n_elements; ++i, ++k) {
110  auto& element = m_eles[i];
111  element.setIntensity(element.intensity() * footprints[k]);
112  }
113 }
114 
115 void SpecularSimulation::addBackgroundIntensity(size_t start_ind, size_t n_elements)
116 {
117  if (!background())
118  return;
119  for (size_t i = start_ind, stop_point = start_ind + n_elements; i < stop_point; ++i) {
120  auto& element = m_eles[i];
121  element.setIntensity(background()->addBackground(element.intensity()));
122  }
123 }
124 
126 {
127  checkCache();
128  for (size_t i = 0, size = m_eles.size(); i < size; ++i)
129  m_cache[i] += m_eles[i].intensity() * weight;
130 }
131 
133 {
134  checkCache();
135  for (size_t i = 0, size = m_eles.size(); i < size; ++i)
136  m_eles[i].setIntensity(m_cache[i]);
137  m_cache.clear();
138  m_cache.shrink_to_fit();
139 }
141 {
142  return m_scan->polarized();
143 }
Declares AlphaScan class.
Defines the macro ASSERT.
#define ASSERT(condition)
Definition: Assert.h:45
Defines CoordSystem1D class and derived classes.
Defines and implements templated class Datafield.
Defines classes representing one-dimensional distributions.
Defines interface IBackground.
Defines interface IFootprintFactor.
Defines class PointwiseAxis.
Defines class reSample.
Defines class SimulationResult.
Defines class SpecularComputation.
Declares the class SpecularElement.
Defines class SpecularSimulation.
Stores radiation power per bin.
Definition: Datafield.h:30
virtual double min() const =0
Returns value of first point of axis.
Interface to provide axis translations to different units for simulation output.
Definition: ICoordSystem.h:40
virtual double mean() const =0
Returns the distribution-specific mean.
Abstract base class, holds the infrastructure to run a simulation.
Definition: ISimulation.h:42
ProgressHandler & progress()
const IBackground * background() const
Definition: ISimulation.h:76
const SimulationOptions & options() const
Abstract base class for all types of specular scans.
Definition: ISpecularScan.h:34
virtual const IAxis * coordinateAxis() const =0
Returns coordinate axis assigned to the data holder.
Our sample model: a stack of layers one below the other.
Definition: MultiLayer.h:43
A parametric distribution function, for use with any model parameter.
const IDistribution1D * getDistribution() const
Wrapper around Datafield that also provides unit conversions.
Specular reflectometry simulation.
SimulationResult pack_result() override
Sets m_result.
void initElementVector() override
Initializes the vector of ISimulation elements.
std::vector< double > m_cache
bool force_polarized() const override
Force polarized computation even in absence of sample magnetization or external fields.
void addDataToCache(double weight) override
ICoordSystem * createCoordSystem() const override
std::unique_ptr< IComputation > createComputation(const reSample &re_sample, size_t start, size_t n_elements) override
Generate a single threaded computation for a given range of simulation elements.
const ISpecularScan * scan() const
Returns internal data handler.
size_t intensityMapSize() const override
Returns the total number of the intensity values in the simulation result.
~SpecularSimulation() override
std::unique_ptr< const ISpecularScan > m_scan
void addBackgroundIntensity(size_t start_ind, size_t n_elements) override
void moveDataFromCache() override
void validateParametrization(const ParameterDistribution &par_distr) const override
Checks the distribution validity for simulation.
std::vector< SpecularElement > m_eles
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.
SpecularSimulation(const ISpecularScan &scan, const MultiLayer &sample)
size_t numberOfElements() const override
Gets the number of elements this simulation needs to calculate.
Data structure that contains all the necessary data for scattering calculations.
Definition: ReSample.h:41