Line | Branch | Exec | Source |
---|---|---|---|
1 | #pragma once | ||
2 | |||
3 | #include "cells.hpp" | ||
4 | #include "particle.hpp" | ||
5 | #include "potentials.hpp" | ||
6 | #include "system.hpp" | ||
7 | #include <yaml-cpp/yaml.h> | ||
8 | |||
9 | class Cells; | ||
10 | |||
11 | class Interaction { | ||
12 | public: | ||
13 | System *system; | ||
14 | std::vector<Particle> &particles; | ||
15 | std::vector<External *> externals; | ||
16 | Internal *internal; | ||
17 | bool allDoE; | ||
18 | bool allDoF; | ||
19 | |||
20 | Interaction(System *system, const YAML::Node &config); | ||
21 | virtual ~Interaction(); | ||
22 | |||
23 | virtual double iteratePairs(Particle &p, PairFunction &func) = 0; | ||
24 | virtual double iterateTriples(Particle &p, TripleFunction &func) = 0; | ||
25 | virtual double iteratePairs(PairFunction &func, bool newton3, bool parallel = true) = 0; | ||
26 | virtual double iterateTriples(TripleFunction &func, bool newton3, bool parallel = true) = 0; | ||
27 | |||
28 | virtual void | ||
29 | 2228 | updateParticleMeta(Particle &p, | |
30 | 2228 | ParticleUpdateType particleUpdateType = ParticleUpdateType::MOVE) {} | |
31 | 16 | virtual void updateMeta() {} | |
32 | |||
33 | 23944 | double external(Particle &p) { | |
34 | 23944 | p.Eext = 0.; | |
35 |
2/2✓ Branch 0 taken 8948 times.
✓ Branch 1 taken 23944 times.
|
32892 | for (External *e : externals) { |
36 | 8948 | p.Eext += (*e)(p); | |
37 | } | ||
38 | 23944 | return p.Eext; | |
39 | } | ||
40 | |||
41 | virtual double | ||
42 | 4946 | updateParticleState(Particle &p, | |
43 | ParticleUpdateType particleUpdateType = ParticleUpdateType::MOVE) { | ||
44 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4946 times.
|
4946 | if (internal->needsGather()) { |
45 | ✗ | throw std::runtime_error("Interactions that need gathering cannot use updateParticleState"); | |
46 | } | ||
47 | 4946 | updateParticleMeta(p, particleUpdateType); | |
48 | 4946 | double E = 0.; | |
49 | 4946 | E = external(p); | |
50 | 4946 | bool newton3Restore = internal->newton3; | |
51 | 4946 | internal->newton3 = false; | |
52 | 4946 | E += iteratePairs(p, *internal); | |
53 |
2/2✓ Branch 0 taken 2977 times.
✓ Branch 1 taken 1969 times.
|
4946 | if (internal->threebody()) { |
54 | 2977 | E += iterateTriples(p, *internal); | |
55 | } | ||
56 | 4946 | internal->newton3 = newton3Restore; | |
57 | 4946 | return E; | |
58 | } | ||
59 | |||
60 | 4811 | virtual void updateState() { | |
61 | 4811 | updateMeta(); | |
62 | 4811 | int n = particles.size(); | |
63 | 4811 | bool newton3 = internal->newton3; | |
64 | 4811 | double Eext = 0.; | |
65 | 4811 | #pragma omp parallel for reduction(+ : Eext) | |
66 | for (int i = 0; i < n; ++i) { | ||
67 | Particle &pi = particles[i]; | ||
68 | Eext += external(pi); | ||
69 | } | ||
70 | 4811 | double Eint = 0.; | |
71 | 4811 | internal->reset(); | |
72 | 4811 | Eint += iteratePairs(*internal, newton3); | |
73 |
2/2✓ Branch 0 taken 663 times.
✓ Branch 1 taken 4148 times.
|
4811 | if (internal->needsGather()) { |
74 | 663 | internal->gather = true; | |
75 | 663 | double Egather = 0.; | |
76 | 663 | #pragma omp parallel for reduction(+ : Egather) | |
77 | for (int i = 0; i < n; ++i) { | ||
78 | Egather += (*internal)(particles[i]); | ||
79 | } | ||
80 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 663 times.
|
663 | if (!newton3) { |
81 | // There is no double counting in this term, so compensate for the correction below | ||
82 | ✗ | Egather *= 2; | |
83 | } | ||
84 | 663 | Eint += Egather; | |
85 | 663 | Eint += iteratePairs(*internal, newton3); | |
86 | 663 | internal->gather = false; | |
87 | } | ||
88 |
2/2✓ Branch 0 taken 662 times.
✓ Branch 1 taken 4149 times.
|
4811 | if (internal->threebody()) { |
89 | 662 | double Etriples = iterateTriples(*internal, newton3); | |
90 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 653 times.
|
662 | if (!newton3) { |
91 | // There is no double counting in this term, so compensate for the correction below | ||
92 | 9 | Etriples *= 2; | |
93 | } | ||
94 | 662 | Eint += Etriples; | |
95 | } | ||
96 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4795 times.
|
4811 | if (!newton3) { |
97 | // Account for double counting in energy | ||
98 | 16 | Eint *= 0.5; | |
99 | } | ||
100 | 4811 | system->E = Eext + Eint; | |
101 | 4811 | } | |
102 | }; | ||
103 | |||
104 | class AllInteraction : public Interaction { | ||
105 | public: | ||
106 | AllInteraction(System *system, const YAML::Node &config); | ||
107 | |||
108 | double iteratePairs(Particle &p, PairFunction &func); | ||
109 | double iterateTriples(Particle &p, TripleFunction &func); | ||
110 | double iteratePairs(PairFunction &func, bool newton3, bool parallel = true); | ||
111 | double iterateTriples(TripleFunction &func, bool newton3, bool parallel = true); | ||
112 | }; | ||
113 | |||
114 | class CellNeighborInteraction : public Interaction { | ||
115 | double doCell(Cell &c, PairFunction &func, bool newton3); | ||
116 | double doCell(Cell &c, TripleFunction &func, bool newton3); | ||
117 | template <typename T> double iterate(T &func, bool newton3, bool parallel); | ||
118 | |||
119 | public: | ||
120 | ArrayI cellCount; | ||
121 | Vec cellL; | ||
122 | Cells cells; | ||
123 | |||
124 | CellNeighborInteraction(System *system, const YAML::Node &config); | ||
125 | |||
126 | double iteratePairs(Particle &p, PairFunction &func); | ||
127 | double iterateTriples(Particle &p, TripleFunction &func); | ||
128 | double iteratePairs(PairFunction &func, bool newton3, bool parallel = true); | ||
129 | double iterateTriples(TripleFunction &func, bool newton3, bool parallel = true); | ||
130 | |||
131 | void updateParticleMeta(Particle &p, | ||
132 | ParticleUpdateType particleUpdateType = ParticleUpdateType::MOVE); | ||
133 | void updateMeta(); | ||
134 | }; | ||
135 | |||
136 | class InteractionFactory { | ||
137 | public: | ||
138 | static Interaction *create(System *system, const YAML::Node &config); | ||
139 | }; | ||
140 |