OpenLB 1.7
Loading...
Searching...
No Matches
context.hh
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2022 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 GPU_CUDA_CONTEXT_HH
25#define GPU_CUDA_CONTEXT_HH
26
27#include "context.h"
28
29#include "registry.hh"
30
31namespace olb {
32
33namespace gpu {
34
35namespace cuda {
36
38template <typename T, typename DESCRIPTOR, typename FIELD>
39static auto getDeviceFieldPointer(ConcreteBlockLattice<T,DESCRIPTOR,Platform::GPU_CUDA>& lattice) {
40 auto& fieldArray = lattice.template getField<FIELD>();
41 return Vector<typename FIELD::template value_type<T>*,DESCRIPTOR::template size<FIELD>()>([&](unsigned iD) {
42 return fieldArray[iD].deviceData();
43 });
44}
45
47template <typename T, typename DESCRIPTOR, typename... FIELDS>
48static auto getDeviceFieldPointers(typename meta::list<FIELDS...>,
49 ConcreteBlockLattice<T,DESCRIPTOR,Platform::GPU_CUDA>& lattice) {
50 return std::make_tuple(getDeviceFieldPointer<T,DESCRIPTOR,FIELDS>(lattice)...);
51}
52
54template <typename T, typename DESCRIPTOR>
56private:
57 const std::size_t _nCells;
58
60 decltype(getDeviceFieldPointers(typename DESCRIPTOR::fields_t(),
62 _staticFieldsD;
64
67 void*** _customFieldsD;
68
69public:
70 using value_t = T;
71 using descriptor_t = DESCRIPTOR;
72
74 _nCells(lattice.getNcells()),
75 _staticFieldsD(getDeviceFieldPointers(typename DESCRIPTOR::fields_t(), lattice)),
76 _customFieldsD(lattice.getDataRegistry().deviceData())
77 { }
78
79 std::size_t getNcells() const any_platform {
80 return _nCells;
81 }
82
83 template <typename FIELD>
84 typename FIELD::template value_type<T>** getField() __device__ {
85 if constexpr (DESCRIPTOR::template provides<FIELD>()) {
86 return std::get<(DESCRIPTOR::fields_t::template index<FIELD>())>(_staticFieldsD).data();
87 } else {
88 return reinterpret_cast<typename FIELD::template value_type<T>**>(
89 _customFieldsD[field_type_index<FieldTypeRegistry<T,DESCRIPTOR,Platform::GPU_CUDA>, Array<FIELD>>]);
90 }
91 }
92
93};
94
96template <typename T, typename DESCRIPTOR, typename FIELD>
97class FieldPtr : public ScalarVector<typename FIELD::template value_type<T>,
98 DESCRIPTOR::template size<FIELD>(),
99 FieldPtr<T,DESCRIPTOR,FIELD>> {
100private:
102 std::size_t _index;
103
105 DESCRIPTOR::template size<FIELD>(),
107
108protected:
109 const typename FIELD::template value_type<T>* getComponentPointer(unsigned iDim) const __device__
110 {
111 return _data.template getField<FIELD>()[iDim] + _index;
112 }
113 typename FIELD::template value_type<T>* getComponentPointer(unsigned iDim) __device__
114 {
115 return _data.template getField<FIELD>()[iDim] + _index;
116 }
117
118public:
119 FieldPtr(DeviceContext<T,DESCRIPTOR>& data, std::size_t index) __device__:
120 _data(data),
121 _index(index) { }
122
124 _data(rhs._data),
125 _index(rhs._index) { }
126
127 template <typename U, typename IMPL>
128 FieldPtr<T,DESCRIPTOR,FIELD>& operator=(const GenericVector<U,DESCRIPTOR::template size<FIELD>(),IMPL>& rhs) __device__
129 {
130 for (unsigned iDim=0; iDim < DESCRIPTOR::template size<FIELD>(); ++iDim) {
131 this->operator[](iDim) = rhs[iDim];
132 }
133 return *this;
134 }
135
136};
137
139template <typename T, typename DESCRIPTOR>
141protected:
144
145public:
146 using value_t = T;
147 using descriptor_t = DESCRIPTOR;
148
150 _data(data),
151 _iCell(iCell)
152 { }
153
154 template <typename FIELD>
155 typename FIELD::template value_type<T> getFieldComponent(unsigned iD) __device__ {
156 return _data.template getField<FIELD>()[iD][_iCell];
157 }
158
159 value_t& operator[](int iPop) __device__ {
160 return _data.template getField<descriptors::POPULATION>()[iPop][_iCell];
161 }
162
163 template <typename FIELD>
164 auto getField() const __device__ {
165 auto fieldArray = _data.template getField<FIELD>();
166 if constexpr (descriptor_t::template size<FIELD>() == 1) {
167 return fieldArray[0][_iCell];
168 } else {
169 return FieldD<value_t,descriptor_t,FIELD>([&](unsigned iD) {
170 return fieldArray[iD][_iCell];
171 });
172 }
173 }
174
175 template <typename FIELD>
179
180 template <typename FIELD>
182 auto fieldArray = _data.template getField<FIELD>();
183 for (unsigned iD=0; iD < descriptor_t::template size<FIELD>(); ++iD) {
184 fieldArray[iD][_iCell] = value[iD];
185 }
186 }
187
188 template <typename FIELD>
189 void setField(const FieldD<value_t,descriptor_t,FIELD>& value) __device__ {
190 auto fieldArray = _data.template getField<FIELD>();
191 for (unsigned iD=0; iD < descriptor_t::template size<FIELD>(); ++iD) {
192 fieldArray[iD][_iCell] = value[iD];
193 }
194 }
195
196};
197
198
199template <typename T, typename DESCRIPTOR>
200class Cell;
201
203
206template <typename T, typename DESCRIPTOR>
207class DeviceBlockLattice final : public DeviceContext<T,DESCRIPTOR> {
208private:
209 LatticeR<DESCRIPTOR::d> _projection;
210 int _padding;
211
212public:
215 _padding{lattice.getPadding()}
216 {
217 auto size = lattice.getExtent() + 2*_padding;
218 if constexpr (DESCRIPTOR::d == 3) {
219 _projection = {size[1]*size[2], size[2], 1};
220 } else {
221 _projection = {size[1], 1};
222 }
223 }
224
226 return (loc+_padding) * _projection;
227 }
228
230 return dir * _projection;
231 }
232
233 Cell<T,DESCRIPTOR> get(CellID iCell) __device__ {
234 return Cell<T,DESCRIPTOR>(*this, iCell);
235 }
236
238 return get(getCellId(loc));
239 }
240
241};
242
244
247template <typename T, typename DESCRIPTOR>
248class Cell final : public DataOnlyCell<T,DESCRIPTOR> {
249protected:
251 return static_cast<DeviceBlockLattice<T,DESCRIPTOR>&>(this->_data);
252 }
253
254public:
256 DataOnlyCell<T,DESCRIPTOR>(data, iCell)
257 { }
258
260 return {getBlock(), CellID(this->_iCell + getBlock().getNeighborDistance(offset))};
261 }
262
264 return *this->template getField<DYNAMICS<T,DESCRIPTOR>>();
265 }
266
267 T computeRho() __device__ {
268 return getDynamics().computeRho(*this);
269 }
270 void computeU(T* u) __device__ {
271 getDynamics().computeU(*this, u);
272 }
273 void computeJ(T* j) __device__ {
274 getDynamics().computeJ(*this, j);
275 }
276 void computeRhoU(T& rho, T* u) __device__ {
277 getDynamics().computeRhoU(*this, rho, u);
278 }
279 void computeStress(T* pi) __device__ {
280 T rho, u[DESCRIPTOR::d] { };
281 getDynamics().computeRhoU(*this, rho, u);
282 getDynamics().computeStress(*this, rho, u, pi);
283 }
284 void computeAllMomenta(T& rho, T* u, T* pi) __device__ {
285 getDynamics().computeAllMomenta(*this, rho, u, pi);
286 }
287
288 void defineRho(T& rho) __device__ {
289 return getDynamics().defineRho(*this, rho);
290 }
291 void defineU(T* u) __device__ {
292 return getDynamics().defineU(*this, u);
293 }
294 void defineRhoU(T& rho, T* u) __device__ {
295 return getDynamics().defineRhoU(*this, rho, u);
296 }
297 void defineAllMomenta(T& rho, T* u, T* pi) __device__ {
298 return getDynamics().defineAllMomenta(*this, rho, u, pi);
299 }
300 void definePopulations(const T* f) __device__ {
301 for (int iPop=0; iPop < descriptors::q<DESCRIPTOR>(); ++iPop) {
302 this->operator[](iPop) = f[iPop];
303 }
304 }
305
306 void iniEquilibrium(T rho, T* u) __device__ {
307 getDynamics().iniEquilibrium(*this, rho, u);
308 }
309 void iniRegularized(T rho, T* u, T* pi) __device__ {
310 getDynamics().iniRegularized(*this, rho, u, pi);
311 }
312 void inverseShiftRhoU(T& rho, T* u) __device__ {
313 getDynamics().inverseShiftRhoU(*this, rho, u);
314 }
315
316};
317
318}
319
320}
321
322template <typename T, typename DESCRIPTOR, typename PARAMETERS>
324 _deviceParameters{gpu::cuda::device::malloc<ParametersD>(1)},
325 parameters{}
326{
328 _deviceParameters.get(),
329 sizeof(ParametersD));
330}
331
332template <typename T, typename DESCRIPTOR, typename PARAMETERS>
334 ProcessingContext context)
335{
336 if (context == ProcessingContext::Simulation) {
338 _deviceParameters.get(),
339 sizeof(ParametersD));
340 }
341}
342
343template<typename T, typename DESCRIPTOR, typename PARAMETERS>
345{
346 return decltype(parameters)::fields_t::size;
347}
348
349template<typename T, typename DESCRIPTOR, typename PARAMETERS>
351{
352 std::size_t size = 0;
353 decltype(parameters)::fields_t::for_each([&size](auto field) {
354 using field_t = typename decltype(field)::type;
356 });
357 return size;
358}
359
360template<typename T, typename DESCRIPTOR, typename PARAMETERS>
362 std::size_t iBlock, std::size_t& sizeBlock, bool loadingMode)
363{
364 std::size_t currentBlock = 0;
365 bool* dataPtr = nullptr;
366 decltype(parameters)::fields_t::for_each([&](auto field) {
367 using field_t = typename decltype(field)::type;
368 if constexpr (DESCRIPTOR::template size<field_t>() == 1) {
369 registerVar(iBlock, sizeBlock, currentBlock, dataPtr,
370 parameters.template get<field_t>(), loadingMode);
371 } else {
372 registerSerializableOfConstSize(iBlock, sizeBlock, currentBlock, dataPtr,
373 parameters.template get<field_t>(), loadingMode);
374 }
375 });
376 return dataPtr;
377}
378
379
380}
381
382#endif
Highest-level interface to Cell data.
Definition cell.h:148
Implementation of BlockLattice on a concrete PLATFORM.
Plain old scalar vector.
Definition vector.h:47
constexpr std::size_t getSerializableSize() const
Definition vector.h:197
Device-side implementation of the Cell concept for post processors.
Definition context.hh:248
void iniEquilibrium(T rho, T *u) __device__
Definition context.hh:306
Cell< T, DESCRIPTOR > neighbor(LatticeR< DESCRIPTOR::d > offset) __device__
Definition context.hh:259
void computeJ(T *j) __device__
Definition context.hh:273
void computeAllMomenta(T &rho, T *u, T *pi) __device__
Definition context.hh:284
T computeRho() __device__
Definition context.hh:267
Cell(DeviceBlockLattice< T, DESCRIPTOR > &data, CellID iCell) __device__
Definition context.hh:255
DeviceBlockLattice< T, DESCRIPTOR > & getBlock() __device__
Definition context.hh:250
void inverseShiftRhoU(T &rho, T *u) __device__
Definition context.hh:312
void defineU(T *u) __device__
Definition context.hh:291
void computeU(T *u) __device__
Definition context.hh:270
void defineRhoU(T &rho, T *u) __device__
Definition context.hh:294
void defineAllMomenta(T &rho, T *u, T *pi) __device__
Definition context.hh:297
Dynamics< T, DESCRIPTOR > & getDynamics() __device__
Definition context.hh:263
void definePopulations(const T *f) __device__
Definition context.hh:300
void iniRegularized(T rho, T *u, T *pi) __device__
Definition context.hh:309
void defineRho(T &rho) __device__
Definition context.hh:288
void computeStress(T *pi) __device__
Definition context.hh:279
void computeRhoU(T &rho, T *u) __device__
Definition context.hh:276
Device-side implementation of the data-only Cell concept for collision steps.
Definition context.hh:140
value_t & operator[](int iPop) __device__
Definition context.hh:159
DataOnlyCell(DeviceContext< T, DESCRIPTOR > &data, CellID iCell) __device__
Definition context.hh:149
void setField(FieldD< value_t, descriptor_t, FIELD > &&value) __device__
Definition context.hh:181
void setField(const FieldD< value_t, descriptor_t, FIELD > &value) __device__
Definition context.hh:189
auto getField() const __device__
Definition context.hh:164
FieldPtr< T, DESCRIPTOR, FIELD > getFieldPointer() __device__
Definition context.hh:176
DeviceContext< T, DESCRIPTOR > & _data
Definition context.hh:142
FIELD::template value_type< T > getFieldComponent(unsigned iD) __device__
Definition context.hh:155
Device-side view of a block lattice.
Definition context.hh:207
CellID getCellId(LatticeR< DESCRIPTOR::d > loc) const __device__
Definition context.hh:225
CellDistance getNeighborDistance(LatticeR< DESCRIPTOR::d > dir) const __device__
Definition context.hh:229
Cell< T, DESCRIPTOR > get(LatticeR< DESCRIPTOR::d > loc) __device__
Definition context.hh:237
Cell< T, DESCRIPTOR > get(CellID iCell) __device__
Definition context.hh:233
DeviceBlockLattice(ConcreteBlockLattice< T, DESCRIPTOR, Platform::GPU_CUDA > &lattice) __host__
Definition context.hh:213
Structure for passing pointers to on-device data into CUDA kernels.
Definition context.hh:55
DeviceContext(ConcreteBlockLattice< T, DESCRIPTOR, Platform::GPU_CUDA > &lattice) __host__
Definition context.hh:73
FIELD::template value_type< T > ** getField() __device__
Definition context.hh:84
std::size_t getNcells() const any_platform
Definition context.hh:79
Pointer to row of a D-dimensional field.
Definition context.hh:99
FieldPtr(FieldPtr< T, DESCRIPTOR, FIELD > &&rhs) __device__
Definition context.hh:123
FieldPtr< T, DESCRIPTOR, FIELD > & operator=(const GenericVector< U, DESCRIPTOR::template size< FIELD >(), IMPL > &rhs) __device__
Definition context.hh:128
FIELD::template value_type< T > * getComponentPointer(unsigned iDim) __device__
Definition context.hh:113
FieldPtr(DeviceContext< T, DESCRIPTOR > &data, std::size_t index) __device__
Definition context.hh:119
const FIELD::template value_type< T > * getComponentPointer(unsigned iDim) const __device__
Definition context.hh:109
void copyToDevice(void *src, void *dst, std::size_t count)
Copy data from host to device.
Definition device.hh:83
Top level namespace for all of OpenLB.
std::uint32_t CellID
Type for sequential block-local cell indices.
ProcessingContext
OpenLB processing contexts.
Definition platform.h:55
@ Simulation
Data available on host for e.g. functor evaluation.
std::int64_t CellDistance
Type for in-memory distance of block-local cell indices.
#define any_platform
Define preprocessor macros for device-side functions, constant storage.
Definition platform.h:78
Describe FieldArray of a FIELD in Data.
Definition data.h:42
std::size_t getNblock() const override
Number of data blocks for the serializable interface.
bool * getBlock(std::size_t iBlock, std::size_t &sizeBlock, bool loadingMode) override
Return a pointer to the memory of the current block and its size for the serializable interface.
void setProcessingContext(ProcessingContext context) override
ParametersD< T, DESCRIPTOR >::template include< PARAMETERS > parameters
std::size_t getSerializableSize() const override
Binary size for the serializer.
Generic vector of values supporting basic arithmetic.
constexpr const T & operator[](unsigned iDim) const any_platform
const auto & get() const any_platform
Vector of scalars.
Virtual interface for device-side dynamically-dispatched dynamics access.
Definition dynamics.hh:41