Vlasiator ebf0dd394 on dev (v5.4.0 + 1054 commits)
Loading...
Searching...
No Matches
spatial_cell_gpu.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 */
25
26#ifndef VLASIATOR_SPATIAL_CELL_GPU_HPP
27#define VLASIATOR_SPATIAL_CELL_GPU_HPP
28
29#include <algorithm>
30#include <cmath>
31#include <fstream>
32#include <iostream>
33#include <mpi.h>
34#include <limits>
35#include <stdint.h>
36#include <vector>
37#include <array>
38#include <unordered_map>
39#include <set>
40#include <map>
41#include <phiprof.hpp>
42#include <tuple>
43
44#include "../memoryallocation.h"
45#include "../common.h"
46#include "../parameters.h"
47#include "../definitions.h"
48
49#include "velocity_mesh_gpu.h"
51
52#ifdef DEBUG_VLASIATOR
53 #ifndef DEBUG_SPATIAL_CELL
54 #define DEBUG_SPATIAL_CELL
55 #endif
56#endif
57
58namespace spatial_cell {
59
61 __global__ static void resize_vmesh_ondevice_kernel (
63 vmesh::LocalID nBlocks
64 ) {
65 vmesh->device_setNewSize(nBlocks);
66 }
67
69 __global__ static void __launch_bounds__(WID3,4) population_scale_kernel (
70 vmesh::LocalID nBlocks,
71 vmesh::VelocityMesh *vmesh,
72 vmesh::VelocityBlockContainer *blockContainer,
73 const Real factor
74 ) {
75 const int blocki = blockIdx.x;
76 const int i = threadIdx.x;
77 const int j = threadIdx.y;
78 const int k = threadIdx.z;
79 const uint ti = k*WID2 + j*WID + i;
80 // loop over whole velocity space and scale the values
81 const uint blockLID = blocki;
82 // Pointer to target block data
83 Realf* data = blockContainer->getData(blockLID);
84 // Scale value
85 data[ti] = data[ti] * factor;
86 }
87
91 __global__ static void __launch_bounds__(WID3,4) population_increment_kernel (
92 vmesh::LocalID nBlocks,
93 vmesh::VelocityMesh *vmesh,
94 vmesh::VelocityBlockContainer *blockContainer,
95 vmesh::VelocityMesh *otherVmesh,
96 vmesh::VelocityBlockContainer *otherBlockContainer,
97 const Real factor
98 // GPUTODO: This could gather into a vector GIDs and (invalidGIDs) of only those GIDs which need to be added
99 // and call another kernel to do just that?
100 ) {
101 //const int gpuBlocks = gridDim.x;
102 //const int blocki = blockIdx.x;
103 const int i = threadIdx.x;
104 const int j = threadIdx.y;
105 const int k = threadIdx.z;
106 const uint ti = k*WID2 + j*WID + i;
107 // if (gpuBlocks != 1) {
108 // if (ti==0 && blocki==0) {
109 // printf("Warning! Calling population_increment_new_kernel from parallel region!\n");
110 // }
111 // }
112 // for (vmesh::LocalID incLID=blocki; incLID<nBlocks; incLID += gpuBlocks) {
113 for (vmesh::LocalID incLID=0; incLID<nBlocks; incLID++) {
114 const Realf* fromData = otherBlockContainer->getData(incLID);
115 // Global ID of the block containing incoming data
116 const vmesh::GlobalID GID = otherVmesh->getGlobalID(incLID);
117 // Get local ID of the target block. If the block doesn't exist, create it.
118 __shared__ vmesh::LocalID writeLID;
119 #ifdef USE_WARPACCESSORS
120 vmesh::LocalID toLID = vmesh->warpGetLocalID(GID,ti);
121 #else
122 vmesh::LocalID toLID = vmesh->getLocalID(GID);
123 #endif
124 if (toLID == vmesh->invalidLocalID()) {
125 #ifdef USE_WARPACCESSORS
126 bool created = vmesh->warpPush_back(GID, ti);
127 #else
128 __shared__ bool created;
129 if (ti==0) {
130 created = vmesh->push_back(GID);
131 }
133 #endif
134 // Thread zero must create new block
135 if (ti==0) {
136 if (!created) {
137 assert(0 && "Error in incrementing blockContainer in population_increment_kernel!");
138 }
139 toLID = blockContainer->push_back();
140 Real* parameters = blockContainer->getParameters(toLID);
141 vmesh->getBlockInfo(GID, parameters+BlockParams::VXCRD);
142 // make new LID available to all threads
143 writeLID = toLID;
144 }
146 Realf* toData = blockContainer->getData(writeLID);
147 if (created) {
148 // Write values from source cells
149 toData[ti] = fromData[ti] * factor;
150 }
151 } else {
152 // Increment with values from source cells
153 Realf* toData = blockContainer->getData(toLID);
154 toData[ti] += fromData[ti] * factor;
155 }
156 } // for-loop over velocity blocks
157 }
160 __global__ static void __launch_bounds__(WID3,4) population_replace_kernel (
161 vmesh::VelocityMesh *vmesh,
162 vmesh::VelocityBlockContainer *blockContainer,
163 vmesh::VelocityMesh *otherVmesh,
164 vmesh::VelocityBlockContainer *otherBlockContainer
165 ) {
166 //const int gpuBlocks = gridDim.x; // incoming LID count - use same GID-LID-pairs as incoming
167 const vmesh::LocalID LID = blockIdx.x;
168 const int i = threadIdx.x;
169 const int j = threadIdx.y;
170 const int k = threadIdx.z;
171 const uint ti = k*WID2 + j*WID + i;
172 // Assumes vmesh and VBC vmesh have correct size before kernel is launched.
173 // They are set before calling this kernel in setNewsizeClear()
174 size_t newSize = otherVmesh->size();
175 #ifdef DEBUG_SPATIAL_CELL
176 if (ti==0) { // Check sizes
177 if (blockContainer->size() != newSize) {
178 printf("Incorrect VBC size in population replace kernel!\n");
179 blockContainer->setNewSize(newSize);
180 }
181 if (vmesh->size() != newSize) {
182 printf("Incorrect vmesh size in population replace kernel!\n");
183 vmesh->device_setNewSize(newSize);
184 }
185 }
187 #endif
188 // Global ID of the block containing incoming data
189 const vmesh::GlobalID GID = otherVmesh->getGlobalID(LID);
190 // Create block in vmesh
191 #ifdef USE_WARPACCESSORS
192 vmesh->warpPlaceBlock(GID,LID,ti);
193 #else
194 if (ti==0) {
195 vmesh->placeBlock(GID,LID);
196 }
198 #endif
199 // Write values from source cells
200 const Realf* fromData = otherBlockContainer->getData(LID);
201 Realf* toData = blockContainer->getData(LID);
202 toData[ti] = fromData[ti];
203 // copy over also blockParameters
204 const Real* fromParameters = otherBlockContainer->getParameters(LID);
205 Real* toParameters = blockContainer->getParameters(LID);
207 toParameters[ti] = fromParameters[ti];
208 }
209 }
215__global__ static void resize_and_empty_kernel (
217 vmesh::VelocityBlockContainer *blockContainer,
218 vmesh::LocalID newSize
219 ) {
220 const int ti = threadIdx.x;
221 const int blockSize = blockDim.x;
222 if (ti==0) {
223 // assert checks already happen in the actual setNewSize calls
224 // assert(vmesh->capacity() >= newSize && "Insufficient vmesh capacity in resize_and_empty_kernel!");
225 // assert(blockContainer->capacity() >= newSize && "Insufficient VBC capacity in resize_and_empty_kernel!");
226 vmesh->device_setNewSize(newSize);
227 blockContainer->setNewSize(newSize);
228 }
230 // check map sizepower
231 Hashinator::Hashmap<vmesh::GlobalID,vmesh::LocalID> *globalToLocalMap = vmesh->gpu_expose_map();
232 Hashinator::Info *info = globalToLocalMap->expose_mapinfo<false>();
233 // Set map fill to zero. Target goal is to have empty map. Even if we need
234 // to recapacitate the map, this will lead to a clean new allocation without
235 // copying old key-value-pairs over.
236 info->fill=0;
237 const size_t len = globalToLocalMap->bucket_count();
238 const vmesh::GlobalID emptybucket = globalToLocalMap->get_emptybucket();
239 Hashinator::hash_pair<vmesh::GlobalID, vmesh::LocalID>* dst = globalToLocalMap->expose_bucketdata<false>();
240 for (size_t i = ti; i < len; i+=blockSize) {
241 if (dst[i].first != emptybucket) {
242 dst[i].first = emptybucket;
243 }
244 }
245}
246
252 struct Population {
253 Real RHO;
254 Real V[3];
255 Real RHO_R;
256 Real V_R[3];
257 Real RHO_V;
258 Real V_V[3];
259 Real P[6];
260 Real P_R[6];
261 Real P_V[6];
262 Real RHOLOSSADJUST = 0.0;
263 Real max_dt[2];
265 vmesh::LocalID reservation = 0; /* Guidance on vector size reservation */
266
267 uint ACCSUBCYCLES;
274 std::vector<char> compressed_state_buffer;
275 float mlp_error = {std::numeric_limits<float>::max()};
276 uint32_t mlp_epochs = {0};
277
278 /* pointers to device copies of vmesh and vbc */
279 size_t dev_vmesh = 0;
281
287
288 // Constructor, destructor
292 // Host registers seem to break in multi-gpu per node runs
293 // CHK_ERR(gpuHostRegister(&vmesh, sizeof(vmesh::VelocityMesh*),gpuHostRegisterPortable));
294 // CHK_ERR(gpuHostRegister(&blockContainer, sizeof(vmesh::VelocityBlockContainer*),gpuHostRegisterPortable));
295 // CHK_ERR(gpuHostRegister(vmesh, sizeof(vmesh::VelocityMesh),gpuHostRegisterPortable));
296 // CHK_ERR(gpuHostRegister(blockContainer, sizeof(vmesh::VelocityBlockContainer),gpuHostRegisterPortable));
297 gpuStream_t stream = gpu_getStream();
298 gpuMemoryManager.createPointer(dev_vmesh);
300 gpuMemoryManager.allocateAsync(dev_vmesh, sizeof(vmesh::VelocityMesh), stream);
304 // Set values to zero in case of zero-block populations
306 for (uint i=0; i<2; ++i) {
307 max_dt[i] = 0;
308 }
309 for (uint i=0; i<3; ++i) {
310 V[i] = V_R[i] = V_V[i] = 0;
311 }
312 for (uint i=0; i<6; i++) {
313 P[i] = P_R[i] = P_V[i] = 0;
314 }
315 }
318 gpuMemoryManager.freePointer(dev_vmesh);
319 }
322 }
323 delete vmesh;
324 delete blockContainer;
325 }
326 Population(const Population& other) {
327 vmesh = new vmesh::VelocityMesh(*(other.vmesh));
328 blockContainer = new vmesh::VelocityBlockContainer(*(other.blockContainer));
329 // Host registers seem to break in multi-gpu per node runs
330 // CHK_ERR(gpuHostRegister(&vmesh, sizeof(vmesh::VelocityMesh*),gpuHostRegisterPortable));
331 // CHK_ERR(gpuHostRegister(&blockContainer, sizeof(vmesh::VelocityBlockContainer*),gpuHostRegisterPortable));
332 // CHK_ERR(gpuHostRegister(vmesh, sizeof(vmesh::VelocityMesh),gpuHostRegisterPortable));
333 // CHK_ERR(gpuHostRegister(blockContainer, sizeof(vmesh::VelocityBlockContainer),gpuHostRegisterPortable));
334 gpuStream_t stream = gpu_getStream();
335 gpuMemoryManager.createPointer(dev_vmesh);
337 gpuMemoryManager.allocateAsync(dev_vmesh, sizeof(vmesh::VelocityMesh), stream);
341
342 RHO = other.RHO;
343 RHO_R = other.RHO_R;
344 RHO_V = other.RHO_V;
345 RHOLOSSADJUST = other.RHOLOSSADJUST;
346 velocityBlockMinValue = other.velocityBlockMinValue;
347 ACCSUBCYCLES = other.ACCSUBCYCLES;
348 N_blocks = other.N_blocks;
349 reservation = other.reservation;
350 for (uint i=0; i<2; ++i) {
351 max_dt[i] = other.max_dt[i];
352 }
353 for (uint i=0; i<3; ++i) {
354 V[i] = other.V[i];
355 V_R[i] = other.V_R[i];
356 V_V[i] = other.V_V[i];
357 }
358 for (uint i=0; i<6; i++) {
359 P[i] = other.P[i];
360 P_R[i] = other.P_R[i];
361 P_V[i] = other.P_V[i];
362 }
363 vmesh->updateCachedSize();
364 blockContainer->updateCachedSize();
365 vmesh->updateCachedCapacity();
366 blockContainer->updateCachedCapacity();
367 }
368 const Population& operator=(const Population& other) {
369 gpuStream_t stream = gpu_getStream();
370 const vmesh::LocalID newSize = other.vmesh->size();
371 ResizeClear(newSize); // Updates cached values too
372
373 if (newSize > 0) {
374 dim3 block(WID,WID,WID);
375 population_replace_kernel<<<newSize, block, 0, stream>>> (
378 gpuMemoryManager.getPointer<vmesh::VelocityMesh>(other.dev_vmesh),
379 gpuMemoryManager.getPointer<vmesh::VelocityBlockContainer>(other.dev_blockContainer)
380 );
382 }
383
384 #ifdef DEBUG_SPATIAL_CELL
385 vmesh->check();
386 #endif
387
388 RHO = other.RHO;
389 RHO_R = other.RHO_R;
390 RHO_V = other.RHO_V;
391 RHOLOSSADJUST = other.RHOLOSSADJUST;
392 velocityBlockMinValue = other.velocityBlockMinValue;
393 ACCSUBCYCLES = other.ACCSUBCYCLES;
394 N_blocks = newSize;
395 reservation = other.reservation;
396 for (uint i=0; i<2; ++i) {
397 max_dt[i] = other.max_dt[i];
398 }
399 for (uint i=0; i<3; ++i) {
400 V[i] = other.V[i];
401 V_R[i] = other.V_R[i];
402 V_V[i] = other.V_V[i];
403 }
404 for (uint i=0; i<6; i++) {
405 P[i] = other.P[i];
406 P_R[i] = other.P_R[i];
407 P_V[i] = other.P_V[i];
408 }
409 return *this;
410 }
411
418
419 void ResizeClear(const uint newSize) {
420 // Clears the vmesh globalToLocalMap. Ensures the vmesh localToGlobalMap is of the requested size
421 // and that the VBC has the correct size, but does not alter contents of these.
422 gpuStream_t stream = gpu_getStream();
423
424 const bool reallocated1 = blockContainer->setNewCapacity(newSize);
425 const bool reallocated2 = vmesh->setNewCapacity(newSize);
426 // vmesh->print_sizes();
427 if (reallocated1 || reallocated2) { // Beware short-circuit evaluation, don't place the recapacitations inside this check!
428 Upload();
429 }
430
431 // The following kernel tries to resize the vmesh localToGlobalMap,
432 // clears the vmesh GlobalToLocalMap, and resizes the velocity block container.
433 // Contents of the localToGlobalMap or the VBC are not edited.
437 newSize
438 );
440 vmesh->setNewCachedSize(newSize);
441 blockContainer->setNewCachedSize(newSize);
442 // CHK_ERR( gpuStreamSynchronize(stream) );
443 }
444
445 void Scale(creal factor) {
446 RHO *= factor;
447 RHO_R *= factor;
448 RHO_V *= factor;
449 for (uint i=0; i<3; ++i) {
450 P[i] *= factor;
451 P_R[i] *= factor;
452 P_V[i] *= factor;
453 }
454 // Now loop over whole velocity space and scale the values
455 vmesh::LocalID nBlocks = vmesh->size();
456 gpuStream_t stream = gpu_getStream();
457 if (nBlocks > 0) {
458 dim3 block(WID,WID,WID);
459 population_scale_kernel<<<nBlocks, block, 0, stream>>> (
460 nBlocks,
463 factor
464 );
466 CHK_ERR( gpuStreamSynchronize(stream) );
467 }
468 }
469 void Increment(const Population& other, creal factor) {
470 // Note: moments will be invalidated.
471 // Ensure the vmesh and VBC are large enough
472 if (factor==0) {
473 // Nothing to add
474 return;
475 }
476 gpuStream_t stream = gpu_getStream();
477 vmesh::LocalID nBlocks = (other.vmesh)->size();
478 vmesh::LocalID nExistingBlocks = vmesh->size();
479 // GPUTODO: Find union size first and allocate based on that?
480 vmesh->setNewCapacity(nExistingBlocks + nBlocks + 1);
481 blockContainer->setNewCapacity(nExistingBlocks + nBlocks + 1);
482 Upload(); // GPUTODO: Only upload if new capacity required re-allocation. VBC setNewCapacity
483 // already returns bool, vmesh not yet.
484 CHK_ERR( gpuStreamSynchronize(stream) );
485 // Loop over the whole velocity space, and add scaled values with
486 // a kernel. Addition of new blocks is not block-parallel-safe.
487 if (nBlocks > 0) {
488 dim3 block(WID,WID,WID);
489 // Now serial
490 population_increment_kernel<<<1, block, 0, stream>>> (
491 nBlocks,
494 gpuMemoryManager.getPointer<vmesh::VelocityMesh>(other.dev_vmesh),
495 gpuMemoryManager.getPointer<vmesh::VelocityBlockContainer>(other.dev_blockContainer),
496 factor
497 );
499 CHK_ERR( gpuStreamSynchronize(stream) );
500 }
501 vmesh->updateCachedSize();
502 blockContainer->updateCachedSize();
503 }
504
505 };
506
510 template <typename fileReal> __global__ void add_blocks_from_buffer_kernel (
512 vmesh::VelocityBlockContainer *blockContainer,
513 const vmesh::LocalID startLID,
514 const vmesh::GlobalID* gpuInitBlocks,
515 const fileReal* gpuInitBuffer,
516 const uint nBlocks
517 ) {
518 const int blocki = blockIdx.x;
519 //const int warpSize = blockDim.x*blockDim.y*blockDim.z;
520 const uint ti = threadIdx.z*blockDim.x*blockDim.y + threadIdx.y*blockDim.x + threadIdx.x;
521 Real* parameters = blockContainer->getParameters(startLID);
522 Realf *cellBlockData = blockContainer->getData(startLID);
523 const uint index = blocki;
524 {
525 // Copy in cell data, perform conversion float<->double if necessary
526 cellBlockData[index*WID3 + ti] = (Realf)gpuInitBuffer[index*WID3 + ti];
527 // Set block parameters
528 if (ti==0) {
529 vmesh::GlobalID GID = gpuInitBlocks[index];
530 vmesh->getBlockInfo(GID, parameters + index*BlockParams::N_VELOCITY_BLOCK_PARAMS + BlockParams::VXCRD);
531 }
533 }
534 }
535
536 typedef std::array<unsigned int, 3> velocity_cell_indices_t;
540
541 typedef std::array<vmesh::LocalID,3> velocity_block_indices_t;
545
546 class SpatialCell {
547 public:
551 const SpatialCell& operator=(const SpatialCell& other);
552
553 void setReservation(const uint popID, const vmesh::LocalID reservationsize, bool force=false);
554 vmesh::LocalID getReservation(const uint popID) const;
555 void applyReservation(const uint popID);
556
557 vmesh::GlobalID find_velocity_block(vmesh::GlobalID cellIndices[3],const uint popID);
558 Realf* get_data(const uint popID);
559 const Realf* get_data(const uint popID) const;
560 Realf* get_data(const vmesh::LocalID& blockLID,const uint popID);
561 const Realf* get_data(const vmesh::LocalID& blockLID,const uint popID) const;
562 Real* get_block_parameters(const uint popID);
563 const Real* get_block_parameters(const uint popID) const;
564 Real* get_block_parameters(const vmesh::LocalID& blockLID,const uint popID);
565 const Real* get_block_parameters(const vmesh::LocalID& blockLID,const uint popID) const;
566
567 Realf* dev_get_data(const uint popID);
568 const Realf* dev_get_data(const uint popID) const;
569 // Realf* dev_get_data(const vmesh::LocalID& blockLID,const uint popID);
570 // const Realf* dev_get_data(const vmesh::LocalID& blockLID,const uint popID) const;
571 Real* dev_get_block_parameters(const uint popID);
572 const Real* dev_get_block_parameters(const uint popID) const;
573 // Real* dev_get_block_parameters(const vmesh::LocalID& blockLID,const uint popID);
574 // const Real* dev_get_block_parameters(const vmesh::LocalID& blockLID,const uint popID) const;
575
577 const Real* get_cell_parameters() const;
578
582 void debug_population_check(const uint popID) const;
583 void debug_population_check(const uint popID, const vmesh::LocalID blockLID) const;
584
585 Population & get_population(const uint popID);
586 const Population & get_population(const uint popID) const;
587 void set_population(const Population& pop, cuint popID);
588 void scale_population(creal factor, cuint popID);
589 void increment_population(const Population& pop, creal factor, cuint popID);
591
592 std::vector<Population>& get_populations();
593 const std::vector<Population>& get_populations() const;
594
595 const Real& get_max_r_dt(const uint popID) const;
596 const Real& get_max_v_dt(const uint popID) const;
597
598 const vmesh::LocalID* get_velocity_grid_length(const uint popID);
599 const vmesh::GlobalID* get_velocity_grid(const uint popID);
600 const Real* get_velocity_grid_block_size(const uint popID);
601 const Real* get_velocity_grid_cell_size(const uint popID);
602 void get_velocity_block_coordinates(const uint popID,const vmesh::GlobalID& globalID,Real* coords);
604 vmesh::GlobalID get_velocity_block(const uint popID,vmesh::GlobalID blockIndices[3]) const;
605 vmesh::GlobalID get_velocity_block(const uint popID,const velocity_block_indices_t indices) const;
606 vmesh::GlobalID get_velocity_block(const uint popID,const Real* coords) const;
607 vmesh::GlobalID get_velocity_block(const uint popID,const Real vx,const Real vy,const Real vz) const;
608 vmesh::GlobalID get_velocity_block_global_id(const vmesh::LocalID& blockLID,const uint popID) const;
609 vmesh::LocalID get_velocity_block_local_id(const vmesh::GlobalID& blockGID,const uint popID) const;
610 void get_velocity_block_size(const uint popID,const vmesh::GlobalID block,Real size[3]);
611 Real get_velocity_block_vx_min(const uint popID,const vmesh::GlobalID block) const;
612 Real get_velocity_block_vx_max(const uint popID,const vmesh::GlobalID block) const;
613 Real get_velocity_block_vy_min(const uint popID,const vmesh::GlobalID block) const;
614 Real get_velocity_block_vy_max(const uint popID,const vmesh::GlobalID block) const;
615 Real get_velocity_block_vz_min(const uint popID,const vmesh::GlobalID block) const;
616 Real get_velocity_block_vz_max(const uint popID,const vmesh::GlobalID block) const;
617
618 static unsigned int invalid_block_index();
621
622 size_t count(const vmesh::GlobalID& block,const uint popID) const;
623
625 static bool setCommunicatedSpecies(const uint popID);
626
627 // Following functions adjust velocity blocks stored on the cell //
628 void adjustSingleCellVelocityBlocks(const uint popID, bool doDeleteEmpty=false);
629 bool add_velocity_block(const vmesh::GlobalID& block,const uint popID);
630 void adjust_velocity_blocks(const uint popID,
631 bool doDeleteEmptyBlocks=true);
633 // Templated function for storing a v-space read from a file or generated elsewhere
634 template <typename fileReal> void add_velocity_blocks(const uint popID,const std::vector<vmesh::GlobalID>& blocks,fileReal* initBuffer);
635
637 bool checkMesh(const uint popID);
638 bool checkSizes(const uint popID);
639 void clear(const uint popID, bool shrink=false);
640 void setNewSizeClear(const uint popID, const vmesh::LocalID& newSize);
641 void setNewSizeClear(const uint popID);
642
645 void prepare_to_receive_blocks(const uint popID);
647 size_t size(const uint popID) const;
648 void dev_resize_vmesh(const uint popID, const uint nBlocks);
651 const vmesh::VelocityBlockContainer* get_velocity_blocks(const size_t& popID) const;
652 void dev_upload_population(const uint popID);
653 vmesh::VelocityMesh* dev_get_velocity_mesh(const size_t& popID);
655 const vmesh::VelocityBlockContainer* dev_get_velocity_blocks(const size_t& popID) const;
656 // Prefetches for both blockContainers and vmeshes, all populations
657 void prefetchDevice();
658 void prefetchHost();
659
660 void set_max_r_dt(const uint popID,const Real& value);
661 void set_max_v_dt(const uint popID,const Real& value);
662
663 // Following functions are related to MPI //
664 std::tuple<void*, int, MPI_Datatype> get_mpi_datatype(const CellID cellID,const int sender_rank,const int receiver_rank,
665 const bool receiving,const int neighborhood);
666 static uint64_t get_mpi_transfer_type(void);
667 static void set_mpi_transfer_type(const uint64_t type,bool atSysBoundaries=false);
668 static void set_mpi_transfer_direction(const int dimension);
669 void set_mpi_transfer_enabled(bool transferEnabled);
670 void updateSparseMinValue(const uint popID);
671 Real getVelocityBlockMinValue(const uint popID) const;
672
673 // Member variables //
674 std::array<Real, vderivatives::N_V_DERIVATIVES> derivativesV;
675 std::array<Real, bvolderivatives::N_BVOL_DERIVATIVES> derivativesBVOL;
677 std::array<Real, CellParams::N_SPATIAL_CELL_PARAMS> parameters;
678 std::array<Realf, WID3> null_block_data;
679
680 uint64_t ioLocalCellId;
682 std::array<Realf*,MAX_NEIGHBORS_PER_DIM> neighbor_block_data;
684 std::array<vmesh::LocalID,MAX_NEIGHBORS_PER_DIM> neighbor_number_of_blocks;
685 std::map<int,std::set<int>> face_neighbor_ranks;
686 uint sysBoundaryFlag;
688 uint sysBoundaryLayer;
691 split::SplitVector<vmesh::GlobalID> *velocity_block_with_content_list=0;
692 split::SplitVector<vmesh::GlobalID> *dev_velocity_block_with_content_list=0;
695 Hashinator::Hashmap<vmesh::GlobalID,vmesh::LocalID> *velocity_block_with_content_map=0, *velocity_block_with_no_content_map=0;
696 Hashinator::Hashmap<vmesh::GlobalID,vmesh::LocalID> *dev_velocity_block_with_content_map=0, *dev_velocity_block_with_no_content_map=0;
698
699 split::SplitVector<vmesh::GlobalID> *list_with_replace_new=0, *dev_list_with_replace_new=0;
700 split::SplitVector<Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>> *list_delete=0, *dev_list_delete=0;
701 split::SplitVector<Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>> *list_to_replace=0, *dev_list_to_replace=0;
702 split::SplitVector<Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>> *list_with_replace_old=0, *dev_list_with_replace_old=0;
704
707 uint64_t largestvmesh = 0;
708
709 static uint64_t mpi_transfer_type;
710 static bool mpiTransferAtSysBoundaries;
711
712 private:
713 static int activePopID;
714 bool initialized;
716
717 std::vector<spatial_cell::Population> populations;
718 };
719
720 inline void SpatialCell::debug_population_check(const uint popID) const {
721 #ifdef DEBUG_SPATIAL_CELL
722 if (popID >= populations.size()) {
723 std::cerr << "ERROR, popID " << popID << " exceeds populations.size() " << populations.size() << " in ";
724 std::cerr << __FILE__ << ":" << __LINE__ << std::endl;
725 exit(1);
726 }
727 #endif
728 }
729 inline void SpatialCell::debug_population_check(const uint popID, const vmesh::LocalID blockLID) const {
731 #ifdef DEBUG_SPATIAL_CELL
732 if (blockLID >= populations[popID].blockContainer->size()) {
733 std::cerr << "ERROR, block LID out of bounds, blockContainer->size() " << populations[popID].blockContainer->size() << " in ";
734 std::cerr << __FILE__ << ":" << __LINE__ << std::endl;
735 exit(1);
736 }
737 #endif
738 }
739
740 inline Realf* SpatialCell::get_data(const uint popID) {
742 return populations[popID].blockContainer->getData();
743 }
744
745 inline const Realf* SpatialCell::get_data(const uint popID) const {
747 return populations[popID].blockContainer->getData();
748 }
749
750 inline Realf* SpatialCell::dev_get_data(const uint popID) {
752 return gpuMemoryManager.getPointer<vmesh::VelocityBlockContainer>(populations[popID].dev_blockContainer)->getData();
753 }
754
755 inline const Realf* SpatialCell::dev_get_data(const uint popID) const {
757 return gpuMemoryManager.getPointer<vmesh::VelocityBlockContainer>(populations[popID].dev_blockContainer)->getData();
758 }
759
760 inline Realf* SpatialCell::get_data(const vmesh::LocalID& blockLID,const uint popID) {
761 debug_population_check(popID,blockLID);
762 if (blockLID == vmesh::VelocityMesh::invalidLocalID()) {
763 return null_block_data.data();
764 }
765 return populations[popID].blockContainer->getData(blockLID);
766 }
767
768 inline const Realf* SpatialCell::get_data(const vmesh::LocalID& blockLID,const uint popID) const {
769 debug_population_check(popID,blockLID);
770 if (blockLID == vmesh::VelocityMesh::invalidLocalID()) {
771 return null_block_data.data();
772 }
773 return populations[popID].blockContainer->getData(blockLID);
774 }
775
776 inline Real* SpatialCell::get_block_parameters(const uint popID) {
778 return populations[popID].blockContainer->getParameters();
779 }
780
781 inline const Real* SpatialCell::get_block_parameters(const uint popID) const {
783 return populations[popID].blockContainer->getParameters();
784 }
785
786 inline void SpatialCell::dev_upload_population(const uint popID) {
787 populations[popID].Upload();
788 }
789
790 inline Real* SpatialCell::dev_get_block_parameters(const uint popID) {
792 return gpuMemoryManager.getPointer<vmesh::VelocityBlockContainer>(populations[popID].dev_blockContainer)->getParameters();
793 }
794
795 inline const Real* SpatialCell::dev_get_block_parameters(const uint popID) const {
797 return gpuMemoryManager.getPointer<vmesh::VelocityBlockContainer>(populations[popID].dev_blockContainer)->getParameters();
798 }
799
800 inline Real* SpatialCell::get_block_parameters(const vmesh::LocalID& blockLID,const uint popID) {
801 debug_population_check(popID,blockLID);
802 return populations[popID].blockContainer->getParameters(blockLID);
803 }
804
805 inline const Real* SpatialCell::get_block_parameters(const vmesh::LocalID& blockLID,const uint popID) const {
806 debug_population_check(popID,blockLID);
807 return populations[popID].blockContainer->getParameters(blockLID);
808 }
809
811 return parameters.data();
812 }
813
814 inline const Real* SpatialCell::get_cell_parameters() const {
815 return parameters.data();
816 }
817
818 inline vmesh::LocalID SpatialCell::get_number_of_velocity_blocks(const uint popID) const {
820 //return populations[popID].blockContainer->size();
821 // Return size from vmesh instead of VBC to allow use of host-cached value
822 return populations[popID].vmesh->size();
823 }
824
829 vmesh::LocalID N_blocks = 0;
830 for (size_t p=0; p<populations.size(); ++p)
831 N_blocks += populations[p].blockContainer->size();
832 return N_blocks;
833 }
834
835 inline int SpatialCell::get_number_of_populations() const {
836 return populations.size();
837 }
838
839 inline Population & SpatialCell::get_population(const uint popID) {
840 return populations[popID];
841 }
842
843 inline const Population & SpatialCell::get_population(const uint popID) const {
844 return populations[popID];
845 }
846
847 inline void SpatialCell::set_population(const Population& pop, cuint popID) {
848 // (this->populations[popID].vmesh)->gpu_prefetchDevice();
849 // (this->populations[popID].blockContainer)->gpu_prefetchDevice();
850 // (pop.vmesh)->gpu_prefetchDevice();
851 // (pop.blockContainer)->gpu_prefetchDevice();
852 this->populations[popID] = pop;
853 // Copy assign includes dev_vmesh upload
854 }
855 inline void SpatialCell::scale_population(creal factor, cuint popID) {
856 // (this->populations[popID].vmesh)->gpu_prefetchDevice();
857 // (this->populations[popID].blockContainer)->gpu_prefetchDevice();
858 (this->populations[popID]).Scale(factor);
859 }
860 inline void SpatialCell::increment_population(const Population& pop, creal factor, cuint popID) {
861 // (this->populations[popID].vmesh)->gpu_prefetchDevice();
862 // (this->populations[popID].blockContainer)->gpu_prefetchDevice();
863 // (pop.vmesh)->gpu_prefetchDevice();
864 // (pop.blockContainer)->gpu_prefetchDevice();
865 (this->populations[popID]).Increment(pop, factor);
866 }
868 (this->populations[popID]).RHOLOSSADJUST += increment;
869 }
870
871 inline std::vector<Population>& SpatialCell::get_populations() {
872 return populations;
873 }
874 inline const std::vector<Population>& SpatialCell::get_populations() const {
875 return populations;
876 }
877
878 inline const vmesh::LocalID* SpatialCell::get_velocity_grid_length(const uint popID) {
879 return populations[popID].vmesh->getGridLength();
880 }
881
882 inline const vmesh::GlobalID* SpatialCell::get_velocity_grid(const uint popID) {
883 return (populations[popID].vmesh->getGrid())->data();
884 }
885
886 inline const Real* SpatialCell::get_velocity_grid_block_size(const uint popID) {
887 return populations[popID].vmesh->getBlockSize();
888 }
889
890 inline const Real* SpatialCell::get_velocity_grid_cell_size(const uint popID) {
891 return populations[popID].vmesh->getCellSize();
892 }
893
894 inline void SpatialCell::get_velocity_block_coordinates(const uint popID,const vmesh::GlobalID& globalID,Real* coords) {
895 populations[popID].vmesh->getBlockCoordinates(globalID,coords);
896 }
897
903 populations[popID].vmesh->getIndices(block,indices[0],indices[1],indices[2]);
904 return indices;
905 }
906
910 inline vmesh::GlobalID SpatialCell::get_velocity_block(const uint popID,const velocity_block_indices_t indices) const {
911 return populations[popID].vmesh->getGlobalID(indices[0],indices[1],indices[2]);
912 }
913
914 inline vmesh::GlobalID SpatialCell::get_velocity_block(const uint popID,vmesh::GlobalID blockIndices[3]) const {
915 return populations[popID].vmesh->getGlobalID(blockIndices[0],blockIndices[1],blockIndices[2]);
916 }
917
922 inline vmesh::GlobalID SpatialCell::get_velocity_block(const uint popID,const Real vx,const Real vy,const Real vz) const {
923 Real coords[3] = {vx,vy,vz};
924 return populations[popID].vmesh->getGlobalID(coords);
925 }
926
927 inline vmesh::GlobalID SpatialCell::get_velocity_block(const uint popID,const Real* coords) const {
928 return populations[popID].vmesh->getGlobalID(coords);
929 }
930
931 inline vmesh::GlobalID SpatialCell::get_velocity_block_global_id(const vmesh::LocalID& blockLID,const uint popID) const {
933 return populations[popID].vmesh->getGlobalID(blockLID);
934 }
935
936 inline vmesh::LocalID SpatialCell::get_velocity_block_local_id(const vmesh::GlobalID& blockGID,const uint popID) const {
938 return populations[popID].vmesh->getLocalID(blockGID);
939 }
940
941 inline void SpatialCell::get_velocity_block_size(const uint popID,const vmesh::GlobalID block,Real blockSize[3]) {
942 populations[popID].vmesh->getBlockSize(block,blockSize);
943 }
944
948 inline Real SpatialCell::get_velocity_block_vx_min(const uint popID,const vmesh::GlobalID block) const {
949 Real coords[3];
950 populations[popID].vmesh->getBlockCoordinates(block,coords);
951 return coords[0];
952 }
953
957 inline Real SpatialCell::get_velocity_block_vx_max(const uint popID,const vmesh::GlobalID block) const {
958 Real coords[3];
959 populations[popID].vmesh->getBlockCoordinates(block,coords);
960
961 Real size[3];
962 populations[popID].vmesh->getBlockSize(block,size);
963 return coords[0]+size[0];
964 }
965
969 inline Real SpatialCell::get_velocity_block_vy_min(const uint popID,const vmesh::GlobalID block) const {
970 Real coords[3];
971 populations[popID].vmesh->getBlockCoordinates(block,coords);
972 return coords[1];
973 }
974
978 inline Real SpatialCell::get_velocity_block_vy_max(const uint popID,const vmesh::GlobalID block) const {
979 Real coords[3];
980 populations[popID].vmesh->getBlockCoordinates(block,coords);
981
982 Real size[3];
983 populations[popID].vmesh->getBlockSize(block,size);
984 return coords[1]+size[1];
985 }
986
990 inline Real SpatialCell::get_velocity_block_vz_min(const uint popID,const vmesh::GlobalID block) const {
991 Real coords[3];
992 populations[popID].vmesh->getBlockCoordinates(block,coords);
993 return coords[2];
994 }
995
999 inline Real SpatialCell::get_velocity_block_vz_max(const uint popID,const vmesh::GlobalID block) const {
1000 Real coords[3];
1001 populations[popID].vmesh->getBlockCoordinates(block,coords);
1002
1003 Real size[3];
1004 populations[popID].vmesh->getBlockSize(block,size);
1005 return coords[2]+size[2];
1006 }
1007
1008 inline unsigned int SpatialCell::invalid_block_index() {
1010 }
1011
1014 }
1015
1018 }
1019
1023 inline size_t SpatialCell::count(const vmesh::GlobalID& block,const uint popID) const {
1025 return populations[popID].vmesh->count(block);
1026 }
1027
1031 inline size_t SpatialCell::size(const uint popID) const {
1033 return populations[popID].vmesh->size();
1034 }
1035
1039 inline void SpatialCell::dev_resize_vmesh(const uint popID, const uint nBlocks) {
1040 gpuStream_t stream = gpu_getStream();
1041 const bool reupload = populations[popID].vmesh->setNewCapacity(nBlocks);
1042 populations[popID].vmesh->setNewCachedSize(nBlocks);
1043 if (reupload) {
1044 CHK_ERR( gpuMemcpyAsync(gpuMemoryManager.getPointer<vmesh::VelocityMesh>(populations[popID].dev_vmesh), populations[popID].vmesh, sizeof(vmesh::VelocityMesh), gpuMemcpyHostToDevice, stream) );
1045 //CHK_ERR( gpuStreamSynchronize(stream) );
1046 }
1048 gpuMemoryManager.getPointer<vmesh::VelocityMesh>(populations[popID].dev_vmesh),
1049 nBlocks
1050 );
1052 // leaving this sync out is a potential cause for issues during MPI communication, but a device-synchronize may do the trick.
1053 // Hewever, inplementing some device synchronizes in grid.cpp balanceLoad() seems to do the trick.
1054 //CHK_ERR( gpuStreamSynchronize(stream) );
1055 }
1056
1057 inline vmesh::VelocityMesh* SpatialCell::get_velocity_mesh(const size_t& popID) {
1059 return populations[popID].vmesh;
1060 }
1063 return gpuMemoryManager.getPointer<vmesh::VelocityMesh>(populations[popID].dev_vmesh);
1064 }
1065
1068 return populations[popID].blockContainer;
1069 }
1070 inline const vmesh::VelocityBlockContainer* SpatialCell::get_velocity_blocks(const size_t& popID) const {
1072 return populations[popID].blockContainer;
1073 }
1076 return gpuMemoryManager.getPointer<vmesh::VelocityBlockContainer>(populations[popID].dev_blockContainer);
1077 }
1080 return gpuMemoryManager.getPointer<vmesh::VelocityBlockContainer>(populations[popID].dev_blockContainer);
1081 }
1082
1083 inline bool SpatialCell::checkMesh(const uint popID) {
1085 const size_t vmeshSize = (populations[popID].vmesh)->size();
1086 const size_t vbcSize = (populations[popID].blockContainer)->size();
1087 if (vmeshSize != vbcSize) {
1088 printf("checkMesh ERROR: population vmesh %zu and blockcontainer %zu sizes do not match!\n",vmeshSize,vbcSize);
1089 }
1090 return populations[popID].vmesh->check();
1091 }
1092 inline bool SpatialCell::checkSizes(const uint popID) {
1094 const size_t vmeshSize = (populations[popID].vmesh)->size();
1095 const size_t vbcSize = (populations[popID].blockContainer)->size();
1096 if (vmeshSize != vbcSize) {
1097 printf("checkSizes ERROR: population vmesh %zu and blockcontainer %zu sizes do not match!\n",vmeshSize,vbcSize);
1098 return false;
1099 }
1100 return true;
1101 }
1102
1106 inline void SpatialCell::clear(const uint popID, bool shrink) {
1108 populations[popID].vmesh->clear(shrink);
1109 populations[popID].blockContainer->clear(shrink);
1110 }
1111
1117 inline void SpatialCell::setNewSizeClear(const uint popID, const vmesh::LocalID& newSize) {
1118 populations[popID].ResizeClear(newSize);
1119 }
1120 inline void SpatialCell::setNewSizeClear(const uint popID) {
1121 populations[popID].ResizeClear(populations[popID].N_blocks);
1122 }
1123
1128 // GPUTODO Update this for GPU memory as well, same for capacity
1129 inline uint64_t SpatialCell::get_cell_memory_size() {
1130 uint64_t size = 0;
1131 size += WID3 * sizeof(Realf);
1133 size += velocity_block_with_content_map->size() * sizeof(Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>);
1134 size += velocity_block_with_no_content_map->size() * sizeof(Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>);
1135 size += list_with_replace_new->size() * sizeof(vmesh::GlobalID);
1136 size += list_delete->size() * sizeof(Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>);
1137 size += list_to_replace->size() * sizeof(Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>);
1138 size += list_with_replace_old->size() * sizeof(Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>);
1141
1142 size += 2 * sizeof(Hashinator::Hashmap<vmesh::GlobalID,vmesh::LocalID>);
1143 size += sizeof(split::SplitVector<vmesh::GlobalID>);
1144 size += 3 * sizeof(split::SplitVector<Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>>);
1145
1146 for (size_t popID=0; popID<populations.size(); ++popID) {
1147 size += populations[popID].vmesh->sizeInBytes();
1148 size += populations[popID].blockContainer->sizeInBytes();
1149 size += sizeof(vmesh::VelocityMesh);
1150 size += sizeof(vmesh::VelocityBlockContainer);
1151 }
1152 return size;
1153 }
1154
1159 inline uint64_t SpatialCell::get_cell_memory_capacity() {
1160 uint64_t capacity = 0;
1161 capacity += WID3 * sizeof(Realf);
1162 // capacity += velocity_block_with_content_list->capacity() * sizeof(vmesh::GlobalID);
1163 // capacity += velocity_block_with_content_map->bucket_count() * sizeof(Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>);
1164 // capacity += velocity_block_with_no_content_map->bucket_count() * sizeof(Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>);
1165 // capacity += list_with_replace_new->capacity() * sizeof(vmesh::GlobalID);
1166 // capacity += list_delete->capacity() * sizeof(Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>);
1167 // capacity += list_to_replace->capacity() * sizeof(Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>);
1168 // capacity += list_with_replace_old->capacity() * sizeof(Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>);
1169 // *** Cached versions:
1171 capacity += pow(2,vbwcl_sizePower) * sizeof(Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>);
1172 capacity += pow(2,vbwncl_sizePower) * sizeof(Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>);
1173 capacity += list_with_replace_new_capacity * sizeof(vmesh::GlobalID);
1174 capacity += list_delete_capacity * sizeof(Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>);
1175 capacity += list_to_replace_capacity * sizeof(Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>);
1176 capacity += list_with_replace_old_capacity * sizeof(Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>);
1177 // *** These two are not in GPU memory so are excluded
1178 // capacity += CellParams::N_SPATIAL_CELL_PARAMS * sizeof(Real);
1179 // capacity += bvolderivatives::N_BVOL_DERIVATIVES * sizeof(Real);
1180
1181 capacity += 2 * sizeof(Hashinator::Hashmap<vmesh::GlobalID,vmesh::LocalID>);
1182 capacity += sizeof(split::SplitVector<vmesh::GlobalID>);
1183 capacity += 3 * sizeof(split::SplitVector<Hashinator::hash_pair<vmesh::GlobalID,vmesh::LocalID>>);
1184 //size_t pops1 = 0, pops2=0;
1185 for (size_t popID=0; popID<populations.size(); ++popID) {
1186 capacity += populations[popID].vmesh->capacityInBytes();
1187 capacity += populations[popID].blockContainer->capacityInBytes();
1188 capacity += sizeof(vmesh::VelocityMesh);
1189 capacity += sizeof(vmesh::VelocityBlockContainer);
1190 // pops1 += populations[popID].vmesh->capacityInBytes();
1191 // pops1 += populations[popID].blockContainer->capacityInBytes();
1192 // pops1 += sizeof(vmesh::VelocityMesh);
1193 // pops1 += sizeof(vmesh::VelocityBlockContainer);
1194 // pops2 += populations[popID].vmesh->sizeInBytes();
1195 // pops2 += populations[popID].blockContainer->sizeInBytes();
1196 // pops2 += sizeof(vmesh::VelocityMesh);
1197 // pops2 += sizeof(vmesh::VelocityBlockContainer);
1198 }
1199 // std::cerr<<"ratio pops/total capacity "<<(float)pops1/(float)capacity<<" pops size/capacity "<<(float)pops2/(float)pops1<<std::endl;
1200 // std::cerr<<"ratio vmesh "<<(float)populations[0].vmesh->sizeInBytes()/(float)populations[0].vmesh->capacityInBytes();
1201 // std::cerr<<" VBC "<<(float)populations[0].blockContainer->sizeInBytes()/(float)populations[0].blockContainer->capacityInBytes();
1202 // std::cerr<<" size(kB) vmesh "<<populations[0].vmesh->sizeInBytes()/1024;
1203 // std::cerr<<" VBC "<<populations[0].blockContainer->sizeInBytes()/1024;
1204 // std::cerr<<" capacity(kB) vmesh "<<populations[0].vmesh->capacityInBytes()/1024;
1205 // std::cerr<<" VBC "<<populations[0].blockContainer->capacityInBytes()/1024<<std::endl;
1206 return capacity;
1207 }
1208
1213 template <typename fileReal> void SpatialCell::add_velocity_blocks(const uint popID,const std::vector<vmesh::GlobalID>& blocks,fileReal* initBuffer) {
1215 // Add blocks to velocity mesh
1216 gpuStream_t stream = gpu_getStream();
1217
1218 if (populations[popID].vmesh->size() != 0) {
1219 // TODO: make methods safe to add to a non-empty vmesh
1220 std::cerr << "Error in adding from buffer: Vmesh not empty!" << __FILE__ << ' ' << __LINE__ << std::endl;
1221 exit(1);
1222 }
1223
1224 const uint nBlocks = blocks.size();
1225 if (nBlocks==0) {
1226 // Return if empty
1227 populations[popID].vmesh->setNewCachedSize(0);
1228 populations[popID].blockContainer->setNewCachedSize(0);
1229 return;
1230 }
1231
1232 populations[popID].vmesh->setNewCapacity(nBlocks*BLOCK_ALLOCATION_PADDING);
1233 populations[popID].blockContainer->setNewCapacity(nBlocks*BLOCK_ALLOCATION_PADDING);
1234
1235 const vmesh::LocalID adds = populations[popID].vmesh->push_back(blocks);
1236 // Verify that we added all requested blocks
1237 if (adds != nBlocks) {
1238 std::cerr << "Failed to add blocks" << __FILE__ << ' ' << __LINE__ << std::endl; exit(1);
1239 return;
1240 }
1241 // populations[popID].vmesh->setNewCachedSize(nBlocks); // handled by push_back
1242 // populations[popID].blockContainer->setNewCachedSize(nBlocks); // handled by push_back
1243
1244 const vmesh::LocalID startLID = populations[popID].blockContainer->push_back(nBlocks);
1245 populations[popID].Upload();
1246
1247 // Copy data to GPU
1248 SUBPOINTER_ALLOCATE_ASYNC(gpuMemoryManager, gpuInitBuffer, gpu_getThread(), WID3*nBlocks*sizeof(fileReal), stream);
1249 SUBPOINTER_ALLOCATE_ASYNC(gpuMemoryManager, gpuInitBlocks, gpu_getThread(), nBlocks*sizeof(vmesh::GlobalID), stream);
1250 fileReal* gpuInitBuffer = GET_POINTER(gpuMemoryManager, fileReal, gpuInitBuffer);
1251 vmesh::GlobalID* gpuInitBlocks = GET_POINTER(gpuMemoryManager, vmesh::GlobalID, gpuInitBlocks);
1252 // TODO: re-use per-thread buffers here, ensuring sufficient allocation.;
1253 CHK_ERR( gpuMemcpyAsync(gpuInitBuffer, initBuffer,
1254 WID3*nBlocks*sizeof(fileReal), gpuMemcpyHostToDevice, stream) );
1255 CHK_ERR( gpuMemcpyAsync(gpuInitBlocks, blocks.data(),
1256 nBlocks*sizeof(vmesh::GlobalID), gpuMemcpyHostToDevice, stream) );
1257
1258 if (nBlocks>0) {
1259 dim3 block(WID,WID,WID);
1260 // Third argument specifies the number of bytes in *shared memory* that is
1261 // dynamically allocated per block for this call in addition to the statically allocated memory.
1262 CHK_ERR( gpuStreamSynchronize(stream) );
1264 gpuMemoryManager.getPointer<vmesh::VelocityMesh>(populations[popID].dev_vmesh),
1265 gpuMemoryManager.getPointer<vmesh::VelocityBlockContainer>(populations[popID].dev_blockContainer),
1266 startLID,
1267 gpuInitBlocks,
1268 gpuInitBuffer,
1269 nBlocks
1270 );
1272 }
1273 CHK_ERR( gpuStreamSynchronize(stream) );
1274
1275 #ifdef DEBUG_SPATIAL_CELL
1276 if (populations[popID].vmesh->size() != populations[popID].blockContainer->size()) {
1277 std::cerr << "size mismatch in " << __FILE__ << ' ' << __LINE__ << std::endl;
1278 std::cerr << " velocity mesh size "<<populations[popID].vmesh->size();
1279 std::cerr << " VBC size "<<populations[popID].blockContainer->size();
1280 std::cerr << " nBlocks "<<nBlocks;
1281 std::cerr << " adds " << adds << std::endl;
1282 exit(1);
1283 }
1284 #endif
1285 #ifdef DEBUG_VLASIATOR
1286 if (!populations[popID].vmesh->check()) {
1287 std::cerr << "vmesh check error in " << __FILE__ << ' ' << __LINE__ << std::endl;
1288 std::cerr << " velocity mesh size "<<populations[popID].vmesh->size();
1289 std::cerr << " VBC size "<<populations[popID].blockContainer->size();
1290 std::cerr << " nBlocks "<<nBlocks;
1291 std::cerr << " adds " << adds << std::endl;
1292 exit(1);
1293 }
1294 #endif
1295 }
1296
1300 inline void SpatialCell::set_mpi_transfer_type(const uint64_t type,bool atSysBoundaries) {
1303 }
1304
1308 inline uint64_t SpatialCell::get_mpi_transfer_type(void) {
1310 }
1311
1315 inline void SpatialCell::set_mpi_transfer_enabled(bool transferEnabled) {
1316 this->mpiTransferEnabled=transferEnabled;
1317 }
1318
1319} // namespaces
1320
1321#endif
for i
Definition Dispersion.m:24
Numerical propagation V
Definition Dispersion.m:98
#define gpuPeekAtLastError
#define gpuStream_t
#define gpuStreamSynchronize
#define gpuMemcpyHostToDevice
#define CHK_ERR(err)
#define gpuMemcpyAsync
Real * get_block_parameters(const vmesh::LocalID &blockLID, const uint popID)
const vmesh::GlobalID * get_velocity_grid(const uint popID)
bool checkMesh(const uint popID)
split::SplitVector< vmesh::GlobalID > * dev_velocity_block_with_content_list
vmesh::LocalID get_number_of_velocity_blocks(const uint popID) const
void debug_population_check(const uint popID) const
void updateSparseMinValue(const uint popID)
const Realf * get_data(const uint popID) const
void set_population(const Population &pop, cuint popID)
const Real * get_velocity_grid_cell_size(const uint popID)
Real get_velocity_block_vx_min(const uint popID, const vmesh::GlobalID block) const
Real * get_block_parameters(const uint popID)
const Real * get_block_parameters(const vmesh::LocalID &blockLID, const uint popID) const
vmesh::VelocityMesh * get_velocity_mesh(const size_t &popID)
void scale_population(creal factor, cuint popID)
const Population & get_population(const uint popID) const
vmesh::GlobalID get_velocity_block_global_id(const vmesh::LocalID &blockLID, const uint popID) const
vmesh::VelocityBlockContainer * get_velocity_blocks(const size_t &popID)
bool checkSizes(const uint popID)
Hashinator::Hashmap< vmesh::GlobalID, vmesh::LocalID > * dev_velocity_block_with_no_content_map
vmesh::LocalID adjust_velocity_blocks_caller(const uint popID)
vmesh::GlobalID get_velocity_block(const uint popID, const Real vx, const Real vy, const Real vz) const
size_t count(const vmesh::GlobalID &block, const uint popID) const
static vmesh::GlobalID invalid_global_id()
void setNewSizeClear(const uint popID)
std::tuple< void *, int, MPI_Datatype > get_mpi_datatype(const CellID cellID, const int sender_rank, const int receiver_rank, const bool receiving, const int neighborhood)
size_t size(const uint popID) const
static vmesh::LocalID invalid_local_id()
const std::vector< Population > & get_populations() const
std::array< Realf *, MAX_NEIGHBORS_PER_DIM > neighbor_block_data
static void set_mpi_transfer_direction(const int dimension)
Realf * dev_get_data(const uint popID)
void increment_population(const Population &pop, creal factor, cuint popID)
Realf * get_data(const vmesh::LocalID &blockLID, const uint popID)
void dev_upload_population(const uint popID)
split::SplitVector< vmesh::GlobalID > * list_with_replace_new
void set_mpi_transfer_enabled(bool transferEnabled)
static unsigned int invalid_block_index()
void set_max_r_dt(const uint popID, const Real &value)
vmesh::GlobalID get_velocity_block(const uint popID, const Real *coords) const
void adjustSingleCellVelocityBlocks(const uint popID, bool doDeleteEmpty=false)
vmesh::LocalID get_velocity_block_local_id(const vmesh::GlobalID &blockGID, const uint popID) const
vmesh::LocalID getReservation(const uint popID) const
void debug_population_check(const uint popID, const vmesh::LocalID blockLID) const
Real getVelocityBlockMinValue(const uint popID) const
Hashinator::Hashmap< vmesh::GlobalID, vmesh::LocalID > * dev_velocity_block_with_content_map
Real get_velocity_block_vz_min(const uint popID, const vmesh::GlobalID block) const
void increment_mass_loss(cuint popID, Real increment)
static bool setCommunicatedSpecies(const uint popID)
Real get_velocity_block_vz_max(const uint popID, const vmesh::GlobalID block) const
void clear(const uint popID, bool shrink=false)
split::SplitVector< Hashinator::hash_pair< vmesh::GlobalID, vmesh::LocalID > > * list_with_replace_old
static unsigned int invalid_block_index()
void prepare_to_receive_blocks(const uint popID)
Real get_velocity_block_vy_min(const uint popID, const vmesh::GlobalID block) const
uint64_t get_cell_memory_capacity()
std::vector< vmesh::GlobalID > * velocity_block_with_content_list
std::array< Real, vderivatives::N_V_DERIVATIVES > derivativesV
split::SplitVector< Hashinator::hash_pair< vmesh::GlobalID, vmesh::LocalID > > * dev_list_to_replace
static uint64_t get_mpi_transfer_type(void)
const Real * get_cell_parameters() const
void add_velocity_blocks(const uint popID, const std::vector< vmesh::GlobalID > &blocks, fileReal *initBuffer)
Real get_velocity_block_vy_max(const uint popID, const vmesh::GlobalID block) const
velocity_block_indices_t get_velocity_block_indices(const uint popID, const vmesh::GlobalID globalID)
split::SplitVector< vmesh::GlobalID > * dev_list_with_replace_new
vmesh::LocalID velocity_block_with_content_list_capacity
void add_velocity_blocks(const uint popID, const std::vector< vmesh::GlobalID > &blocks, fileReal *avgBuffer)
void dev_resize_vmesh(const uint popID, const uint nBlocks)
std::array< Realf, WID3 > null_block_data
vmesh::LocalID list_to_replace_capacity
void get_velocity_block_size(const uint popID, const vmesh::GlobalID block, Real size[3])
void set_max_v_dt(const uint popID, const Real &value)
void setNewSizeClear(const uint popID, const vmesh::LocalID &newSize)
const Real & get_max_r_dt(const uint popID) const
split::SplitVector< Hashinator::hash_pair< vmesh::GlobalID, vmesh::LocalID > > * list_delete
vmesh::LocalID get_number_of_all_velocity_blocks() const
Hashinator::Hashmap< vmesh::GlobalID, vmesh::LocalID > * velocity_block_with_no_content_map
vmesh::LocalID list_with_replace_new_capacity
static void set_mpi_transfer_type(const uint64_t type, bool atSysBoundaries=false)
std::array< vmesh::LocalID, MAX_NEIGHBORS_PER_DIM > neighbor_number_of_blocks
std::vector< Population > & get_populations()
void applyReservation(const uint popID)
std::array< Real, bvolderivatives::N_BVOL_DERIVATIVES > derivativesBVOL
void adjust_velocity_blocks(const std::vector< SpatialCell * > &spatial_neighbors, const uint popID, bool doDeleteEmptyBlocks=true)
split::SplitVector< Hashinator::hash_pair< vmesh::GlobalID, vmesh::LocalID > > * dev_list_delete
const vmesh::LocalID * get_velocity_grid_length(const uint popID)
split::SplitVector< Hashinator::hash_pair< vmesh::GlobalID, vmesh::LocalID > > * dev_list_with_replace_old
Realf * get_data(const uint popID)
const Real & get_max_v_dt(const uint popID) const
Population & get_population(const uint popID)
vmesh::LocalID list_with_replace_old_capacity
vmesh::GlobalID find_velocity_block(vmesh::GlobalID cellIndices[3], const uint popID)
vmesh::LocalID velocity_block_with_content_list_size
void get_velocity_block_coordinates(const uint popID, const vmesh::GlobalID &globalID, Real *coords)
SpatialCell(const SpatialCell &other)
const Real * get_block_parameters(const uint popID) const
Real get_velocity_block_vx_max(const uint popID, const vmesh::GlobalID block) const
void update_velocity_block_content_lists(const uint popID)
static void set_mpi_transfer_type(const uint64_t type, bool atSysBoundaries=false)
std::array< Real, CellParams::N_SPATIAL_CELL_PARAMS > parameters
const SpatialCell & operator=(const SpatialCell &other)
const vmesh::VelocityBlockContainer * get_velocity_blocks(const size_t &popID) const
split::SplitVector< Hashinator::hash_pair< vmesh::GlobalID, vmesh::LocalID > > * list_to_replace
const Realf * get_data(const vmesh::LocalID &blockLID, const uint popID) const
void setReservation(const uint popID, const vmesh::LocalID reservationsize, bool force=false)
Hashinator::Hashmap< vmesh::GlobalID, vmesh::LocalID > * velocity_block_with_content_map
static uint64_t get_mpi_transfer_type(void)
Real * dev_get_block_parameters(const uint popID)
vmesh::VelocityBlockContainer * dev_get_velocity_blocks(const size_t &popID)
int get_number_of_populations() const
std::vector< spatial_cell::Population > populations
vmesh::GlobalID get_velocity_block(const uint popID, vmesh::GlobalID blockIndices[3]) const
vmesh::GlobalID get_velocity_block(const uint popID, const velocity_block_indices_t indices) const
static vmesh::GlobalID invalid_global_id()
static vmesh::LocalID invalid_local_id()
vmesh::VelocityMesh * dev_get_velocity_mesh(const size_t &popID)
std::map< int, std::set< int > > face_neighbor_ranks
bool add_velocity_block(const vmesh::GlobalID &block, const uint popID)
const Real * get_velocity_grid_block_size(const uint popID)
ARCH_HOSTDEV bool setNewSize(const vmesh::LocalID newSize)
ARCH_DEV void placeBlock(const vmesh::GlobalID GID, const vmesh::LocalID LID)
static vmesh::LocalID invalidBlockIndex()
static vmesh::LocalID invalidLocalID()
ARCH_DEV void device_setNewSize(const vmesh::LocalID newSize)
ARCH_DEV void warpPlaceBlock(const vmesh::GlobalID GID, const vmesh::LocalID LID, const size_t b_tid)
static vmesh::GlobalID invalidGlobalID()
size_t size(bool dummy=0) const
void getBlockInfo(const vmesh::GlobalID &globalID, Real *array) const
#define WID
Definition common.h:514
const int WID3
Definition common.h:517
const int WID2
Definition common.h:516
Parameters P
const uint32_t cuint
Definition definitions.h:50
float Real
Definition definitions.h:41
uint64_t CellID
Definition definitions.h:54
float Realf
Definition definitions.h:33
const float creal
Definition definitions.h:42
const vmesh::VelocityMesh *__restrict__ vmesh
const uint ti
GPUMemoryManager gpuMemoryManager
Definition gpu_base.cpp:64
__host__ gpuStream_t gpu_getStream()
Definition gpu_base.cpp:244
__host__ uint gpu_getThread()
Definition gpu_base.cpp:77
static const double BLOCK_ALLOCATION_PADDING
Definition gpu_base.hpp:60
#define SUBPOINTER_ALLOCATE_ASYNC(object, member, index, bytes, stream)
Definition gpu_base.hpp:669
#define GET_POINTER(object, type, member)
Definition gpu_base.hpp:809
const Real increment
dev_velocityBlockContainer[cellIdx] getData()[velocityIdx *WID3+k *WID2+j *WID+i]
const int blockSize
const int j
__syncthreads()
const int k
#define index(i, j, k)
@ N_VELOCITY_BLOCK_PARAMS
Definition common.h:115
@ N_SPATIAL_CELL_PARAMS
Definition common.h:229
uint32_t uint
std::array< vmesh::LocalID, 3 > velocity_block_indices_t
static __global__ void resize_and_empty_kernel(vmesh::VelocityMesh *vmesh, vmesh::VelocityBlockContainer *blockContainer, vmesh::LocalID newSize)
__global__ void add_blocks_from_buffer_kernel(const vmesh::VelocityMesh *vmesh, vmesh::VelocityBlockContainer *blockContainer, const vmesh::LocalID startLID, const vmesh::GlobalID *gpuInitBlocks, const fileReal *gpuInitBuffer, const uint nBlocks)
static __global__ void __launch_bounds__(WID3, 4) population_scale_kernel(vmesh
std::array< unsigned int, 3 > velocity_cell_indices_t
static __global__ void resize_vmesh_ondevice_kernel(vmesh::VelocityMesh *vmesh, vmesh::LocalID nBlocks)
uint32_t LocalID
Definition definitions.h:60
uint32_t GlobalID
Definition definitions.h:59
T * getPointer(const size_t &pointerIndex) const
Definition gpu_base.hpp:812
vmesh::VelocityBlockContainer * blockContainer
std::vector< char > compressed_state_buffer
void ResizeClear(const uint newSize)
const Population & operator=(const Population &other)
void Increment(const Population &other, creal factor)
Population(const Population &other)