OpenLB 1.8.1
Loading...
Searching...
No Matches
integral.hh
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2024 Adrian Kummerlaender
4 * E-mail contact: info@openlb.net
5 * The most recent release of OpenLB can be downloaded at
6 * <http://www.openlb.net/>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22*/
23
24#ifndef FSI_PLATFORM_GPU_CUDA_INTEGRAL_HH
25#define FSI_PLATFORM_GPU_CUDA_INTEGRAL_HH
26
27#include "integral.h"
28
29#include <thrust/partition.h>
30#include <thrust/sort.h>
31#include <thrust/reduce.h>
32#include <thrust/execution_policy.h>
33
34namespace olb {
35
36namespace gpu {
37
38namespace cuda {
39
40template <typename F, std::size_t... INDICES>
41auto make_thrust_tuple_f(F&& f, std::index_sequence<INDICES...>) {
42 return thrust::make_tuple(f(INDICES)...);
43}
44
45template <unsigned D, typename F>
47 return make_thrust_tuple_f<F>(std::forward<F&&>(f), std::make_index_sequence<D>{});
48}
49
50template <typename A, std::size_t... AIs>
51auto thrust_tuple_cat(A& a, std::index_sequence<AIs...>) {
52 return thrust::make_tuple(thrust::get<AIs>(a)...);
53}
54
55template <typename A, typename B, std::size_t... AIs, std::size_t... BIs>
56auto thrust_tuple_cat(A& a, B& b, std::index_sequence<AIs...>, std::index_sequence<BIs...>) {
57 return thrust::make_tuple(thrust::get<AIs>(a)...,
58 thrust::get<BIs>(b)...);
59}
60
61template <typename A, typename B, typename C, std::size_t... AIs, std::size_t... BIs, std::size_t... CIs>
62auto thrust_tuple_cat(A& a, B& b, C& c, std::index_sequence<AIs...>, std::index_sequence<BIs...>, std::index_sequence<CIs...>) {
63 return thrust::make_tuple(thrust::get<AIs>(a)...,
64 thrust::get<BIs>(b)...,
65 thrust::get<CIs>(c)...);
66}
67
68template <typename... ARGS>
69auto thrust_tuple_cat(ARGS&&... args) {
70 return thrust_tuple_cat(args...,
71 std::make_index_sequence<thrust::tuple_size<ARGS>::value>{}...);
72}
73
74template <typename T, unsigned D>
76 return gpu::cuda::make_thrust_tuple_f<f.d>([&](unsigned iDim) {
77 return f[iDim];
78 });
79}
80
81template <typename T>
83 return thrust::make_tuple(f);
84}
85
86template <typename VECTOR>
88 return gpu::cuda::make_thrust_tuple_f<f.d>([&](unsigned iDim) {
89 return f[iDim].deviceData();
90 });
91}
92
94 template <typename TUPLE>
95 bool operator()(const TUPLE& t) __host__ __device__ {
96 return thrust::get<0>(t) != 0;
97 }
98};
99
101 template <typename TUPLE, std::size_t... INDICES>
102 auto operator()(const TUPLE& t1, const TUPLE& t2,
103 std::index_sequence<INDICES...>) __host__ __device__ {
104 return thrust::make_tuple((thrust::get<INDICES>(t1) + thrust::get<INDICES>(t2))...);
105 }
106
107 template <typename TUPLE>
108 auto operator()(const TUPLE& t1, const TUPLE& t2) __host__ __device__ {
109 return operator()(t1, t2, std::make_index_sequence<thrust::tuple_size<TUPLE>::value>{});
110 }
111};
112
113}
114
115}
116
117template <typename... FIELDS>
118template <typename T, typename DESCRIPTOR>
119void IntegratePorousElementFieldsO<FIELDS...>::type<ConcreteBlockLattice<T,DESCRIPTOR,Platform::GPU_CUDA>>::setup(
121{
122 blockLattice.template getData<OperatorParameters<IntegratePorousElementFieldsO>>();
123}
124
125template <typename... FIELDS>
126template <typename T, typename DESCRIPTOR>
127void IntegratePorousElementFieldsO<FIELDS...>::type<ConcreteBlockLattice<T,DESCRIPTOR,Platform::GPU_CUDA>>::apply(
129{
130 auto& tag = blockLattice.template getField<fields::fsi::REDUCED_ELEMENT_TAG>();
131
132 auto begin = thrust::make_zip_iterator(gpu::cuda::thrust_tuple_cat(
135 blockLattice.template getField<FIELDS>())...
136 ));
137 auto end = thrust::partition(thrust::device,
138 begin,
139 begin + blockLattice.getNcells(),
141 std::size_t nActiveCells = end - begin;
142
143 if (nActiveCells > 0) {
144 // Group per-cell field values by FSI tag
145 thrust::sort_by_key(thrust::device,
146 tag[0].deviceData(),
147 tag[0].deviceData() + nActiveCells,
148 thrust::make_zip_iterator(gpu::cuda::thrust_tuple_cat(
150 blockLattice.template getField<FIELDS>())...
151 )));
152 }
153
154 // Sum up grouped force values
155 auto& parameters = blockLattice.template getData<OperatorParameters<IntegratePorousElementFieldsO>>().parameters;
156 if (nActiveCells > 0) {
157 auto reducedElementTag = parameters.template get<fields::array_of<fields::fsi::REDUCED_ELEMENT_TAG>>();
158 const std::size_t nKeys = thrust::reduce_by_key(
159 thrust::device,
160 tag[0].deviceData(),
161 tag[0].deviceData() + nActiveCells,
162 thrust::make_zip_iterator(gpu::cuda::thrust_tuple_cat(
164 blockLattice.template getField<FIELDS>())...
165 )),
166 reducedElementTag,
167 thrust::make_zip_iterator(gpu::cuda::thrust_tuple_cat(
169 )),
170 thrust::equal_to<T>{},
172 ).first - reducedElementTag;
173 parameters.template set<fields::fsi::REDUCED_ELEMENTS_COUNT>(nKeys);
174 } else {
175 parameters.template set<fields::fsi::REDUCED_ELEMENTS_COUNT>(0);
176 }
177
178 if (nActiveCells > 0) {
179 thrust::fill(thrust::device,
180 tag[0].deviceData(),
181 tag[0].deviceData() + nActiveCells,
182 0);
183 }
184}
185
186}
187
188#endif
std::size_t getNcells() const
Get number of cells.
Implementation of BlockLattice on a concrete PLATFORM.
Plain old scalar vector.
auto make_thrust_tuple_f(F &&f, std::index_sequence< INDICES... >)
Definition integral.hh:41
auto thrust_tuple_cat(A &a, std::index_sequence< AIs... >)
Definition integral.hh:51
auto make_thrust_tuple_of_device_data(VECTOR &f)
Definition integral.hh:87
auto make_thrust_tuple_of(Vector< T, D > &f)
Definition integral.hh:75
Top level namespace for all of OpenLB.
static constexpr unsigned d
Operator for integrating per-element momentum exchange forces in a HLBM-FSI context.
Definition integral.h:33
Base of a field of pointers to the individual columns of FIELD.
Definition fields.h:175
bool operator()(const TUPLE &t) __host__ __device__
Definition integral.hh:95
auto operator()(const TUPLE &t1, const TUPLE &t2, std::index_sequence< INDICES... >) __host__ __device__
Definition integral.hh:102
auto operator()(const TUPLE &t1, const TUPLE &t2) __host__ __device__
Definition integral.hh:108
Plain wrapper for list of types.
Definition meta.h:276