110 void integrate_batch(StateRange&& states,
typename IntegratorDecorator<S>::time_type dt,
111 typename IntegratorDecorator<S>::time_type end_time) {
112 const size_t batch_size = std::ranges::size(states);
114 if (batch_size == 0) {
118 if (batch_size == 1 || config_.max_threads == 1) {
120 for (
auto& state : states) {
121 this->wrapped_integrator_->integrate(state, dt, end_time);
128#ifdef PARALLEL_EXECUTION_AVAILABLE
129 std::for_each(std::execution::par_unseq,
130 std::ranges::begin(states), std::ranges::end(states),
131 [
this, dt, end_time](
auto& state) {
133 auto local_integrator = this->create_copy();
134 local_integrator->integrate(state, dt, end_time);
138 for (
auto& state : states) {
139 this->wrapped_integrator_->integrate(state, dt, end_time);
142 }
catch (
const std::exception& e) {
144 for (
auto& state : states) {
145 this->wrapped_integrator_->integrate(state, dt, end_time);
164 Processor&& processor,
typename IntegratorDecorator<S>::time_type dt,
165 typename IntegratorDecorator<S>::time_type end_time) {
166 using result_type = std::invoke_result_t<Processor, S>;
167 std::vector<result_type> results(num_simulations);
169 if (num_simulations == 0) {
173 if (num_simulations == 1 || config_.max_threads == 1) {
175 for (
size_t i = 0; i < num_simulations; ++i) {
176 auto state = generator(i);
177 this->wrapped_integrator_->integrate(state, dt, end_time);
178 results[i] = processor(state);
185#ifdef PARALLEL_EXECUTION_AVAILABLE
186 std::for_each(std::execution::par_unseq,
187 std::views::iota(0UL, num_simulations).begin(),
188 std::views::iota(0UL, num_simulations).end(),
190 auto local_integrator = this->create_copy();
191 auto state = generator(i);
192 local_integrator->integrate(state, dt, end_time);
193 results[i] = processor(state);
197 for (
size_t i = 0; i < num_simulations; ++i) {
198 auto state = generator(i);
199 this->wrapped_integrator_->integrate(state, dt, end_time);
200 results[i] = processor(state);
203 }
catch (
const std::exception& e) {
205 for (
size_t i = 0; i < num_simulations; ++i) {
206 auto state = generator(i);
207 this->wrapped_integrator_->integrate(state, dt, end_time);
208 results[i] = processor(state);
224 typename IntegratorDecorator<S>::time_type end_time) {
225 const size_t batch_size = std::ranges::size(states);
227 if (batch_size <= config_.chunk_size || config_.max_threads == 1) {
233 size_t effective_chunk_size = config_.enable_auto_chunking ?
234 calculate_optimal_chunk_size(batch_size) : config_.chunk_size;
237 auto states_begin = std::ranges::begin(states);
238 auto states_end = std::ranges::end(states);
240 for (
auto chunk_start = states_begin; chunk_start < states_end;) {
241 auto chunk_end = chunk_start;
242 std::advance(chunk_end, std::min(effective_chunk_size,
243 static_cast<size_t>(std::distance(chunk_start, states_end))));
246#ifdef PARALLEL_EXECUTION_AVAILABLE
247 std::for_each(std::execution::par_unseq, chunk_start, chunk_end,
248 [
this, dt, end_time](
auto& state) {
249 auto local_integrator = this->create_copy();
250 local_integrator->integrate(state, dt, end_time);
254 std::for_each(chunk_start, chunk_end,
255 [
this, dt, end_time](
auto& state) {
256 this->wrapped_integrator_->integrate(state, dt, end_time);
260 chunk_start = chunk_end;