23 template <
int dim,
typename NT,
typename KERNEL,
typename ExecutionSpace>
41 static constexpr int sdim = dim - 1;
44 std::array<ctype, sdim> grid_min, std::array<ctype, sdim> grid_max,
45 const std::array<QuadratureType, sdim> quadrature_type,
const ctype T = 1,
46 const ctype typical_E = 1)
47 : quadrature_provider(quadrature_provider), T(T), typical_E(typical_E)
49 for (
int d = 0; d < sdim; ++d)
50 grid_size[d] = _grid_size[d];
52 quadrature_provider.template matsubara_nodes<ctype, typename ExecutionSpace::memory_space>(T, typical_E);
54 quadrature_provider.template matsubara_weights<ctype, typename ExecutionSpace::memory_space>(T, typical_E);
55 matsubara_sum_T = quadrature_provider.template matsubara_T<ctype>(T, typical_E);
56 for (
int i = 0; i < sdim; ++i) {
57 nodes[i] = quadrature_provider.template nodes<ctype, typename ExecutionSpace::memory_space>(grid_size[i],
59 weights[i] = quadrature_provider.template weights<ctype, typename ExecutionSpace::memory_space>(
60 grid_size[i], quadrature_type[i]);
62 set_grid_extents(grid_min, grid_max);
63 grid_size[dim - 1] = matsubara_nodes.size();
66 void set_grid_extents(
const std::array<ctype, sdim> grid_min,
const std::array<ctype, sdim> grid_max)
68 for (
int d = 0; d < sdim; ++d) {
69 grid_extents[0][d] = grid_min[d];
70 grid_extents[1][d] = grid_max[d];
72 for (
int i = 0; i < sdim; ++i) {
73 grid_start[i] = grid_extents[0][i];
74 grid_scale[i] = (grid_extents[1][i] - grid_extents[0][i]);
82 quadrature_provider.template matsubara_nodes<ctype, typename ExecutionSpace::memory_space>(T, typical_E);
84 quadrature_provider.template matsubara_weights<ctype, typename ExecutionSpace::memory_space>(T, typical_E);
85 matsubara_sum_T = quadrature_provider.template matsubara_T<ctype>(T, typical_E);
86 grid_size[dim - 1] = matsubara_nodes.size();
91 if (
is_close(this->typical_E, typical_E, 1e-4 * T + std::numeric_limits<ctype>::epsilon() * 10))
return;
93 this->typical_E = typical_E;
95 quadrature_provider.template matsubara_nodes<ctype, typename ExecutionSpace::memory_space>(T, typical_E);
97 quadrature_provider.template matsubara_weights<ctype, typename ExecutionSpace::memory_space>(T, typical_E);
98 matsubara_sum_T = quadrature_provider.template matsubara_T<ctype>(T, typical_E);
99 grid_size[dim - 1] = matsubara_nodes.size();
104 template <
typename... T>
void get(NT &dest,
const T &...t)
const
107 ExecutionSpace space;
109 if (!m_result_views_initialized) {
110 m_result_view = Kokkos::View<NT, typename ExecutionSpace::memory_space>(
"result");
111 m_result_host = Kokkos::create_mirror_view(m_result_view);
112 m_result_views_initialized =
true;
114 get(space, m_result_view, t...);
115 Kokkos::deep_copy(space, m_result_host, m_result_view);
117 dest = m_result_host();
120 template <
typename OT,
typename... T>
121 requires(!std::is_same_v<OT, NT>)
122 void get(OT &dest,
const T &...t)
const
124 ExecutionSpace space;
125 get(space, dest, t...);
128 template <
typename OT,
typename... Args>
129 requires(!std::is_same_v<OT, NT>)
130 void get(ExecutionSpace &space, OT &dest,
const Args &...t)
const
132 const auto args = device::make_tuple(t...);
134 const auto &n = nodes;
135 const auto &w = weights;
136 const auto &m_n = matsubara_nodes;
137 const auto &m_w = matsubara_weights;
138 const auto &start = grid_start;
139 const auto &scale = grid_scale;
141 const auto &m_T = matsubara_sum_T;
147 bool is_first =
true;
148 for (
int i = 0; i < sdim; ++i) {
149 x[i] = Kokkos::fma(scale[i], n[i][idx[i]], start[i]);
150 weight *= w[i][idx[i]] * scale[i];
151 is_first &= idx[i] == 0;
153 is_first &= idx[dim - 1] == 0;
154 const ctype xt = m_n[idx[dim - 1]];
155 const ctype wt = m_w[idx[dim - 1]];
157 [&](
const auto &...iargs) {
159 [&](
const auto &...posargs) {
161 if constexpr (kernel_is_matsubara_even<KERNEL>)
163 msum =
ctype(2) * KERNEL::kernel(posargs..., xt, iargs...);
166 msum = KERNEL::kernel(posargs..., xt, iargs...) + KERNEL::kernel(posargs..., -xt, iargs...);
170 + (idx[dim - 1] != 0 ? NT{} : m_T * KERNEL::kernel(posargs..., (
ctype)0, iargs...)));
175 device::apply([&](
const auto &...iargs) { update += is_first ? KERNEL::constant(iargs...) : NT(0); }, args);
178 Kokkos::parallel_reduce(
"QuadratureIntegral_fT_" + std::to_string(dim) +
"D",
179 make_kokkos_nd_range<dim, ExecutionSpace>(space, {0}, grid_size),
183 template <
typename view_type,
typename Coordinates,
typename... Args>
184 void map(ExecutionSpace &space,
const view_type integral_view,
const Coordinates &coordinates,
const Args &...args)
187 extents[0] = integral_view.size();
188 for (
int i = 0; i < dim; ++i)
189 extents[1 + i] = grid_size[i];
193 bool needs_realloc =
false;
194 for (
size_t i = 0; i < 1 + dim; ++i)
195 needs_realloc |= (extents[i] > m_cache_extents[i]);
197 for (
size_t i = 0; i < 1 + dim; ++i)
198 m_cache_extents[i] = std::max(m_cache_extents[i], extents[i]);
199 m_cache = make_kokkos_nd_view<1 + dim, NT, ExecutionSpace>(
"cache", m_cache_extents);
205 const auto m_args = device::make_tuple(args...);
207 const auto &n = nodes;
208 const auto &w = weights;
209 const auto &m_n = matsubara_nodes;
210 const auto &m_w = matsubara_weights;
211 const auto &start = grid_start;
212 const auto &scale = grid_scale;
214 const auto &m_T = matsubara_sum_T;
219 auto subview = device::apply([&](
const auto &...i) {
return Kokkos::subview(cache, i...); }, idx);
222 const auto idx_v = coordinates.from_linear_index(idx[0]);
223 const auto pos = coordinates.forward(idx_v);
225 const auto full_args = device::tuple_cat(pos, m_args);
229 for (
int i = 0; i < sdim; ++i) {
230 x[i] = Kokkos::fma(scale[i], n[i][idx[1 + i]], start[i]);
231 weight *= w[i][idx[1 + i]] * scale[i];
233 const ctype xt = m_n[idx[1 + dim - 1]];
234 const ctype wt = m_w[idx[1 + dim - 1]];
236 [&](
const auto &...iargs) {
238 [&](
const auto &...posargs) {
240 if constexpr (kernel_is_matsubara_even<KERNEL>)
242 msum =
ctype(2) * KERNEL::kernel(posargs..., xt, iargs...);
245 msum = KERNEL::kernel(posargs..., xt, iargs...) + KERNEL::kernel(posargs..., -xt, iargs...);
250 + (idx[1 + dim - 1] != 0 ? NT{} : m_T * KERNEL::kernel(posargs..., (
ctype)0, iargs...)));
257 Kokkos::parallel_for(make_kokkos_nd_range<1 + dim, ExecutionSpace>(space, {0}, extents),
260 using TeamType = Kokkos::TeamPolicy<ExecutionSpace>::member_type;
262 constexpr int vector_width = 32;
263 Kokkos::parallel_for(
264 Kokkos::TeamPolicy(space, integral_view.size(), Kokkos::AUTO, vector_width),
265 KOKKOS_CLASS_LAMBDA(
const TeamType &team) {
267 const uint k = team.league_rank();
269 if (k > integral_view.size())
return;
276 size_t total_elements = 1;
277 for (
int d = 0; d < dim; ++d)
278 total_elements *= grid_size[d];
283 strides[dim - 1] = 1;
284 for (
int d = dim - 2; d >= 0; --d)
285 strides[d] = strides[d + 1] * grid_size[d + 1];
288 Kokkos::parallel_reduce(
289 Kokkos::TeamThreadRange(team, (total_elements + vector_width - 1) / vector_width),
290 [&](
const size_t outer, NT &team_update) {
292 Kokkos::parallel_reduce(
293 Kokkos::ThreadVectorRange(team, vector_width),
294 [&](
const size_t inner, NT &vec_update) {
295 const size_t flat = outer * vector_width + inner;
296 if (flat < total_elements) {
299 size_t remainder = flat;
300 for (
int d = 0; d < dim; ++d) {
301 ridx[d] = remainder / strides[d];
302 remainder -= ridx[d] * strides[d];
304 device::apply([&](
const auto &...iargs) { vec_update += cache(k, iargs...); }, ridx);
308 team_update += vec_sum;
313 Kokkos::single(Kokkos::PerTeam(team), [&]() {
314 const auto idx = coordinates.from_linear_index(k);
315 const auto pos = coordinates.forward(idx);
316 const auto full_args = device::tuple_cat(pos, m_args);
318 res + device::apply([&](
const auto &...iargs) {
return KERNEL::constant(iargs...); }, full_args);
323 template <
typename Coordinates,
typename... Args>
324 auto map(NT *dest,
const Coordinates &coordinates,
const Args &...args)
328 if (node_distribution.mpi_comm != MPI_COMM_NULL && node_distribution.total_size > 0) {
329 auto mpi_comm = node_distribution.
mpi_comm;
330 const auto &nodes = node_distribution.nodes;
331 const auto &sizes = node_distribution.sizes;
336 if (std::find(nodes.begin(), nodes.end(), m_rank) == nodes.end())
return ExecutionSpace();
339 const size_t rank_size = sizes[m_rank];
341 const size_t offset = std::accumulate(sizes.begin(), sizes.begin() + m_rank, 0);
344 const auto sub_coordinates =
SubCoordinates(coordinates, offset, rank_size);
346 NT *dest_offset = dest + offset;
348 return map_dist(dest_offset, sub_coordinates, args...);
351 return map_dist(dest, coordinates, args...);
354 template <
typename Coordinates,
typename... Args>
355 auto map_dist(NT *dest,
const Coordinates &coordinates,
const Args &...args)
358 auto dest_view = Kokkos::View<NT *, CPU_memory, Kokkos::MemoryUnmanaged>(dest, coordinates.size());
361 if (m_dest_device_size < coordinates.size()) {
362 m_dest_device = Kokkos::View<NT *, ExecutionSpace>(Kokkos::view_alloc(space,
"MapIntegrators_device_view"),
364 m_dest_device_size = coordinates.size();
366 auto dest_device_view =
367 Kokkos::View<NT *, ExecutionSpace>(m_dest_device, Kokkos::make_pair(
size_t(0), coordinates.size()));
370 map(space, dest_device_view, coordinates, args...);
373 Kokkos::deep_copy(space, dest_view, dest_device_view);
400 mutable size_t m_dest_device_size = 0;
401 mutable Kokkos::View<NT, typename ExecutionSpace::memory_space>
m_result_view;
402 mutable typename Kokkos::View<NT, typename ExecutionSpace::memory_space>::host_mirror_type
m_result_host;
403 mutable bool m_result_views_initialized =
false;
406 template <
int dim,
typename NT,
typename KERNEL>
420 static constexpr int sdim = dim - 1;
423 std::array<ctype, sdim> grid_min, std::array<ctype, sdim> grid_max,
424 const std::array<QuadratureType, sdim> quadrature_type,
const ctype T = 1,
430 template <
typename... Args>
432 void get(NT &dest,
const Args &...t)
const
434 const auto args = device::tie(t...);
436 const auto &n =
nodes;
448 for (
int i = 0; i <
sdim; ++i) {
449 x[i] = Kokkos::fma(scale[i], n[i][idx[i]], start[i]);
450 weight *= w[i][idx[i]] * scale[i];
452 const ctype xt = m_n[idx[dim - 1]];
453 const ctype wt = m_w[idx[dim - 1]];
456 [&](
const auto &...iargs) {
458 [&](
const auto &...posargs) {
460 if constexpr (kernel_is_matsubara_even<KERNEL>)
462 msum =
ctype(2) * KERNEL::kernel(posargs..., xt, iargs...);
465 msum = KERNEL::kernel(posargs..., xt, iargs...) + KERNEL::kernel(posargs..., -xt, iargs...);
469 + (idx[dim - 1] != 0 ? NT{} : m_T * KERNEL::kernel(posargs..., (
ctype)0, iargs...)));
477 dest = KERNEL::constant(t...) + TBBReduction<dim, NT, decltype(functor)>(
grid_size, functor);
480 template <
typename Coordinates,
typename... Args>
483 const auto m_args = device::tie(args...);
485 tbb::parallel_for(tbb::blocked_range<uint>(0, coordinates.size()), [&](
const tbb::blocked_range<uint> &r) {
486 for (uint idx = r.begin(); idx != r.end(); ++idx) {
487 const auto dis_idx = coordinates.from_linear_index(idx);
488 const auto pos = coordinates.forward(dis_idx);
490 const auto full_args = device::tuple_cat(pos, m_args);
491 device::apply([&](const auto &...iargs) { get(dest[idx], iargs...); }, full_args);
496 template <
typename Coordinates,
typename... Args>
497 auto map(NT *dest,
const Coordinates &coordinates,
const Args &...args)
503 if (node_distribution.mpi_comm != MPI_COMM_NULL && node_distribution.total_size > 0) {
504 auto mpi_comm = node_distribution.
mpi_comm;
505 const auto &nodes = node_distribution.nodes;
506 const auto &sizes = node_distribution.sizes;
511 if (std::find(nodes.begin(), nodes.end(), m_rank) == nodes.end())
return execution_space();
514 const size_t rank_size = sizes[m_rank];
516 const size_t offset = std::accumulate(sizes.begin(), sizes.begin() + m_rank, 0);
519 const auto sub_coordinates =
SubCoordinates(coordinates, offset, rank_size);
521 NT *dest_offset = dest + offset;
523 map(space, dest_offset, sub_coordinates, args...);
525 map(space, dest, coordinates, args...);
530 using Base::grid_extents;
531 using Base::grid_scale;
532 using Base::grid_size;
533 using Base::grid_start;
534 using Base::quadrature_provider;
536 using Base::matsubara_nodes;
537 using Base::matsubara_weights;
541 using Base::matsubara_sum_T;
543 using Base::typical_E;
Definition abstract_integrator.hh:64
NodeDistribution node_distribution
Definition abstract_integrator.hh:73
QuadratureIntegrator_fT(QuadratureProvider &quadrature_provider, const std::array< size_t, sdim > _grid_size, std::array< ctype, sdim > grid_min, std::array< ctype, sdim > grid_max, const std::array< QuadratureType, sdim > quadrature_type, const ctype T=1, const ctype typical_E=1)
Definition quadrature_integrator_fT.hh:422
void get(NT &dest, const Args &...t) const
Definition quadrature_integrator_fT.hh:432
auto map(NT *dest, const Coordinates &coordinates, const Args &...args)
Definition quadrature_integrator_fT.hh:497
typename get_type::ctype< NT > ctype
Numerical type to be used for integration tasks e.g. the argument or possible jacobians.
Definition quadrature_integrator_fT.hh:417
void map(execution_space &, NT *dest, const Coordinates &coordinates, const Args &...args)
Definition quadrature_integrator_fT.hh:481
Definition quadrature_integrator_fT.hh:26
Kokkos::View< const ctype *, typename ExecutionSpace::memory_space > matsubara_weights
Definition quadrature_integrator_fT.hh:394
device::array< device::array< ctype, sdim >, 2 > grid_extents
Definition quadrature_integrator_fT.hh:381
static constexpr int sdim
Spatial dimension of the integration problem.
Definition quadrature_integrator_fT.hh:41
ctype typical_E
Definition quadrature_integrator_fT.hh:390
QuadratureProvider & quadrature_provider
Definition quadrature_integrator_fT.hh:380
device::array< Kokkos::View< const ctype *, typename ExecutionSpace::memory_space >, sdim > nodes
Definition quadrature_integrator_fT.hh:387
void get(OT &dest, const T &...t) const
Definition quadrature_integrator_fT.hh:122
device::array< ctype, sdim > grid_start
Definition quadrature_integrator_fT.hh:382
void set_typical_E(const ctype typical_E)
Definition quadrature_integrator_fT.hh:89
ExecutionSpace space
Definition quadrature_integrator_fT.hh:379
device::array< Kokkos::View< const ctype *, typename ExecutionSpace::memory_space >, sdim > weights
Definition quadrature_integrator_fT.hh:388
void get(ExecutionSpace &space, OT &dest, const Args &...t) const
Definition quadrature_integrator_fT.hh:130
auto map(NT *dest, const Coordinates &coordinates, const Args &...args)
Definition quadrature_integrator_fT.hh:324
Kokkos::View< NT *, ExecutionSpace > m_dest_device
Definition quadrature_integrator_fT.hh:399
void set_grid_extents(const std::array< ctype, sdim > grid_min, const std::array< ctype, sdim > grid_max)
Definition quadrature_integrator_fT.hh:66
KokkosNDView< 1+dim, NT, ExecutionSpace > m_cache
Definition quadrature_integrator_fT.hh:397
device::array< size_t, dim > grid_size
Definition quadrature_integrator_fT.hh:385
auto map_dist(NT *dest, const Coordinates &coordinates, const Args &...args)
Definition quadrature_integrator_fT.hh:355
device::array< ctype, sdim > grid_scale
Definition quadrature_integrator_fT.hh:383
ctype matsubara_sum_T
Definition quadrature_integrator_fT.hh:391
size_t get_matsubara_size() const
Definition quadrature_integrator_fT.hh:102
ExecutionSpace execution_space
Execution space to be used for the integration, e.g. GPU_exec, TBB_exec.
Definition quadrature_integrator_fT.hh:35
Kokkos::View< NT, typenameExecutionSpace::memory_space >::host_mirror_type m_result_host
Definition quadrature_integrator_fT.hh:402
void set_T(const ctype T)
Definition quadrature_integrator_fT.hh:78
Kokkos::View< NT, typename ExecutionSpace::memory_space > m_result_view
Definition quadrature_integrator_fT.hh:401
void map(ExecutionSpace &space, const view_type integral_view, const Coordinates &coordinates, const Args &...args)
Definition quadrature_integrator_fT.hh:184
typename get_type::ctype< NT > ctype
Numerical type to be used for integration tasks e.g. the argument or possible jacobians.
Definition quadrature_integrator_fT.hh:31
Kokkos::View< const ctype *, typename ExecutionSpace::memory_space > matsubara_nodes
Definition quadrature_integrator_fT.hh:393
void get(NT &dest, const T &...t) const
Definition quadrature_integrator_fT.hh:104
QuadratureIntegrator_fT(QuadratureProvider &quadrature_provider, const std::array< size_t, sdim > _grid_size, std::array< ctype, sdim > grid_min, std::array< ctype, sdim > grid_max, const std::array< QuadratureType, sdim > quadrature_type, const ctype T=1, const ctype typical_E=1)
Definition quadrature_integrator_fT.hh:43
ctype T
Definition quadrature_integrator_fT.hh:390
A class that provides quadrature points and weights, in host and device memory. The quadrature points...
Definition quadrature_provider.hh:137
Definition coordinates.hh:149
Definition abstract_integrator.hh:51
std::array< T, N > array
Definition kokkos.hh:133
typename internal::_ctype< CT >::value ctype
Definition types.hh:134
Definition complex_math.hh:10
constexpr bool kernel_is_matsubara_even
Definition quadrature_integrator_fT.hh:21
::value bool KOKKOS_INLINE_FUNCTION is_close(T1 a, T2 b, T3 eps_)
Function to evaluate whether two floats are equal to numerical precision. Tests for both relative and...
Definition math.hh:168
Kokkos::View< typename GetKokkosNDStarType< dim, T >::type, ExecutionSpace > KokkosNDView
Definition kokkos.hh:163
ExecutionSpaces::TBB_exec_space TBB_exec
Definition kokkos.hh:49
unsigned int uint
Definition utils.hh:24
constexpr auto & get(named_tuple< tuple_type, strSet > &ob)
get a reference to the element with the given name
Definition tuples.hh:111
Kokkos::View< typename GetKokkosNDStarType< dim, T >::type, ExecutionSpace, Kokkos::MemoryTraits< Kokkos::Restrict > > KokkosNDViewRestrict
Definition kokkos.hh:170
This is a functor which wraps a lambda for reduction. Basically, this is necessary when one wants to ...
Definition kokkos.hh:314
This is a functor which wraps a lambda. Basically, this is necessary when one wants to call a variadi...
Definition kokkos.hh:288
MPI_Comm mpi_comm
Definition distribution.hh:8
This execution space is optimal when used in conjunction with the FE discretizations.
Definition kokkos.hh:23