| 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 | 23303 | double external(Particle &p) { | |
| 35 | 23303 | p.Eext = 0.; | |
| 36 | 
        2/2✓ Branch 0 taken 8948 times. 
          ✓ Branch 1 taken 23303 times. 
         | 
      32251 | for (External *e : externals) { | 
| 37 | 8948 | p.Eext += (*e)(p); | |
| 38 | } | ||
| 39 | 23303 | return p.Eext; | |
| 40 | } | ||
| 41 | |||
| 42 | virtual double | ||
| 43 | 4947 | updateParticleState(Particle &p, | |
| 44 | ParticleUpdateType particleUpdateType = ParticleUpdateType::MOVE) { | ||
| 45 | 
        1/2✗ Branch 0 not taken. 
          ✓ Branch 1 taken 4947 times. 
         | 
      4947 | if (internal->needsGather()) { | 
| 46 | ✗ | throw std::runtime_error("Interactions that need gathering cannot use updateParticleState"); | |
| 47 | } | ||
| 48 | 4947 | updateParticleMeta(p, particleUpdateType); | |
| 49 | 4947 | double E = 0.; | |
| 50 | 4947 | E = external(p); | |
| 51 | 4947 | bool newton3Restore = internal->newton3; | |
| 52 | 4947 | internal->newton3 = false; | |
| 53 | 4947 | E += iteratePairs(p, *internal); | |
| 54 | 
        2/2✓ Branch 0 taken 2977 times. 
          ✓ Branch 1 taken 1970 times. 
         | 
      4947 | if (internal->threebody()) { | 
| 55 | 2977 | E += iterateTriples(p, *internal); | |
| 56 | } | ||
| 57 | 4947 | internal->newton3 = newton3Restore; | |
| 58 | 4947 | return E; | |
| 59 | } | ||
| 60 | |||
| 61 | 4597 | virtual void updateState() { | |
| 62 | 4597 | updateMeta(); | |
| 63 | 4597 | int n = particles.size(); | |
| 64 | 4597 | bool newton3 = internal->newton3; | |
| 65 | 4597 | double Eext = 0.; | |
| 66 | 4597 | #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 | 4597 | double Eint = 0.; | |
| 72 | 4597 | internal->reset(); | |
| 73 | 4597 | Eint += iteratePairs(*internal, newton3); | |
| 74 | 
        2/2✓ Branch 0 taken 658 times. 
          ✓ Branch 1 taken 3939 times. 
         | 
      4597 | if (internal->needsGather()) { | 
| 75 | 658 | internal->gather = true; | |
| 76 | 658 | double Egather = 0.; | |
| 77 | 658 | #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 658 times. 
         | 
      658 | if (!newton3) { | 
| 82 | // There is no double counting in this term, so compensate for the correction below | ||
| 83 | ✗ | Egather *= 2; | |
| 84 | } | ||
| 85 | 658 | Eint += Egather; | |
| 86 | 658 | Eint += iteratePairs(*internal, newton3); | |
| 87 | 658 | internal->gather = false; | |
| 88 | } | ||
| 89 | 
        2/2✓ Branch 0 taken 649 times. 
          ✓ Branch 1 taken 3948 times. 
         | 
      4597 | if (internal->threebody()) { | 
| 90 | 649 | double Etriples = iterateTriples(*internal, newton3); | |
| 91 | 
        2/2✓ Branch 0 taken 9 times. 
          ✓ Branch 1 taken 640 times. 
         | 
      649 | if (!newton3) { | 
| 92 | // There is no double counting in this term, so compensate for the correction below | ||
| 93 | 9 | Etriples *= 2; | |
| 94 | } | ||
| 95 | 649 | Eint += Etriples; | |
| 96 | } | ||
| 97 | 
        2/2✓ Branch 0 taken 16 times. 
          ✓ Branch 1 taken 4581 times. 
         | 
      4597 | if (!newton3) { | 
| 98 | // Account for double counting in energy | ||
| 99 | 16 | Eint *= 0.5; | |
| 100 | } | ||
| 101 | 4597 | system->E = Eext + Eint; | |
| 102 | 4597 | } | |
| 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 |