32
32
33
33
#include " BoxGeometry.hpp"
34
34
#include " Particle.hpp"
35
+ #include " ParticlePropertyIterator.hpp"
35
36
#include " ParticleRange.hpp"
36
37
#include " cell_system/CellStructure.hpp"
37
38
#include " communication.hpp"
43
44
#include < utils/math/sqr.hpp>
44
45
45
46
#include < boost/mpi/collectives/all_reduce.hpp>
47
+ #include < boost/range/combine.hpp>
46
48
47
49
#include < algorithm>
48
50
#include < cassert>
@@ -1118,59 +1120,62 @@ static void p3m_assign_image_charge(elc_data const &elc, CoulombP3M &p3m,
1118
1120
}
1119
1121
}
1120
1122
1121
- template <ChargeProtocol protocol>
1123
+ template <ChargeProtocol protocol, typename combined_ranges >
1122
1124
void charge_assign (elc_data const &elc, CoulombP3M &solver,
1123
- ParticleRange const &particles ) {
1125
+ combined_ranges const &p_q_pos_range ) {
1124
1126
if (protocol == ChargeProtocol::BOTH or protocol == ChargeProtocol::IMAGE) {
1125
1127
solver.p3m .inter_weights .reset (solver.p3m .params .cao );
1126
1128
}
1127
1129
/* prepare local FFT mesh */
1128
1130
for (int i = 0 ; i < solver.p3m .local_mesh .size ; i++)
1129
1131
solver.p3m .rs_mesh [i] = 0 .;
1130
1132
1131
- for (auto const &p : particles) {
1132
- if (p.q () != 0 .) {
1133
+ for (auto zipped : p_q_pos_range) {
1134
+ auto const p_q = boost::get<0 >(zipped);
1135
+ auto const &p_pos = boost::get<1 >(zipped);
1136
+ if (p_q != 0 .) {
1133
1137
if (protocol == ChargeProtocol::BOTH or
1134
1138
protocol == ChargeProtocol::REAL) {
1135
- solver.assign_charge (p. q (), p. pos () , solver.p3m .inter_weights );
1139
+ solver.assign_charge (p_q, p_pos , solver.p3m .inter_weights );
1136
1140
}
1137
1141
if (protocol == ChargeProtocol::BOTH or
1138
1142
protocol == ChargeProtocol::IMAGE) {
1139
- p3m_assign_image_charge (elc, solver, p. q (), p. pos () );
1143
+ p3m_assign_image_charge (elc, solver, p_q, p_pos );
1140
1144
}
1141
1145
}
1142
1146
}
1143
1147
}
1144
1148
1145
- template <ChargeProtocol protocol>
1149
+ template <ChargeProtocol protocol, typename combined_range >
1146
1150
void modify_p3m_sums (elc_data const &elc, CoulombP3M &solver,
1147
- ParticleRange const &particles ) {
1151
+ combined_range const &p_q_pos_range ) {
1148
1152
1149
1153
Utils::Vector3d node_sums{};
1150
- for (auto const &p : particles) {
1151
- auto const q = p.q ();
1152
- if (q != 0 .) {
1153
- auto const z = p.pos ()[2 ];
1154
+ for (auto zipped : p_q_pos_range) {
1155
+ auto const p_q = boost::get<0 >(zipped);
1156
+ auto const &p_pos = boost::get<1 >(zipped);
1157
+ if (p_q != 0 .) {
1158
+ auto const p_z = p_pos[2 ];
1154
1159
1155
1160
if (protocol == ChargeProtocol::BOTH or
1156
1161
protocol == ChargeProtocol::REAL) {
1157
1162
node_sums[0 ] += 1 .;
1158
- node_sums[1 ] += Utils::sqr (q );
1159
- node_sums[2 ] += q ;
1163
+ node_sums[1 ] += Utils::sqr (p_q );
1164
+ node_sums[2 ] += p_q ;
1160
1165
}
1161
1166
1162
1167
if (protocol == ChargeProtocol::BOTH or
1163
1168
protocol == ChargeProtocol::IMAGE) {
1164
- if (z < elc.space_layer ) {
1169
+ if (p_z < elc.space_layer ) {
1165
1170
node_sums[0 ] += 1 .;
1166
- node_sums[1 ] += Utils::sqr (elc.delta_mid_bot * q );
1167
- node_sums[2 ] += elc.delta_mid_bot * q ;
1171
+ node_sums[1 ] += Utils::sqr (elc.delta_mid_bot * p_q );
1172
+ node_sums[2 ] += elc.delta_mid_bot * p_q ;
1168
1173
}
1169
1174
1170
- if (z > (elc.box_h - elc.space_layer )) {
1175
+ if (p_z > (elc.box_h - elc.space_layer )) {
1171
1176
node_sums[0 ] += 1 .;
1172
- node_sums[1 ] += Utils::sqr (elc.delta_mid_top * q );
1173
- node_sums[2 ] += elc.delta_mid_top * q ;
1177
+ node_sums[1 ] += Utils::sqr (elc.delta_mid_top * p_q );
1178
+ node_sums[2 ] += elc.delta_mid_top * p_q ;
1174
1179
}
1175
1180
}
1176
1181
}
@@ -1190,6 +1195,10 @@ double ElectrostaticLayerCorrection::long_range_energy(
1190
1195
auto &solver = *solver_ptr;
1191
1196
auto const &box_geo = *get_system ().box_geo ;
1192
1197
1198
+ auto p_q_range = ParticlePropertyRange::charge_range (particles);
1199
+ auto p_pos_range = ParticlePropertyRange::pos_range (particles);
1200
+ auto p_q_pos_range = boost::combine (p_q_range, p_pos_range);
1201
+
1193
1202
// assign the original charges (they may not have been assigned yet)
1194
1203
solver.charge_assign (particles);
1195
1204
@@ -1203,17 +1212,17 @@ double ElectrostaticLayerCorrection::long_range_energy(
1203
1212
0.5 * elc.dielectric_layers_self_energy (solver, box_geo, particles);
1204
1213
1205
1214
// assign both original and image charges
1206
- charge_assign<ChargeProtocol::BOTH>(elc, solver, particles );
1207
- modify_p3m_sums<ChargeProtocol::BOTH>(elc, solver, particles );
1215
+ charge_assign<ChargeProtocol::BOTH>(elc, solver, p_q_pos_range );
1216
+ modify_p3m_sums<ChargeProtocol::BOTH>(elc, solver, p_q_pos_range );
1208
1217
energy += 0.5 * solver.long_range_energy (particles);
1209
1218
1210
1219
// assign only the image charges now
1211
- charge_assign<ChargeProtocol::IMAGE>(elc, solver, particles );
1212
- modify_p3m_sums<ChargeProtocol::IMAGE>(elc, solver, particles );
1220
+ charge_assign<ChargeProtocol::IMAGE>(elc, solver, p_q_pos_range );
1221
+ modify_p3m_sums<ChargeProtocol::IMAGE>(elc, solver, p_q_pos_range );
1213
1222
energy -= 0.5 * solver.long_range_energy (particles);
1214
1223
1215
1224
// restore modified sums
1216
- modify_p3m_sums<ChargeProtocol::REAL>(elc, solver, particles );
1225
+ modify_p3m_sums<ChargeProtocol::REAL>(elc, solver, p_q_pos_range );
1217
1226
1218
1227
return energy;
1219
1228
},
@@ -1226,17 +1235,20 @@ void ElectrostaticLayerCorrection::add_long_range_forces(
1226
1235
std::visit (
1227
1236
[this , &particles](auto const &solver_ptr) {
1228
1237
auto &solver = *solver_ptr;
1238
+ auto p_q_range = ParticlePropertyRange::charge_range (particles);
1239
+ auto p_pos_range = ParticlePropertyRange::pos_range (particles);
1240
+ auto p_q_pos_range = boost::combine (p_q_range, p_pos_range);
1229
1241
if (elc.dielectric_contrast_on ) {
1230
1242
auto const &box_geo = *get_system ().box_geo ;
1231
- modify_p3m_sums<ChargeProtocol::BOTH>(elc, solver, particles );
1232
- charge_assign<ChargeProtocol::BOTH>(elc, solver, particles );
1243
+ modify_p3m_sums<ChargeProtocol::BOTH>(elc, solver, p_q_pos_range );
1244
+ charge_assign<ChargeProtocol::BOTH>(elc, solver, p_q_pos_range );
1233
1245
elc.dielectric_layers_self_forces (solver, box_geo, particles);
1234
1246
} else {
1235
1247
solver.charge_assign (particles);
1236
1248
}
1237
1249
solver.add_long_range_forces (particles);
1238
1250
if (elc.dielectric_contrast_on ) {
1239
- modify_p3m_sums<ChargeProtocol::REAL>(elc, solver, particles );
1251
+ modify_p3m_sums<ChargeProtocol::REAL>(elc, solver, p_q_pos_range );
1240
1252
}
1241
1253
},
1242
1254
base_solver);
0 commit comments