104 }
catch (std::runtime_error
const &err) {
110 auto &cell_structure = *system.cell_structure;
111 auto const &coulomb = system.coulomb;
112 auto const particles = cell_structure.local_particles();
113 auto const prefactor = std::visit(
114 [](
auto const &ptr) {
return ptr->prefactor; }, *coulomb.impl->solver);
115 auto const pref = 1. / (prefactor * 2. * std::numbers::pi);
116 auto const kernel = coulomb.pair_force_kernel();
117 auto const elc_kernel = coulomb.pair_force_elc_kernel();
120 using execution_space = Kokkos::DefaultExecutionSpace;
121 auto const &unique_particles = cell_structure.get_unique_particles();
122 auto &local_force = cell_structure.get_local_force();
123 auto scatter_force = system.cell_structure->get_scatter_force();
125 auto global_max_rel_diff = 0.;
128 auto charge_density_max = 0.;
132 system.coulomb.calc_long_range_force();
133 cell_structure.ghosts_reduce_forces();
135 Kokkos::Experimental::contribute(local_force, scatter_force);
136 kokkos_parallel_range_for<Kokkos::RangePolicy<execution_space>>(
137 "reduction", std::size_t{0}, unique_particles.size(),
138 [&local_force, &unique_particles](std::size_t
const i) {
139 auto &force = unique_particles.at(i)->force();
140 force[0] += local_force(i, 0);
141 force[1] += local_force(i, 1);
142 force[2] += local_force(i, 2);
146 auto max_rel_diff = 0.;
148 for (
auto &p : particles) {
149 auto const pid = p.id();
153 <<
"ICC found zero electric charge on a particle. This must "
161 auto const del_eps = (eps_in - eps_out) / (eps_in + eps_out);
165 if (local_e_field.norm2() == 0.) {
167 <<
"ICC found zero electric field on a charge. This must "
171 auto const charge_density_old = p.q() /
icc_cfg.
areas[id];
174 std::max(charge_density_max, std::abs(charge_density_old));
176 auto const charge_density_update =
182 auto const charge_density_new =
187 auto const relative_difference =
188 std::abs((charge_density_new - charge_density_old) /
189 (charge_density_max +
190 std::abs(charge_density_new + charge_density_old)));
192 max_rel_diff = std::max(max_rel_diff, relative_difference);
199 if (std::abs(p.q()) > 1e6) {
201 <<
"Particle with id " << p.id() <<
" has a charge (q=" << p.q()
202 <<
") that is too large for the ICC algorithm";
204 max_rel_diff = std::numeric_limits<double>::max();
217 boost::mpi::all_reduce(
comm_cart, max_rel_diff, global_max_rel_diff,
218 boost::mpi::maximum<double>());
226 <<
"ICC failed to converge in the given number of maximal steps.";
229 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.