26 #include <gsl/gsl_errno.h>
32 size_t indexStep(
size_t total_size,
size_t n_handlers)
36 size_t result = total_size / n_handlers;
37 return total_size % n_handlers ? ++result : result;
40 size_t startIndex(
size_t n_handlers,
size_t current_handler,
size_t n_elements)
42 const size_t handler_size = indexStep(n_elements, n_handlers);
43 const size_t start_index = current_handler * handler_size;
44 if (start_index >= n_elements)
49 size_t batchSize(
size_t n_handlers,
size_t current_handler,
size_t n_elements)
51 const size_t handler_size = indexStep(n_elements, n_handlers);
52 const size_t start_index = current_handler * handler_size;
53 if (start_index >= n_elements)
55 return std::min(handler_size, n_elements - start_index);
58 void runComputations(
const std::vector<std::unique_ptr<IComputation>>& computations)
60 ASSERT(!computations.empty());
62 if (computations.size() == 1) {
63 const auto& computation = computations.front();
64 computation->compute();
65 if (computation->isCompleted())
67 std::string message = computation->errorMessage();
68 throw std::runtime_error(
"Error in runComputations: ISimulation has "
69 "terminated unexpectedly with following error: "
77 std::vector<std::unique_ptr<std::thread>> threads;
80 for (
const auto& comp : computations)
81 threads.emplace_back(
new std::thread([&comp]() { comp->compute(); }));
84 for (
auto& thread : threads)
88 std::vector<std::string> failure_messages;
89 for (
const auto& comp : computations)
90 if (!comp->isCompleted())
91 failure_messages.push_back(comp->errorMessage());
93 if (failure_messages.empty())
95 throw std::runtime_error(
"Error in runComputations: "
96 "At least one simulation thread has terminated unexpectedly.\n"
109 : m_sample(sample.clone())
144 m_progress->subscribe([](
size_t percentage_done) ->
bool {
145 if (percentage_done < 100)
146 std::cout << std::setprecision(2) <<
"\r... " << percentage_done <<
"%" << std::flush;
148 std::cout <<
"\r... 100%\n";
157 throw std::runtime_error(
"Sample contains incompatible material definitions");
158 gsl_set_error_handler_off();
168 m_progress->setExpectedNTicks(param_combinations * total_size);
171 const size_t n_batches =
m_options->getNumberOfBatches();
172 const size_t current_batch =
m_options->getCurrentBatch();
174 const size_t batch_start = startIndex(n_batches, current_batch, total_size);
175 const size_t batch_size = batchSize(n_batches, current_batch, total_size);
178 if (param_combinations == 1)
182 for (
size_t index = 0; index < param_combinations; ++index) {
203 std::vector<const INode*> result;
218 throw std::runtime_error(
"ISimulation::unitOfParameter(): missing implementation");
224 double sigma_factor,
const RealLimits& limits)
246 size_t batch_size,
double weight)
250 const size_t n_threads =
m_options->getNumberOfThreads();
253 std::vector<std::unique_ptr<IComputation>> computations;
255 for (
size_t i_thread = 0; i_thread < n_threads; ++i_thread) {
256 const size_t thread_start = batch_start + startIndex(n_threads, i_thread, batch_size);
257 const size_t thread_size = batchSize(n_threads, i_thread, batch_size);
258 if (thread_size == 0)
260 computations.emplace_back(
createComputation(re_sample, thread_start, thread_size));
262 runComputations(computations);
Defines the macro ASSERT.
#define ASSERT(condition)
Defines a few helper functions.
Defines interface IBackground.
Defines interface IComputation.
Defines interface ISimulation.
Defines class MultiLayer.
Defines namespace SampleUtils::Multilayer.
Defines class ProgressHandler.
Defines class SimulationOptions.
Defines class SimulationResult.
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(size_t index)
set the parameter values of the simulation object to a specific combination of values,...
const std::vector< ParameterDistribution > & getDistributions() const
size_t getTotalNumberOfSamples() const
get the total number of parameter value combinations (product of the individual sizes of each paramet...
Abstract base class for background noise, to be added to simulated scattering.
IBackground * clone() const override=0
Interface for one-dimensional distributions.
void addParameterDistribution(ParameterDistribution::WhichParameter whichParameter, const IDistribution1D &distribution, size_t nbr_samples, double sigma_factor=0.0, const RealLimits &limits=RealLimits())
std::shared_ptr< MultiLayer > m_sample
virtual size_t numberOfElements() const =0
Gets the number of elements this simulation needs to calculate.
virtual void prepareSimulation()=0
Put into a clean state for running a simulation.
virtual void initElementVector()=0
Initializes the vector of ISimulation elements.
ProgressHandler & progress()
virtual void validateParametrization(const ParameterDistribution &) const
Checks the distribution validity for simulation.
virtual void addDataToCache(double weight)=0
virtual SimulationResult pack_result()=0
Sets m_result.
void subscribe(const std::function< bool(size_t)> &inform)
const MultiLayer * sample() const
std::vector< const INode * > nodeChildren() const override
Returns all children.
const SimulationOptions & options() const
virtual void moveDataFromCache()=0
virtual void addBackgroundIntensity(size_t start_ind, size_t n_elements)=0
void runSingleSimulation(const reSample &re_sample, size_t batch_start, size_t batch_size, double weight=1.0)
Runs a single simulation with fixed parameter values. If desired, the simulation is run in several th...
const std::vector< ParameterDistribution > & getDistributions() const
virtual std::unique_ptr< IComputation > createComputation(const reSample &re_sample, size_t start, size_t n_elements)=0
Generate a single threaded computation for a given range of simulation elements.
std::shared_ptr< SimulationOptions > m_options
std::shared_ptr< ProgressHandler > m_progress
virtual bool force_polarized() const =0
Force polarized computation even in absence of sample magnetization or external fields.
ISimulation(const MultiLayer &sample)
SimulationResult simulate()
Run a simulation, and return the result.
std::shared_ptr< IBackground > m_background
void setBackground(const IBackground &bg)
virtual void initDistributionHandler()
std::string unitOfParameter(ParameterDistribution::WhichParameter which) const
DistributionHandler m_distribution_handler
virtual void normalize(size_t start_ind, size_t n_elements)=0
Normalize the detector counts to beam intensity, to solid angle, and to exposure angle.
void setTerminalProgressMonitor()
Initializes a progress monitor that prints to stdout.
Our sample model: a stack of layers one below the other.
A parametric distribution function, for use with any model parameter.
Maintains information about progress of a computation.
Limits for a real fit parameter.
Collect the different options for simulation.SimulationOptions.
Wrapper around Datafield that also provides unit conversions.
Data structure that contains all the necessary data for scattering calculations.
static reSample make(const MultiLayer &sample, const SimulationOptions &options, bool forcePolarized=false)
Factory method that wraps the private constructor.
std::string join(const std::vector< std::string > &joinable, const std::string &joint)
Returns string obtain by joining vector elements.
bool ContainsCompatibleMaterials(const MultiLayer &sample)
Returns true if the sample contains non-default materials of one type only.