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

DiFfRG: /home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/physics/integration/lattice/integrator_lat_4d.hh Source File
DiFfRG
integrator_lat_4d.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 IntegratorLat4D
12 {
13 public:
17 using ctype = typename get_type::ctype<NT>;
18 using execution_space = ExecutionSpace;
19
20 IntegratorLat4D(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("IntegratorLat4D: Grid size must be even");
24 if (grid_size[1] % 2 != 0) throw std::runtime_error("IntegratorLat4D: 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<-3>(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_4D", // name of the kernel
70 Kokkos::MDRangePolicy<ExecutionSpace, Kokkos::Rank<4>>(space, {0, 0, 0, 0},
71 {x0size, x1size / 2, x1size / 2, x1size / 2}),
72 KOKKOS_LAMBDA(const uint idx_x0, const uint idx_x1, const uint idx_x2, const uint idx_x3, NT &update) {
73 const ctype q0 = x0fac * idx_x0;
74 const ctype q1 = x1fac * idx_x1;
75 const ctype q2 = x1fac * idx_x2;
76 const ctype q3 = x1fac * idx_x3;
77 const NT result =
78 std::apply([&](const auto &...args) { return KERNEL::kernel(q0, q1, q2, q3, args...); }, args);
79 update += q0_mult * 8 * fac * result;
80 },
81 SumPlus<NT, NT, ExecutionSpace>(dest, KERNEL::constant(t...)));
82 }
83
84 template <typename view_type, typename Coordinates, typename... Args>
85 void map(ExecutionSpace &space, const view_type integral_view, const Coordinates &coordinates, const Args &...args)
86 {
87 const auto m_args = std::make_tuple(args...);
88
89 using TeamPolicy = Kokkos::TeamPolicy<ExecutionSpace>;
90 using TeamType = Kokkos::TeamPolicy<ExecutionSpace>::member_type;
91
92 const ctype fac = powr<-1>(a[0] * (ctype)grid_size[0]) * powr<-3>(a[1] * (ctype)grid_size[1]);
93
94 const uint q0_mult = (q0_symmetric ? 2 : 1);
95
96 const ctype x0fac = 2 * M_PI / (ctype)grid_size[0] / a[0];
97 const ctype x1fac = 2 * M_PI / (ctype)grid_size[1] / a[1];
98 const auto x0size = grid_size[0] / q0_mult;
99 const auto &x1size = grid_size[1];
100
101 Kokkos::parallel_for(
102 Kokkos::TeamPolicy(space, integral_view.size(), Kokkos::AUTO), KOKKOS_LAMBDA(const TeamType &team) {
103 // get the current (continuous) index
104 const uint k = team.league_rank();
105 // make subview
106 auto subview = Kokkos::subview(integral_view, k);
107 // get the position for the current index
108 const auto idx = coordinates.from_linear_index(k);
109 const auto pos = coordinates.forward(idx);
110
111 const auto full_args = std::tuple_cat(pos, m_args);
112
113 NT res = 0;
114 Kokkos::parallel_reduce(
115 Kokkos::TeamThreadMDRange(team, x0size, x1size / 2, x1size / 2, x1size / 2), // range of the kernel
116 [&](const uint idx_x0, const uint idx_x1, const uint idx_x2, const uint idx_x3, NT &update) {
117 const ctype q0 = x0fac * idx_x0;
118 const ctype q1 = x1fac * idx_x1;
119 const ctype q2 = x1fac * idx_x2;
120 const ctype q3 = x1fac * idx_x3;
121 const NT result = std::apply(
122 [&](const auto &...iargs) { return KERNEL::kernel(q0, q1, q2, q3, iargs...); }, full_args);
123 update += q0_mult * 8 * fac * result;
124 },
125 res);
126
127 // add the constant value
128 team.team_barrier();
129 Kokkos::single(Kokkos::PerTeam(team), [=]() {
130 subview() = res + std::apply([&](const auto &...iargs) { return KERNEL::constant(iargs...); }, full_args);
131 });
132 });
133 }
134
135 template <typename Coordinates, typename... Args>
136 auto map(NT *dest, const Coordinates &coordinates, const Args &...args)
137 {
138 // create an execution space
139 ExecutionSpace space;
140
141 // create unmanaged host view for dest
142 auto dest_view = Kokkos::View<NT *, CPU_memory, Kokkos::MemoryUnmanaged>(dest, coordinates.size());
143
144 // create device view for dest
145 auto dest_device_view = Kokkos::View<NT *, ExecutionSpace>(
146 Kokkos::view_alloc(space, "MapIntegrators_device_view"), coordinates.size());
147
148 // run the map function
149 map(space, dest_device_view, coordinates, args...);
150
151 // copy the result from device to host
152 auto dest_host_view = Kokkos::create_mirror_view(space, dest_device_view);
153 Kokkos::deep_copy(space, dest_host_view, dest_device_view);
154
155 // copy the result from the mirror to the requested destination
156 Kokkos::deep_copy(space, dest_view, dest_host_view);
157
158 return std::move(space);
159 }
160
161 const std::array<uint, 2> grid_size;
162
163 private:
164 std::array<ctype, 2> a;
166 };
167} // namespace DiFfRG
Definition integrator_lat_4d.hh:12
void get(ExecutionSpace &space, OT &dest, const T &...t) const
Definition integrator_lat_4d.hh:55
bool q0_symmetric
Definition integrator_lat_4d.hh:165
void map(ExecutionSpace &space, const view_type integral_view, const Coordinates &coordinates, const Args &...args)
Definition integrator_lat_4d.hh:85
void get(OT &dest, const T &...t) const
Definition integrator_lat_4d.hh:47
void get(NT &dest, const T &...t) const
Definition integrator_lat_4d.hh:30
std::array< ctype, 2 > a
Definition integrator_lat_4d.hh:164
void set_q0_symmetric(bool symmetric)
Definition integrator_lat_4d.hh:28
ExecutionSpace execution_space
Definition integrator_lat_4d.hh:18
const std::array< uint, 2 > grid_size
Definition integrator_lat_4d.hh:161
void set_a(const std::array< ctype, 2 > a)
Definition integrator_lat_4d.hh:27
IntegratorLat4D(const std::array< uint, 2 > grid_size, const std::array< ctype, 2 > a, bool q0_symmetric=false)
Definition integrator_lat_4d.hh:20
typename get_type::ctype< NT > ctype
Numerical type to be used for integration tasks e.g. the argument or possible jacobians.
Definition integrator_lat_4d.hh:17
auto map(NT *dest, const Coordinates &coordinates, const Args &...args)
Definition integrator_lat_4d.hh:136
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