ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
electrostatics/scafacos_impl.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 "config/config.hpp"
23
24#ifdef SCAFACOS
25
28
29#include "BoxGeometry.hpp"
30#include "LocalBox.hpp"
32#include "communication.hpp"
33#include "system/System.hpp"
34#include "tuning.hpp"
35
36#include <utils/Span.hpp>
37#include <utils/Vector.hpp>
38
39#include <boost/range/algorithm/min_element.hpp>
40
41#include <algorithm>
42#include <cassert>
43#include <cmath>
44#include <limits>
45#include <string>
46
47std::shared_ptr<CoulombScafacos>
48make_coulomb_scafacos(std::string const &method,
49 std::string const &parameters) {
50 return std::make_shared<CoulombScafacosImpl>(comm_cart, method, parameters);
51}
52
54 auto const &system = get_system();
55 auto const &box_geo = *system.box_geo;
56 auto const &cell_structure = *system.cell_structure;
57
58 positions.clear();
59 charges.clear();
60
61 for (auto const &p : cell_structure.local_particles()) {
62 auto const pos = box_geo.folded_position(p.pos());
63 positions.push_back(pos[0]);
64 positions.push_back(pos[1]);
65 positions.push_back(pos[2]);
66 charges.push_back(p.q());
67 }
68}
69
71 if (positions.empty())
72 return;
73
74 auto const &cell_structure = *get_system().cell_structure;
75
76 auto it_fields = fields.begin();
77 for (auto &p : cell_structure.local_particles()) {
78 p.force() += prefactor * p.q() *
80 it_fields += 3;
81 }
82
83 /* Check that the particle number did not change */
84 assert(it_fields == fields.end());
85}
86
87double CoulombScafacosImpl::time_r_cut(double r_cut) {
88 set_r_cut_and_tune(r_cut);
89 auto &system = get_system();
90 return benchmark_integration_step(system, 10);
91}
92
93void CoulombScafacosImpl::tune_r_cut() {
94 auto constexpr convergence_threshold = 1e-3;
95 auto const &system = get_system();
96 auto const &box_geo = *system.box_geo;
97 auto const &local_geo = *system.local_geo;
98 auto const verlet_skin = system.cell_structure->get_verlet_skin();
99
100 auto const min_box_l = *boost::min_element(box_geo.length());
101 auto const min_local_box_l = *boost::min_element(local_geo.length());
102
103 /* The bisection code breaks down when r_min < 1 for several methods
104 * (e.g. p2nfft, p3m, ewald) if the mesh size is not fixed (ScaFaCoS
105 * either hangs or allocates too much memory) */
106 auto r_min = 1.0;
107 auto r_max = std::min(min_local_box_l, min_box_l / 2.0) - verlet_skin;
108 assert(r_max >= r_min);
109 auto t_min = 0.0;
110 auto t_max = std::numeric_limits<double>::max();
111 auto r_opt = -1.0;
112
113 /* Run bisection */
114 while (std::fabs(r_min - r_max) > convergence_threshold) {
115 r_opt = (r_max + r_min) / 2.;
116 auto const dr = 0.5 * (r_max - r_min);
117 auto const t_mid = time_r_cut(r_min + dr);
118 t_min = time_r_cut(r_min);
119 t_max = time_r_cut(r_max);
120
121 if (t_min <= 0.0 or t_max <= 0.0) {
122 break;
123 }
124
125 if (t_mid > t_min) {
126 r_max = r_min += dr;
127 } else {
128 r_min += dr;
129 }
130 }
131 assert(r_opt >= 0.);
132 set_r_cut(r_opt);
133}
134
137
138 // Check whether we have to do a bisection for the short-range cutoff
139 // Check if there is a user-supplied cutoff
140 if (ScafacosContext::get_near_field_delegation() and
141 ScafacosContext::r_cut() <= 0.0) {
142 tune_r_cut();
143 } else {
144 // ESPResSo is not affected by a short-range cutoff -> tune in parallel
145 ScafacosContext::tune(charges, positions);
146 }
147 get_system().on_coulomb_change();
148}
149
150#endif // SCAFACOS
Vector implementation and trait types for boost qvm interoperability.
float dr[3]
__shared__ int pos[MAXDEPTH *THREADS5/WARPSIZE]
double prefactor
Electrostatics prefactor.
A stripped-down version of std::span from C++17.
Definition Span.hpp:38
boost::mpi::communicator comm_cart
The communicator.
This file contains the defaults for ESPResSo.
std::shared_ptr< CoulombScafacos > make_coulomb_scafacos(std::string const &method, std::string const &parameters)
VectorXd< 3 > Vector3d
Definition Vector.hpp:157
void update_particle_forces() const override
double benchmark_integration_step(System::System &system, int int_steps)
Benchmark the integration loop.
Definition tuning.cpp:75