ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
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(ESPRESSO_CUDA) and \
51 (defined(ESPRESSO_ELECTROSTATICS) or defined(ESPRESSO_DIPOLES))
52 gpu.clear_energy_on_device();
53 gpu.update();
54#endif
55 on_observable_calc();
56
57 auto const local_parts = cell_structure->local_particles();
58
59 for (auto const &p : local_parts) {
60 obs_energy.kinetic_lin[0] += translational_kinetic_energy(p);
61 obs_energy.kinetic_rot[0] += rotational_kinetic_energy(p);
62 }
63
64 auto const coulomb_kernel = coulomb.pair_energy_kernel();
65 auto const dipoles_kernel = dipoles.pair_energy_kernel();
66
68 [this, coulomb_kernel_ptr = get_ptr(coulomb_kernel), &obs_energy](
69 Particle const &p1, int bond_id, std::span<Particle *> partners) {
70 auto const &iaparams = *bonded_ias->at(bond_id);
71 auto const result = calc_bonded_energy(iaparams, p1, partners, *box_geo,
72 coulomb_kernel_ptr);
73 if (result) {
74 obs_energy.bonded_contribution(bond_id)[0] += result.value();
75 return false;
76 }
77 return true;
78 },
79 [coulomb_kernel_ptr = get_ptr(coulomb_kernel),
80 dipoles_kernel_ptr = get_ptr(dipoles_kernel), this,
81 &obs_energy](Particle const &p1, Particle const &p2, Distance const &d) {
82 auto const &ia_params =
83 nonbonded_ias->get_ia_param(p1.type(), p2.type());
84 add_non_bonded_pair_energy(p1, p2, d.vec21, sqrt(d.dist2), d.dist2,
85 ia_params, *bonded_ias, coulomb_kernel_ptr,
86 dipoles_kernel_ptr, obs_energy);
87 },
88 *cell_structure, maximal_cutoff(), bonded_ias->maximal_cutoff());
89
90#ifdef ESPRESSO_ELECTROSTATICS
91 /* calculate k-space part of electrostatic interaction. */
92 obs_energy.coulomb[1] = coulomb.calc_energy_long_range(local_parts);
93#endif
94
95#ifdef ESPRESSO_DIPOLES
96 /* calculate k-space part of magnetostatic interaction. */
97 obs_energy.dipolar[1] = dipoles.calc_energy_long_range(local_parts);
98#endif
99
100 constraints->add_energy(local_parts, get_sim_time(), obs_energy);
101
102#if defined(ESPRESSO_CUDA) and \
103 (defined(ESPRESSO_ELECTROSTATICS) or defined(ESPRESSO_DIPOLES))
104 auto const energy_host = gpu.copy_energy_to_host();
105 if (!obs_energy.coulomb.empty())
106 obs_energy.coulomb[1] += static_cast<double>(energy_host.coulomb);
107 if (!obs_energy.dipolar.empty())
108 obs_energy.dipolar[1] += static_cast<double>(energy_host.dipolar);
109#endif
110
111 obs_energy.mpi_reduce();
112 return obs_energy_ptr;
113 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
114}
115
117 if (cell_structure->get_resort_particles()) {
118 cell_structure->update_ghosts_and_resort_particle(get_global_ghost_flags());
119 }
120
121 auto ret = 0.0;
122 if (auto const p = cell_structure->get_local_particle(pid)) {
123 auto const coulomb_kernel = coulomb.pair_energy_kernel();
124 auto kernel = [coulomb_kernel_ptr = get_ptr(coulomb_kernel), &ret,
125 this](Particle const &p, Particle const &p1,
126 Utils::Vector3d const &vec) {
127#ifdef ESPRESSO_EXCLUSIONS
128 if (not do_nonbonded(p, p1))
129 return;
130#endif
131 auto const &ia_params = nonbonded_ias->get_ia_param(p.type(), p1.type());
132 // Add energy for current particle pair to result
133 ret += calc_non_bonded_pair_energy(p, p1, ia_params, vec, vec.norm(),
134 *bonded_ias, coulomb_kernel_ptr);
135 };
136 cell_structure->run_on_particle_short_range_neighbors(*p, kernel);
137 }
138 return ret;
139}
140
141std::optional<double> System::particle_bond_energy(int pid, int bond_id,
142 std::vector<int> partners) {
143 if (cell_structure->get_resort_particles()) {
144 cell_structure->update_ghosts_and_resort_particle(get_global_ghost_flags());
145 }
146 Particle const *p = cell_structure->get_local_particle(pid);
147 if (not p or p->is_ghost())
148 return {}; // not available on this MPI rank or ghost
149 auto const &iaparams = *bonded_ias->at(bond_id);
150 try {
151 auto resolved_partners = cell_structure->resolve_bond_partners(partners);
152 auto const coulomb_kernel = coulomb.pair_energy_kernel();
153 return calc_bonded_energy(
154 iaparams, *p,
155 std::span(resolved_partners.data(), resolved_partners.size()), *box_geo,
156 get_ptr(coulomb_kernel));
157 } catch (const BondResolutionError &) {
158 bond_broken_error(p->id(), partners);
159 return {};
160 }
161}
162
163} // 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:116
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:141
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:450
auto const & type() const
Definition Particle.hpp:473
bool is_ghost() const
Definition Particle.hpp:495
auto const & id() const
Definition Particle.hpp:469