BornAgain  1.19.79
Simulate and fit neutron and x-ray scattering at grazing incidence
SimulationToCore.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/Model/ToCore/SimulationToCore.cpp
6 //! @brief Implements class DomainSimulationBuilder
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/Const/Units.h"
17 #include "Base/Util/Assert.h"
18 #include "Device/Beam/Beam.h"
19 #include "Device/Beam/IFootprintFactor.h"
30 #include "GUI/Util/Error.h"
31 #include "Param/Distrib/RangedDistributions.h"
32 #include "Resample/Options/SimulationOptions.h"
33 #include "Sample/Multilayer/MultiLayer.h"
34 #include "Sim/Background/IBackground.h"
35 #include "Sim/Scan/AlphaScan.h"
36 #include "Sim/Scan/ScanResolution.h"
37 #include "Sim/Simulation/includeSimulations.h"
38 
39 namespace {
40 
41 //! If the given item has distributions, then add these distributions to the simulation's
42 //! distributions handler.
43 template <class T>
44 void setParameterDistributionToSimulation(ParameterDistribution::WhichParameter which,
45  const BeamDistributionItem* item, ISimulation& simulation)
46 {
47  const auto* const parameter_item = dynamic_cast<const T*>(item);
48  ASSERT(parameter_item);
49 
50  auto par_distr = parameter_item->getParameterDistributionForName(which);
51  if (par_distr)
52  simulation.addParameterDistribution(*par_distr);
53 }
54 
55 //! adds DistributionParameters to the ISimulation
56 void addDistributionParametersToSimulation(const BeamItem& item, ScatteringSimulation& simulation)
57 {
58  ASSERT(dynamic_cast<const GISASBeamItem*>(&item));
59 
60  setParameterDistributionToSimulation<BeamWavelengthItem>(ParameterDistribution::BeamWavelength,
61  item.wavelengthItem(), simulation);
62  setParameterDistributionToSimulation<BeamInclinationAngleItem>(
63  ParameterDistribution::BeamInclinationAngle, item.inclinationAngleItem(), simulation);
64  setParameterDistributionToSimulation<BeamAzimuthalAngleItem>(
65  ParameterDistribution::BeamAzimuthalAngle, item.azimuthalAngleItem(), simulation);
66 }
67 
68 void addBackgroundToSimulation(const InstrumentItem& item, ISimulation& simulation)
69 {
70  if (const auto background = item.backgroundItem()->createBackground())
71  simulation.setBackground(*background);
72 }
73 
74 std::unique_ptr<ScanResolution> createScanResolution(const BeamDistributionItem* item)
75 {
76  if (!item)
77  return nullptr;
78 
79  const auto* distr_item = dynamic_cast<const SymmetricResolutionItem*>(item->distribution());
80  if (!distr_item)
81  return nullptr;
82 
83  const double scale = item->scaleFactor();
84  auto ranged_distr = distr_item->createIRangedDistribution(scale);
85  if (!ranged_distr)
86  return nullptr;
87 
88  const double deviation = distr_item->deviation(scale);
89  return std::unique_ptr<ScanResolution>(
90  ScanResolution::scanAbsoluteResolution(*ranged_distr, deviation));
91 }
92 
93 void setSimulationOptions(ISimulation* simulation, const SimulationOptionsItem& item)
94 {
95  simulation->options().setNumberOfThreads(item.numberOfThreads());
96  if (item.useMonteCarloIntegration())
97  simulation->options().setMonteCarloIntegration(true, item.numberOfMonteCarloPoints());
98  simulation->options().setUseAvgMaterials(item.useAverageMaterials());
99  simulation->options().setIncludeSpecular(item.includeSpecularPeak());
100 }
101 
102 ScatteringSimulation* createScatteringSimulation(std::unique_ptr<MultiLayer> sample,
103  const GISASInstrumentItem* item)
104 {
105  ScatteringSimulation* result = item->createScatteringSimulation(*sample);
106 
107  addDistributionParametersToSimulation(*item->beamItem(), *result);
108 
109  addBackgroundToSimulation(*item, *result);
110 
111  return result;
112 }
113 
114 OffspecSimulation* createOffspecSimulation(std::unique_ptr<MultiLayer> sample,
115  const OffspecInstrumentItem* item)
116 {
117  OffspecSimulation* result = item->createOffspecSimulation(*sample);
118 
119  auto* beamItem = item->beamItem();
120  const auto axis = item->alphaAxis().createAxis(Units::deg);
121  result->setBeamParameters(beamItem->wavelength(), *axis, beamItem->getAzimuthalAngle());
122 
123  addBackgroundToSimulation(*item, *result);
124 
125  return result;
126 }
127 
128 SpecularSimulation* createSpecularSimulation(std::unique_ptr<MultiLayer> sample,
129  const SpecularInstrumentItem* item)
130 {
131  auto* beam_item = item->beamItem();
132  auto* const axis_item = beam_item->inclinationAxis();
133  auto* const footprint_item = beam_item->footprint();
134 
135  AlphaScan scan(beam_item->wavelength(), *axis_item->createAxis(Units::deg));
136  scan.setFootprintFactor(footprint_item->createFootprint().get());
137 
138  if (const auto resolution = createScanResolution(beam_item->wavelengthItem()))
139  scan.setWavelengthResolution(*resolution);
140  if (const auto resolution = createScanResolution(beam_item->inclinationAngleItem()))
141  scan.setAngleResolution(*resolution);
142 
143  auto* result = new SpecularSimulation(scan, *sample);
144  // result->beam().setIntensity(beam_item->intensity());
145 
146  addBackgroundToSimulation(*item, *result);
147 
148  return result;
149 }
150 
151 DepthProbeSimulation* createDepthProbeSimulation(std::unique_ptr<MultiLayer> sample,
152  const DepthProbeInstrumentItem* item)
153 {
154  return item->createSimulation(*sample);
155 }
156 
157 } // namespace
158 
159 
160 std::unique_ptr<ISimulation>
162  const InstrumentItem* instrumentItem,
163  const SimulationOptionsItem& optionsItem)
164 {
165  ASSERT(sampleItem);
166  ASSERT(instrumentItem);
167 
168  std::unique_ptr<MultiLayer> sample = GUI::Transform::ToCore::itemToSample(*sampleItem);
169  std::unique_ptr<ISimulation> result;
170 
171  if (const auto* gisasInstrument = dynamic_cast<const GISASInstrumentItem*>(instrumentItem))
172  result.reset(createScatteringSimulation(std::move(sample), gisasInstrument));
173  else if (const auto* offspecInstrument =
174  dynamic_cast<const OffspecInstrumentItem*>(instrumentItem))
175  result.reset(createOffspecSimulation(std::move(sample), offspecInstrument));
176  else if (const auto* specular_instrument =
177  dynamic_cast<const SpecularInstrumentItem*>(instrumentItem))
178  result.reset(createSpecularSimulation(std::move(sample), specular_instrument));
179  else if (const auto* penetrator = dynamic_cast<const DepthProbeInstrumentItem*>(instrumentItem))
180  result.reset(createDepthProbeSimulation(std::move(sample), penetrator));
181  else
182  ASSERT(0);
183 
184  setSimulationOptions(result.get(), optionsItem);
185 
186  return result;
187 }
Defines various axis items.
Defines BackgroundItem classes.
Defines class BeamAngleItems.
Defines class BeamWavelengthItem.
Defines error class.
Declares FootprintItem classes.
Defines class InstrumentItem and all its children.
Defines class Instrument.
Defines class MultiLayerItem.
Defines namespace GUI::Transform::ToCore.
Defines class SimulationOptionsItem.
Defines namespace GUI::Transform::ToCore.
virtual std::unique_ptr< IBackground > createBackground() const =0
The BeamDistributionItem handles wavelength, inclination and azimuthal parameter distribution for Bea...
DistributionItem * distribution() const
virtual double scaleFactor() const
virtual BeamDistributionItem * inclinationAngleItem() const
Definition: BeamItems.cpp:77
BeamAzimuthalAngleItem * azimuthalAngleItem() const
Definition: BeamItems.cpp:92
BeamWavelengthItem * wavelengthItem() const
Definition: BeamItems.cpp:67
DepthProbeSimulation * createSimulation(const MultiLayer &sample) const
ScatteringSimulation * createScatteringSimulation(const MultiLayer &sample) const
OffspecSimulation * createOffspecSimulation(const MultiLayer &sample) const
Abstract base class for instrument-specific item classes.
virtual BeamItem * beamItem() const
BackgroundItem * backgroundItem() const
The SimulationOptionsItem class holds simulation status (run policy, number of threads,...
unsigned numberOfThreads() const
unsigned numberOfMonteCarloPoints() const
BasicAxisItem * inclinationAxis() const
Definition: BeamItems.cpp:156
SpecularBeamItem * beamItem() const override
std::unique_ptr< ISimulation > itemsToSimulation(const MultiLayerItem *sampleItem, const InstrumentItem *instrumentItem, const SimulationOptionsItem &optionsItem)
Creates domain simulation from sample and instrument items.
std::unique_ptr< MultiLayer > itemToSample(const MultiLayerItem &item)