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.