ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
tuning.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2022 The ESPResSo project
3 * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010
4 * Max-Planck-Institute for Polymer Research, Theory Group
5 *
6 * This file is part of ESPResSo.
7 *
8 * ESPResSo is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * ESPResSo is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include "tuning.hpp"
23
25#include "communication.hpp"
26#include "errorhandling.hpp"
27#include "integrate.hpp"
29#include "system/System.hpp"
30
32
33#include <boost/mpi/collectives/all_reduce.hpp>
34#include <boost/mpi/collectives/broadcast.hpp>
35#include <boost/range/algorithm/max_element.hpp>
36#include <boost/range/algorithm/min_element.hpp>
37
38#include <mpi.h>
39
40#include <algorithm>
41#include <functional>
42#include <string>
43
44std::string TuningFailed::get_first_error() const {
45 using namespace ErrorHandling;
46 auto const queued_warnings = mpi_gather_runtime_errors_all(this_node == 0);
47 auto message = std::string("tuning failed: an exception was thrown while "
48 "benchmarking the integration loop");
49 for (auto const &warning : queued_warnings) {
50 if (warning.level() == RuntimeError::ErrorLevel::ERROR) {
51 message += " (" + warning.what() + ")";
52 break;
53 }
54 }
55 return message;
56}
57
59 if (acc.avg() <= 5 * MPI_Wtick()) {
61 << "Clock resolution is too low to reliably time integration.";
62 }
63 if (acc.sig() >= 0.1 * acc.avg()) {
64 runtimeWarningMsg() << "Statistics of tuning samples is very bad.";
65 }
66}
67
68static void run_full_force_calc(System::System &system, int reuse_forces) {
69 auto const error_code = system.integrate(0, reuse_forces);
70 if (error_code == INTEG_ERROR_RUNTIME) {
71 throw TuningFailed{};
72 }
73}
74
75double benchmark_integration_step(System::System &system, int int_steps) {
77
78 // check if the system can be integrated with the current parameters
80
81 // measure force calculation time
82 for (int i = 0; i < int_steps; i++) {
83 auto const tick = MPI_Wtime();
85 auto const tock = MPI_Wtime();
86 running_average.add_sample((tock - tick));
87 }
88
89 if (this_node == 0) {
90 check_statistics(running_average);
91 }
92
93 /* MPI returns in seconds, returned value should be in ms. */
94 auto retval = 1000. * running_average.avg();
95 boost::mpi::broadcast(::comm_cart, retval, 0);
96 return retval;
97}
98
99/**
100 * \brief Time the integration.
101 * This times the integration and
102 * propagates the system.
103 *
104 * @param system The system to tune.
105 * @param int_steps Number of steps to integrate.
106 * @return Time per integration in ms.
107 */
108static double time_calc(System::System &system, int int_steps) {
109 auto const error_code_init =
111 if (error_code_init == INTEG_ERROR_RUNTIME) {
112 return -1;
113 }
114
115 /* perform force calculation test */
116 auto const tick = MPI_Wtime();
117 auto const error_code = system.integrate(int_steps, INTEG_REUSE_FORCES_NEVER);
118 auto const tock = MPI_Wtime();
119 if (error_code == INTEG_ERROR_RUNTIME) {
120 return -1;
121 }
122
123 /* MPI returns in seconds, returned value should be in ms. */
124 return 1000. * (tock - tick) / int_steps;
125}
126
127namespace System {
128void System::tune_verlet_skin(double min_skin, double max_skin, double tol,
129 int int_steps, bool adjust_max_skin) {
130
131 double a = min_skin;
132 double b = max_skin;
133
134 /* The maximal skin is the remainder from the required cutoff to
135 * the maximal range that can be supported by the cell system, but
136 * never larger than half the box size. */
137 auto const max_permissible_skin = std::min(
138 *boost::min_element(cell_structure->max_cutoff()) - maximal_cutoff(),
139 0.5 * *boost::max_element(box_geo->length()));
140
141 if (adjust_max_skin and max_skin > max_permissible_skin)
142 b = max_permissible_skin;
143
144 while (fabs(a - b) > tol) {
145 cell_structure->set_verlet_skin(a);
146 auto const time_a = time_calc(*this, int_steps);
147
148 cell_structure->set_verlet_skin(b);
149 auto const time_b = time_calc(*this, int_steps);
150
151 if (time_a > time_b) {
152 a = 0.5 * (a + b);
153 } else {
154 b = 0.5 * (a + b);
155 }
156 }
157 cell_structure->set_verlet_skin(0.5 * (a + b));
158}
159} // namespace System
Main system class.
void tune_verlet_skin(double min_skin, double max_skin, double tol, int int_steps, bool adjust_max_skin)
Tune the Verlet skin.
Definition tuning.cpp:128
int integrate(int n_steps, int reuse_forces)
Integrate equations of motion.
Keep running average and variance.
Scalar avg() const
Average of the samples.
Scalar sig() const
Standard deviation of the samples.
boost::mpi::communicator comm_cart
The communicator.
int this_node
The number of this node.
This file contains the errorhandling code for severe errors, like a broken bond or illegal parameter ...
#define runtimeWarningMsg()
Molecular dynamics integrator.
#define INTEG_ERROR_RUNTIME
Definition integrate.hpp:42
#define INTEG_REUSE_FORCES_CONDITIONALLY
recalculate forces only if Propagation::recalc_forces is set
Definition integrate.hpp:51
#define INTEG_REUSE_FORCES_NEVER
recalculate forces unconditionally (mostly used for timing)
Definition integrate.hpp:49
std::vector< RuntimeError > mpi_gather_runtime_errors_all(bool is_head_node)
Gather messages on main rank.
Various procedures concerning interactions between particles.
static void run_full_force_calc(System::System &system, int reuse_forces)
Definition tuning.cpp:68
static void check_statistics(Utils::Statistics::RunningAverage< double > &acc)
Definition tuning.cpp:58
static double time_calc(System::System &system, int int_steps)
Time the integration.
Definition tuning.cpp:108
double benchmark_integration_step(System::System &system, int int_steps)
Benchmark the integration loop.
Definition tuning.cpp:75