107 }
catch (std::runtime_error
const &err) {
113 auto &cell_structure = *system.cell_structure;
114 auto const &coulomb = system.coulomb;
115 auto const particles = cell_structure.local_particles();
116 auto const prefactor = std::visit(
117 [](
auto const &ptr) {
return ptr->prefactor; }, *coulomb.impl->solver);
118 auto const pref = 1. / (prefactor * 2. * std::numbers::pi);
119 auto const kernel = coulomb.pair_force_kernel();
120 auto const elc_kernel = coulomb.pair_force_elc_kernel();
123#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
124 using execution_space = Kokkos::DefaultExecutionSpace;
125 auto const &unique_particles = cell_structure.get_unique_particles();
126 auto const &local_force = cell_structure.get_local_force();
129 auto global_max_rel_diff = 0.;
132 auto charge_density_max = 0.;
136 system.coulomb.calc_long_range_force();
137 cell_structure.ghosts_reduce_forces();
138#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
140 int num_threads = execution_space().concurrency();
141 kokkos_parallel_range_for<Kokkos::RangePolicy<execution_space>>(
142 "reduction", std::size_t{0}, unique_particles.size(),
143 [&local_force, &unique_particles, num_threads](std::size_t
const i) {
144 auto &force = unique_particles.at(i)->force();
145 for (
int tid = 0; tid < num_threads; ++tid) {
146 force[0] += local_force(i, tid, 0);
147 force[1] += local_force(i, tid, 1);
148 force[2] += local_force(i, tid, 2);
154 auto max_rel_diff = 0.;
156 for (
auto &p : particles) {
157 auto const pid = p.id();
161 <<
"ICC found zero electric charge on a particle. This must "
169 auto const del_eps = (eps_in - eps_out) / (eps_in + eps_out);
173 if (local_e_field.norm2() == 0.) {
175 <<
"ICC found zero electric field on a charge. This must "
179 auto const charge_density_old = p.q() /
icc_cfg.
areas[id];
182 std::max(charge_density_max, std::abs(charge_density_old));
184 auto const charge_density_update =
190 auto const charge_density_new =
195 auto const relative_difference =
196 std::abs((charge_density_new - charge_density_old) /
197 (charge_density_max +
198 std::abs(charge_density_new + charge_density_old)));
200 max_rel_diff = std::max(max_rel_diff, relative_difference);
207 if (std::abs(p.q()) > 1e6) {
209 <<
"Particle with id " << p.id() <<
" has a charge (q=" << p.q()
210 <<
") that is too large for the ICC algorithm";
212 max_rel_diff = std::numeric_limits<double>::max();
220#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
227 boost::mpi::all_reduce(
comm_cart, max_rel_diff, global_max_rel_diff,
228 boost::mpi::maximum<double>());
236 <<
"ICC failed to converge in the given number of maximal steps.";
239 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.