108 }
catch (std::runtime_error
const &err) {
114 auto &cell_structure = *system.cell_structure;
115 auto const &coulomb = system.coulomb;
116 auto const particles = cell_structure.local_particles();
117 auto const prefactor = std::visit(
118 [](
auto const &ptr) {
return ptr->prefactor; }, *coulomb.impl->solver);
119 auto const pref = 1. / (prefactor * 2. * std::numbers::pi);
120 auto const kernel = coulomb.pair_force_kernel();
121 auto const elc_kernel = coulomb.pair_force_elc_kernel();
124#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
125 using execution_space = Kokkos::DefaultExecutionSpace;
126 auto const &unique_particles = cell_structure.get_unique_particles();
127 auto const &local_force = cell_structure.get_local_force();
130 auto global_max_rel_diff = 0.;
133 auto charge_density_max = 0.;
137 system.coulomb.calc_long_range_force(particles);
138 cell_structure.ghosts_reduce_forces();
139#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
141 int num_threads = execution_space().concurrency();
142 kokkos_parallel_range_for<Kokkos::RangePolicy<execution_space>>(
143 "reduction", std::size_t{0}, unique_particles.size(),
144 [&local_force, &unique_particles, num_threads](std::size_t
const i) {
145 auto &force = unique_particles.at(i)->force();
146 for (
int tid = 0; tid < num_threads; ++tid) {
147 force[0] += local_force(i, tid, 0);
148 force[1] += local_force(i, tid, 1);
149 force[2] += local_force(i, tid, 2);
155 auto max_rel_diff = 0.;
157 for (
auto &p : particles) {
158 auto const pid = p.id();
162 <<
"ICC found zero electric charge on a particle. This must "
170 auto const del_eps = (eps_in - eps_out) / (eps_in + eps_out);
174 if (local_e_field.norm2() == 0.) {
176 <<
"ICC found zero electric field on a charge. This must "
180 auto const charge_density_old = p.q() /
icc_cfg.
areas[id];
183 std::max(charge_density_max, std::abs(charge_density_old));
185 auto const charge_density_update =
191 auto const charge_density_new =
196 auto const relative_difference =
197 std::abs((charge_density_new - charge_density_old) /
198 (charge_density_max +
199 std::abs(charge_density_new + charge_density_old)));
201 max_rel_diff = std::max(max_rel_diff, relative_difference);
208 if (std::abs(p.q()) > 1e6) {
210 <<
"Particle with id " << p.id() <<
" has a charge (q=" << p.q()
211 <<
") that is too large for the ICC algorithm";
213 max_rel_diff = std::numeric_limits<double>::max();
221#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
228 boost::mpi::all_reduce(
comm_cart, max_rel_diff, global_max_rel_diff,
229 boost::mpi::maximum<double>());
237 <<
"ICC failed to converge in the given number of maximal steps.";
240 system.on_particle_charge_change();
static void force_calc_icc(CellStructure &cell_structure, Coulomb::ShortRangeForceKernel::result_type const &coulomb_kernel, Coulomb::ShortRangeForceCorrectionsKernel::result_type const &elc_kernel)
Calculate the electrostatic forces between source charges (= real charges) and wall charges.
Struct holding all information for one particle.