GCC Code Coverage Report


Directory: ./
File: src/interaction.cpp
Date: 2024-04-18 12:22:13
Exec Total Coverage
Lines: 188 188 100.0%
Functions: 22 22 100.0%
Branches: 198 258 76.7%

Line Branch Exec Source
1 #include <algorithm>
2 #include <iostream>
3 #include <iterator>
4 #ifndef NO_OMP
5 #include <omp.h>
6 #endif
7
8 #include "cells.hpp"
9 #include "integrator.hpp"
10 #include "interaction.hpp"
11 #include "particle.hpp"
12 #include "potentials.hpp"
13 #include "system.hpp"
14
15 107 Interaction::Interaction(System *system, const YAML::Node &config)
16 107 : system(system), particles(system->particles),
17
1/2
✓ Branch 1 taken 107 times.
✗ Branch 2 not taken.
107 externals(PotentialFactory::createExternals(system, config["external"])),
18
2/4
✓ Branch 1 taken 107 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 107 times.
✗ Branch 5 not taken.
107 internal(PotentialFactory::createInternal(system, config["internal"],
19
8/14
✓ Branch 1 taken 107 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 50 times.
✓ Branch 4 taken 57 times.
✓ Branch 6 taken 50 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 50 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 50 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 50 times.
✓ Branch 15 taken 57 times.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
214 config["strategy"] && config["strategy"]["newton3"]
20
13/19
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 57 times.
✓ Branch 3 taken 50 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 50 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 50 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 35 times.
✓ Branch 12 taken 15 times.
✓ Branch 13 taken 50 times.
✓ Branch 14 taken 57 times.
✓ Branch 16 taken 50 times.
✓ Branch 17 taken 57 times.
✓ Branch 19 taken 50 times.
✓ Branch 20 taken 57 times.
✗ Branch 22 not taken.
✗ Branch 25 not taken.
✗ Branch 28 not taken.
264 ? config["strategy"]["newton3"].as<bool>()
21 : true)),
22 321 allDoE([this]() {
23 107 bool doesE = true;
24
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 107 times.
159 for (External *e : externals) {
25 52 doesE &= e->doesE();
26 }
27 107 doesE &= internal->doesE();
28 107 return doesE;
29
1/2
✓ Branch 1 taken 107 times.
✗ Branch 2 not taken.
107 }()),
30 321 allDoF([this]() {
31 107 bool doesF = true;
32
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 107 times.
159 for (External *e : externals) {
33 52 doesF &= e->doesF();
34 }
35 107 doesF &= internal->doesF();
36 107 return doesF;
37
1/2
✓ Branch 2 taken 107 times.
✗ Branch 3 not taken.
214 }()) {
38
1/2
✓ Branch 1 taken 107 times.
✗ Branch 2 not taken.
107 std::clog << "\nInteraction method:";
39
2/4
✓ Branch 1 taken 107 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 107 times.
✗ Branch 5 not taken.
107 std::clog << "\n\tNewton III: " << this->internal->newton3;
40
2/2
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 88 times.
107 if ((system->L.array() < internal->range).any()) {
41 19 std::clog << "\nWARNING: The range of the internal interactions is larger than some length of "
42
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
19 "the system size.";
43 }
44 107 }
45
46 210 Interaction::~Interaction() {
47
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 105 times.
314 for (External *e : externals) {
48
1/2
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
104 delete e;
49 }
50
1/2
✓ Branch 0 taken 105 times.
✗ Branch 1 not taken.
210 delete internal;
51 }
52
53 16 AllInteraction::AllInteraction(System *system, const YAML::Node &config)
54 16 : Interaction(system, config) {
55
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 std::clog << "\n\tstrategy: all";
56 16 }
57
58 2222 double AllInteraction::iteratePairs(Particle &p, PairFunction &func) {
59 2222 int n = particles.size();
60 2222 double sum = 0.;
61
2/2
✓ Branch 0 taken 355886 times.
✓ Branch 1 taken 2222 times.
358108 for (int j = 0; j < n; ++j) {
62
2/2
✓ Branch 0 taken 353664 times.
✓ Branch 1 taken 2222 times.
355886 Particle &pj = particles[j];
63
2/2
✓ Branch 0 taken 353664 times.
✓ Branch 1 taken 2222 times.
355886 if (&p != &pj) {
64 353664 sum += func(p, pj);
65 }
66 }
67 2222 return sum;
68 }
69
70 1488 double AllInteraction::iterateTriples(Particle &p, TripleFunction &func) {
71 1488 int n = particles.size();
72 1488 double sum = 0.;
73
2/2
✓ Branch 0 taken 237294 times.
✓ Branch 1 taken 1488 times.
238782 for (int j = 0; j < n; ++j) {
74
2/2
✓ Branch 0 taken 1488 times.
✓ Branch 1 taken 235806 times.
237294 Particle &pj = particles[j];
75
2/2
✓ Branch 0 taken 1488 times.
✓ Branch 1 taken 235806 times.
237294 if (&p == &pj) {
76 1488 continue;
77 }
78
2/2
✓ Branch 0 taken 26911706 times.
✓ Branch 1 taken 235806 times.
27147512 for (int k = j + 1; k < n; ++k) {
79
2/2
✓ Branch 0 taken 26675900 times.
✓ Branch 1 taken 235806 times.
26911706 Particle &pk = particles[k];
80
2/2
✓ Branch 0 taken 26675900 times.
✓ Branch 1 taken 235806 times.
26911706 if (&p != &pk) {
81 26675900 sum += func(p, pj, pk);
82 }
83 }
84 }
85 1488 return sum;
86 }
87
88 17 double AllInteraction::iteratePairs(PairFunction &func, bool newton3, bool parallel) {
89 17 int n = particles.size();
90 17 double sum = 0.;
91 17 #pragma omp parallel for if (!newton3 && parallel) reduction(+ : sum)
92 for (int i = 0; i < n; ++i) {
93 Particle &pi = particles[i];
94 int jStart = newton3 ? i + 1 : 0;
95 for (int j = jStart; j < n; ++j) {
96 Particle &pj = particles[j];
97 if (&pi != &pj) {
98 sum += func(pi, pj);
99 }
100 }
101 }
102 17 return sum;
103 }
104
105 11 double AllInteraction::iterateTriples(TripleFunction &func, bool newton3, bool parallel) {
106 11 int n = particles.size();
107 11 double sum = 0.;
108 11 #pragma omp parallel for if (!newton3 && parallel) reduction(+ : sum)
109 for (int i = 0; i < n; ++i) {
110 Particle &pi = particles[i];
111 for (int j = 0; j < n; ++j) {
112 Particle &pj = particles[j];
113 if (&pi == &pj) {
114 continue;
115 }
116 for (int k = j + 1; k < n; ++k) {
117 Particle &pk = particles[k];
118 if (&pi != &pk) {
119 sum += func(pi, pj, pk);
120 }
121 }
122 }
123 }
124 11 return sum;
125 }
126
127 83 CellNeighborInteraction::CellNeighborInteraction(System *system, const YAML::Node &config)
128 249 : Interaction(system, config), cellCount([this]() -> ArrayI {
129 83 ArrayI count = floor(this->system->L.array() / internal->range).max(1).cast<int>();
130 #ifndef NO_OMP
131
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 36 times.
75 if (internal->newton3 &&
132
17/18
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 37 times.
✓ Branch 4 taken 23 times.
✓ Branch 5 taken 15 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 22 times.
✓ Branch 8 taken 22 times.
✓ Branch 9 taken 15 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 21 times.
✓ Branch 12 taken 75 times.
✓ Branch 13 taken 8 times.
✓ Branch 14 taken 39 times.
✓ Branch 15 taken 36 times.
✓ Branch 16 taken 39 times.
✗ Branch 17 not taken.
234 count.unaryExpr([](int x) -> bool { return x > 1 && x % 2; }).any() &&
133 39 omp_get_max_threads() > 1) {
134 39 std::clog << "\n\tWARNING: forcing even cell count in all directions to prevent race "
135 39 "conditions with newton3.";
136
3/4
✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 77 times.
✓ Branch 3 taken 40 times.
156 count = count.unaryExpr([](int x) -> int { return x > 1 && x % 2 ? --x : x; });
137 }
138 #endif
139 83 return count;
140 }()),
141 83 cellL(system->L.array() / cellCount.cast<double>()),
142
1/2
✓ Branch 1 taken 83 times.
✗ Branch 2 not taken.
83 cells(cellL, cellCount,
143
3/9
✓ Branch 1 taken 83 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 83 times.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 83 times.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
166 config["interaction"] && config["interaction"]["cellColoring"]
144
5/13
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
✓ Branch 12 taken 83 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 83 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 83 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 83 times.
✗ Branch 23 not taken.
✗ Branch 26 not taken.
✗ Branch 29 not taken.
166 ? config["interaction"]["cellColoring"].as<std::string>()
145 : "",
146
2/4
✓ Branch 2 taken 83 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 83 times.
✗ Branch 6 not taken.
166 internal->threebody()) {
147
1/2
✓ Branch 1 taken 83 times.
✗ Branch 2 not taken.
83 std::clog << "\n\tstrategy: cells";
148 83 }
149
150 4795 void CellNeighborInteraction::updateMeta() {
151
2/2
✓ Branch 0 taken 766602 times.
✓ Branch 1 taken 4795 times.
771397 for (auto &c : cells) {
152 766602 c.particleIndices.clear();
153 }
154 4795 size_t n = particles.size();
155
2/2
✓ Branch 0 taken 16770 times.
✓ Branch 1 taken 4795 times.
21565 for (size_t i = 0; i < n; ++i) {
156 16770 int cIndex = cells.getIndex(particles[i].r);
157 16770 cells[cIndex].particleIndices.push_back(i);
158 16770 cells.particle2cell.insert_or_assign(i, cIndex);
159 }
160 4795 }
161
162 2729 void CellNeighborInteraction::updateParticleMeta(Particle &p,
163 ParticleUpdateType particleUpdateType) {
164
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 2664 times.
2729 int i = std::distance(&particles.front(), &p);
165
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 2664 times.
2729 if (particleUpdateType != ParticleUpdateType::INSERT) { // p was deleted or moved
166
1/2
✓ Branch 1 taken 65 times.
✗ Branch 2 not taken.
65 Cell &cOld = cells[cells.particle2cell[i]];
167
1/2
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
65 if (auto found = std::find(cOld.particleIndices.begin(), cOld.particleIndices.end(), i);
168
1/2
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
65 found != cOld.particleIndices.end()) {
169 65 std::iter_swap(found, cOld.particleIndices.end() - 1);
170 65 cOld.particleIndices.pop_back();
171 }
172 }
173
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 1 times.
65 if (particleUpdateType != ParticleUpdateType::DELETE) { // p was inserted or moved
174 2728 int cIndex = cells.getIndex(p.r);
175 2728 cells[cIndex].particleIndices.push_back(i);
176 2728 cells.particle2cell.insert_or_assign(i, cIndex);
177 }
178 2729 }
179
180 2724 double CellNeighborInteraction::iteratePairs(Particle &p, PairFunction &func) {
181 2724 double sum = 0.;
182 2724 Cell &c = cells[p.r];
183
2/2
✓ Branch 0 taken 39192 times.
✓ Branch 1 taken 2724 times.
41916 for (auto &[_, icj] : c.pairsAll) {
184 39192 Cell &cj = cells[icj];
185 39192 int nj = cj.particleIndices.size();
186
2/2
✓ Branch 0 taken 293984 times.
✓ Branch 1 taken 39192 times.
333176 for (int j = 0; j < nj; ++j) {
187
2/2
✓ Branch 0 taken 291260 times.
✓ Branch 1 taken 2724 times.
293984 Particle &pj = particles[cj.particleIndices[j]];
188
2/2
✓ Branch 0 taken 291260 times.
✓ Branch 1 taken 2724 times.
293984 if (&p != &pj) {
189 291260 sum += func(p, pj);
190 }
191 }
192 }
193 2724 return sum;
194 }
195
196 1489 double CellNeighborInteraction::iterateTriples(Particle &p, TripleFunction &func) {
197 1489 double sum = 0.;
198 1489 Cell &c = cells[p.r];
199
2/2
✓ Branch 0 taken 49509 times.
✓ Branch 1 taken 1489 times.
50998 for (auto &[_, icj, ick] : c.triplesAll) {
200 49509 Cell &cj = cells[icj];
201 49509 Cell &ck = cells[ick];
202 49509 int nj = cj.particleIndices.size();
203 49509 int nk = ck.particleIndices.size();
204
2/2
✓ Branch 0 taken 1260077 times.
✓ Branch 1 taken 49509 times.
1309586 for (int j = 0; j < nj; ++j) {
205
2/2
✓ Branch 0 taken 6977 times.
✓ Branch 1 taken 1253100 times.
1260077 Particle &pj = particles[cj.particleIndices[j]];
206
2/2
✓ Branch 0 taken 6977 times.
✓ Branch 1 taken 1253100 times.
1260077 if (&p == &pj) {
207 6977 continue;
208 }
209
2/2
✓ Branch 0 taken 235860 times.
✓ Branch 1 taken 1017240 times.
1253100 int kStart = icj == ick ? j + 1 : 0;
210
2/2
✓ Branch 0 taken 26830388 times.
✓ Branch 1 taken 1253100 times.
28083488 for (int k = kStart; k < nk; ++k) {
211
2/2
✓ Branch 0 taken 26676176 times.
✓ Branch 1 taken 154212 times.
26830388 Particle &pk = particles[ck.particleIndices[k]];
212
2/2
✓ Branch 0 taken 26676176 times.
✓ Branch 1 taken 154212 times.
26830388 if (&p != &pk) {
213 26676176 sum += func(p, pj, pk);
214 }
215 }
216 }
217 }
218 1489 return sum;
219 }
220
221 808970 double CellNeighborInteraction::doCell(Cell &c, PairFunction &func, bool newton3) {
222 808970 double sum = 0.;
223
2/2
✓ Branch 0 taken 808860 times.
✓ Branch 1 taken 110 times.
808970 auto &pairs = newton3 ? c.pairsNewton3 : c.pairsAll;
224
2/2
✓ Branch 0 taken 11219623 times.
✓ Branch 1 taken 808970 times.
12028593 for (auto &[ici, icj] : pairs) {
225 11219623 Cell &ci = cells[ici];
226 11219623 Cell &cj = cells[icj];
227 11219623 int ni = ci.particleIndices.size();
228 11219623 int nj = cj.particleIndices.size();
229
2/2
✓ Branch 0 taken 228269 times.
✓ Branch 1 taken 11219623 times.
11447892 for (int i = 0; i < ni; ++i) {
230
2/2
✓ Branch 0 taken 213136 times.
✓ Branch 1 taken 15133 times.
228269 Particle &pi = particles[ci.particleIndices[i]];
231
4/4
✓ Branch 0 taken 213136 times.
✓ Branch 1 taken 15133 times.
✓ Branch 2 taken 17625 times.
✓ Branch 3 taken 195511 times.
228269 int jStart = newton3 && ici == icj ? i + 1 : 0;
232
2/2
✓ Branch 0 taken 445889 times.
✓ Branch 1 taken 228269 times.
674158 for (int j = jStart; j < nj; ++j) {
233
2/2
✓ Branch 0 taken 444758 times.
✓ Branch 1 taken 1131 times.
445889 Particle &pj = particles[cj.particleIndices[j]];
234
2/2
✓ Branch 0 taken 444758 times.
✓ Branch 1 taken 1131 times.
445889 if (&pi != &pj) {
235 444758 sum += func(pi, pj);
236 }
237 }
238 }
239 }
240 808970 return sum;
241 }
242
243 5082 double CellNeighborInteraction::doCell(Cell &c, TripleFunction &func, bool newton3) {
244 5082 double sum = 0.;
245
2/2
✓ Branch 0 taken 5064 times.
✓ Branch 1 taken 18 times.
5082 auto &triples = newton3 ? c.triplesNewton3 : c.triplesAll;
246
2/2
✓ Branch 0 taken 182322 times.
✓ Branch 1 taken 5082 times.
187404 for (auto &[ici, icj, ick] : triples) {
247 182322 Cell &ci = cells[ici];
248 182322 Cell &cj = cells[icj];
249 182322 Cell &ck = cells[ick];
250 182322 int ni = ci.particleIndices.size();
251 182322 int nj = cj.particleIndices.size();
252 182322 int nk = ck.particleIndices.size();
253
2/2
✓ Branch 0 taken 117469 times.
✓ Branch 1 taken 182322 times.
299791 for (int i = 0; i < ni; ++i) {
254 117469 Particle &pi = particles[ci.particleIndices[i]];
255
2/2
✓ Branch 0 taken 2388822 times.
✓ Branch 1 taken 117469 times.
2506291 for (int j = 0; j < nj; ++j) {
256
2/2
✓ Branch 0 taken 18112 times.
✓ Branch 1 taken 2370710 times.
2388822 Particle &pj = particles[cj.particleIndices[j]];
257
2/2
✓ Branch 0 taken 18112 times.
✓ Branch 1 taken 2370710 times.
2388822 if (&pi == &pj) {
258 18112 continue;
259 }
260
2/2
✓ Branch 0 taken 475374 times.
✓ Branch 1 taken 1895336 times.
2370710 int kStart = icj == ick ? j + 1 : 0;
261
2/2
✓ Branch 0 taken 80266953 times.
✓ Branch 1 taken 2370710 times.
82637663 for (int k = kStart; k < nk; ++k) {
262
2/2
✓ Branch 0 taken 80029266 times.
✓ Branch 1 taken 237687 times.
80266953 Particle &pk = particles[ck.particleIndices[k]];
263
2/2
✓ Branch 0 taken 80029266 times.
✓ Branch 1 taken 237687 times.
80266953 if (&pi != &pk) {
264 80029266 sum += func(pi, pj, pk);
265 }
266 }
267 }
268 }
269 }
270 5082 return sum;
271 }
272
273 template <typename T>
274 12216 double CellNeighborInteraction::iterate(T &func, bool newton3, bool parallel) {
275 12216 double sum = 0.;
276
2/2
✓ Branch 0 taken 6095 times.
✓ Branch 1 taken 13 times.
12216 if (newton3) {
277
2/2
✓ Branch 0 taken 97520 times.
✓ Branch 1 taken 6095 times.
207230 for (auto &sameColorIndices : cells.sameColorIndices) {
278 195040 #pragma omp parallel for schedule(dynamic) if (parallel) reduction(+ : sum)
279 for (int ic : sameColorIndices) {
280 Cell &c = cells[ic];
281 sum += doCell(c, func, newton3);
282 }
283 }
284 } else {
285 26 #pragma omp parallel for schedule(dynamic) if (parallel) reduction(+ : sum)
286 for (Cell &c : cells) {
287 sum += doCell(c, func, newton3);
288 }
289 }
290 12216 return sum;
291 }
292
293 5457 double CellNeighborInteraction::iteratePairs(PairFunction &func, bool newton3, bool parallel) {
294 5457 return iterate(func, newton3, parallel);
295 }
296
297 651 double CellNeighborInteraction::iterateTriples(TripleFunction &func, bool newton3, bool parallel) {
298 651 return iterate(func, newton3, parallel);
299 }
300
301 99 Interaction *InteractionFactory::create(System *system, const YAML::Node &configInteraction) {
302 99 Interaction *interaction = nullptr;
303
11/16
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 50 times.
✓ Branch 4 taken 49 times.
✓ Branch 6 taken 50 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 50 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 49 times.
✓ Branch 12 taken 1 times.
✓ Branch 14 taken 50 times.
✓ Branch 15 taken 49 times.
✓ Branch 18 taken 16 times.
✓ Branch 19 taken 83 times.
✗ Branch 22 not taken.
✗ Branch 25 not taken.
198 if (configInteraction["strategy"] && configInteraction["strategy"]["neighbors"] &&
304
13/19
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 49 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 33 times.
✓ Branch 10 taken 16 times.
✓ Branch 11 taken 49 times.
✓ Branch 12 taken 50 times.
✓ Branch 13 taken 49 times.
✓ Branch 14 taken 50 times.
✓ Branch 16 taken 49 times.
✓ Branch 17 taken 50 times.
✓ Branch 19 taken 50 times.
✓ Branch 20 taken 49 times.
✗ Branch 22 not taken.
✗ Branch 25 not taken.
✗ Branch 28 not taken.
181 configInteraction["strategy"]["neighbors"].as<std::string>() == "all") {
305
1/2
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 interaction = new AllInteraction(system, configInteraction);
306 } else {
307
1/2
✓ Branch 2 taken 83 times.
✗ Branch 3 not taken.
83 interaction = new CellNeighborInteraction(system, configInteraction);
308 }
309 99 return interaction;
310 }
311