DP3
SolveData.h
Go to the documentation of this file.
1 // Copyright (C) 2021 ASTRON (Netherlands Institute for Radio Astronomy)
2 // SPDX-License-Identifier: GPL-3.0-or-later
3 
4 #ifndef DDECAL_SOLVE_DATA_H
5 #define DDECAL_SOLVE_DATA_H
6 
7 #include <cstddef>
8 #include <numeric>
9 #include <vector>
10 
11 #include <aocommon/matrix2x2.h>
12 #include <aocommon/staticfor.h>
13 #include <xtensor/containers/xtensor.hpp>
14 
15 #include "base/DPBuffer.h"
16 
17 namespace dp3 {
18 namespace ddecal {
19 
20 class BdaSolverBuffer;
21 
28 template <typename MatrixType = aocommon::MC2x2F>
29 class SolveData {
30  public:
32  public:
33  using const_iterator = typename std::vector<MatrixType>::const_iterator;
34 
35  void Resize(size_t n_visibilities, size_t n_directions) {
36  data_.resize(n_visibilities);
37  model_data_.resize({n_directions, n_visibilities});
38  antenna_indices_.resize(n_visibilities);
39  n_solutions_.resize(n_directions);
40  solution_map_.resize({n_directions, n_visibilities});
41  }
42  void ResizeWeights(size_t n_visibilities) {
43  constexpr size_t kNCorrelations = 4;
44  weights_.resize({n_visibilities, kNCorrelations});
45  }
46  size_t NDirections() const { return model_data_.shape(0); }
47  size_t NVisibilities() const { return data_.size(); }
51  size_t NAntennaVisibilities(size_t antenna_index) const {
52  return antenna_visibility_counts_[antenna_index];
53  }
63  size_t NSolutionVisibilities(size_t direction_index,
64  uint32_t solution_index) const;
65 
66  uint32_t Antenna1Index(size_t visibility_index) const {
67  return antenna_indices_[visibility_index].first;
68  }
69  uint32_t Antenna2Index(size_t visibility_index) const {
70  return antenna_indices_[visibility_index].second;
71  }
81  uint32_t SolutionIndex(size_t direction_index,
82  size_t visibility_index) const {
83  return solution_map_(direction_index, visibility_index);
84  }
85 
86  const uint32_t* SolutionMapData() const { return solution_map_.data(); }
87 
88  const float& Weight(size_t index) const { return weights_(index, 0); }
89  const MatrixType& Visibility(size_t index) const { return data_[index]; }
90  const MatrixType& ModelVisibility(size_t direction, size_t index) const {
91  return model_data_(direction, index);
92  }
93 
94  const_iterator DataBegin() const { return data_.begin(); }
95  const_iterator DataEnd() const { return data_.end(); }
96 
100  uint32_t NSolutionsForDirection(size_t direction_index) const {
101  return n_solutions_[direction_index];
102  }
103 
108  uint32_t NSubSolutions() const {
109  return std::accumulate(n_solutions_.begin(), n_solutions_.end(),
110  uint32_t(0));
111  }
112 
113  private:
114  friend class SolveData<MatrixType>;
115 
116  std::vector<MatrixType> data_;
117  // weights_(i, pol) contains the weight for data_[i][pol]. The vector will
118  // be left empty when the algorithm does not need the weights.
119  xt::xtensor<float, 2> weights_;
120  // model_data_(d, i) is the model data for direction d, element i
121  xt::xtensor<MatrixType, 2> model_data_;
122  // Element i contains the first and second antenna corresponding with
123  // data_[i] and model_data_(d, i). Using uint32_t instead of size_t reduces
124  // memory usage and improves cache/memory performance (same holds for
125  // n_solutions_ and solution_map_).
126  std::vector<std::pair<uint32_t, uint32_t>> antenna_indices_;
127  std::vector<size_t> antenna_visibility_counts_;
129  std::vector<uint32_t> n_solutions_;
132  xt::xtensor<uint32_t, 2> solution_map_;
133  };
134 
150  SolveData(const std::vector<base::DPBuffer>& buffers,
151  const std::vector<std::string>& direction_names,
152  size_t n_channel_blocks, size_t n_antennas,
153  const std::vector<size_t>& n_solutions_per_direction,
154  const std::vector<int>& antennas1,
155  const std::vector<int>& antennas2);
156 
166  SolveData(const BdaSolverBuffer& buffer, size_t n_channel_blocks,
167  size_t n_antennas,
168  const std::vector<size_t>& n_solutions_per_direction,
169  const std::vector<int>& antennas1,
170  const std::vector<int>& antennas2, bool with_weights);
171 
172  size_t NChannelBlocks() const { return channel_blocks_.size(); }
173 
174  const ChannelBlockData& ChannelBlock(size_t i) const {
175  return channel_blocks_[i];
176  }
177 
186  std::vector<std::vector<double>> GetSolutionWeights() const;
187 
188  private:
189  void CountAntennaVisibilities();
190 
192  std::vector<ChannelBlockData> channel_blocks_;
193  size_t n_antennas_;
194 };
195 
203 
204 template <bool Add, typename MatrixType>
206  const typename SolveData<MatrixType>::ChannelBlockData& cb_data,
207  std::vector<MatrixType>& v_residual, size_t direction, size_t n_solutions,
208  const std::vector<std::complex<double>>& solutions, size_t max_threads) {
209  using DComplex = std::complex<double>;
210  using Complex = std::complex<float>;
211  const size_t n_visibilities = cb_data.NVisibilities();
212  aocommon::RunConstrainedStaticFor<size_t>(
213  0, n_visibilities, max_threads,
214  [&](size_t start_vis_index, size_t end_vis_index) {
215  for (size_t vis_index = start_vis_index; vis_index != end_vis_index;
216  ++vis_index) {
217  const uint32_t antenna_1 = cb_data.Antenna1Index(vis_index);
218  const uint32_t antenna_2 = cb_data.Antenna2Index(vis_index);
219  const uint32_t solution_index =
220  cb_data.SolutionIndex(direction, vis_index);
221  const DComplex* solution_1 =
222  &solutions[(antenna_1 * n_solutions + solution_index) * 2];
223  const DComplex* solution_2 =
224  &solutions[(antenna_2 * n_solutions + solution_index) * 2];
225 
226  MatrixType& data = v_residual[vis_index];
227  const MatrixType& model =
228  cb_data.ModelVisibility(direction, vis_index);
229  // Convert first to single precision to make calculation easier
230  const aocommon::MC2x2FDiag solution_a(
231  static_cast<Complex>(solution_1[0]),
232  static_cast<Complex>(solution_1[1]));
233  const aocommon::MC2x2FDiag solution_b(
234  static_cast<Complex>(solution_2[0]),
235  static_cast<Complex>(solution_2[1]));
236  const MatrixType contribution(solution_a * model *
237  HermTranspose(solution_b));
238  if constexpr (Add)
239  data += contribution;
240  else
241  data -= contribution;
242  }
243  });
244 }
245 
246 extern template class SolveData<std::complex<float>>;
247 extern template class SolveData<aocommon::MC2x2F>;
248 extern template class SolveData<aocommon::MC2x2FDiag>;
249 
250 } // namespace ddecal
251 } // namespace dp3
252 
253 #endif
Buffer holding the data of a timeslot/band.
Definition: BdaSolverBuffer.h:19
void ResizeWeights(size_t n_visibilities)
Definition: SolveData.h:42
uint32_t Antenna1Index(size_t visibility_index) const
Definition: SolveData.h:66
size_t NDirections() const
Definition: SolveData.h:46
const MatrixType & Visibility(size_t index) const
Definition: SolveData.h:89
typename std::vector< MatrixType >::const_iterator const_iterator
Definition: SolveData.h:33
uint32_t SolutionIndex(size_t direction_index, size_t visibility_index) const
Definition: SolveData.h:81
const_iterator DataBegin() const
Definition: SolveData.h:94
uint32_t NSolutionsForDirection(size_t direction_index) const
Definition: SolveData.h:100
uint32_t Antenna2Index(size_t visibility_index) const
Definition: SolveData.h:69
uint32_t NSubSolutions() const
Definition: SolveData.h:108
size_t NVisibilities() const
Definition: SolveData.h:47
size_t NSolutionVisibilities(size_t direction_index, uint32_t solution_index) const
const uint32_t * SolutionMapData() const
Definition: SolveData.h:86
const_iterator DataEnd() const
Definition: SolveData.h:95
const MatrixType & ModelVisibility(size_t direction, size_t index) const
Definition: SolveData.h:90
size_t NAntennaVisibilities(size_t antenna_index) const
Definition: SolveData.h:51
void Resize(size_t n_visibilities, size_t n_directions)
Definition: SolveData.h:35
const float & Weight(size_t index) const
Definition: SolveData.h:88
Definition: SolveData.h:29
std::vector< std::vector< double > > GetSolutionWeights() const
SolveData(const std::vector< base::DPBuffer > &buffers, const std::vector< std::string > &direction_names, size_t n_channel_blocks, size_t n_antennas, const std::vector< size_t > &n_solutions_per_direction, const std::vector< int > &antennas1, const std::vector< int > &antennas2)
SolveData(const BdaSolverBuffer &buffer, size_t n_channel_blocks, size_t n_antennas, const std::vector< size_t > &n_solutions_per_direction, const std::vector< int > &antennas1, const std::vector< int > &antennas2, bool with_weights)
const ChannelBlockData & ChannelBlock(size_t i) const
Definition: SolveData.h:174
size_t NChannelBlocks() const
Definition: SolveData.h:172
void DiagonalAddOrSubtractDirection(const typename SolveData< MatrixType >::ChannelBlockData &cb_data, std::vector< MatrixType > &v_residual, size_t direction, size_t n_solutions, const std::vector< std::complex< double >> &solutions, size_t max_threads)
Definition: SolveData.h:205
This file has generic helper routines for testing steps.
Definition: AntennaConfig.h:53