Cabana 0.8.0-dev
 
Loading...
Searching...
No Matches
Cabana_CartesianGrid.hpp
1/****************************************************************************
2 * Copyright (c) 2018-2023 by the Cabana authors *
3 * All rights reserved. *
4 * *
5 * This file is part of the Cabana library. Cabana is distributed under a *
6 * BSD 3-clause license. For the licensing terms see the LICENSE file in *
7 * the top-level directory. *
8 * *
9 * SPDX-License-Identifier: BSD-3-Clause *
10 ****************************************************************************/
11
12#ifndef CABANA_CARTESIANGRID_HPP
13#define CABANA_CARTESIANGRID_HPP
14
15#include <Kokkos_Core.hpp>
16
17#include <limits>
18#include <type_traits>
19
20namespace Cabana
21{
22namespace Impl
23{
25
26template <class Real, std::size_t NumSpaceDim = 3>
27class CartesianGrid
28{
29 static_assert( std::is_floating_point<Real>::value,
30 "Scalar type must be floating point type." );
31
32 public:
33 using real_type = Real;
34 static constexpr std::size_t num_space_dim = NumSpaceDim;
35
36 Kokkos::Array<real_type, num_space_dim> _min;
37 Kokkos::Array<real_type, num_space_dim> _max;
38 Kokkos::Array<real_type, num_space_dim> _dx;
39 Kokkos::Array<real_type, num_space_dim> _rdx;
40 Kokkos::Array<int, num_space_dim> _nx;
41
42 CartesianGrid() = default;
43
44 template <class ArrayType>
45 CartesianGrid( const ArrayType min, const ArrayType max,
46 const real_type delta_x )
47 {
48 Kokkos::Array<real_type, num_space_dim> delta;
49 for ( std::size_t d = 0; d < num_space_dim; ++d )
50 delta[d] = delta_x;
51 init( min, max, delta );
52 }
53
54 template <class ArrayType>
55 CartesianGrid( const ArrayType min, const ArrayType max,
56 const ArrayType delta )
57 {
58 init( min, max, delta );
59 }
60
61 template <class ArrayType, class DeltaArrayType>
62 void init( const ArrayType min, const ArrayType max,
63 const DeltaArrayType delta )
64 {
65 for ( std::size_t d = 0; d < num_space_dim; ++d )
66 {
67 _min[d] = min[d];
68 _max[d] = max[d];
69 _nx[d] = cellsBetween( max[d], min[d], 1.0 / delta[d] );
70 _dx[d] = ( max[d] - min[d] ) / _nx[d];
71 _rdx[d] = 1.0 / _dx[d];
72 }
73 }
74
75 template <std::size_t NSD = num_space_dim>
76 CartesianGrid( const Real min_x, const Real min_y, const Real min_z,
77 const Real max_x, const Real max_y, const Real max_z,
78 const Real delta_x, const Real delta_y, const Real delta_z,
79 typename std::enable_if<NSD == 3, int>::type* = 0 )
80 : _min( { min_x, min_y, min_z } )
81 , _max( { max_x, max_y, max_z } )
82 {
83 _nx[0] = cellsBetween( max_x, min_x, 1.0 / delta_x );
84 _nx[1] = cellsBetween( max_y, min_y, 1.0 / delta_y );
85 _nx[2] = cellsBetween( max_z, min_z, 1.0 / delta_z );
86
87 _dx[0] = ( max_x - min_x ) / _nx[0];
88 _dx[1] = ( max_y - min_y ) / _nx[1];
89 _dx[2] = ( max_z - min_z ) / _nx[2];
90
91 _rdx[0] = 1.0 / _dx[0];
92 _rdx[1] = 1.0 / _dx[1];
93 _rdx[2] = 1.0 / _dx[2];
94 }
95
96 // Get the total number of cells.
97 KOKKOS_INLINE_FUNCTION
98 std::size_t totalNumCells() const
99 {
100 std::size_t total = 1;
101 for ( std::size_t d = 0; d < num_space_dim; ++d )
102 total *= _nx[d];
103 return total;
104 }
105
106 // Get the number of cells in each direction.
107 template <std::size_t NSD = num_space_dim>
108 KOKKOS_INLINE_FUNCTION std::enable_if_t<3 == NSD, void>
109 numCells( int& num_x, int& num_y, int& num_z )
110 {
111 num_x = _nx[0];
112 num_y = _nx[1];
113 num_z = _nx[2];
114 }
115
116 // Get the number of cells in each direction.
117 template <std::size_t NSD = num_space_dim>
118 KOKKOS_INLINE_FUNCTION std::enable_if_t<2 == NSD, void>
119 numCells( int& num_x, int& num_y )
120 {
121 num_x = _nx[0];
122 num_y = _nx[1];
123 }
124
125 // Get the number of cells in a given direction.
126 KOKKOS_INLINE_FUNCTION
127 int numBin( const int dim ) const
128 {
129 assert( static_cast<std::size_t>( dim ) < num_space_dim );
130
131 if ( 0 == dim )
132 return _nx[0];
133 else if ( 1 == dim )
134 return _nx[1];
135 else if ( 2 == dim )
136 return _nx[2];
137 else
138 return -1;
139 }
140
141 // Given a position get the ijk indices of the cell in which
142 template <std::size_t NSD = num_space_dim>
143 KOKKOS_INLINE_FUNCTION std::enable_if_t<3 == NSD, void>
144 locatePoint( const Real xp, const Real yp, const Real zp, int& ic, int& jc,
145 int& kc ) const
146 {
147 // Since we use a floor function a point on the outer boundary
148 // will be found in the next cell, causing an out of bounds error
149 ic = cellsBetween( xp, _min[0], _rdx[0] );
150 ic = ( ic == _nx[0] ) ? ic - 1 : ic;
151 jc = cellsBetween( yp, _min[1], _rdx[1] );
152 jc = ( jc == _nx[1] ) ? jc - 1 : jc;
153 kc = cellsBetween( zp, _min[2], _rdx[2] );
154 kc = ( kc == _nx[2] ) ? kc - 1 : kc;
155 }
156
157 // Given a position get the ijk indices of the cell in which
158 template <std::size_t NSD = num_space_dim>
159 KOKKOS_INLINE_FUNCTION std::enable_if_t<2 == NSD, void>
160 locatePoint( const Real xp, const Real yp, int& ic, int& jc ) const
161 {
162 // Since we use a floor function a point on the outer boundary
163 // will be found in the next cell, causing an out of bounds error
164 ic = cellsBetween( xp, _min[0], _rdx[0] );
165 ic = ( ic == _nx[0] ) ? ic - 1 : ic;
166 jc = cellsBetween( yp, _min[1], _rdx[1] );
167 jc = ( jc == _nx[1] ) ? jc - 1 : jc;
168 }
169
170 // Given a position get the ijk indices of the cell in which
171 KOKKOS_INLINE_FUNCTION void
172 locatePoint( const Kokkos::Array<Real, num_space_dim> p,
173 Kokkos::Array<int, num_space_dim>& c ) const
174 {
175 // Since we use a floor function a point on the outer boundary
176 // will be found in the next cell, causing an out of bounds error
177 for ( std::size_t d = 0; d < num_space_dim; ++d )
178 {
179 c[d] = cellsBetween( p[d], _min[d], _rdx[d] );
180 c[d] = ( c[d] == _nx[d] ) ? c[d] - 1 : c[d];
181 }
182 }
183
184 // Given a position and a cell index get square of the minimum distance to
185 // that point to any point in the cell. If the point is in the cell the
186 // returned distance is zero.
187 template <std::size_t NSD = num_space_dim>
188 KOKKOS_INLINE_FUNCTION std::enable_if_t<3 == NSD, Real>
189 minDistanceToPoint( const Real xp, const Real yp, const Real zp,
190 const int ic, const int jc, const int kc ) const
191 {
192 Kokkos::Array<Real, num_space_dim> x;
193 x[0] = xp;
194 x[1] = yp;
195 x[2] = zp;
196 Kokkos::Array<int, num_space_dim> c;
197 c[0] = ic;
198 c[1] = jc;
199 c[2] = kc;
200
201 return minDistanceToPoint( x, c );
202 }
203
204 // Given a position and a cell index get square of the minimum distance to
205 // that point to any point in the cell. If the point is in the cell the
206 // returned distance is zero.
207 KOKKOS_INLINE_FUNCTION Real
208 minDistanceToPoint( const Kokkos::Array<Real, num_space_dim> x,
209 const Kokkos::Array<int, num_space_dim> c ) const
210 {
211 Real rsqr = 0.0;
212 for ( std::size_t d = 0; d < num_space_dim; ++d )
213 {
214 Real xc = _min[d] + ( c[d] + 0.5 ) * _dx[d];
215 Real rx = fabs( x[d] - xc ) - 0.5 * _dx[d];
216
217 rx = ( rx > 0.0 ) ? rx : 0.0;
218
219 rsqr += rx * rx;
220 }
221
222 return rsqr;
223 }
224
225 // Given the ijk index of a cell get its cardinal index.
226 template <std::size_t NSD = num_space_dim>
227 KOKKOS_INLINE_FUNCTION std::enable_if_t<3 == NSD, int>
228 cardinalCellIndex( const int i, const int j, const int k ) const
229 {
230 return ( i * _nx[1] + j ) * _nx[2] + k;
231 }
232
233 // Given the ij index of a cell get its cardinal index.
234 template <std::size_t NSD = num_space_dim>
235 KOKKOS_INLINE_FUNCTION std::enable_if_t<2 == NSD, int>
236 cardinalCellIndex( const int i, const int j ) const
237 {
238 return i * _nx[1] + j;
239 }
240
241 // Given the ij index of a cell get its cardinal index.
242 KOKKOS_INLINE_FUNCTION int
243 cardinalCellIndex( const Kokkos::Array<int, num_space_dim> ijk ) const
244 {
245 if constexpr ( num_space_dim == 3 )
246 return cardinalCellIndex( ijk[0], ijk[1], ijk[2] );
247 else
248 return cardinalCellIndex( ijk[0], ijk[1] );
249 }
250
251 template <std::size_t NSD = num_space_dim>
252 KOKKOS_INLINE_FUNCTION std::enable_if_t<3 == NSD, void>
253 ijkBinIndex( const int cardinal, int& i, int& j, int& k ) const
254 {
255 i = cardinal / ( _nx[1] * _nx[2] );
256 j = ( cardinal / _nx[2] ) % _nx[1];
257 k = cardinal % _nx[2];
258 }
259
260 template <std::size_t NSD = num_space_dim>
261 KOKKOS_INLINE_FUNCTION std::enable_if_t<2 == NSD, void>
262 ijkBinIndex( const int cardinal, int& i, int& j ) const
263 {
264 i = cardinal / ( _nx[1] );
265 j = cardinal % _nx[1];
266 }
267
268 KOKKOS_INLINE_FUNCTION void
269 ijkBinIndex( const int cardinal,
270 Kokkos::Array<int, num_space_dim>& ijk ) const
271 {
272 if constexpr ( num_space_dim == 3 )
273 return ijkBinIndex( cardinal, ijk[0], ijk[1], ijk[2] );
274 else
275 return ijkBinIndex( cardinal, ijk[0], ijk[1] );
276 }
277
278 // Calculate the number of full cells between 2 points.
279 KOKKOS_INLINE_FUNCTION
280 int cellsBetween( const Real max, const Real min, const Real rdelta ) const
281 {
282 return Kokkos::floor( ( max - min ) * rdelta );
283 }
284};
285
287} // end namespace Impl
288} // end namespace Cabana
289
290#endif // end CABANA_CARTESIANGRID_HPP
Core: particle data structures and algorithms.
Definition Cabana_AoSoA.hpp:36