PURIFY
Next-generation radio interferometric imaging
integration.cc
Go to the documentation of this file.
1 #include "purify/config.h"
2 #include "purify/types.h"
3 #include <iostream>
4 #include "catch2/catch_all.hpp"
5 #include "purify/directories.h"
6 #include "purify/logging.h"
7 
8 #include "purify/integration.h"
9 #include "purify/kernels.h"
10 using namespace purify;
11 
12 TEST_CASE("integration") {
13  const t_uint max_evaluations = 1000;
14  std::function<t_real(Vector<t_real>)> func;
15  std::function<t_complex(Vector<t_real>)> cfunc;
16  for (auto int_method : {integration::method::p, integration::method::h}) {
17  SECTION("1d") {
18  const t_uint ndim = 1;
19  const Vector<t_real> xmin = -Vector<t_real>::Ones(ndim);
20  const Vector<t_real> xmax = Vector<t_real>::Ones(ndim);
21  func = [=](const Vector<t_real> &x) {
22  assert(x.size() == ndim);
23  return (x.array() * x.array()).sum();
24  };
25  cfunc = [=](const Vector<t_real> &x) {
26  assert(x.size() == ndim);
27  return (x.array() * x.array()).sum();
28  };
29  const t_real result = integration::integrate(xmin, xmax, func, integration::norm_type::l2,
30  1e-4, 1e-4, max_evaluations, int_method);
31  const t_complex cresult =
32  integration::integrate(xmin, xmax, cfunc, integration::norm_type::paired, 1e-4, 1e-4,
33  max_evaluations, integration::method::p);
34  CAPTURE(result);
35  CAPTURE(cresult);
36  CHECK(std::abs(result - ndim * std::pow(2, ndim - 1) * 2. / 3) < 1e-4);
37  CHECK(std::abs(cresult - ndim * std::pow(2, ndim - 1) * 2. / 3) < 1e-4);
38  }
39  SECTION("2d") {
40  const t_uint ndim = 2;
41  const Vector<t_real> xmin = -Vector<t_real>::Ones(ndim);
42  const Vector<t_real> xmax = Vector<t_real>::Ones(ndim);
43  func = [=](const Vector<t_real> &x) {
44  assert(x.size() == ndim);
45  return (x.array() * x.array()).sum();
46  };
47  cfunc = [=](const Vector<t_real> &x) {
48  assert(x.size() == ndim);
49  return (x.array() * x.array()).sum();
50  };
51  const t_real result = integration::integrate(xmin, xmax, func, integration::norm_type::l2,
52  1e-4, 1e-4, max_evaluations, int_method);
53  const t_complex cresult =
54  integration::integrate(xmin, xmax, cfunc, integration::norm_type::paired, 1e-4, 1e-4,
55  max_evaluations, int_method);
56  CAPTURE(result);
57  CAPTURE(cresult);
58  CHECK(std::abs(result - ndim * std::pow(2, ndim - 1) * 2. / 3) < 1e-4);
59  CHECK(std::abs(cresult - ndim * std::pow(2, ndim - 1) * 2. / 3) < 1e-4);
60  }
61  SECTION("3d") {
62  const t_uint ndim = 3;
63  const Vector<t_real> xmin = -Vector<t_real>::Ones(ndim);
64  const Vector<t_real> xmax = Vector<t_real>::Ones(ndim);
65  func = [=](const Vector<t_real> &x) {
66  assert(x.size() == ndim);
67  return (x.array() * x.array()).sum();
68  };
69  cfunc = [=](const Vector<t_real> &x) {
70  assert(x.size() == ndim);
71  return (x.array() * x.array()).sum();
72  };
73  const t_real result = integration::integrate(xmin, xmax, func, integration::norm_type::l2,
74  1e-4, 1e-4, max_evaluations, int_method);
75  const t_complex cresult =
76  integration::integrate(xmin, xmax, cfunc, integration::norm_type::paired, 1e-4, 1e-4,
77  max_evaluations, integration::method::p);
78  CAPTURE(result);
79  CAPTURE(cresult);
80  CHECK(std::abs(result - ndim * std::pow(2, ndim - 1) * 2. / 3) < 1e-4);
81  CHECK(std::abs(cresult - ndim * std::pow(2, ndim - 1) * 2. / 3) < 1e-4);
82  }
83  }
84 }
85 
86 TEST_CASE("complex") {
87  const t_uint max_evaluations = 100000;
88  std::function<t_complex(Vector<t_real>)> cfunc1;
89  for (auto int_method : {integration::method::p, integration::method::h}) {
90  SECTION("Fourier Series") {
91  const t_uint ndim = 1;
92  const Vector<t_real> xmin = -Vector<t_real>::Ones(ndim) * constant::pi;
93  const Vector<t_real> xmax = Vector<t_real>::Ones(ndim) * constant::pi;
94  const t_real n = 1.;
95  const t_complex I(0., 1.);
96  cfunc1 = [=](const Vector<t_real> &x) {
97  assert(x.size() == ndim);
98  return (x(0) >= 0) ? std::exp(I * n * x(0)) * 1. / 2. : -std::exp(I * n * x(0)) * 1. / 2.;
99  };
100  const t_complex cresult = integration::integrate(
101  xmin, xmax, cfunc1, integration::norm_type::l2, 1e-6, 1e-6, max_evaluations, int_method);
102  CAPTURE(cresult);
103  CHECK(std::abs(cresult - t_complex(0., 2.)) / 2. < 1e-4);
104  }
105  SECTION("Fourier Series omp") {
106  const t_uint ndim = 1;
107  const Vector<t_real> xmin = -Vector<t_real>::Ones(ndim) * constant::pi;
108  const Vector<t_real> xmax = Vector<t_real>::Ones(ndim) * constant::pi;
109  const t_real n = 1.;
110  const t_complex I(0., 1.);
111  std::vector<std::function<t_complex(Vector<t_real>)>> funcs;
112  for (int i = 0; i < 4; i++) {
113  funcs.push_back([=](const Vector<t_real> &x) -> t_complex {
114  assert(x.size() == ndim);
115  return ((x(0) >= 0) ? std::exp(I * n * x(0)) * 1. / 2.
116  : -std::exp(I * n * x(0)) * 1. / 2.) *
117  (i + 1.);
118  });
119  }
120 #pragma omp parallel for
121  for (int i = 0; i < funcs.size(); i++) {
122  const t_complex cresult =
123  integration::integrate(xmin, xmax, funcs.at(i), integration::norm_type::l2, 1e-6, 1e-6,
124  max_evaluations, int_method);
125  CAPTURE(cresult);
126  CHECK(std::abs(cresult - t_complex(0., 2. * static_cast<t_real>(i + 1))) /
127  (2. * static_cast<t_real>(i + 1)) <
128  1e-4);
129  }
130  }
131  }
132 }
133 
134 TEST_CASE("Numerical_Fourier_transform") {
135  const t_uint max_evaluations = 1e7;
136  const t_uint J = 4;
137  const t_real w = 10;
138  const t_real u = 10;
139  const t_real v = 10;
140  std::function<t_complex(Vector<t_real>)> cfunc;
141  const t_uint ndim = 2;
142  const Vector<t_real> xmin = Vector<t_real>::Zero(ndim);
143  Vector<t_real> xmax = Vector<t_real>::Ones(ndim);
144  xmax(0) = 0.99;
145  xmax(1) = 2 * constant::pi;
146  t_real width = 1.;
147  const t_complex I(0., 1.);
148  t_uint evals = 0;
149  cfunc = [=, &evals](const Vector<t_real> &x) -> t_complex {
150  assert(x.size() == ndim);
151  evals++;
152  return std::exp(-2 * constant::pi * I *
153  (x(0) * std::cos(x(1)) * u + x(0) * std::sin(x(1)) * v +
154  w * (std::sqrt(1 - std::pow(x(0), 2)) - 1))) *
155  x(0) / std::sqrt(1 - std::pow(x(0), 2)) / (2 * constant::pi);
156  };
157  const t_complex cresult =
158  integration::integrate(xmin, xmax, cfunc, integration::norm_type::paired, 1e-5, 1e-5,
159  max_evaluations, integration::method::p);
160  CAPTURE(cresult);
161  CAPTURE(evals);
162  CHECK(std::abs(cresult - t_complex(0.007601618963237, -0.003167113583181)) / std::abs(cresult) <
163  1e-6);
164 }
#define CHECK(CONDITION, ERROR)
Definition: casa.cc:6
const std::vector< t_real > u
data for u coordinate
Definition: operators.cc:18
const std::vector< t_real > v
data for v coordinate
Definition: operators.cc:20
const t_real pi
mathematical constant
Definition: types.h:70
t_real integrate(const Vector< t_real > &xmin, const Vector< t_real > &xmax, const std::function< t_real(Vector< t_real >)> &func, const norm_type norm, const t_real required_abs_error, const t_real required_rel_error, const t_uint max_evaluations, const method methodtype)
adaptive integration with cubature for real scalar to vector
Definition: integration.cc:7
TEST_CASE("integration")
Definition: integration.cc:12