ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
ShapeBasedConstraint.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2022 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
21
22#include "BoxGeometry.hpp"
23#include "Observable_stat.hpp"
24#include "communication.hpp"
25#include "config/config.hpp"
26#include "dpd.hpp"
27#include "energy_inline.hpp"
28#include "errorhandling.hpp"
29#include "forces_inline.hpp"
31#include "system/System.hpp"
32#include "thermostat.hpp"
33
34#include <utils/Vector.hpp>
35
36#include <boost/mpi/collectives.hpp>
37
38#include <algorithm>
39#include <functional>
40#include <limits>
41#include <numeric>
42
43namespace Constraints {
44/** Check if a non-bonded interaction is defined */
45static bool is_active(IA_parameters const &data) {
46 return data.max_cut != INACTIVE_CUTOFF;
47}
48
50 return all_reduce(comm_cart, m_local_force, std::plus<>());
51}
52
54 return all_reduce(comm_cart, m_outer_normal_force, std::plus<double>());
55}
56
58 ParticleRange const &particles) const {
59 auto global_mindist = std::numeric_limits<double>::infinity();
60
61 auto const local_mindist = std::accumulate(
62 particles.begin(), particles.end(),
63 std::numeric_limits<double>::infinity(),
64 [this, &box_geo](double min, Particle const &p) {
65 auto const &ia_params = get_ia_param(p.type());
66 if (is_active(ia_params)) {
67 double dist;
68 Utils::Vector3d vec;
69 m_shape->calculate_dist(box_geo.folded_position(p.pos()), dist, vec);
70 return std::min(min, dist);
71 }
72 return min;
73 });
74 boost::mpi::reduce(comm_cart, local_mindist, global_mindist,
75 boost::mpi::minimum<double>(), 0);
76 return global_mindist;
77}
78
79ParticleForce ShapeBasedConstraint::force(Particle const &p,
80 Utils::Vector3d const &folded_pos,
81 double) {
82 ParticleForce pf{};
83 auto const &ia_params = get_ia_param(p.type());
84
85 if (is_active(ia_params)) {
86 double dist = 0.;
87 Utils::Vector3d dist_vec;
88 m_shape->calculate_dist(folded_pos, dist, dist_vec);
89 auto const coulomb_kernel = m_system.coulomb.pair_force_kernel();
90
91#ifdef DPD
92 Utils::Vector3d dpd_force{};
93#endif
94 Utils::Vector3d outer_normal_vec{};
95
96 if (dist > 0) {
97 outer_normal_vec = -dist_vec / dist;
98 pf = calc_central_radial_force(ia_params, dist_vec, dist) +
99 calc_central_radial_charge_force(p, part_rep, ia_params, dist_vec,
100 dist, get_ptr(coulomb_kernel)) +
101 calc_non_central_force(p, part_rep, ia_params, dist_vec, dist);
102
103#ifdef DPD
104 if (m_system.thermostat->thermo_switch & THERMO_DPD) {
105 dpd_force = dpd_pair_force(p, part_rep, *m_system.thermostat->dpd,
106 *m_system.box_geo, ia_params, dist_vec, dist,
107 dist * dist);
108 // Additional use of DPD here requires counter increase
109 m_system.thermostat->dpd->rng_increment();
110 }
111#endif
112 } else if (m_penetrable && (dist <= 0)) {
113 if ((!m_only_positive) && (dist < 0)) {
114 pf = calc_central_radial_force(ia_params, dist_vec, -dist) +
115 calc_central_radial_charge_force(p, part_rep, ia_params, dist_vec,
116 -dist, get_ptr(coulomb_kernel)) +
117 calc_non_central_force(p, part_rep, ia_params, dist_vec, -dist);
118
119#ifdef DPD
120 if (m_system.thermostat->thermo_switch & THERMO_DPD) {
121 dpd_force = dpd_pair_force(p, part_rep, *m_system.thermostat->dpd,
122 *m_system.box_geo, ia_params, dist_vec,
123 dist, dist * dist);
124 // Additional use of DPD here requires counter increase
125 m_system.thermostat->dpd->rng_increment();
126 }
127#endif
128 }
129 } else {
130 runtimeErrorMsg() << "Constraint violated by particle " << p.id()
131 << " dist " << dist;
132 }
133
134#ifdef ROTATION
135 part_rep.torque() += calc_opposing_force(pf, dist_vec).torque;
136#endif
137#ifdef DPD
138 pf.f += dpd_force;
139#endif
140 m_local_force -= pf.f;
141 m_outer_normal_force -= outer_normal_vec * pf.f;
142 }
143 return pf;
144}
145
146void ShapeBasedConstraint::add_energy(const Particle &p,
147 const Utils::Vector3d &folded_pos, double,
148 Observable_stat &obs_energy) const {
149 double energy = 0.0;
150 auto const &ia_params = get_ia_param(p.type());
151
152 if (is_active(ia_params)) {
153 auto const coulomb_kernel = m_system.coulomb.pair_energy_kernel();
154 double dist = 0.0;
155 Utils::Vector3d vec;
156 m_shape->calculate_dist(folded_pos, dist, vec);
157 if (dist > 0) {
158 energy = calc_non_bonded_pair_energy(p, part_rep, ia_params, vec, dist,
159 get_ptr(coulomb_kernel));
160 } else if ((dist <= 0) && m_penetrable) {
161 if (!m_only_positive && (dist < 0)) {
162 energy = calc_non_bonded_pair_energy(p, part_rep, ia_params, vec, -dist,
163 get_ptr(coulomb_kernel));
164 }
165 } else {
166 runtimeErrorMsg() << "Constraint violated by particle " << p.id();
167 }
168 }
169 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
170 if (part_rep.type() >= 0) {
172 p.type(), part_rep.type(), p.mol_id(), part_rep.mol_id(), energy);
173 }
174}
175} // namespace Constraints
@ THERMO_DPD
Vector implementation and trait types for boost qvm interoperability.
double min_dist(BoxGeometry const &box_geo, ParticleRange const &particles) const
Calculate the minimum distance between all particle pairs.
Observable for the pressure and energy.
void add_non_bonded_contribution(int type1, int type2, int molid1, int molid2, Utils::Span< const double > data)
A range of particles.
boost::mpi::communicator comm_cart
The communicator.
This file contains the defaults for ESPResSo.
const T * get_ptr(std::optional< T > const &opt)
Utils::Vector3d dpd_pair_force(DPDParameters const &params, Utils::Vector3d const &v, double dist, Utils::Vector3d const &noise)
Definition dpd.cpp:86
Routines to use DPD as thermostat or pair force .
Energy calculation.
double calc_non_bonded_pair_energy(Particle const &p1, Particle const &p2, IA_parameters const &ia_params, Utils::Vector3d const &d, double const dist, Coulomb::ShortRangeEnergyKernel::kernel_type const *coulomb_kernel)
Calculate non-bonded energies between a pair of particles.
This file contains the errorhandling code for severe errors, like a broken bond or illegal parameter ...
#define runtimeErrorMsg()
Force calculation.
ParticleForce calc_central_radial_force(IA_parameters const &ia_params, Utils::Vector3d const &d, double const dist)
ParticleForce calc_opposing_force(ParticleForce const &pf, Utils::Vector3d const &d)
ParticleForce calc_central_radial_charge_force(Particle const &p1, Particle const &p2, IA_parameters const &ia_params, Utils::Vector3d const &d, double const dist, Coulomb::ShortRangeForceKernel::kernel_type const *coulomb_kernel)
ParticleForce calc_non_central_force(Particle const &p1, Particle const &p2, IA_parameters const &ia_params, Utils::Vector3d const &d, double const dist)
static bool is_active(IA_parameters const &data)
Check if a non-bonded interaction is defined.
Various procedures concerning interactions between particles.
constexpr double INACTIVE_CUTOFF
Cutoff for deactivated interactions.
Parameters for non-bonded interactions.
double max_cut
maximal cutoff for this pair of particle types.
Force information on a particle.
Definition Particle.hpp:290
Utils::Vector3d torque
torque.
Definition Particle.hpp:318
Struct holding all information for one particle.
Definition Particle.hpp:393
auto const & type() const
Definition Particle.hpp:416
auto const & mol_id() const
Definition Particle.hpp:414
auto const & id() const
Definition Particle.hpp:412