119#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
122 std::size_t
p1, std::size_t
p2,
123 auto &aosoa,
double q1q2,
124 auto &&kernel)
const {
127 auto pos2 = aosoa.get_vector_at(aosoa.position,
p2);
128 auto pos1 = aosoa.get_vector_at(aosoa.position,
p1);
135 auto const z = 2. *
box_h - aosoa.position(
p1, 2);
136 auto pos2 = aosoa.get_vector_at(aosoa.position,
p2);
137 auto pos1 = aosoa.get_vector_at(aosoa.position,
p1);
138 pos1[2] = 2. *
box_h - pos1[2];
149 auto &&kernel)
const {
152 auto const d = box_geo.
get_mi_vector(pos2, {pos1[0], pos1[1], -pos1[2]});
157 auto const z = 2. *
box_h - pos1[2];
158 auto const d = box_geo.
get_mi_vector(pos2, {pos1[0], pos1[1], z});
168 for (
auto const &p : particles) {
172 energy += p3m.pair_energy(q1q2, d.norm());
182 for (
auto &p : particles) {
186 p.force() += p3m.pair_force(q1q2, d, d.norm());
194 using BaseSolver = std::variant<std::shared_ptr<CoulombP3M>>;
206 [
this](
auto &solver) { solver->bind_system(
m_system.lock()); });
207 sanity_checks_periodicity();
208 sanity_checks_cell_structure();
210 sanity_checks_dielectric_contrasts();
216 visit_base_solver([](
auto &solver) { solver->on_activation(); });
221 recalc_space_layer();
222 visit_base_solver([](
auto &actor) { actor->init(); });
227 visit_base_solver([](
auto &actor) { actor->on_boxl_change(); });
230 recalc_space_layer();
233 visit_base_solver([](
auto &solver) { solver->on_node_grid_change(); });
236 sanity_checks_periodicity();
237 visit_base_solver([](
auto &solver) { solver->on_periodicity_change(); });
240 sanity_checks_cell_structure();
241 visit_base_solver([](
auto &solver) { solver->on_cell_structure_change(); });
245 recalc_space_layer();
246 visit_base_solver([](
auto &actor) { actor->init(); });
251 visit_base_solver([](
auto &actor) { actor->init(); });
254 recalc_space_layer();
258 sanity_checks_periodicity();
259 sanity_checks_cell_structure();
261 sanity_checks_dielectric_contrasts();
262 visit_base_solver([](
auto &actor) { actor->sanity_checks(); });
272 return {std::string(
"conflict with ELC w/ dielectric contrasts")};
280 [&](
auto &solver) {
return solver->pair_force(q1q2, d,
dist); },
284#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
297 energy += p3m.pair_energy(
q_eff, d.
norm());
302 energy += p3m.pair_energy(
q_eff, d.
norm());
319 [
this, &pos1, &pos2, q1q2](
auto &
p3m_ptr) {
325 energy += p3m.pair_energy(
q_eff, d.
norm());
330 energy += p3m.pair_energy(
q_eff, d.
norm());
371 void check_gap(
Particle const &p)
const;
372 double tune_far_cut()
const;
375 double dipole_energy()
const;
376 void add_dipole_force()
const;
377 double z_energy()
const;
378 void add_z_force()
const;
381 void recalc_far_cut() {
387 void recalc_space_layer();
389 void sanity_checks_cell_structure()
const {}
390 void sanity_checks_periodicity()
const;
391 void sanity_checks_dielectric_contrasts()
const;
394 void add_force()
const;
396 double calc_energy()
const;
398 void visit_base_solver(
auto &&
visitor)
const {
Vector implementation and trait types for boost qvm interoperability.
ESPRESSO_ATTR_ALWAYS_INLINE Utils::Vector3< T > get_mi_vector(Utils::Vector3< T > const &a, Utils::Vector3< T > const &b) const
Get the minimum-image vector between two coordinates.
void sanity_checks_charge_neutrality() const
std::weak_ptr< System > m_system
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
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
void add_long_range_forces() const
Accumulate long-range electrostatic forces with corrections.
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()
Utils::Vector3d pair_force(double q1q2, Utils::Vector3d const &d, double dist) const
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.
double long_range_energy() const
Calculate long-range electrostatic energy with corrections.
void on_node_grid_change() 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.