7 Vector<t_real>
const &w, t_int
const number_of_nodes,
9 t_int
const &grid_size) {
11 Vector<t_int> index = Vector<t_int>::LinSpaced(
u.size(), 0,
u.size());
12 t_int
const partition_size =
13 std::ceil(
static_cast<t_real
>(
u.size()) /
static_cast<t_real
>(number_of_nodes));
15 std::string plan_name =
"";
16 switch (distribution_plan) {
37 throw std::runtime_error(
"Distribution plan not recognised or implimented.");
42 "Using {} to make {} partitions from {} visibilities, with {} visibilities per a node.",
43 plan_name, number_of_nodes, index.size(), partition_size);
44 std::vector<t_int> partitions(
u.size());
45 if (std::floor(
static_cast<t_real
>(index.size() - 1) /
static_cast<t_real
>(partition_size)) >
46 number_of_nodes - 1) {
47 PURIFY_ERROR(
"Error: Probably a bug in distribution plan.");
48 throw std::runtime_error(
"Distributing data into too many nodes");
51 for (t_int i = 0; i < index.size(); ++i) {
52 partitions[index(i)] = std::floor(
static_cast<t_real
>(i) /
static_cast<t_real
>(partition_size));
58 Vector<t_real>
const &w) {
64 Vector<t_int> index = Vector<t_int>::LinSpaced(w.size(), 0, w.size());
65 std::sort(index.data(), index.data() + index.size(), [&w](
int a,
int b) { return w(a) < w(b); });
71 Vector<t_int> index = Vector<t_int>::LinSpaced(
u.size(), 0,
u.size());
72 std::sort(index.data(), index.data() + index.size(), [&
u, &
v](
int a,
int b) {
73 return std::sqrt(u(a) * u(a) + v(a) * v(a)) < std::sqrt(u(b) * u(b) + v(b) * v(b));
79 t_int
const &grid_size) {
81 t_real
const max_u =
u.array().maxCoeff();
82 t_real
const max_v =
v.array().maxCoeff();
83 t_real
const min_u =
u.array().minCoeff();
84 t_real
const min_v =
v.array().minCoeff();
86 Vector<t_real>
const scaled_u = (
u.array() - min_u) * (grid_size - 1) / (max_u - min_u);
87 Vector<t_real>
const scaled_v = (
v.array() - min_v) * (grid_size - 1) / (max_v - min_v);
88 Image<t_int> histogram = Image<t_int>::Zero(grid_size, grid_size);
89 Vector<t_int> index = Vector<t_int>::LinSpaced(
u.size(), 0,
u.size());
91 for (t_int i = 0; i < index.size(); i++) {
92 histogram((t_int)std::floor(scaled_u(i)), (t_int)std::floor(scaled_v(i))) += 1;
95 std::sort(index.data(), index.data() + index.size(),
96 [&histogram, &scaled_u, &scaled_v](
int a,
int b) {
97 return (histogram((t_int)std::floor(scaled_u(a)), (t_int)std::floor(scaled_v(a))) <
98 histogram((t_int)std::floor(scaled_u(b)), (t_int)std::floor(scaled_v(b))));
104 const Vector<t_real> &w,
const t_int number_of_nodes,
const t_int iters,
105 const std::function<t_real(t_real)> &cost,
const t_real rel_diff) {
106 std::vector<t_int> w_node(w.size(), 0);
107 std::vector<t_real> w_centre(number_of_nodes, 0);
108 std::vector<t_real> w_sum(number_of_nodes, 0);
109 std::vector<t_real> w_count(number_of_nodes, 0);
111 t_real
const wmin = w.minCoeff();
112 t_real
const wmax = w.maxCoeff();
115 for (
int i = 0; i < w_centre.size(); i++)
116 w_centre[i] = (i * (wmax - wmin) / number_of_nodes + wmin);
118 for (
int n = 0; n < iters; n++) {
120 for (
int i = 0; i < w.size(); i++) {
121 t_real min = 2 * cost(wmax - wmin);
122 for (
int node = 0; node < number_of_nodes; node++) {
123 const t_real cost_val = cost(w(i) - w_centre.at(node));
124 if (cost_val < min) {
129 w_sum[w_node.at(i)] += w(i);
130 w_count[w_node.at(i)]++;
132 for (
int j = 0; j < number_of_nodes; j++) {
133 diff += std::abs(((w_count.at(j) > 0) ? w_sum.at(j) / w_count.at(j) : 0) - w_centre.at(j)) /
134 std::abs(w_centre.at(j) * number_of_nodes);
135 w_centre[j] = (w_count.at(j) > 0) ? w_sum.at(j) / w_count.at(j) : 0;
136 PURIFY_DEBUG(
"Node {} has {} visibilities, using w-stack w = {}.", j, w_count.at(j),
141 if (diff < rel_diff) {
150 return std::make_tuple(w_node, w_centre);
154 std::tuple<std::vector<t_int>, std::vector<t_real>>
kmeans_algo(
155 const Vector<t_real> &w,
const t_int number_of_nodes,
const t_int iters,
156 sopt::mpi::Communicator
const &comm,
const std::function<t_real(t_real)> &cost,
157 const t_real rel_diff) {
158 std::vector<t_int> w_node(w.size(), 0);
159 std::vector<t_real> w_centre(number_of_nodes, 0);
160 std::vector<t_real> w_sum(number_of_nodes, 0);
161 std::vector<t_real> w_count(number_of_nodes, 0);
163 t_real
const wmin = comm.all_reduce<t_real>(w.minCoeff(), MPI_MIN);
164 t_real
const wmax = comm.all_reduce<t_real>(w.maxCoeff(), MPI_MAX);
167 for (
int i = 0; i < w_centre.size(); i++)
169 (
static_cast<t_real
>(i) * (wmax - wmin) /
static_cast<t_real
>(number_of_nodes) + wmin);
171 for (
int n = 0; n < iters; n++) {
172 if (comm.is_root())
PURIFY_DEBUG(
"clustering iteration {}", n);
173 for (
int i = 0; i < w.size(); i++) {
174 t_real min = 2 * cost(wmax - wmin);
175 for (
int node = 0; node < number_of_nodes; node++) {
176 const t_real cost_val = cost(w(i) - w_centre.at(node));
177 if (cost_val < min) {
182 w_sum[w_node.at(i)] += w(i);
183 w_count[w_node.at(i)]++;
185 for (
int j = 0; j < number_of_nodes; j++) {
186 const t_real global_w_sum = comm.all_sum_all<t_real>(w_sum.at(j));
187 const t_real global_w_count = comm.all_sum_all<t_real>(w_count.at(j));
189 std::abs(((global_w_count > 0) ? global_w_sum / global_w_count : 0) - w_centre.at(j)) /
190 std::abs(w_centre.at(j) * number_of_nodes);
191 w_centre[j] = (global_w_count > 0) ? global_w_sum / global_w_count : 0;
193 PURIFY_DEBUG(
"Node {} has {} visibilities, using w-stack w = {}.", j, global_w_count,
198 if (diff < rel_diff) {
202 if (comm.is_root())
PURIFY_DEBUG(
"relative_diff = {}", diff);
207 return std::make_tuple(w_node, w_centre);
210 std::vector<t_int>
w_support(Vector<t_real>
const &w,
const std::vector<t_int> &image_index,
211 const std::vector<t_real> &w_stacks,
const t_real du,
212 const t_int min_support,
const t_int max_support,
213 const t_real fill_relaxation, sopt::mpi::Communicator
const &comm) {
214 t_real coeff_total = 0;
215 for (t_int i = 0; i < w.size(); i++)
217 min_support, max_support) *
219 min_support, max_support);
220 const t_real coeff_average =
221 comm.all_sum_all<t_real>(coeff_total) /
static_cast<t_real
>(comm.size());
222 if (comm.is_root()) {
223 PURIFY_DEBUG(
"Each node should have on average {} coefficients.", coeff_average);
225 t_real coeff_sum = 0;
227 std::vector<t_int> groups(w.size(), comm.rank());
228 std::vector<t_int> coeffs(comm.size(), comm.rank());
229 long long int total = 0;
230 for (t_int rank = 0; rank < comm.size(); rank++) {
231 const auto size = comm.broadcast(w.size(), rank);
232 for (t_int i = 0; i < size; i++) {
233 if (comm.rank() == rank) {
235 min_support, max_support) *
237 min_support, max_support);
239 if (group < (comm.size() - 1))
240 if ((cost + coeff_sum) > coeff_average * (1. + fill_relaxation)) {
241 PURIFY_DEBUG(
"{} node should have {} coefficients.", group, coeff_sum);
249 if (group > comm.size() - 1) {
250 throw std::runtime_error(
251 "Error distributing visibilites to even computational load for wide field imaging. Group "
252 "number out of bounds.");
254 coeff_sum = comm.broadcast(coeff_sum, rank);
255 group = comm.broadcast(group, rank);
257 if (total != coeff_total and comm.rank() == rank) {
258 throw std::runtime_error(
259 "Total number of coefficients calculated is not the same, loop might be broken. " +
260 std::to_string(total) +
" != " + std::to_string(coeff_total));
263 if (comm.is_root())
PURIFY_DEBUG(
"{} node should have {} coefficients.", group, coeff_sum);
#define PURIFY_ERROR(...)
\macro Something is definitely wrong, algorithm exits
#define PURIFY_DEBUG(...)
\macro Output some debugging
const std::vector< t_real > u
data for u coordinate
const std::vector< t_real > v
data for v coordinate
Vector< t_int > w_distribution(const Vector< t_real > &u, const Vector< t_real > &v, Vector< t_real > const &w)
Distribute visibilities into nodes in order of w terms (useful for w-stacking)
std::tuple< std::vector< t_int >, std::vector< t_real > > kmeans_algo(const Vector< t_real > &w, const t_int number_of_nodes, const t_int iters, const std::function< t_real(t_real)> &cost, const t_real rel_diff)
patition w terms using k-means
Vector< t_int > equal_distribution(Vector< t_real > const &u, Vector< t_real > const &v, t_int const &grid_size)
Distribute the visiblities into nodes in order of density.
std::vector< t_int > distribute_measurements(Vector< t_real > const &u, Vector< t_real > const &v, Vector< t_real > const &w, t_int const number_of_nodes, distribute::plan const distribution_plan, t_int const &grid_size)
Distribute visiblities into groups.
Vector< t_int > distance_distribution(Vector< t_real > const &u, Vector< t_real > const &v)
Distribute visiblities into nodes in order of distance from the centre.
t_int w_support(const t_real w, const t_real du, const t_int min, const t_int max)
estimate support size of w given u resolution du