Loading...
Searching...
No Matches
GroupSchedule.h
Go to the documentation of this file.
1/*
2** This file is part of eOn.
3**
4** SPDX-License-Identifier: BSD-3-Clause
5**
6** Copyright (c) 2010--present, eOn Development Team
7** All rights reserved.
8**
9** Repo:
10** https://github.com/TheochemUI/eOn
11*/
12#pragma once
13
14#include "eon/PbcSimd.h"
15
16#include <algorithm>
17#include <cstddef>
18#include <cstdint>
19#include <limits>
20#include <map>
21#include <vector>
22
23namespace eonc {
24
40public:
41 explicit GroupSchedule(int groups) : groups_{std::max(groups, 1)} {}
42
43 [[nodiscard]] int groups() const noexcept { return groups_; }
44
47 [[nodiscard]] int defaultHome(std::int64_t key, long position) const {
48 const std::int64_t base = key >= 0 ? key : position;
49 return static_cast<int>(((base % groups_) + groups_) % groups_);
50 }
51
53 [[nodiscard]] std::vector<int> assign(const std::vector<std::int64_t> &keys) {
54 const long m = static_cast<long>(keys.size());
55 const long cap = (m + groups_ - 1) / groups_;
56 std::vector<long> load(static_cast<size_t>(groups_), 0);
57 std::vector<int> route(static_cast<size_t>(m), -1);
58 for (long j = 0; j < m; ++j) {
59 const int home = homeOf(keys[static_cast<size_t>(j)], j);
60 if (load[static_cast<size_t>(home)] < cap) {
61 route[static_cast<size_t>(j)] = home;
62 ++load[static_cast<size_t>(home)];
63 }
64 }
65 for (long j = 0; j < m; ++j) {
66 if (route[static_cast<size_t>(j)] >= 0)
67 continue;
68 const auto least = std::min_element(load.begin(), load.end());
69 const int g = static_cast<int>(least - load.begin());
70 route[static_cast<size_t>(j)] = g;
71 ++*least;
72 }
73 for (long j = 0; j < m; ++j)
74 home_[keys[static_cast<size_t>(j)]] = route[static_cast<size_t>(j)];
75 return route;
76 }
77
79 void record(std::int64_t key, const double *positions, long n3,
80 const double *cell = nullptr) {
81 auto &stored = last_[key];
82 stored.assign(positions, positions + n3);
83 if (cell)
84 cells_[key].assign(cell, cell + 9);
85 else
86 cells_.erase(key);
87 }
88
92 [[nodiscard]] int nearest(const double *positions, long n3,
93 const double *cell = nullptr) const {
94 double best = std::numeric_limits<double>::infinity();
95 int group = 0;
96 for (const auto &[key, stored] : last_) {
97 if (static_cast<long>(stored.size()) != n3)
98 continue;
99 const auto recordedCell = cells_.find(key);
100 if (cell && recordedCell != cells_.end() &&
101 !std::equal(recordedCell->second.begin(), recordedCell->second.end(),
102 cell))
103 continue;
104 std::vector<double> differences(static_cast<size_t>(n3));
105 for (long i = 0; i < n3; ++i) {
106 differences[static_cast<size_t>(i)] =
107 stored[static_cast<size_t>(i)] - positions[i];
108 }
109 if (cell &&
110 std::any_of(cell, cell + 9, [](double x) { return x != 0.0; }))
111 pbc::closestDisplacements(differences.data(), differences.size(), cell);
112 double d2 = 0.0;
113 for (double d : differences)
114 d2 += d * d;
115 const auto home = home_.find(key);
116 if (d2 < best && home != home_.end()) {
117 best = d2;
118 group = home->second;
119 }
120 }
121 return group;
122 }
123
125 void settle(std::int64_t key, int group) { home_[key] = group; }
126
127private:
128 [[nodiscard]] int homeOf(std::int64_t key, long position) const {
129 const auto it = home_.find(key);
130 return it != home_.end() ? it->second : defaultHome(key, position);
131 }
132
134 std::map<std::int64_t, int> home_;
135 std::map<std::int64_t, std::vector<double>> last_;
136 std::map<std::int64_t, std::vector<double>> cells_;
137};
138
139} // namespace eonc
std::map< std::int64_t, std::vector< double > > cells_
int groups() const noexcept
std::vector< int > assign(const std::vector< std::int64_t > &keys)
Groups for a batch of systems with these keys.
int nearest(const double *positions, long n3, const double *cell=nullptr) const
The group for a single request: the home of the recorded geometry nearest to positions (root-mean-squ...
int homeOf(std::int64_t key, long position) const
std::map< std::int64_t, int > home_
int defaultHome(std::int64_t key, long position) const
The home of a key never seen: key mod G for a key of zero or more, the batch position mod G otherwise...
void settle(std::int64_t key, int group)
A single request's group becomes the home of the single-request key.
std::map< std::int64_t, std::vector< double > > last_
void record(std::int64_t key, const double *positions, long n3, const double *cell=nullptr)
Remember the geometry a key was last evaluated at.
GroupSchedule(int groups)
void closestDisplacements(double *data, size_t coordinates, const double *rowMajorCell)
RAII resource manager for the ARTn C library with global synchronization.