119 template <
typename Kernel>
124 Kernel &&kernel)
const {
127 auto const d = box_geo.
get_mi_vector(pos2, {pos1[0], pos1[1], -pos1[2]});
132 auto const z = 2. *
box_h - pos1[2];
133 auto const d = box_geo.
get_mi_vector(pos2, {pos1[0], pos1[1], z});
143 for (
auto const &p : particles) {
145 p3m, box_geo, p.pos(), p.pos(),
Utils::sqr(p.q()),
147 energy += p3m.pair_energy(q1q2, d.norm());
157 for (
auto &p : particles) {
159 p3m, box_geo, p.pos(), p.pos(),
Utils::sqr(p.q()),
161 p.force() += p3m.pair_force(q1q2, d, d.norm());
171 std::shared_ptr<CoulombP3MGPU>,
173 std::shared_ptr<CoulombP3M>>;
185 [
this](
auto &solver) { solver->bind_system(
m_system.lock()); });
186 sanity_checks_periodicity();
187 sanity_checks_cell_structure();
189 sanity_checks_dielectric_contrasts();
195 visit_base_solver([](
auto &solver) { solver->on_activation(); });
200 recalc_space_layer();
201 visit_base_solver([](
auto &actor) { actor->init(); });
206 visit_base_solver([](
auto &actor) { actor->on_boxl_change(); });
209 recalc_space_layer();
212 visit_base_solver([](
auto &solver) { solver->on_node_grid_change(); });
215 sanity_checks_periodicity();
216 visit_base_solver([](
auto &solver) { solver->on_periodicity_change(); });
219 sanity_checks_cell_structure();
220 visit_base_solver([](
auto &solver) { solver->on_cell_structure_change(); });
224 recalc_space_layer();
225 visit_base_solver([](
auto &actor) { actor->init(); });
230 visit_base_solver([](
auto &actor) { actor->init(); });
233 recalc_space_layer();
237 sanity_checks_periodicity();
238 sanity_checks_cell_structure();
240 sanity_checks_dielectric_contrasts();
241 visit_base_solver([](
auto &actor) { actor->sanity_checks(); });
251 return {std::string(
"conflict with ELC w/ dielectric contrasts")};
262 [
this, &p1, &p2, q1q2](
auto &p3m_ptr) {
263 auto const &pos1 = p1.
pos();
264 auto const &pos2 = p2.
pos();
265 auto const &p3m = *p3m_ptr;
270 energy += p3m.pair_energy(q_eff, d.
norm());
275 energy += p3m.pair_energy(q_eff, d.
norm());
289 [
this, &p1, &p2, q1q2](
auto &p3m_ptr) {
290 auto const &pos1 = p1.
pos();
291 auto const &pos2 = p2.
pos();
292 auto const &p3m = *p3m_ptr;
296 p1.
force() += p3m.pair_force(q_eff, d, d.
norm());
301 p2.
force() += p3m.pair_force(q_eff, d, d.
norm());
313 void check_gap(
Particle const &p)
const;
314 double tune_far_cut()
const;
323 void recalc_far_cut() {
329 void recalc_space_layer();
331 void sanity_checks_cell_structure()
const {}
332 void sanity_checks_periodicity()
const;
333 void sanity_checks_dielectric_contrasts()
const;
340 template <
class Visitor>
void visit_base_solver(Visitor &&visitor)
const {
Vector implementation and trait types for boost qvm interoperability.
Utils::Vector< T, 3 > get_mi_vector(const Utils::Vector< T, 3 > &a, const Utils::Vector< T, 3 > &b) const
Get the minimum-image vector between two coordinates.
void sanity_checks_charge_neutrality() const
std::weak_ptr< System > m_system
This file contains the defaults for ESPResSo.
DEVICE_QUALIFIER constexpr T sqr(T x)
Calculates the SQuaRe of x.
P3M algorithm for long-range Coulomb interaction.
P3M electrostatics on GPU.
double pair_energy_correction(Particle const &p1, Particle const &p2, double q1q2) const
Calculate short-range pair energy correction.
void on_boxl_change()
Recalculate all box-length-dependent parameters.
void on_periodicity_change() const
void sanity_checks() const
std::optional< std::string > veto_r_cut(double r_cut) const
Veto real-space cutoff values that are incompatible with ELC.
BaseSolver base_solver
Electrostatics solver that is adapted.
void on_cell_structure_change()
void init()
Recalculate all derived parameters.
std::variant< std::shared_ptr< CoulombP3MGPU >, std::shared_ptr< CoulombP3M > > BaseSolver
void add_pair_force_corrections(Particle &p1, Particle &p2, double q1q2) const
Add short-range pair force corrections.
void on_node_grid_change() const
void add_long_range_forces(ParticleRange const &particles) const
double long_range_energy(ParticleRange const &particles) const
Struct holding all information for one particle.
auto const & force() const
Parameters for the ELC method.
double dielectric_layers_self_energy(CoulombP3M const &p3m, BoxGeometry const &box_geo, ParticleRange const &particles) const
self energies of top and bottom layers with their virtual images
double maxPWerror
Maximal allowed pairwise error for the potential and force.
double pot_diff
Constant potential difference.
void dielectric_layers_contribution(CoulombP3M const &, BoxGeometry const &box_geo, Utils::Vector3d const &pos1, Utils::Vector3d const &pos2, double q1q2, Kernel &&kernel) const
pairwise contributions from the lowest and top layers
double box_h
Up to where particles can be found.
bool dielectric_contrast_on
Flag whether there is any dielectric contrast in the system.
double space_box
The space that is finally left.
bool neutralize
Flag whether the box is neutralized by a homogeneous background.
double far_cut
Cutoff of the exponential sum.
double space_layer
Layer around the dielectric contrast in which we trick around.
bool far_calculated
Flag whether far_cut was set by the user, or calculated by ESPResSo.
double gap_size
Size of the empty gap.
double delta_mid_bot
dielectric contrast in the lower part of the simulation cell.
void dielectric_layers_self_forces(CoulombP3M const &p3m, BoxGeometry const &box_geo, ParticleRange const &particles) const
forces of particles in border layers with themselves
bool const_pot
Flag whether a constant potential difference is applied.
double far_cut2
Squared value of far_cut.
double delta_mid_top
dielectric contrast in the upper part of the simulation cell.
Whether an actor is a layer correction method.