25 #include <gsl/gsl_errno.h>
38 for (
size_t i = 0; i < detector.
dimension(); ++i)
45 size_t getIndexStep(
size_t total_size,
size_t n_handlers)
47 ASSERT(total_size > 0);
48 ASSERT(n_handlers > 0);
49 size_t result = total_size / n_handlers;
50 return total_size % n_handlers ? ++result : result;
53 size_t getStartIndex(
size_t n_handlers,
size_t current_handler,
size_t n_elements)
55 const size_t handler_size = getIndexStep(n_elements,
static_cast<size_t>(n_handlers));
56 const size_t start_index = current_handler * handler_size;
57 if (start_index >= n_elements)
62 size_t getNumberOfElements(
size_t n_handlers,
size_t current_handler,
size_t n_elements)
64 const size_t handler_size = getIndexStep(n_elements,
static_cast<size_t>(n_handlers));
65 const size_t start_index = current_handler * handler_size;
66 if (start_index >= n_elements)
68 return std::min(handler_size, n_elements - start_index);
71 void runComputations(std::vector<std::unique_ptr<IComputation>> computations)
73 ASSERT(!computations.empty());
75 if (computations.size() == 1) {
76 auto& computation = computations.front();
78 if (computation->isCompleted())
80 std::string message = computation->errorMessage();
82 "terminated unexpectedly with following error: "
90 std::vector<std::unique_ptr<std::thread>> threads;
93 for (
auto& comp : computations)
94 threads.emplace_back(
new std::thread([&comp]() { comp->run(); }));
97 for (
auto& thread : threads)
101 std::vector<std::string> failure_messages;
102 for (
auto& comp : computations)
103 if (!comp->isCompleted())
104 failure_messages.push_back(comp->errorMessage());
106 if (failure_messages.empty())
109 "Error in runComputations: "
110 "At least one simulation thread has terminated unexpectedly.\n"
121 Simulation::Simulation()
126 Simulation::Simulation(
const Simulation& other)
127 :
ICloneable(),
INode(), m_options(other.m_options), m_progress(other.m_progress),
128 m_sample_provider(other.m_sample_provider),
129 m_distribution_handler(other.m_distribution_handler), m_instrument(other.instrument())
131 if (other.m_background)
132 setBackground(*other.m_background);
136 Simulation::~Simulation() =
default;
138 void Simulation::initialize()
140 registerChild(&m_instrument);
141 registerChild(&m_sample_provider);
147 m_progress.subscribe([](
size_t percentage_done) ->
bool {
148 if (percentage_done < 100)
149 std::cout << std::setprecision(2) <<
"\r... " << percentage_done <<
"%" << std::flush;
151 std::cout <<
"\r... 100%\n";
161 void Simulation::removeDetectorResolutionFunction()
168 double total_transmission)
173 void Simulation::setBeamIntensity(
double intensity)
175 instrument().setBeamIntensity(intensity);
178 double Simulation::getBeamIntensity()
const
180 return instrument().getBeamIntensity();
192 if (!MultiLayerUtils::ContainsCompatibleMaterials(*m_sample_provider.
sample()))
193 throw std::runtime_error(
194 "Error in Simulation::prepareSimulation(): non-default materials of"
195 " several different types are used in the sample provided");
196 gsl_set_error_handler_off();
208 m_progress.setExpectedNTicks(param_combinations * total_size);
211 const size_t n_batches = m_options.getNumberOfBatches();
212 const size_t current_batch = m_options.getCurrentBatch();
214 const size_t batch_start = getStartIndex(n_batches, current_batch, total_size);
215 const size_t batch_size = getNumberOfElements(n_batches, current_batch, total_size);
220 for (
size_t index = 0; index < param_combinations; ++index) {
222 runSingleSimulation(batch_start, batch_size, weight);
232 ompi.runSimulation(
this);
235 void Simulation::setInstrument(
const Instrument& instrument_)
237 m_instrument = instrument_;
238 updateIntensityMap();
244 m_sample_provider.setSample(sample);
249 return m_sample_provider.
sample();
252 void Simulation::setSampleBuilder(
const std::shared_ptr<class ISampleBuilder>& sample_builder)
254 m_sample_provider.setBuilder(sample_builder);
257 void Simulation::setBackground(
const IBackground& bg)
259 m_background.reset(bg.clone());
260 registerChild(m_background.get());
265 std::vector<const INode*>
result;
266 result.push_back(&instrument());
269 result.push_back(m_background.get());
273 void Simulation::addParameterDistribution(
const std::string& param_name,
275 double sigma_factor,
const RealLimits& limits)
278 addParameterDistribution(par_distr);
283 validateParametrization(par_distr);
289 void Simulation::runSingleSimulation(
size_t batch_start,
size_t batch_size,
double weight)
293 const size_t n_threads = m_options.getNumberOfThreads();
294 ASSERT(n_threads > 0);
296 std::vector<std::unique_ptr<IComputation>> computations;
298 for (
size_t i_thread = 0; i_thread < n_threads;
300 const size_t thread_start = batch_start + getStartIndex(n_threads, i_thread, batch_size);
301 const size_t thread_size = getNumberOfElements(n_threads, i_thread, batch_size);
302 if (thread_size == 0)
304 computations.push_back(generateSingleThreadedComputation(thread_start, thread_size));
306 runComputations(std::move(computations));
308 normalize(batch_start, batch_size);
309 addBackgroundIntensity(batch_start, batch_size);
310 addDataToCache(weight);
318 bool put_masked_areas_to_zero)
320 auto converter = UnitConverterUtils::createConverter(*
this);
323 const IDetector& detector = instrument().detector();
325 if (roi_data->hasSameDimensions(data)) {
327 if (put_masked_areas_to_zero) {
330 (*roi_data)[it.roiIndex()] = data[it.roiIndex()];
337 }
else if (detHasSameDimensions(detector, data)) {
341 (*roi_data)[it.roiIndex()] = data[it.detectorIndex()];
343 !put_masked_areas_to_zero);
346 throw std::runtime_error(
"FitObject::init_dataset() -> Error. Detector and exp data have "
Defines interface IBackground.
Defines interface IComputation.
Defines pure virtual base class ISampleBuilder.
Defines class MPISimulation.
Defines helper functions for MultiLayer objects.
Defines class MultiLayer.
Defines class ParameterPool.
Defines class Simulation.
Defines a few helper functions.
Declares utilities for unit converters.
void addParameterDistribution(const std::string ¶m_name, const IDistribution1D &distribution, size_t nbr_samples, double sigma_factor=0.0, const RealLimits &limits=RealLimits())
add a sampled parameter distribution
double setParameterValues(ParameterPool *p_parameter_pool, size_t index)
set the parameter values of the simulation object to a specific combination of values,...
void setParameterToMeans(ParameterPool *p_parameter_pool) const
Sets mean distribution values to the parameter pool.
size_t getTotalNumberOfSamples() const
get the total number of parameter value combinations (product of the individual sizes of each paramet...
virtual size_t size() const =0
retrieve the number of bins
Interface for a simulating the background signal.
Interface for polymorphic classes that should not be copied, except by explicit cloning.
Abstract detector interface.
size_t dimension() const
Returns actual dimensionality of the detector (number of defined axes)
Interface for one-dimensional distributions.
Base class for tree-like structures containing parameterized objects.
ParameterPool * createParameterTree() const
Creates new parameter pool, with all local parameters and those of its children.
Interface providing two-dimensional resolution function.
Assembles beam, detector and their relative positions with respect to the sample.
void setAnalyzerProperties(const kvector_t direction, double efficiency, double total_transmission)
Sets the polarization analyzer characteristics of the detector.
void setDetectorResolutionFunction(const IResolutionFunction2D &p_resolution_function)
Sets detector resolution function.
void removeDetectorResolution()
Removes detector resolution function.
void setBeamPolarization(const kvector_t bloch_vector)
Sets the beam's polarization according to the given Bloch vector.
Our sample model: a stack of layers one below the other.
std::vector< T > getRawDataVector() const
Returns copy of raw data vector.
size_t getRank() const
Returns number of dimensions.
const IAxis & getAxis(size_t serial_number) const
returns axis with given serial number
A parametric distribution function, for use with any model parameter.
Limits for a real fit parameter.
void updateSample()
Generates new sample if sample builder defined.
const MultiLayer * sample() const
Returns current sample.
std::vector< const INode * > getChildren() const override
Returns a vector of children (const).
An iterator for SimulationArea.
Wrapper around OutputData<double> that also provides unit conversions.
Pure virtual base class of OffSpecularSimulation, GISASSimulation and SpecularSimulation.
void setTerminalProgressMonitor()
Initializes a progress monitor that prints to stdout.
void runMPISimulation()
Run a simulation in a MPI environment.
void setSample(const MultiLayer &sample)
The MultiLayer object will not be owned by the Simulation object.
virtual void initSimulationElementVector()=0
Initializes the vector of Simulation elements.
void runSimulation()
Run a simulation, possibly averaged over parameter distributions.
void setAnalyzerProperties(const kvector_t direction, double efficiency, double total_transmission)
Sets the polarization analyzer characteristics of the detector.
std::vector< const INode * > getChildren() const
Returns a vector of children (const).
virtual void prepareSimulation()
Put into a clean state for running a simulation.
virtual void transferResultsToIntensityMap()
Creates the appropriate data structure (e.g.
SimulationResult convertData(const OutputData< double > &data, bool put_masked_areas_to_zero=true)
Convert user data to SimulationResult object for later drawing in various axes units.
virtual SimulationResult result() const =0
Returns the results of the simulation in a format that supports unit conversion and export to numpy a...
void setBeamPolarization(const kvector_t bloch_vector)
Sets the beam polarization according to the given Bloch vector.
virtual size_t numberOfSimulationElements() const =0
Gets the number of elements this simulation needs to calculate.
std::string join(const std::vector< std::string > &joinable, const std::string &joint)
Returns string obtain by joining vector elements.
std::unique_ptr< OutputData< double > > createOutputData(const IUnitConverter &converter, Axes::Units units)
Returns zero-valued output data array in specified units.