/home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/physics/integration/lattice/integrator_lat_2d.hh Source File#

DiFfRG: /home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/physics/integration/lattice/integrator_lat_2d.hh Source File
DiFfRG
integrator_lat_2d.hh
Go to the documentation of this file.
1#pragma once
2
3// DiFfRG
5
6// standard libraries
7#include <array>
8
9namespace DiFfRG
10{
11 template <typename NT, typename KERNEL, typename ExecutionSpace> class IntegratorLat2D
12 {
13 public:
17 using ctype = typename get_type::ctype<NT>;
18 using execution_space = ExecutionSpace;
19
20 IntegratorLat2D(const std::array<uint, 2> grid_size, const std::array<ctype, 2> a, bool q0_symmetric = false)
22 {
23 if (grid_size[0] % 2 != 0) throw std::runtime_error("IntegratorLat2D: Grid size must be even");
24 if (grid_size[1] % 2 != 0) throw std::runtime_error("IntegratorLat2D: Grid size must be even");
25 }
26
27 void set_a(const std::array<ctype, 2> a) { this->a = a; }
28 void set_q0_symmetric(bool symmetric) { this->q0_symmetric = symmetric; }
29
30 template <typename... T> void get(NT &dest, const T &...t) const
31 {
32 // create an execution space
33 ExecutionSpace space;
34
35 Kokkos::View<NT, typename ExecutionSpace::memory_space> result(Kokkos::view_alloc(space, "result"));
36
37 get(space, result, t...);
38 space.fence();
39
40 auto result_host = Kokkos::create_mirror_view(result);
41 Kokkos::deep_copy(space, result_host, result);
42 dest = result_host();
43 }
44
45 template <typename OT, typename... T>
46 requires(!std::is_same_v<OT, NT>)
47 void get(OT &dest, const T &...t) const
48 {
49 ExecutionSpace space;
50 get(space, dest, t...);
51 }
52
53 template <typename OT, typename... T>
54 requires(!std::is_same_v<OT, NT>)
55 void get(ExecutionSpace &space, OT &dest, const T &...t) const
56 {
57 const auto args = std::make_tuple(t...);
58
59 const ctype fac = powr<-1>(a[0] * (ctype)grid_size[0]) * powr<-1>(a[1] * (ctype)grid_size[1]);
60
61 const uint q0_mult = (q0_symmetric ? 2 : 1);
62
63 const ctype x0fac = 2 * M_PI / (ctype)grid_size[0] / a[0];
64 const ctype x1fac = 2 * M_PI / (ctype)grid_size[1] / a[1];
65 const auto x0size = grid_size[0] / q0_mult;
66 const auto &x1size = grid_size[1];
67
68 Kokkos::parallel_reduce(
69 "integral_lat_2D", // name of the kernel
70 Kokkos::MDRangePolicy<ExecutionSpace, Kokkos::Rank<2>>(space, {0, 0}, {x0size, x1size / 2}),
71 KOKKOS_LAMBDA(const uint idx_x0, const uint idx_x1, NT &update) {
72 const ctype q0 = x0fac * idx_x0;
73 const ctype q1 = x1fac * idx_x1;
74 const NT result = std::apply([&](const auto &...args) { return KERNEL::kernel(q0, q1, args...); }, args);
75 update += q0_mult * 2 * fac * result;
76 },
77 SumPlus<NT, NT, ExecutionSpace>(dest, KERNEL::constant(t...)));
78 }
79
80 template <typename view_type, typename Coordinates, typename... Args>
81 void map(ExecutionSpace &space, const view_type integral_view, const Coordinates &coordinates, const Args &...args)
82 {
83 const auto m_args = std::make_tuple(args...);
84
85 using TeamPolicy = Kokkos::TeamPolicy<ExecutionSpace>;
86 using TeamType = Kokkos::TeamPolicy<ExecutionSpace>::member_type;
87
88 const ctype fac = powr<-1>(a[0] * (ctype)grid_size[0]) * powr<-1>(a[1] * (ctype)grid_size[1]);
89
90 const uint q0_mult = (q0_symmetric ? 2 : 1);
91
92 const ctype x0fac = 2 * M_PI / (ctype)grid_size[0] / a[0];
93 const ctype x1fac = 2 * M_PI / (ctype)grid_size[1] / a[1];
94 const auto x0size = grid_size[0] / q0_mult;
95 const auto &x1size = grid_size[1];
96
97 Kokkos::parallel_for(
98 Kokkos::TeamPolicy(space, integral_view.size(), Kokkos::AUTO), KOKKOS_LAMBDA(const TeamType &team) {
99 // get the current (continuous) index
100 const uint k = team.league_rank();
101 // make subview
102 auto subview = Kokkos::subview(integral_view, k);
103 // get the position for the current index
104 const auto idx = coordinates.from_linear_index(k);
105 const auto pos = coordinates.forward(idx);
106
107 const auto full_args = std::tuple_cat(pos, m_args);
108
109 NT res = 0;
110 Kokkos::parallel_reduce(
111 Kokkos::TeamThreadMDRange(team, x0size, x1size / 2), // range of the kernel
112 [&](const uint idx_x0, const uint idx_x1, NT &update) {
113 const ctype q0 = x0fac * idx_x0;
114 const ctype q1 = x1fac * idx_x1;
115 const NT result =
116 std::apply([&](const auto &...iargs) { return KERNEL::kernel(q0, q1, iargs...); }, full_args);
117 update += q0_mult * 2 * fac * result;
118 },
119 res);
120
121 // add the constant value
122 team.team_barrier();
123 Kokkos::single(Kokkos::PerTeam(team), [=]() {
124 subview() = res + std::apply([&](const auto &...iargs) { return KERNEL::constant(iargs...); }, full_args);
125 });
126 });
127 }
128
129 template <typename Coordinates, typename... Args>
130 auto map(NT *dest, const Coordinates &coordinates, const Args &...args)
131 {
132 // create an execution space
133 ExecutionSpace space;
134
135 // create unmanaged host view for dest
136 auto dest_view = Kokkos::View<NT *, CPU_memory, Kokkos::MemoryUnmanaged>(dest, coordinates.size());
137
138 // create device view for dest
139 auto dest_device_view = Kokkos::View<NT *, ExecutionSpace>(
140 Kokkos::view_alloc(space, "MapIntegrators_device_view"), coordinates.size());
141
142 // run the map function
143 map(space, dest_device_view, coordinates, args...);
144
145 // copy the result from device to host
146 auto dest_host_view = Kokkos::create_mirror_view(space, dest_device_view);
147 Kokkos::deep_copy(space, dest_host_view, dest_device_view);
148
149 // copy the result from the mirror to the requested destination
150 Kokkos::deep_copy(space, dest_view, dest_host_view);
151
152 return std::move(space);
153 }
154
155 const std::array<uint, 2> grid_size;
156
157 private:
158 std::array<ctype, 2> a;
160 };
161} // namespace DiFfRG
Definition integrator_lat_2d.hh:12
void set_q0_symmetric(bool symmetric)
Definition integrator_lat_2d.hh:28
void map(ExecutionSpace &space, const view_type integral_view, const Coordinates &coordinates, const Args &...args)
Definition integrator_lat_2d.hh:81
void get(OT &dest, const T &...t) const
Definition integrator_lat_2d.hh:47
std::array< ctype, 2 > a
Definition integrator_lat_2d.hh:158
IntegratorLat2D(const std::array< uint, 2 > grid_size, const std::array< ctype, 2 > a, bool q0_symmetric=false)
Definition integrator_lat_2d.hh:20
auto map(NT *dest, const Coordinates &coordinates, const Args &...args)
Definition integrator_lat_2d.hh:130
typename get_type::ctype< NT > ctype
Numerical type to be used for integration tasks e.g. the argument or possible jacobians.
Definition integrator_lat_2d.hh:17
ExecutionSpace execution_space
Definition integrator_lat_2d.hh:18
bool q0_symmetric
Definition integrator_lat_2d.hh:159
void set_a(const std::array< ctype, 2 > a)
Definition integrator_lat_2d.hh:27
const std::array< uint, 2 > grid_size
Definition integrator_lat_2d.hh:155
void get(NT &dest, const T &...t) const
Definition integrator_lat_2d.hh:30
void get(ExecutionSpace &space, OT &dest, const T &...t) const
Definition integrator_lat_2d.hh:55
typename internal::_ctype< CT >::value ctype
Definition types.hh:134
Definition complex_math.hh:10
unsigned int uint
Definition utils.hh:24
An extension of the Kokkos::Sum reducer that adds a constant value to the result.
Definition kokkos.hh:66