Vlasiator ebf0dd394 on dev (v5.4.0 + 1054 commits)
Loading...
Searching...
No Matches
projectTriAxisSearch.cpp
Go to the documentation of this file.
1/*
2 * This file is part of Vlasiator.
3 * Copyright 2010-2016 Finnish Meteorological Institute
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 */
23#include "../object_wrapper.h"
24
25using namespace std;
26using namespace spatial_cell;
27
28using namespace std;
29
30namespace projects {
34 uint TriAxisSearch::findBlocksToInitialize(SpatialCell* cell,const uint popID) const {
36
37 vmesh::GlobalID *GIDbuffer;
38 const vmesh::LocalID* vblocks_ini = cell->get_velocity_grid_length(popID);
39 const uint blocksCount = vblocks_ini[0]*vblocks_ini[1]*vblocks_ini[2];
40 #ifdef USE_GPU
41 // Host-pinned memory buffer, max possible size
42 CHK_ERR( gpuMallocHost((void**)&GIDbuffer,blocksCount*sizeof(vmesh::GlobalID)) );
43 #endif
44 // Non-GPU: insert directly into vmesh
45
46 std::set<vmesh::GlobalID> singleSet;
47 bool search;
48 unsigned int counterX, counterY, counterZ;
49
50 creal minValue = cell->getVelocityBlockMinValue(popID);
51 // And how big a buffer do we add to the edges?
52 uint buffer = 2;
53 if (WID > 4 && blocksCount > 8) {
54 // With WID8 a two-block buffer increases memory requirements too much.
55 // However, we allow extra buffer for very minimal v-spaces.
56 buffer = 1;
57 }
58 // How much below the sparsity can a cell be to still be included?
59 creal tolerance = 0.1;
60
67 creal dvxBlock = cell->get_velocity_grid_block_size(popID)[0];
68 creal dvyBlock = cell->get_velocity_grid_block_size(popID)[1];
69 creal dvzBlock = cell->get_velocity_grid_block_size(popID)[2];
70 // creal dvxCell = cell->get_velocity_grid_cell_size(popID)[0];
71 // creal dvyCell = cell->get_velocity_grid_cell_size(popID)[1];
72 // creal dvzCell = cell->get_velocity_grid_cell_size(popID)[2];
73
74 const size_t vxblocks_ini = cell->get_velocity_grid_length(popID)[0];
75 const size_t vyblocks_ini = cell->get_velocity_grid_length(popID)[1];
76 const size_t vzblocks_ini = cell->get_velocity_grid_length(popID)[2];
77
78 vmesh::LocalID LID = 0;
79 const vector<std::array<Real, 3>> V0 = this->getV0(x+0.5*dx, y+0.5*dy, z+0.5*dz, popID);
80 const bool singlePeak = ( V0.size() == 1 );
81 // Loop over possible V peaks
82 for (vector<std::array<Real, 3>>::const_iterator it = V0.begin(); it != V0.end(); it++) {
83 // VX search
84 search = true;
85 counterX = 0;
86 while (search) {
87 if ( (tolerance * minValue >
88 probePhaseSpace(cell, popID, it->at(0) + counterX*dvxBlock, it->at(1), it->at(2))
89 || counterX > vxblocks_ini ) ) {
90 search = false;
91 }
92 counterX++;
93 }
94 counterX+=buffer;
95 Real vRadiusSquared = (Real)counterX*(Real)counterX*dvxBlock*dvxBlock;
96
97 // VY search
98 search = true;
99 counterY = 0;
100 while(search) {
101 if ( (tolerance * minValue >
102 probePhaseSpace(cell, popID, it->at(0), it->at(1) + counterY*dvyBlock, it->at(2))
103 || counterY > vyblocks_ini ) ) {
104 search = false;
105 }
106 counterY++;
107 }
108 counterY+=buffer;
109 vRadiusSquared = max(vRadiusSquared, (Real)counterY*(Real)counterY*dvyBlock*dvyBlock);
110
111 // VZ search
112 search = true;
113 counterZ = 0;
114 while(search) {
115 if ( (tolerance * minValue >
116 probePhaseSpace(cell, popID, it->at(0), it->at(1), it->at(2) + counterZ*dvzBlock)
117 || counterZ > vzblocks_ini ) ) {
118 search = false;
119 }
120 counterZ++;
121 }
122 counterZ+=buffer;
123 vRadiusSquared = max(vRadiusSquared, (Real)counterZ*(Real)counterZ*dvzBlock*dvzBlock);
124
125 #ifndef USE_GPU // non-GPU mesh resizing
126 // sphere volume is 4/3 pi r^3, approximate that 5*counterX*counterY*counterZ is enough.
127 vmesh::LocalID currentMaxSize = LID + 5*counterX*counterY*counterZ;
128 vmesh->setNewSize(currentMaxSize);
129 GIDbuffer = vmesh->getGrid()->data();
130 #endif
131
132 // Block listing
133 Real V_crds[3];
134 for (uint kv=0; kv<vzblocks_ini; ++kv) {
135 for (uint jv=0; jv<vyblocks_ini; ++jv) {
136 for (uint iv=0; iv<vxblocks_ini; ++iv) {
137 const vmesh::GlobalID GID = vmesh->getGlobalID(iv,jv,kv);
138 vmesh->getBlockCoordinates(GID,V_crds);
139
140 // Check block center point
141 V_crds[0] += (2*dvxBlock - it->at(0) );
142 V_crds[1] += (2*dvyBlock - it->at(1) );
143 V_crds[2] += (2*dvzBlock - it->at(2) );
144 Real R2 = ((V_crds[0])*(V_crds[0])
145 + (V_crds[1])*(V_crds[1])
146 + (V_crds[2])*(V_crds[2]));
147
148 #ifndef USE_GPU // non-GPU mesh resizing
149 if (LID >= currentMaxSize) {
150 currentMaxSize = LID + counterX*counterY*counterZ;
151 vmesh->setNewSize(currentMaxSize);
152 GIDbuffer = vmesh->getGrid()->data();
153 }
154 #endif
155 if (singlePeak) {
156 // Add this block
157 if (R2 < vRadiusSquared) {
158 GIDbuffer[LID] = GID;
159 LID++;
160 }
161 } else {
162 // Add this block only if it doesn't exist yet
163 if (R2 < vRadiusSquared && singleSet.count(GID)==0) {
164 singleSet.insert(GID);
165 GIDbuffer[LID] = GID;
166 LID++;
167 }
168 }
169 } // vxblocks_ini
170 } // vyblocks_ini
171 } // vzblocks_ini
172 } // iteration over V0's
173 // Set final size of vmesh
174 cell->get_population(popID).N_blocks = LID;
175
176 #ifdef USE_GPU
177 // Copy data from CPU to GPU
178 cell->dev_resize_vmesh(popID,LID);
179 vmesh::GlobalID *GIDtarget = vmesh->getGrid()->data();
180 gpuStream_t stream = gpu_getStream();
181 CHK_ERR( gpuMemcpyAsync(GIDtarget, GIDbuffer, LID*sizeof(vmesh::GlobalID), gpuMemcpyHostToDevice, stream));
182 CHK_ERR( gpuStreamSynchronize(stream) );
183 CHK_ERR( gpuFreeHost(GIDbuffer));
184 #else
185 // Resize vmesh down to final size
186 vmesh->setNewSize(LID);
187 #endif
188
189 return LID;
190 }
191
192} // namespace projects
dx
Definition Dispersion.m:38
#define gpuStream_t
#define gpuStreamSynchronize
#define gpuMemcpyHostToDevice
#define CHK_ERR(err)
#define gpuMemcpyAsync
#define gpuMallocHost
#define gpuFreeHost
virtual uint findBlocksToInitialize(spatial_cell::SpatialCell *cell, const uint popID) const
Find blocks above the threshold centred isotropically around a bulk velocity.
virtual std::vector< std::array< Real, 3 > > getV0(creal x, creal y, creal z, const uint popID) const =0
Return a vector containing the velocity coordinate of the centre of each ion population in the distri...
virtual Realf probePhaseSpace(spatial_cell::SpatialCell *cell, const uint popID, Real vx_in, Real vy_in, Real vz_in) const =0
vmesh::VelocityMesh * get_velocity_mesh(const size_t &popID)
Real getVelocityBlockMinValue(const uint popID) const
void dev_resize_vmesh(const uint popID, const uint nBlocks)
const vmesh::LocalID * get_velocity_grid_length(const uint popID)
Population & get_population(const uint popID)
std::array< Real, CellParams::N_SPATIAL_CELL_PARAMS > parameters
const Real * get_velocity_grid_block_size(const uint popID)
#define WID
Definition common.h:514
float Real
Definition definitions.h:41
const float creal
Definition definitions.h:42
__host__ gpuStream_t gpu_getStream()
Definition gpu_base.cpp:244
uint32_t LocalID
Definition definitions.h:60
uint32_t GlobalID
Definition definitions.h:59
static ARCH_HOSTDEV VecSimple< T > max(VecSimple< T > const &l, VecSimple< T > const &r)