33 const double zero_phi_i = 0.0;
34 const double zero_alpha_i = 0.0;
37 DepthProbeSimulation::DepthProbeSimulation() :
Simulation()
42 DepthProbeSimulation::~DepthProbeSimulation() =
default;
49 size_t DepthProbeSimulation::numberOfSimulationElements()
const
57 auto data = createIntensityData();
64 FixedBinAxis axis(
"alpha_i",
static_cast<size_t>(nbins), alpha_i_min, alpha_i_max);
71 throw std::runtime_error(
"Error in DepthProbeSimulation::setZSpan: maximum on-axis value "
72 "is less or equal to the minimum one");
73 m_z_axis = std::make_unique<FixedBinAxis>(
"z", n_bins, z_min, z_max);
79 throw std::runtime_error(
"Error in DepthProbeSimulation::getAlphaAxis: incident angle axis "
80 "was not initialized.");
81 return m_alpha_axis.get();
87 throw std::runtime_error(
"Error in DepthProbeSimulation::getZAxis: position axis "
88 "was not initialized.");
89 return m_z_axis.get();
94 if (!m_z_axis || !m_alpha_axis)
95 throw std::runtime_error(
"Error in DepthProbeSimulation::intensityMapSize: attempt to "
96 "access non-initialized data.");
97 return m_z_axis->size() * m_alpha_axis->size();
100 std::unique_ptr<IUnitConverter> DepthProbeSimulation::createUnitConverter()
const
102 return std::make_unique<DepthProbeConverter>(instrument().getBeam(), *m_alpha_axis, *m_z_axis);
106 :
Simulation(other), m_sim_elements(other.m_sim_elements), m_cache(other.m_cache)
108 if (other.m_alpha_axis)
109 m_alpha_axis.reset(other.m_alpha_axis->clone());
111 m_z_axis.reset(other.m_z_axis->clone());
112 for (
auto iter = m_sim_elements.begin(); iter != m_sim_elements.end(); ++iter)
113 iter->setZPositions(m_alpha_axis.get());
121 throw std::runtime_error(
122 "Error in DepthProbeSimulation::setBeamParameters: wavelength must be positive.");
123 if (alpha_axis.
getMin() < 0.0)
124 throw std::runtime_error(
125 "Error in DepthProbeSimulation::setBeamParameters: minimum value on "
126 "angle axis is negative.");
128 throw std::runtime_error(
129 "Error in DepthProbeSimulation::setBeamParameters: maximal value on "
130 "angle axis is less or equal to the minimal one.");
131 if (alpha_axis.
size() == 0)
132 throw std::runtime_error(
133 "Error in DepthProbeSimulation::setBeamParameters: angle axis is empty");
137 m_alpha_axis.reset(alpha_axis.
clone());
148 void DepthProbeSimulation::initSimulationElementVector()
150 const auto& beam = instrument().getBeam();
151 m_sim_elements = generateSimulationElements(beam);
153 if (!m_cache.empty())
155 m_cache.resize(m_sim_elements.size(), std::valarray<double>(0.0,
getZAxis()->size()));
158 std::vector<DepthProbeElement> DepthProbeSimulation::generateSimulationElements(
const Beam& beam)
160 std::vector<DepthProbeElement>
result;
162 const double wavelength = beam.getWavelength();
163 const double angle_shift = beam.getAlpha();
166 result.reserve(axis_size);
167 for (
size_t i = 0; i < axis_size; ++i) {
168 double result_angle = incidentAngle(i) + angle_shift;
170 if (!alpha_limits.isInRange(result_angle))
171 result.back().setCalculationFlag(
false);
176 std::unique_ptr<IComputation>
177 DepthProbeSimulation::generateSingleThreadedComputation(
size_t start,
size_t n_elements)
179 ASSERT(start < m_sim_elements.size() && start + n_elements <= m_sim_elements.size());
180 const auto& begin = m_sim_elements.begin() +
static_cast<long>(start);
181 return std::make_unique<DepthProbeComputation>(*sample(), options(), progress(), begin,
182 begin +
static_cast<long>(n_elements));
185 void DepthProbeSimulation::validityCheck()
const
189 throw std::runtime_error(
190 "Error in DepthProbeSimulation::validityCheck: no sample found in the simulation.");
192 const size_t data_size = m_sim_elements.size();
194 throw std::runtime_error(
195 "Error in DepthProbeSimulation::validityCheck: length of simulation "
196 "element vector is not equal to the number of inclination angles");
199 void DepthProbeSimulation::checkCache()
const
201 if (m_sim_elements.size() != m_cache.size())
202 throw std::runtime_error(
"Error in DepthProbeSimulation: the sizes of simulation element "
203 "vector and of its cache are different");
208 const bool zero_mean = par_distr.getDistribution()->
getMean() == 0.0;
213 const std::vector<RealParameter*> names =
215 for (
const auto par : names)
216 if (par->getName().find(
"InclinationAngle") != std::string::npos && !zero_mean)
217 throw std::runtime_error(
"Error in DepthProbeSimulation: parameter distribution of "
218 "beam inclination angle should have zero mean.");
221 void DepthProbeSimulation::initialize()
223 setName(
"DepthProbeSimulation");
227 auto inclination = instrument().getBeam().
parameter(
"InclinationAngle");
231 void DepthProbeSimulation::normalize(
size_t start_ind,
size_t n_elements)
233 const double beam_intensity = getBeamIntensity();
234 if (beam_intensity == 0.0)
236 for (
size_t i = start_ind, stop_point = start_ind + n_elements; i < stop_point; ++i) {
237 auto& element = m_sim_elements[i];
238 const double alpha_i = -element.getAlphaI();
240 double intensity_factor = beam_intensity;
241 if (footprint !=
nullptr)
242 intensity_factor = intensity_factor * footprint->
calculate(alpha_i);
243 element.setIntensities(element.getIntensities() * intensity_factor);
247 void DepthProbeSimulation::addBackgroundIntensity(
size_t,
size_t)
250 throw std::runtime_error(
251 "Error: nonzero background is not supported by DepthProbeSimulation");
254 void DepthProbeSimulation::addDataToCache(
double weight)
257 for (
size_t i = 0, size = m_sim_elements.size(); i < size; ++i)
258 m_cache[i] += m_sim_elements[i].getIntensities() * weight;
261 void DepthProbeSimulation::moveDataFromCache()
264 for (
size_t i = 0, size = m_sim_elements.size(); i < size; ++i)
265 m_sim_elements[i].setIntensities(std::move(m_cache[i]));
267 m_cache.shrink_to_fit();
270 double DepthProbeSimulation::incidentAngle(
size_t index)
const
272 return m_alpha_axis->getBin(index).getMidPoint();
275 std::unique_ptr<OutputData<double>> DepthProbeSimulation::createIntensityData()
const
277 std::unique_ptr<OutputData<double>>
result = std::make_unique<OutputData<double>>();
281 std::vector<double> rawData;
283 for (
size_t i = 0, size = m_sim_elements.size(); i < size; ++i) {
284 const std::valarray<double>& fixed_angle_result = m_sim_elements[i].getIntensities();
285 rawData.insert(rawData.end(), std::begin(fixed_angle_result), std::end(fixed_angle_result));
287 result->setRawDataVector(rawData);
292 std::vector<double> DepthProbeSimulation::rawResults()
const
298 std::vector<double>
result;
299 result.reserve(alpha_size * z_size);
300 for (
size_t i = 0; i < alpha_size; ++i) {
301 if (m_sim_elements[i].size() != z_size)
302 throw std::runtime_error(
"Error in DepthProbeSimulation::rawResults: simulation "
303 "element size is not equal to the size of the position axis");
304 const auto& intensities = m_sim_elements[i].getIntensities();
305 result.insert(
result.end(), std::begin(intensities), std::end(intensities));
311 void DepthProbeSimulation::setRawResults(
const std::vector<double>& raw_results)
317 if (raw_results.size() != z_size * alpha_size)
318 throw std::runtime_error(
319 "Error in DepthProbeSimulation::setRawResults: the vector to set is of invalid size");
321 const double* raw_array = raw_results.data();
322 for (
size_t i = 0; i < alpha_size; ++i) {
323 std::valarray<double> fixed_angle_result(raw_array, z_size);
324 m_sim_elements[i].setIntensities(std::move(fixed_angle_result));
Declares class DepthProbeComputation.
Defines class DepthProbeSimulation.
Defines classes representing one-dimensional distributions.
Defines class Histogram1D.
Defines interface IBackground.
Defines pure virtual base class ISampleBuilder.
Declares functions in namespace MaterialUtils.
Defines M_PI and some more mathematical constants.
Defines class MultiLayer.
Defines class ParameterPool.
Defines class RealParameter.
Defines interface UnitConverterSimple and its subclasses.
Defines a detector for specular simulations.
Beam defined by wavelength, direction and intensity.
const IFootprintFactor * footprintFactor() const
Returns footprint factor.
void setFootprintFactor(const IFootprintFactor &shape_factor)
Sets footprint factor to the beam.
const IAxis * getAlphaAxis() const
Returns a pointer to incident angle axis.
SimulationResult result() const override
Returns the results of the simulation in a format that supports unit conversion and export to numpy a...
void setBeamParameters(double lambda, int nbins, double alpha_i_min, double alpha_i_max, const IFootprintFactor *beam_shape=nullptr)
Sets beam parameters with alpha_i of the beam defined in the range.
void setZSpan(size_t n_bins, double z_min, double z_max)
Set z positions for intensity calculations.
const IAxis * getZAxis() const
Returns a pointer to z-position axis.
size_t intensityMapSize() const override
Returns the total number of the intensity values in the simulation result.
Axis with fixed bin size.
Interface for one-dimensional axes.
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 getMax() const =0
Returns value of last point of axis.
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.
RealParameter * parameter(const std::string &name) const
Returns parameter with given 'name'.
void setBeamParameters(double wavelength, double alpha_i, double phi_i)
Sets the beam wavelength and incoming angles.
void setDetector(const IDetector &detector)
Sets the detector (axes can be overwritten later)
Our sample model: a stack of layers one below the other.
A parametric distribution function, for use with any model parameter.
std::string getMainParameterName() const
get the main parameter's name
Limits for a real fit parameter.
static RealLimits limited(double left_bound_value, double right_bound_value)
Creates an object bounded from the left and right.
Wrapper around OutputData<double> that also provides unit conversions.
Pure virtual base class of OffSpecularSimulation, GISASSimulation and SpecularSimulation.
1D detector for specular simulations.