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