Loading [MathJax]/extensions/TeX/AMSmath.js
ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages Concepts
energy.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 "BoxGeometry.hpp"
23#include "Observable_stat.hpp"
25#include "constraints/Constraints.hpp"
26#include "energy_inline.hpp"
28#include "short_range_loop.hpp"
29#include "system/System.hpp"
30
33
34#include <memory>
35#include <span>
36
37namespace System {
38
39std::shared_ptr<Observable_stat> System::calculate_energy() {
40
41 auto obs_energy_ptr = std::make_shared<Observable_stat>(
42 1ul, static_cast<std::size_t>(bonded_ias->get_next_key()),
43 nonbonded_ias->get_max_seen_particle_type());
44
45 if (long_range_interactions_sanity_checks()) {
46 return obs_energy_ptr;
47 }
48
49 auto &obs_energy = *obs_energy_ptr;
50#if defined(CUDA) and (defined(ELECTROSTATICS) or defined(DIPOLES))
51 gpu.clear_energy_on_device();
52 gpu.update();
53#endif
54 on_observable_calc();
55
56 auto const local_parts = cell_structure->local_particles();
57
58 for (auto const &p : local_parts) {
59 obs_energy.kinetic_lin[0] += translational_kinetic_energy(p);
60 obs_energy.kinetic_rot[0] += rotational_kinetic_energy(p);
61 }
62
63 auto const coulomb_kernel = coulomb.pair_energy_kernel();
64 auto const dipoles_kernel = dipoles.pair_energy_kernel();
65
67 [this, coulomb_kernel_ptr = get_ptr(coulomb_kernel), &obs_energy](
68 Particle const &p1, int bond_id, std::span<Particle *> partners) {
69 auto const &iaparams = *bonded_ias->at(bond_id);
70 auto const result = calc_bonded_energy(iaparams, p1, partners, *box_geo,
71 coulomb_kernel_ptr);
72 if (result) {
73 obs_energy.bonded_contribution(bond_id)[0] += result.value();
74 return false;
75 }
76 return true;
77 },
78 [coulomb_kernel_ptr = get_ptr(coulomb_kernel),
79 dipoles_kernel_ptr = get_ptr(dipoles_kernel), this,
80 &obs_energy](Particle const &p1, Particle const &p2, Distance const &d) {
81 auto const &ia_params =
82 nonbonded_ias->get_ia_param(p1.type(), p2.type());
83 add_non_bonded_pair_energy(p1, p2, d.vec21, sqrt(d.dist2), d.dist2,
84 ia_params, *bonded_ias, coulomb_kernel_ptr,
85 dipoles_kernel_ptr, obs_energy);
86 },
87 *cell_structure, maximal_cutoff(), bonded_ias->maximal_cutoff());
88
89#ifdef ELECTROSTATICS
90 /* calculate k-space part of electrostatic interaction. */
91 obs_energy.coulomb[1] = coulomb.calc_energy_long_range(local_parts);
92#endif
93
94#ifdef DIPOLES
95 /* calculate k-space part of magnetostatic interaction. */
96 obs_energy.dipolar[1] = dipoles.calc_energy_long_range(local_parts);
97#endif
98
99 constraints->add_energy(local_parts, get_sim_time(), obs_energy);
100
101#if defined(CUDA) and (defined(ELECTROSTATICS) or defined(DIPOLES))
102 auto const energy_host = gpu.copy_energy_to_host();
103 if (!obs_energy.coulomb.empty())
104 obs_energy.coulomb[1] += static_cast<double>(energy_host.coulomb);
105 if (!obs_energy.dipolar.empty())
106 obs_energy.dipolar[1] += static_cast<double>(energy_host.dipolar);
107#endif
108
109 obs_energy.mpi_reduce();
110 return obs_energy_ptr;
111 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
112}
113
115 if (cell_structure->get_resort_particles()) {
116 cell_structure->update_ghosts_and_resort_particle(get_global_ghost_flags());
117 }
118
119 auto ret = 0.0;
120 if (auto const p = cell_structure->get_local_particle(pid)) {
121 auto const coulomb_kernel = coulomb.pair_energy_kernel();
122 auto kernel = [coulomb_kernel_ptr = get_ptr(coulomb_kernel), &ret,
123 this](Particle const &p, Particle const &p1,
124 Utils::Vector3d const &vec) {
125#ifdef EXCLUSIONS
126 if (not do_nonbonded(p, p1))
127 return;
128#endif
129 auto const &ia_params = nonbonded_ias->get_ia_param(p.type(), p1.type());
130 // Add energy for current particle pair to result
131 ret += calc_non_bonded_pair_energy(p, p1, ia_params, vec, vec.norm(),
132 *bonded_ias, coulomb_kernel_ptr);
133 };
134 cell_structure->run_on_particle_short_range_neighbors(*p, kernel);
135 }
136 return ret;
137}
138
139std::optional<double> System::particle_bond_energy(int pid, int bond_id,
140 std::vector<int> partners) {
141 if (cell_structure->get_resort_particles()) {
142 cell_structure->update_ghosts_and_resort_particle(get_global_ghost_flags());
143 }
144 Particle const *p = cell_structure->get_local_particle(pid);
145 if (not p or p->is_ghost())
146 return {}; // not available on this MPI rank or ghost
147 auto const &iaparams = *bonded_ias->at(bond_id);
148 try {
149 auto resolved_partners = cell_structure->resolve_bond_partners(partners);
150 auto const coulomb_kernel = coulomb.pair_energy_kernel();
151 return calc_bonded_energy(
152 iaparams, *p,
153 std::span(resolved_partners.data(), resolved_partners.size()), *box_geo,
154 get_ptr(coulomb_kernel));
155 } catch (const BondResolutionError &) {
156 bond_broken_error(p->id(), partners);
157 return {};
158 }
159}
160
161#ifdef DIPOLE_FIELD_TRACKING
163 dipoles.calc_long_range_field(cell_structure->local_particles());
164}
165#endif
166
167} // namespace System
void bond_broken_error(int id, std::span< const int > partner_ids)
double particle_short_range_energy_contribution(int pid)
Compute the short-range energy of a particle.
Definition energy.cpp:114
std::optional< double > particle_bond_energy(int pid, int bond_id, std::vector< int > partners)
Compute the energy of a given bond which has to exist on the given particle.
Definition energy.cpp:139
void calculate_long_range_fields()
Calculate dipole fields.
Definition energy.cpp:162
std::shared_ptr< Observable_stat > calculate_energy()
Calculate the total energy.
Definition energy.cpp:39
const T * get_ptr(std::optional< T > const &opt)
Energy calculation.
std::optional< double > calc_bonded_energy(Bonded_IA_Parameters const &iaparams, Particle const &p1, std::span< Particle * > partners, BoxGeometry const &box_geo, Coulomb::ShortRangeEnergyKernel::kernel_type const *kernel)
double translational_kinetic_energy(Particle const &p)
Calculate kinetic energies from translation for one particle.
double calc_non_bonded_pair_energy(Particle const &p1, Particle const &p2, IA_parameters const &ia_params, Utils::Vector3d const &d, double const dist, BondedInteractionsMap const &bonded_ias, Coulomb::ShortRangeEnergyKernel::kernel_type const *coulomb_kernel)
Calculate non-bonded energies between a pair of particles.
double rotational_kinetic_energy(Particle const &p)
Calculate kinetic energies from rotation for one particle.
void add_non_bonded_pair_energy(Particle const &p1, Particle const &p2, Utils::Vector3d const &d, double const dist, double const dist2, IA_parameters const &ia_params, BondedInteractionsMap const &bonded_ias, Coulomb::ShortRangeEnergyKernel::kernel_type const *coulomb_kernel, Dipoles::ShortRangeEnergyKernel::kernel_type const *dipoles_kernel, Observable_stat &obs_energy)
Add non-bonded and short-range Coulomb energies between a pair of particles to the energy observable.
bool do_nonbonded(Particle const &p1, Particle const &p2)
Determine if the non-bonded interactions between p1 and p2 should be calculated.
Various procedures concerning interactions between particles.
void short_range_loop(BondKernel bond_kernel, PairKernel pair_kernel, CellStructure &cell_structure, double pair_cutoff, double bond_cutoff, VerletCriterion const &verlet_criterion={})
Exception indicating that a particle id could not be resolved.
Distance vector and length handed to pair kernels.
Struct holding all information for one particle.
Definition Particle.hpp:395
auto const & type() const
Definition Particle.hpp:418
bool is_ghost() const
Definition Particle.hpp:440
auto const & id() const
Definition Particle.hpp:414