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());
169 using BaseSolver = std::variant<std::shared_ptr<CoulombP3M>>;
181 [
this](
auto &solver) { solver->bind_system(
m_system.lock()); });
182 sanity_checks_periodicity();
183 sanity_checks_cell_structure();
185 sanity_checks_dielectric_contrasts();
191 visit_base_solver([](
auto &solver) { solver->on_activation(); });
196 recalc_space_layer();
197 visit_base_solver([](
auto &actor) { actor->init(); });
202 visit_base_solver([](
auto &actor) { actor->on_boxl_change(); });
205 recalc_space_layer();
208 visit_base_solver([](
auto &solver) { solver->on_node_grid_change(); });
211 sanity_checks_periodicity();
212 visit_base_solver([](
auto &solver) { solver->on_periodicity_change(); });
215 sanity_checks_cell_structure();
216 visit_base_solver([](
auto &solver) { solver->on_cell_structure_change(); });
220 recalc_space_layer();
221 visit_base_solver([](
auto &actor) { actor->init(); });
226 visit_base_solver([](
auto &actor) { actor->init(); });
229 recalc_space_layer();
233 sanity_checks_periodicity();
234 sanity_checks_cell_structure();
236 sanity_checks_dielectric_contrasts();
237 visit_base_solver([](
auto &actor) { actor->sanity_checks(); });
247 return {std::string(
"conflict with ELC w/ dielectric contrasts")};
258 [
this, &p1, &p2, q1q2](
auto &p3m_ptr) {
259 auto const &pos1 = p1.
pos();
260 auto const &pos2 = p2.
pos();
261 auto const &p3m = *p3m_ptr;
266 energy += p3m.pair_energy(q_eff, d.
norm());
271 energy += p3m.pair_energy(q_eff, d.
norm());
285 [
this, &p1, &p2, q1q2](
auto &p3m_ptr) {
286 auto const &pos1 = p1.
pos();
287 auto const &pos2 = p2.
pos();
288 auto const &p3m = *p3m_ptr;
292 p1.
force() += p3m.pair_force(q_eff, d, d.
norm());
297 p2.
force() += p3m.pair_force(q_eff, d, d.
norm());
309 void check_gap(
Particle const &p)
const;
310 double tune_far_cut()
const;
319 void recalc_far_cut() {
325 void recalc_space_layer();
327 void sanity_checks_cell_structure()
const {}
328 void sanity_checks_periodicity()
const;
329 void sanity_checks_dielectric_contrasts()
const;
336 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.
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.
std::variant< std::shared_ptr< CoulombP3M > > BaseSolver
BaseSolver base_solver
Electrostatics solver that is adapted.
void on_cell_structure_change()
void init()
Recalculate all derived parameters.
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.