Vlasiator ebf0dd394 on dev (v5.4.0 + 1054 commits)
Loading...
Searching...
No Matches
spatial_cell_gpu_kernels.hpp
Go to the documentation of this file.
1/*
2 * This file is part of Vlasiator.
3 * Copyright 2010-2024 Finnish Meteorological Institute and University of Helsinki
4 *
5 * For details of usage, see the COPYING file and read the "Rules of the Road"
6 * at http://www.physics.helsinki.fi/vlasiator/
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (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 License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23#ifndef VLASIATOR_SPATIAL_CELL_KERNELS_HPP
24#define VLASIATOR_SPATIAL_CELL_KERNELS_HPP
25
26#ifdef USE_WARPACCESSORS
27 #define USE_BATCH_WARPACCESSORS
28#endif
29
30// GPUTODO: Make error-checking functions to be called inside kernels instead of duplicating so much code.
31// Same for gathering mass loss.
32
36
38__global__ void __launch_bounds__(WID3,4) update_velocity_block_content_lists_kernel (
39 const vmesh::VelocityMesh* __restrict__ vmesh,
40 const vmesh::VelocityBlockContainer* __restrict__ blockContainer,
41 Hashinator::Hashmap<vmesh::GlobalID,vmesh::LocalID>* vbwcl_map,
42 Hashinator::Hashmap<vmesh::GlobalID,vmesh::LocalID>* vbwncl_map,
43 const Real velocity_block_min_value
44 ) {
45 // const int gpuBlocks = gridDim.x;
46 const int blocki = blockIdx.x;
47 const uint ti = threadIdx.x;
48
49 // Each GPU block / workunit can manage several Vlasiator velocity blocks at once.
50 const uint vlasiBlocksPerWorkUnit = 1;
51 const uint workUnitIndex = 0; // [0,vlasiBlocksPerWorkUnit)
52 // const uint vlasiBlocksPerWorkUnit = WARPSPERBLOCK * GPUTHREADS / WID3;
53 // const uint workUnitIndex = ti / WID3; // [0,vlasiBlocksPerWorkUnit)
54 const uint b_tid = ti % WID3; // [0,WID3)
55 const uint blockLID = blocki * vlasiBlocksPerWorkUnit + workUnitIndex; // [0,nBlocksToChange)
56
57 __shared__ int has_content[WARPSPERBLOCK * GPUTHREADS];
58 // maps can only be cleared from host
59 const uint nBlocks = vmesh->size();
60 if (blockLID < nBlocks) {
61 const vmesh::GlobalID blockGID = vmesh->getGlobalID(blockLID);
62 #ifdef DEBUG_SPATIAL_CELL
63 if (blockGID == vmesh->invalidGlobalID()) {
64 if (b_tid==0) {
65 printf("Invalid GID encountered in update_velocity_block_content_lists_kernel!\n");
66 }
67 return;
68 }
69 if (blockLID == vmesh->invalidLocalID()) {
70 if (b_tid==0) {
71 printf("Invalid LID encountered in update_velocity_block_content_lists_kernel!\n");
72 }
73 return;
74 }
75 #endif
76 // Check each velocity cell if it is above the threshold
77 const Realf* avgs = blockContainer->getData(blockLID);
78 has_content[ti] = avgs[b_tid] >= velocity_block_min_value ? 1 : 0;
79 __syncthreads(); // THIS SYNC IS CRUCIAL!
80 // Implemented just a simple non-optimized thread OR
81 // GPUTODO reductions via warp voting
82
83 // Perform loop only until first value fulfills condition
84 for (unsigned int s=WID3/2; s>0; s>>=1) {
85 if (has_content[0]) {
86 break;
87 }
88 if (b_tid < s) {
89 has_content[ti] = has_content[ti] || has_content[ti + s];
90 }
92 }
93 #ifdef USE_WARPACCESSORS
94 // Insert into map only from threads 0...WARPSIZE
95 if (b_tid < GPUTHREADS) {
96 if (has_content[0]) {
97 vbwcl_map->warpInsert(blockGID,blockLID,b_tid);
98 } else {
99 vbwncl_map->warpInsert(blockGID,blockLID,b_tid);
100 }
101 }
102 #else
103 // Insert into map only from thread 0
104 if (b_tid == 0) {
105 if (has_content[0]) {
106 vbwcl_map->set_element(blockGID,blockLID);
107 } else {
108 vbwncl_map->set_element(blockGID,blockLID);
109 }
110 }
111 #endif
113 }
114}
115
122//__launch_bounds__(GPUTHREADS,4)
124 const vmesh::VelocityMesh* __restrict__ vmesh,
125 const vmesh::LocalID velocity_block_with_content_list_size, // actually not used
126 const vmesh::GlobalID* __restrict__ velocity_block_with_content_list_data,
127 Hashinator::Hashmap<vmesh::GlobalID,vmesh::LocalID>* dev_velocity_block_with_content_map,
128 Hashinator::Hashmap<vmesh::GlobalID,vmesh::LocalID>* dev_velocity_block_with_no_content_map
129 ) {
130 //const int gpuBlocks = gridDim.x; // Equal to VB with content list size (or at least 1)
131 const int blocki = blockIdx.x;
132 const int ti = threadIdx.x;
133 //const int blockSize = blockDim.x; // should be 26*32 or 13*64
134 const int offsetIndex1 = ti / GPUTHREADS; // [0,26) (NVIDIA) or [0,13) (AMD)
135 const int w_tid = ti % GPUTHREADS; // [0,WARPSIZE)
136 // Assumes addWidthV = 1
137 #ifdef __CUDACC__
138 const int max_i=1;
139 #endif
140 #ifdef __HIP_PLATFORM_HCC___
141 const int max_i=2;
142 #endif
143 for (int i=0; i<max_i; i++) {
144 int offsetIndex = offsetIndex1 + 13*i;
145 // nudge latter half in order to exclude self
146 if (offsetIndex > 12) {
147 offsetIndex++;
148 }
149 const int offset_vx = (offsetIndex % 3) - 1;
150 const int offset_vy = ((offsetIndex / 3) % 3) - 1;
151 const int offset_vz = (offsetIndex / 9) - 1;
152 // Offsets verified in python
153 const vmesh::GlobalID GID = velocity_block_with_content_list_data[blocki];
154 vmesh::LocalID ind0,ind1,ind2;
155 vmesh->getIndices(GID,ind0,ind1,ind2);
156 const int nind0 = ind0 + offset_vx;
157 const int nind1 = ind1 + offset_vy;
158 const int nind2 = ind2 + offset_vz;
159 const vmesh::GlobalID nGID
160 = vmesh->getGlobalID(nind0,nind1,nind2);
161 #ifdef USE_WARPACCESSORS
162 // Does block already exist in mesh?
163 const vmesh::LocalID LID = vmesh->warpGetLocalID(nGID, w_tid);
164 // Try adding this nGID to velocity_block_with_content_map. If it exists, do not overwrite.
165 const bool newlyadded = dev_velocity_block_with_content_map->warpInsert_V<true>(nGID,LID, w_tid);
166 if (newlyadded) {
167 // Block did not previously exist in velocity_block_with_content_map
168 if ( LID != vmesh->invalidLocalID()) {
169 // Block exists in mesh, ensure it won't get deleted:
170 dev_velocity_block_with_no_content_map->warpErase(nGID, w_tid);
171 }
172 // else:
173 // Block does not yet exist in mesh at all. Needs adding!
174 // Identified as invalidLID entries in velocity_block_with_content_map.
175 }
176 #else
177 if (w_tid==0) {
178 // Does block already exist in mesh?
179 const vmesh::LocalID LID = vmesh->getLocalID(nGID);
180 // Add this nGID to velocity_block_with_content_map.
181 const bool newEntry = dev_velocity_block_with_content_map->set_element<true>(nGID,LID);
182 if (newEntry) {
183 // Block did not previously exist in velocity_block_with_content_map
184 if ( LID != vmesh->invalidLocalID()) {
185 // Block exists in mesh, ensure it won't get deleted:
186 dev_velocity_block_with_no_content_map->device_erase(nGID);
187 }
188 }
189 }
190 #endif
192 }
193}
194
197//__launch_bounds__(GPUTHREADS,4)
199 const vmesh::VelocityMesh* __restrict__ vmesh,
200 const uint neighbour_count,
201 const vmesh::GlobalID* __restrict__ const *dev_neigh_vbwcls,
202 const vmesh::LocalID* __restrict__ dev_neigh_Nvbwcls,
203 Hashinator::Hashmap<vmesh::GlobalID,vmesh::LocalID>* dev_velocity_block_with_content_map,
204 Hashinator::Hashmap<vmesh::GlobalID,vmesh::LocalID>* dev_velocity_block_with_no_content_map
205 ) {
206 //const int blockSize = blockDim.x; // should be 32*32 or 16*64
207 //const int gpuBlocks = gridDim.x; // Equal to count of neighbour content blocks divided by (warps/block)
208 const int ti = threadIdx.x; // [0,blockSize)
209 const int w_tid = ti % GPUTHREADS; // [0,WARPSIZE)
210 int myindex = blockIdx.x * WARPSPERBLOCK + ti / GPUTHREADS; // Starts off as total index
211 // Find which neighbour we should access
212 uint neigh_i = 0;
213 for (uint i=0; i<neighbour_count; i++) {
214 if (myindex < (int)dev_neigh_Nvbwcls[neigh_i]) {
215 break;
216 }
217 myindex -= dev_neigh_Nvbwcls[neigh_i];
218 neigh_i++;
219 } // Now we know which neighbour buffer to access
220 // Access neighbour GID from buffer and act on it
221 if (neigh_i < neighbour_count) {
222 const vmesh::GlobalID nGID = (dev_neigh_vbwcls[neigh_i])[myindex];
223 #ifdef USE_WARPACCESSORS
224 // Does block already exist in mesh?
225 const vmesh::LocalID LID = vmesh->warpGetLocalID(nGID, w_tid);
226 // Try adding this nGID to velocity_block_with_content_map. If it exists, do not overwrite.
227 const bool newlyadded = dev_velocity_block_with_content_map->warpInsert_V<true>(nGID,LID, w_tid);
228 if (newlyadded) {
229 // Block did not previously exist in velocity_block_with_content_map
230 if ( LID != vmesh->invalidLocalID()) {
231 // Block exists in mesh, ensure it won't get deleted:
232 dev_velocity_block_with_no_content_map->warpErase(nGID, w_tid);
233 }
234 // else:
235 // Block does not yet exist in mesh at all. Needs adding!
236 // Identified as invalidLID entries in velocity_block_with_content_map.
237 }
238 #else
239 if (w_tid==0) {
240 // Does block already exist in mesh?
241 const vmesh::LocalID LID = vmesh->getLocalID(nGID);
242 // Add this nGID to velocity_block_with_content_map.
243 const bool newEntry = dev_velocity_block_with_content_map->set_element<true>(nGID,LID);
244 if (newEntry) {
245 // Block did not previously exist in velocity_block_with_content_map
246 if ( LID != vmesh->invalidLocalID()) {
247 // Block exists in mesh, ensure it won't get deleted:
248 dev_velocity_block_with_no_content_map->device_erase(nGID);
249 }
250 }
251 }
252 #endif
254 }
255}
256
263 vmesh::VelocityMesh *dev_vmesh,
264 vmesh::VelocityBlockContainer *dev_blockContainer,
265 const vmesh::LocalID nLIDs // newSize
266 ) {
267 //const int gpuBlocks = gridDim.x;
268 const int blocki = blockIdx.x;
269 const int blockSize = blockDim.x*blockDim.y*blockDim.z;
270 const uint ti = threadIdx.z*blockDim.x*blockDim.y + threadIdx.y*blockDim.x + threadIdx.x;
271 // if (dev_blockContainer->size() != nLIDs) {
272 // dev_blockContainer->setNewSize(nLIDs);
273 // }
274
275 Hashinator::Hashmap<vmesh::GlobalID,vmesh::LocalID> *map = dev_vmesh->gpu_expose_map();
276 split::SplitVector<vmesh::GlobalID> *list = dev_vmesh->getGrid();
277
278 #ifdef USE_WARPACCESSORS
279 const uint w_tid = ti % GPUTHREADS;
280 const vmesh::LocalID LID = ti/GPUTHREADS + blocki*blockSize;
281 #else
282 const uint w_tid = 0;
283 const vmesh::LocalID LID = ti + blocki*blockSize;
284 #endif
285
286 if (LID < nLIDs) {
287 // Set velocity block parameters:
288 const vmesh::GlobalID GID = (*list)[LID];
289
290 #ifdef USE_WARPACCESSORS
291 // Add this GID to the velocity_block_with_content_map.
292 map->warpInsert_V<true>(GID,LID, w_tid);
293 #else
294 map->set_element<true>(GID,LID);
295 #endif
296 // Write in block parameters
297 if (w_tid==0) {
298 Real* blockParameters = dev_blockContainer->getParameters(LID);
300 }
301 }
302}
303
305__global__ void resize_vbc_kernel_pre(
307 vmesh::VelocityBlockContainer *blockContainer,
308 const split::SplitVector<vmesh::GlobalID>* __restrict__ list_with_replace_new,
309 const split::SplitVector<Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>>* __restrict__ list_delete,
310 const split::SplitVector<Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>>* __restrict__ list_to_replace,
311 const split::SplitVector<Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>>* __restrict__ list_with_replace_old,
312 vmesh::LocalID* returnLID, // return values: nbefore, nafter, nblockstochange, resize success
313 Realf* gpu_rhoLossAdjust // mass loss, set to zero
314 ) {
315 const vmesh::LocalID nBlocksBeforeAdjust = vmesh->size();
316 const vmesh::LocalID nToAdd = list_with_replace_new->size();
317 const vmesh::LocalID nToRemove = list_delete->size() + list_to_replace->size();
318 const vmesh::LocalID nBlocksAfterAdjust = nBlocksBeforeAdjust + nToAdd - nToRemove;
319 const vmesh::LocalID nBlocksToChange = nToAdd > nToRemove ? nToAdd : nToRemove;
320
321 gpu_rhoLossAdjust[0] = 0.0;
322 returnLID[0] = nBlocksBeforeAdjust;
323 returnLID[1] = nBlocksAfterAdjust;
324 returnLID[2] = nBlocksToChange;
325 // Should we grow the size?
326 if (nBlocksAfterAdjust > nBlocksBeforeAdjust) {
327 if ((nBlocksAfterAdjust <= vmesh->capacity()) && (nBlocksAfterAdjust <= blockContainer->capacity())) {
328 returnLID[3] = 1; // Resize on-device will work.
329 vmesh->device_setNewSize(nBlocksAfterAdjust);
330 blockContainer->setNewSize(nBlocksAfterAdjust);
331 } else {
332 returnLID[3] = 0; // Need to recapacitate and resize from host
333 }
334 } else {
335 // No error as no resize.
336 returnLID[3] = 1;
337 }
338}
339
343 vmesh::VelocityBlockContainer *blockContainer,
344 const vmesh::LocalID nBlocksAfterAdjust
345 ) {
346 vmesh->device_setNewSize(nBlocksAfterAdjust);
347 blockContainer->setNewSize(nBlocksAfterAdjust);
348}
349
351__global__ void __launch_bounds__(WID3,4) update_velocity_blocks_kernel(
352 vmesh::VelocityMesh *vmesh,
353 vmesh::VelocityBlockContainer *blockContainer,
354 const split::SplitVector<vmesh::GlobalID>* __restrict__ list_with_replace_new,
355 const split::SplitVector<Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>>* __restrict__ list_delete,
356 const split::SplitVector<Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>>* __restrict__ list_to_replace,
357 const split::SplitVector<Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>>* __restrict__ list_with_replace_old,
358 const vmesh::LocalID nBlocksBeforeAdjust,
359 const vmesh::LocalID nBlocksToChange,
360 const vmesh::LocalID nBlocksAfterAdjust,
361 Realf* gpu_rhoLossAdjust
362 ) {
363 //const int gpuBlocks = gridDim.x;
364 //const int blocki = blockIdx.x;
365 //const int blockSize = blockDim.x; // WID3
366 const uint ti = threadIdx.x; // [0,blockSize)
367
368 // Each GPU block / workunit could manage several Vlasiator velocity blocks at once.
369 // However, thread syncs inside the kernel prevent this.
370 //const uint vlasiBlocksPerWorkUnit = WARPSPERBLOCK * GPUTHREADS / WID3;
371 //const uint workUnitIndex = ti / WID3; // [0,vlasiBlocksPerWorkUnit)
372 //const uint index = blocki * vlasiBlocksPerWorkUnit + workUnitIndex; // [0,nBlocksToChange)
373 //const uint vlasiBlocksPerWorkUnit = 1;
374 //const uint workUnitIndex = 1;
375
376 // This index into vectors can be adjusted along the way
377 uint index = (uint)blockIdx.x;
378
379 const int b_tid = ti % WID3; // [0,WID3)
380
381 const vmesh::LocalID n_with_replace_new = list_with_replace_new->size();
382 const vmesh::LocalID n_delete = list_delete->size();
383 const vmesh::LocalID n_to_replace = list_to_replace->size();
384 const vmesh::LocalID n_with_replace_old = list_with_replace_old->size();
385 // For tracking mass-loss
386 //__shared__ Realf massloss[blockSize];
387 __shared__ Realf massloss[WID3];
388
389 // Each block / workunit Processes one block from the lists.
390
391 /*********
392 Check if should delete item from end of vmesh.
393 For this, we get both GID and LID from the vector.
394 **/
395 if (index < n_delete) {
396 #ifdef DEBUG_SPATIAL_CELL
397 const vmesh::GlobalID rmGID = (list_delete->at(index)).first;
398 const vmesh::GlobalID rmLID = (list_delete->at(index)).second;
399 #else
400 const vmesh::GlobalID rmGID = ((*list_delete)[index]).first;
401 const vmesh::GlobalID rmLID = ((*list_delete)[index]).second;
402 #endif
403
404 #ifdef DEBUG_SPATIAL_CELL
405 if (rmGID == vmesh->invalidGlobalID()) {
406 if (rmLID != vmesh->invalidLocalID()) {
407 // Valid LID but invalid GID: only remove from vmesh localToGlobal?
408 if (b_tid==0) {
409 printf("Removing blocks: Valid LID %u but invalid GID!\n",rmLID);
410 }
411 } else {
412 if (b_tid==0) {
413 printf("Removing blocks: Invalid LID and GID!\n");
414 }
415 }
416 return;
417 }
418 if (rmLID == vmesh->invalidLocalID()) {
419 if (rmGID != vmesh->invalidGlobalID()) {
420 // Valid GID but invalid LID: only remove from vmesh globalToLocal?
421 if (b_tid==0) {
422 printf("Removing blocks: Valid GID %ul but invalid LID!\n",rmGID);
423 }
424 }
425 return;
426 }
427 if ((unsigned long)rmLID >= (unsigned long)nBlocksBeforeAdjust) {
428 if (b_tid==0) {
429 printf("Trying to outright remove block which has LID %ul >= nBlocksBeforeAdjust %ul!\n",rmLID,nBlocksBeforeAdjust);
430 }
431 return;
432 }
433 if ((unsigned long)rmLID < (unsigned long)nBlocksAfterAdjust) {
434 if (b_tid==0) {
435 printf("Trying to outright remove block which has LID %u smaller than nBlocksAfterAdjust %u!\n",rmLID,nBlocksAfterAdjust);
436 }
437 return;
438 }
439 #endif
440
441 // Track mass loss:
442 Realf* rm_avgs = blockContainer->getData(rmLID);
443 Real* rm_block_parameters = blockContainer->getParameters(rmLID);
444 const Real rm_DV3 = rm_block_parameters[BlockParams::DVX]
445 * rm_block_parameters[BlockParams::DVY]
446 * rm_block_parameters[BlockParams::DVZ];
447 // thread-sum for rho
448 massloss[ti] = rm_avgs[b_tid]*rm_DV3;
450 // Implemented just a simple non-optimized thread sum
451 for (int s=WID3/2; s>0; s>>=1) {
452 if (b_tid < s) {
453 massloss[ti] += massloss[ti + s];
454 }
456 }
457 // Bookkeeping only by one thread
458 if (b_tid==0) {
459 Realf old = atomicAdd(gpu_rhoLossAdjust, massloss[ti]);
460 }
462
463 // Delete from vmesh
464 #ifdef USE_WARPACCESSORS
465 vmesh->warpDeleteBlock(rmGID,rmLID,b_tid);
466 #else
467 if (b_tid==0) {
468 vmesh->deleteBlock(rmGID,rmLID);
469 }
470 #endif
471 // GPUTODO debug checks
472 return;
473 }
474 index -= n_delete;
475
476 /*********
477 Check if should replace existing block with either
478 existing block from end of vmesh or new block
479 **/
480 if (index < n_to_replace) {
481 #ifdef DEBUG_SPATIAL_CELL
482 const vmesh::GlobalID rmGID = (list_to_replace->at(index)).first;
483 const vmesh::GlobalID rmLID = (list_to_replace->at(index)).second;
484 #else
485 const vmesh::GlobalID rmGID = ((*list_to_replace)[index]).first;
486 const vmesh::GlobalID rmLID = ((*list_to_replace)[index]).second;
487 #endif
488 //const vmesh::LocalID rmLID = vmesh->warpGetLocalID(rmGID,b_tid);
489
490 #ifdef DEBUG_SPATIAL_CELL
491 if (rmGID == vmesh->invalidGlobalID()) {
492 if (rmLID != vmesh->invalidLocalID()) {
493 // Valid LID but invalid GID: only remove from vmesh localToGlobal?
494 if (b_tid==0) {
495 printf("Replacing blocks: Valid LID %u but invalid GID!\n",rmLID);
496 }
497 } else {
498 if (b_tid==0) {
499 printf("Replacing blocks: Invalid LID and GID!\n");
500 }
501 }
502 return;
503 }
504 if (rmLID == vmesh->invalidLocalID()) {
505 if (rmGID != vmesh->invalidGlobalID()) {
506 // Valid GID but invalid LID: only remove from vmesh globalToLocal?
507 if (b_tid==0) {
508 printf("Replacing blocks: Valid GID %ul but invalid LID!\n",rmGID);
509 }
510 }
511 return;
512 }
513 if (rmLID >= nBlocksBeforeAdjust) {
514 if (b_tid==0) {
515 printf("Trying to replace block which has LID %ul >= nBlocksBeforeAdjust %ul!\n",rmLID,nBlocksBeforeAdjust);
516 }
517 return;
518 }
519 #endif
520
521 // Track mass loss:
522 Realf* rm_avgs = blockContainer->getData(rmLID);
523 Real* rm_block_parameters = blockContainer->getParameters(rmLID);
524 const Real rm_DV3 = rm_block_parameters[BlockParams::DVX]
525 * rm_block_parameters[BlockParams::DVY]
526 * rm_block_parameters[BlockParams::DVZ];
527 // thread-sum for rho
528 massloss[ti] = rm_avgs[b_tid]*rm_DV3;
530 // Implemented just a simple non-optimized thread sum
531 for (int s=WID3/2; s>0; s>>=1) {
532 if (b_tid < s) {
533 massloss[ti] += massloss[ti + s];
534 }
536 }
537 // Bookkeeping only by one thread
538 if (b_tid==0) {
539 Realf old = atomicAdd(gpu_rhoLossAdjust, massloss[ti]);
540 }
542
543 // Figure out what to use as replacement
544 vmesh::GlobalID replaceGID;
545 vmesh::LocalID replaceLID;
546
547 // First option: replace with existing block from end of vmesh
548 if (index < n_with_replace_old) {
549 #ifdef DEBUG_SPATIAL_CELL
550 replaceGID = (list_with_replace_old->at(index)).first;
551 replaceLID = (list_with_replace_old->at(index)).second;
552 #else
553 replaceGID = ((*list_with_replace_old)[index]).first;
554 replaceLID = ((*list_with_replace_old)[index]).second;
555 #endif
556
557 Realf* repl_avgs = blockContainer->getData(replaceLID);
558 Real* repl_block_parameters = blockContainer->getParameters(replaceLID);
559 rm_avgs[b_tid] = repl_avgs[b_tid];
561 rm_block_parameters[b_tid] = repl_block_parameters[b_tid];
562 }
564
565 } else {
566 // Second option: add new block instead
567 #ifdef DEBUG_SPATIAL_CELL
568 replaceGID = list_with_replace_new->at(index - n_with_replace_old);
569 #else
570 replaceGID = (*list_with_replace_new)[index - n_with_replace_old];
571 #endif
572 replaceLID = vmesh->invalidLocalID();
573
574 rm_avgs[b_tid] = 0;
575 if (b_tid==0) {
576 // Write in block parameters
577 vmesh->getBlockInfo(replaceGID, rm_block_parameters+BlockParams::VXCRD);
578 }
580 }
581 // Remove hashmap entry for removed block, add instead created block
582 #ifdef USE_WARPACCESSORS
583 vmesh->warpReplaceBlock(rmGID,rmLID,replaceGID,b_tid);
584 #else
585 if (b_tid==0) {
586 vmesh->replaceBlock(rmGID,rmLID,replaceGID);
587 }
588 #endif
589
590 #ifdef DEBUG_SPATIAL_CELL
592 if (vmesh->getGlobalID(rmLID) != replaceGID) {
593 if (b_tid==0) {
594 printf("Error! Replacing did not result in wanted GID at old LID in update_velocity_blocks_kernel! \n");
595 }
597 }
598 if (vmesh->getLocalID(replaceGID) != rmLID) {
599 if (b_tid==0) {
600 printf("Error! Replacing did not result in old LID at replaced GID in update_velocity_blocks_kernel! \n");
601 }
603 }
604 #endif
605
606 return;
607 }
608 index -= n_to_replace;
609
610 /*********
611 Finally check if we should add new block after end of current vmesh
612 We have reserved/used some entries from the beginning of the list_with_replace_new
613 for the previous section, so now we access that with a different index.
614 **/
615 const uint add_index = index + (n_to_replace - n_with_replace_old);
616 if (add_index < n_with_replace_new) {
617 #ifdef DEBUG_SPATIAL_CELL
618 const vmesh::GlobalID addGID = list_with_replace_new->at(add_index);
619 if (b_tid==0) {
620 if (vmesh->getLocalID(addGID) != vmesh->invalidLocalID()) {
621 printf("Trying to add new GID %u to mesh which already contains it! index=%u addindex=%u\n",addGID,index,add_index);
622 }
623 }
624 #else
625 const vmesh::GlobalID addGID = (*list_with_replace_new)[add_index];
626 #endif
627
628 // We need to add the data of addGID to a new LID. Here we still use the regular index.
629 const vmesh::LocalID addLID = nBlocksBeforeAdjust + index;
630 Realf* add_avgs = blockContainer->getData(addLID);
631 #ifdef DEBUG_SPATIAL_CELL
632 if (addGID == vmesh->invalidGlobalID()) {
633 printf("Error! invalid addGID!\n");
634 return;
635 }
636 if (addLID == vmesh->invalidLocalID()) {
637 printf("Error! invalid addLID!\n");
638 return;
639 }
640 #endif
641 Real* add_block_parameters = blockContainer->getParameters(addLID);
642 // Zero out blockdata
643 add_avgs[b_tid] = 0;
644 if (b_tid==0) {
645 // Write in block parameters
646 vmesh->getBlockInfo(addGID, add_block_parameters+BlockParams::VXCRD);
647 }
649
650 // Insert new hashmap entry into vmesh
651 #ifdef USE_WARPACCESSORS
652 vmesh->warpPlaceBlock(addGID,addLID,b_tid);
653 #else
654 if (b_tid==0) {
655 vmesh->placeBlock(addGID,addLID);
656 }
657 #endif
658
659 #ifdef DEBUG_SPATIAL_CELL
661 if (vmesh->getGlobalID(addLID) == vmesh->invalidGlobalID()) {
662 printf("Error! invalid GID after add from addLID!\n");
663 }
664 if (vmesh->getLocalID(addGID) == vmesh->invalidLocalID()) {
665 printf("Error! invalid LID after add from addGID!\n");
666 }
667 #endif
668 return;
669 }
670
671 // Fall-through error!
672 if (b_tid==0) {
673 printf("Error! Fall through in update_velocity_blocks_kernel! index %u nBlocksBeforeAdjust %u nBlocksAfterAdjust %u \n",
674 index,nBlocksBeforeAdjust,nBlocksAfterAdjust);
675 }
677}
678
679#endif
for i
Definition Dispersion.m:24
#define WARPSPERBLOCK
#define GPUTHREADS
ARCH_HOSTDEV bool setNewSize(const vmesh::LocalID newSize)
ARCH_HOSTDEV Hashinator::Hashmap< vmesh::GlobalID, vmesh::LocalID > * gpu_expose_map()
std::vector< vmesh::GlobalID > * getGrid()
void getBlockInfo(const vmesh::GlobalID &globalID, Real *array) const
const int WID3
Definition common.h:517
float Real
Definition definitions.h:41
float Realf
Definition definitions.h:33
const uint ti
split::SplitVector< vmesh::GlobalID > * list_with_replace_new
const int blockSize
const Real *__restrict__ blockParameters
__syncthreads()
#define index(i, j, k)
@ N_VELOCITY_BLOCK_PARAMS
Definition common.h:115
uint32_t uint
uint32_t LocalID
Definition definitions.h:60
uint32_t GlobalID
Definition definitions.h:59
__global__ void update_neighbour_halo_kernel(const vmesh::VelocityMesh *__restrict__ vmesh, const uint neighbour_count, const vmesh::GlobalID *__restrict__ const *dev_neigh_vbwcls, const vmesh::LocalID *__restrict__ dev_neigh_Nvbwcls, Hashinator::Hashmap< vmesh::GlobalID, vmesh::LocalID > *dev_velocity_block_with_content_map, Hashinator::Hashmap< vmesh::GlobalID, vmesh::LocalID > *dev_velocity_block_with_no_content_map)
__global__ void __launch_bounds__(WID3, 4) update_velocity_block_content_lists_kernel(const vmesh
__global__ void resize_vbc_kernel_pre(vmesh::VelocityMesh *vmesh, vmesh::VelocityBlockContainer *blockContainer, const split::SplitVector< vmesh::GlobalID > *__restrict__ list_with_replace_new, const split::SplitVector< Hashinator::hash_pair< vmesh::GlobalID, vmesh::LocalID > > *__restrict__ list_delete, const split::SplitVector< Hashinator::hash_pair< vmesh::GlobalID, vmesh::LocalID > > *__restrict__ list_to_replace, const split::SplitVector< Hashinator::hash_pair< vmesh::GlobalID, vmesh::LocalID > > *__restrict__ list_with_replace_old, vmesh::LocalID *returnLID, Realf *gpu_rhoLossAdjust)
__global__ void update_velocity_halo_kernel(const vmesh::VelocityMesh *__restrict__ vmesh, const vmesh::LocalID velocity_block_with_content_list_size, const vmesh::GlobalID *__restrict__ velocity_block_with_content_list_data, Hashinator::Hashmap< vmesh::GlobalID, vmesh::LocalID > *dev_velocity_block_with_content_map, Hashinator::Hashmap< vmesh::GlobalID, vmesh::LocalID > *dev_velocity_block_with_no_content_map)
__global__ void resize_vbc_kernel_post(vmesh::VelocityMesh *vmesh, vmesh::VelocityBlockContainer *blockContainer, const vmesh::LocalID nBlocksAfterAdjust)
__global__ void update_vmesh_and_blockparameters_kernel(vmesh::VelocityMesh *dev_vmesh, vmesh::VelocityBlockContainer *dev_blockContainer, const vmesh::LocalID nLIDs)