-
Notifications
You must be signed in to change notification settings - Fork 189
/
steepest_descent.cpp
112 lines (94 loc) · 3.56 KB
/
steepest_descent.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/*
* Copyright (C) 2010-2019 The ESPResSo project
* Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010
* Max-Planck-Institute for Polymer Research, Theory Group
*
* This file is part of ESPResSo.
*
* ESPResSo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ESPResSo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "integrators/steepest_descent.hpp"
#include "cells.hpp"
#include "communication.hpp"
#include "event.hpp"
#include "integrate.hpp"
#include "particle_data.hpp"
#include "rotation.hpp"
#include <utils/math/sqr.hpp>
#include <boost/algorithm/clamp.hpp>
#include <boost/mpi/collectives/all_reduce.hpp>
#include <boost/mpi/collectives/broadcast.hpp>
#include <boost/mpi/operations.hpp>
#include <algorithm>
#include <limits>
/** Currently active steepest descent instance */
static SteepestDescentParameters params{};
bool steepest_descent_step(const ParticleRange &particles) {
// Maximal force encountered on node
auto f_max = -std::numeric_limits<double>::max();
// Iteration over all local particles
for (auto &p : particles) {
auto f = 0.0;
// For all Cartesian coordinates
for (int j = 0; j < 3; j++) {
// Skip, if coordinate is fixed
if (!(p.p.ext_flag & COORD_FIXED(j)))
// Skip positional increments of virtual particles
if (!p.p.is_virtual) {
// Square of force on particle
f += Utils::sqr(p.f.f[j]);
// Positional increment, crop to maximum allowed by user
auto const dp = boost::algorithm::clamp(params.gamma * p.f.f[j],
-params.max_displacement,
params.max_displacement);
// Move particle
p.r.p[j] += dp;
}
}
#ifdef ROTATION
{
// Rotational increment
auto const dq = params.gamma * p.f.torque; // Vector parallel to torque
auto const t = p.f.torque.norm2();
// Normalize rotation axis and compute amount of rotation
auto const l = dq.norm();
if (l > 0.0) {
auto const axis = dq / l;
auto const angle = boost::algorithm::clamp(l, -params.max_displacement,
params.max_displacement);
// Rotate the particle around axis dq by amount l
local_rotate_particle(p, axis, angle);
}
f_max = std::max(f_max, t);
}
#endif
// Note maximum force/torque encountered
f_max = std::max(f_max, f);
}
cell_structure.set_resort_particles(Cells::RESORT_LOCAL);
// Synchronize maximum force/torque encountered
namespace mpi = boost::mpi;
auto const f_max_global =
mpi::all_reduce(comm_cart, f_max, mpi::maximum<double>());
return sqrt(f_max_global) < params.f_max;
}
void steepest_descent_init(const double f_max, const double gamma,
const double max_displacement) {
params.f_max = f_max;
params.gamma = gamma;
params.max_displacement = max_displacement;
}
void mpi_bcast_steepest_descent_worker(int, int) {
boost::mpi::broadcast(comm_cart, params, 0);
}