118#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
121 std::size_t p1, std::size_t p2,
122 auto &aosoa,
double q1q2,
123 auto &&kernel)
const {
126 auto pos2 = aosoa.get_vector_at(aosoa.position, p2);
127 auto pos1 = aosoa.get_vector_at(aosoa.position, p1);
134 auto const z = 2. *
box_h - aosoa.position(p1, 2);
135 auto pos2 = aosoa.get_vector_at(aosoa.position, p2);
136 auto pos1 = aosoa.get_vector_at(aosoa.position, p1);
137 pos1[2] = 2. *
box_h - pos1[2];
148 auto &&kernel)
const {
151 auto const d = box_geo.
get_mi_vector(pos2, {pos1[0], pos1[1], -pos1[2]});
156 auto const z = 2. *
box_h - pos1[2];
157 auto const d = box_geo.
get_mi_vector(pos2, {pos1[0], pos1[1], z});
167 for (
auto const &p : particles) {
171 energy += p3m.pair_energy(q1q2, d.norm());
181 for (
auto &p : particles) {
185 p.force() += p3m.pair_force(q1q2, d, d.norm());
193 using BaseSolver = std::variant<std::shared_ptr<CoulombP3M>>;
205 [
this](
auto &solver) { solver->bind_system(
m_system.lock()); });
206 sanity_checks_periodicity();
207 sanity_checks_cell_structure();
209 sanity_checks_dielectric_contrasts();
215 visit_base_solver([](
auto &solver) { solver->on_activation(); });
220 recalc_space_layer();
221 visit_base_solver([](
auto &actor) { actor->init(); });
226 visit_base_solver([](
auto &actor) { actor->on_boxl_change(); });
229 recalc_space_layer();
232 visit_base_solver([](
auto &solver) { solver->on_node_grid_change(); });
235 sanity_checks_periodicity();
236 visit_base_solver([](
auto &solver) { solver->on_periodicity_change(); });
239 sanity_checks_cell_structure();
240 visit_base_solver([](
auto &solver) { solver->on_cell_structure_change(); });
244 recalc_space_layer();
245 visit_base_solver([](
auto &actor) { actor->init(); });
250 visit_base_solver([](
auto &actor) { actor->init(); });
253 recalc_space_layer();
257 sanity_checks_periodicity();
258 sanity_checks_cell_structure();
260 sanity_checks_dielectric_contrasts();
261 visit_base_solver([](
auto &actor) { actor->sanity_checks(); });
271 return {std::string(
"conflict with ELC w/ dielectric contrasts")};
276#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
283 [
this, &aosoa, p1, p2, q1q2](
auto &p3m_ptr) {
284 auto const &p3m = *p3m_ptr;
289 energy += p3m.pair_energy(q_eff, d.
norm());
294 energy += p3m.pair_energy(q_eff, d.
norm());
311 [
this, &pos1, &pos2, q1q2](
auto &p3m_ptr) {
312 auto const &p3m = *p3m_ptr;
317 energy += p3m.pair_energy(q_eff, d.
norm());
322 energy += p3m.pair_energy(q_eff, d.
norm());
339 [
this, &pos1, &pos2, &p1f_asym, &p2f_asym, q1q2](
auto &p3m_ptr) {
340 auto const &p3m = *p3m_ptr;
344 p1f_asym += p3m.pair_force(q_eff, d, d.
norm());
349 p2f_asym += p3m.pair_force(q_eff, d, d.
norm());
361 void check_gap(
Particle const &p)
const;
362 double tune_far_cut()
const;
371 void recalc_far_cut() {
377 void recalc_space_layer();
379 void sanity_checks_cell_structure()
const {}
380 void sanity_checks_periodicity()
const;
381 void sanity_checks_dielectric_contrasts()
const;
388 void visit_base_solver(
auto &&visitor)
const {
Vector implementation and trait types for boost qvm interoperability.
ESPRESSO_ATTR_ALWAYS_INLINE 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
DEVICE_QUALIFIER constexpr T sqr(T x)
Calculates the SQuaRe of x.
P3M algorithm for long-range Coulomb interaction.
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.
double pair_energy_correction(Utils::Vector3d const &pos1, Utils::Vector3d const &pos2, double q1q2) const
Calculate short-range pair energy correction.
void on_cell_structure_change()
void add_pair_force_corrections(Utils::Vector3d const &pos1, Utils::Vector3d const &pos2, Utils::Vector3d &p1f_asym, Utils::Vector3d &p2f_asym, double q1q2) const
Add short-range pair force corrections.
void init()
Recalculate all derived parameters.
void on_node_grid_change() const
void add_long_range_forces(ParticleRange const &particles) const
double long_range_energy(ParticleRange const &particles) const
double pair_energy_correction(std::size_t p1, std::size_t p2, auto &aosoa, double q1q2) const
Calculate short-range pair energy correction.
Struct holding all information for one particle.
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.
double box_h
Up to where particles can be found.
void dielectric_layers_contribution(BoxGeometry const &box_geo, std::size_t p1, std::size_t p2, auto &aosoa, double q1q2, auto &&kernel) const
pairwise contributions from lower and upper layers
bool dielectric_contrast_on
Flag whether there is any dielectric contrast in the system.
double space_box
The space that is finally left.
void dielectric_layers_contribution(BoxGeometry const &box_geo, Utils::Vector3d const &pos1, Utils::Vector3d const &pos2, double q1q2, auto &&kernel) const
pairwise contributions from lower and upper layers
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.