BornAgain  1.19.79
Open-source research software to simulate and fit neutron and x-ray reflectometry and grazing-incidence small-angle scattering
ISimulation2D.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Sim/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 
16 #include "Base/Util/Assert.h"
17 #include "Device/Beam/Beam.h"
24 
25 ISimulation2D::ISimulation2D(const Beam& beam, const MultiLayer& sample, const IDetector& detector)
26  : ISimulation(sample)
27  , m_beam(beam.clone())
28  , m_detector(detector.clone())
29 {
30  m_detector->setDetectorNormal(m_beam->direction().zReflected());
31 }
32 
34  : ISimulation(sample)
35  , m_beam(Beam::horizontalBeam().clone())
36  , m_detector(new SphericalDetector())
37 {
38 }
39 
41 
42 std::vector<const INode*> ISimulation2D::nodeChildren() const
43 {
44  std::vector<const INode*> result = ISimulation::nodeChildren();
45  result.push_back(m_beam.get());
46  if (m_detector)
47  result.push_back(m_detector.get());
48  return result;
49 }
50 
52 {
54 }
55 
56 void ISimulation2D::addMask(const IShape2D& shape, bool mask_value)
57 {
58  detector().addMask(shape, mask_value);
59 }
60 
62 {
63  detector().maskAll();
64 }
65 
66 void ISimulation2D::setRegionOfInterest(double xlow, double ylow, double xup, double yup)
67 {
68  detector().setRegionOfInterest(xlow, ylow, xup, yup);
69 }
70 
72 {
73  if (!m_detector_context)
74  throw std::runtime_error("Error in numberOfElements(): no detector context");
75  return m_detector_context->numberOfElements();
76 }
77 
78 std::unique_ptr<IComputation> ISimulation2D::createComputation(const reSample& re_sample,
79  size_t start, size_t n_elements)
80 {
81  ASSERT(start < m_eles.size() && start + n_elements <= m_eles.size());
82  const auto& begin = m_eles.begin() + static_cast<long>(start);
83  return std::make_unique<DWBAComputation>(re_sample, options(), progress(), begin,
84  begin + static_cast<long>(n_elements));
85 }
86 
87 std::vector<std::unique_ptr<DiffuseElement>> ISimulation2D::generateElements(const Beam& beam)
88 {
89  const double wavelength = beam.wavelength();
90  const double alpha_i = -beam.direction().alpha(); // Defined to be always positive in Beam
91  const double phi_i = beam.direction().phi();
92  const SpinMatrix beam_polMatrices = beam.polMatrix();
93 
94  const SpinMatrix analyzer_operator = detector().analyzer().matrix();
95  const size_t spec_index = detector().indexOfSpecular(beam);
96 
97  const size_t N = m_detector_context->numberOfElements();
98 
99  std::vector<std::unique_ptr<DiffuseElement>> result;
100  result.reserve(N);
101  for (size_t element_index = 0; element_index < N; ++element_index)
102  result.emplace_back(std::make_unique<DiffuseElement>(
103  wavelength, alpha_i, phi_i, m_detector_context->createPixel(element_index),
104  beam_polMatrices, analyzer_operator,
105  m_detector_context->detectorIndex(element_index) == spec_index));
106  return result;
107 }
108 
109 void ISimulation2D::normalize(size_t start_ind, size_t n_elements)
110 {
111  const double beam_intensity = beam().intensity();
112  for (size_t i = start_ind, stop_point = start_ind + n_elements; i < stop_point; ++i) {
113  DiffuseElement& element = *m_eles[i];
114  double sin_alpha_i = std::abs(std::sin(element.alphaI()));
115  if (sin_alpha_i == 0.0) {
116  element.setIntensity(0);
117  continue;
118  }
119  const double solid_angle = element.solidAngle();
120  element.setIntensity(element.intensity() * beam_intensity * solid_angle / sin_alpha_i);
121  }
122 }
123 
124 void ISimulation2D::addBackgroundIntensity(size_t start_ind, size_t n_elements)
125 {
126  if (!background())
127  return;
128  for (size_t i = start_ind, stop_point = start_ind + n_elements; i < stop_point; ++i) {
129  DiffuseElement& element = *m_eles[i];
130  element.setIntensity(background()->addBackground(element.intensity()));
131  }
132 }
133 
134 void ISimulation2D::addDataToCache(double weight)
135 {
136  if (m_eles.size() != m_cache.size())
137  throw std::runtime_error("Error in ISimulation2D::addDataToCache(double): cache size"
138  " not the same as element size");
139  for (unsigned i = 0; i < m_eles.size(); i++)
140  m_cache[i] += m_eles[i]->intensity() * weight;
141 }
142 
144 {
145  ASSERT(!m_cache.empty());
146  if (!m_cache.empty()) {
147  for (unsigned i = 0; i < m_eles.size(); i++)
148  m_eles[i]->setIntensity(m_cache[i]);
149  m_cache.clear();
150  }
151 }
152 
154 {
155  return detector().analyzer().analyzerDirection() != R3{};
156 }
157 
158 //! init callbacks for setting the parameter values
160 {
161  for (const auto& distribution : m_distribution_handler.getDistributions()) {
162  const auto* dc = const_cast<ParameterDistribution*>(&distribution);
163 
164  switch (dc->whichParameter()) {
167  dc, [&](double d) { beam().setAzimuthalAngleGuarded(d); });
168  break;
171  dc, [&](double d) { beam().setInclinationAngleGuarded(d); });
172  break;
175  dc, [&](double d) { beam().setWavelengthGuarded(d); });
176  break;
177  default:
178  ASSERT(0);
179  }
180  }
181 }
Defines the macro ASSERT.
#define ASSERT(condition)
Definition: Assert.h:45
Defines class Beam.
Defines class DWBAComputation.
Define DetectorContext class.
Defines class DiffuseElement.
Defines interface IBackground.
Defines common detector interface.
Defines interface ISimulation2D.
Defines class SphericalDetector.
An incident neutron or x-ray beam.
Definition: Beam.h:28
Direction direction() const
Definition: Beam.h:46
void setAzimuthalAngleGuarded(double value)
Check for limits, set the value if within limits. Throws if limits are violated.
Definition: Beam.cpp:123
void setInclinationAngleGuarded(double value)
Check for limits, set the value if within limits. Throws if limits are violated.
Definition: Beam.cpp:117
double intensity() const
Returns the beam intensity in neutrons/sec.
Definition: Beam.h:43
double wavelength() const
Definition: Beam.h:44
void setWavelengthGuarded(double value)
Check for limits, set the value if within limits. Throws if limits are violated.
Definition: Beam.cpp:129
SpinMatrix polMatrix() const
Returns the polarization density matrix (in spin basis along z-axis)
Definition: Beam.cpp:155
Data stucture containing both input and output of a single detector cell.
double alphaI() const
double solidAngle() const
double intensity() const
void setIntensity(double intensity)
double phi() const
Definition: Direction.h:37
double alpha() const
Definition: Direction.h:36
const std::vector< ParameterDistribution > & getDistributions() const
void defineCallbackForDistribution(const ParameterDistribution *distribution, std::function< void(double)> fn)
Abstract detector interface.
Definition: IDetector.h:57
virtual size_t indexOfSpecular(const Beam &beam) const =0
Returns index of pixel that contains the specular wavevector. If no pixel contains this specular wave...
void setRegionOfInterest(double xlow, double ylow, double xup, double yup)
Sets rectangular region of interest with lower left and upper right corners defined.
Definition: IDetector.cpp:337
const PolFilter & analyzer() const
Returns detection properties.
Definition: IDetector.h:204
void maskAll()
Put the mask for all detector channels (i.e. exclude whole detector from the analysis)
Definition: IDetector.cpp:365
void addMask(const IShape2D &shape, bool mask_value=true)
Adds mask of given shape to the stack of detector masks. The mask value 'true' means that the channel...
Definition: IDetector.cpp:360
std::unique_ptr< DetectorContext > createContext() const
Definition: IDetector.cpp:355
Basic class for all shapes in 2D.
Definition: IShape2D.h:26
std::unique_ptr< DetectorContext > m_detector_context
void moveDataFromCache() override
IDetector & detector()
Definition: ISimulation2D.h:58
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::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.
void setRegionOfInterest(double xlow, double ylow, double xup, double yup)
Sets rectangular region of interest with lower left and upper right corners defined.
std::vector< const INode * > nodeChildren() const override
Returns all children.
bool force_polarized() const override
Force polarized computation even in absence of sample magnetization or external fields.
std::vector< std::unique_ptr< DiffuseElement > > generateElements(const Beam &beam)
Generate simulation elements for given beam.
~ISimulation2D() override
std::unique_ptr< IDetector > m_detector
Definition: ISimulation2D.h:99
Beam & beam()
Definition: ISimulation2D.h:57
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::unique_ptr< Beam > m_beam
Definition: ISimulation2D.h:98
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
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. The mask value 'true' means that the channel...
ISimulation2D(const Beam &beam, const MultiLayer &sample, const IDetector &detector)
void initDistributionHandler() override
init callbacks for setting the parameter values
Abstract base class, holds the infrastructure to run a simulation.
Definition: ISimulation.h:42
ProgressHandler & progress()
const IBackground * background() const
Definition: ISimulation.h:76
std::vector< const INode * > nodeChildren() const override
Returns all children.
const SimulationOptions & options() const
DistributionHandler m_distribution_handler
Definition: ISimulation.h:104
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.
R3 analyzerDirection() const
Retrieve the analyzer characteristics.
Definition: PolFilter.cpp:48
SpinMatrix matrix() const
Return the polarization density matrix (in spin basis along z-axis)
Definition: PolFilter.cpp:40
A detector with coordinate axes along angles phi and alpha.
Data structure that contains all the necessary data for scattering calculations.
Definition: ReSample.h:41
#define N
Definition: mixmax.h:31