Vlasiator ebf0dd394 on dev (v5.4.0 + 1054 commits)
Loading...
Searching...
No Matches
cpu_acc_map.cpp
Go to the documentation of this file.
1/*
2 * This file is part of Vlasiator.
3 * Copyright 2010-2016 Finnish Meteorological Institute
4 * 2017 CSC - IT center for Science
5 *
6 * For details of usage, see the COPYING file and read the "Rules of the Road"
7 * at http://www.physics.helsinki.fi/vlasiator/
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23
24#include <cmath>
25#include <algorithm>
26#include <utility>
27
28#include "vec.h"
29#include "../object_wrapper.h"
32#include "cpu_1d_pqm.hpp"
33#include "cpu_1d_ppm.hpp"
34#include "cpu_1d_plm.hpp"
35#include "cpu_acc_map.hpp"
36
37using namespace std;
38using namespace spatial_cell;
49 vmesh::VelocityBlockContainer* blockContainer) {
50 // Block insert will fail if the block already exists, or if
51 // there are too many blocks in the velocity mesh.
52 if (vmesh->push_back(blockGID) == false) {
54 }
55
56 // Insert velocity block data, this will set values to 0.
57 const vmesh::LocalID newBlockLID = blockContainer->push_back_and_zero();
58
59 #ifdef DEBUG_ACC
60 bool ok = true;
61 if (vmesh->size() != blockContainer->size()) {
62 ok = false;
63 }
64 if (vmesh->getLocalID(blockGID) != newBlockLID) {
65 ok = false;
66 }
67 if (ok == false) {
68 stringstream ss;
69 ss << "ERROR in acc: sizes " << vmesh->size() << ' ' << blockContainer->size() << endl;
70 ss << "\t local IDs " << vmesh->getLocalID(blockGID) << " vs " << newBlockLID << endl;
71 cerr << ss.str();
72 exit(1);
73 }
74 #endif
75
76 // Set block parameters:
77 Real* parameters = blockContainer->getParameters(newBlockLID);
78 vmesh->getBlockInfo(blockGID, parameters+BlockParams::VXCRD);
79 return newBlockLID;
80}
81
82
83
84
85void inline swapBlockIndices(velocity_block_indices_t &blockIndices, const uint dimension){
86
87 uint temp;
88 // Switch block indices according to dimensions, the algorithm has
89 // been written for integrating along z.
90 switch (dimension){
91 case 0:
92 /*i and k coordinates have been swapped*/
93 temp=blockIndices[2];
94 blockIndices[2]=blockIndices[0];
95 blockIndices[0]=temp;
96 break;
97 case 1:
98 /*in values j and k coordinates have been swapped*/
99 temp=blockIndices[2];
100 blockIndices[2]=blockIndices[1];
101 blockIndices[1]=temp;
102 break;
103 case 2:
104 break;
105 }
106}
107
108
109
110/*
111 Here we map from the current time step grid, to a target grid which
112 is the lagrangian departure grid (so th grid at timestep +dt,
113 tracked backwards by -dt)
114
115 TODO: parallelize with openMP over block-columns. If one also
116 pre-creates new blocks in a separate loop first (serial operation),
117 then the openmp parallization would scale well (better than over
118 spatial cells), and would not need synchronization.
119
120*/
122 const uint popID,
123 Real in_intersection, Real in_intersection_di, Real in_intersection_dj, Real in_intersection_dk,
124 const uint dimension) {
125 no_subnormals(); // Needed by Agner's vectorclass
126
127 // Conversion here:
128 Realf intersection = (Realf)in_intersection;
129 Realf intersection_di = (Realf)in_intersection_di;
130 Realf intersection_dj = (Realf)in_intersection_dj;
131 Realf intersection_dk = (Realf)in_intersection_dk;
132
133 Realf dv,v_min;
134 Realf is_temp;
135 int max_v_length;
136 uint block_indices_to_id[3] = {0, 0, 0}; /*< used when computing id of target block, 0 for compiler */
137 uint cell_indices_to_id[3] = {0, 0, 0}; /*< used when computing id of target cell in block, 0 for compiler */
138
139 vmesh::VelocityMesh* vmesh = spatial_cell->get_velocity_mesh(popID);
140 vmesh::VelocityBlockContainer* blockContainer = spatial_cell->get_velocity_blocks(popID);
141
142 //nothing to do if no blocks
143 if(vmesh->size() == 0) {
144 return true;
145 }
146
147 dv = vmesh->getCellSize()[dimension];
148 v_min = vmesh->getMeshMinLimits()[dimension];
149 max_v_length = vmesh->getGridLength()[dimension];
150
151 switch (dimension) {
152 case 0:
153 /* i and k coordinates have been swapped*/
154
155 /*swap intersection i and k coordinates*/
156 is_temp=intersection_di;
158 intersection_dk=is_temp;
159
160 /*set values in array that is used to convert block indices to id using a dot product*/
161 block_indices_to_id[0] = vmesh->getGridLength()[0]*vmesh->getGridLength()[1];
162 block_indices_to_id[1] = vmesh->getGridLength()[0];
163 block_indices_to_id[2] = 1;
164
165 /*set values in array that is used to convert block indices to id using a dot product*/
166 cell_indices_to_id[0]=WID2;
167 cell_indices_to_id[1]=WID;
168 cell_indices_to_id[2]=1;
169 break;
170 case 1:
171 /* j and k coordinates have been swapped*/
172
173 /*swap intersection j and k coordinates*/
174 is_temp=intersection_dj;
176 intersection_dk=is_temp;
177
178 /*set values in array that is used to convert block indices to id using a dot product*/
179 block_indices_to_id[0]=1;
180 block_indices_to_id[1] = vmesh->getGridLength()[0]*vmesh->getGridLength()[1];
181 block_indices_to_id[2] = vmesh->getGridLength()[0];
182
183 /*set values in array that is used to convert block indices to id using a dot product*/
184 cell_indices_to_id[0]=1;
185 cell_indices_to_id[1]=WID2;
186 cell_indices_to_id[2]=WID;
187 break;
188 case 2:
189 /*set values in array that is used to convert block indices to id using a dot product*/
190 block_indices_to_id[0]=1;
191 block_indices_to_id[1] = vmesh->getGridLength()[0];
192 block_indices_to_id[2] = vmesh->getGridLength()[0]*vmesh->getGridLength()[1];
193
194 // set values in array that is used to convert block indices to id using a dot product.
195 cell_indices_to_id[0]=1;
196 cell_indices_to_id[1]=WID;
197 cell_indices_to_id[2]=WID2;
198 break;
199 }
200
201 const Real i_dv=1.0/dv;
202
203 // sort blocks according to dimension, and divide them into columns
204 vmesh::LocalID* blocks = new vmesh::LocalID[vmesh->size()];
205 std::vector<uint> columnBlockOffsets;
206 std::vector<uint> columnNumBlocks;
207 std::vector<uint> setColumnOffsets;
208 std::vector<uint> setNumColumns;
209 std::vector<int> columnMinBlockK;
210 std::vector<int> columnMaxBlockK;
211
212 sortBlocklistByDimension(vmesh, dimension, blocks,
213 columnBlockOffsets, columnNumBlocks,
214 setColumnOffsets, setNumColumns);
215
216 // loop over block column sets (all columns along the dimension with the other dimensions being equal )
217
218/*
219 values array used to store column data The max size is the worst
220 case scenario with every second block having content, creating up
221 to ( MAX_BLOCKS_PER_DIM / 2 + 1) columns with each needing three
222 blocks (two for padding)
223*/
224 Vec values[(3 * ( MAX_BLOCKS_PER_DIM / 2 + 1)) * WID3 / VECL];
225 /*pointers to target block datas*/
226 Realf *blockIndexToBlockData[MAX_BLOCKS_PER_DIM];
229
230 for(uint setIndex=0; setIndex< setColumnOffsets.size(); ++setIndex) {
231 //init
232 for (uint blockK = 0; blockK < MAX_BLOCKS_PER_DIM; blockK++){
233 blockIndexToBlockData[blockK] = NULL;
234 isTargetBlock[blockK] = false;
235 isSourceBlock[blockK] = false;
236 }
237
238 //Load data into values array (this also zeroes the original data)
239 uint valuesColumnOffset = 0; //offset to values array for data in a column in this set
240 for(uint columnIndex = setColumnOffsets[setIndex]; columnIndex < setColumnOffsets[setIndex] + setNumColumns[setIndex] ; columnIndex ++){
241 const vmesh::LocalID n_cblocks = columnNumBlocks[columnIndex];
242 vmesh::GlobalID* cblocks = blocks + columnBlockOffsets[columnIndex]; //column blocks
243 loadColumnBlockData(vmesh, blockContainer, cblocks, n_cblocks, dimension, values + valuesColumnOffset);
244 valuesColumnOffset += (n_cblocks + 2) * (WID3/VECL); // there are WID3/VECL elements of type Vec per block
245 }
246
247
248 /*need x,y coordinate of this column set of blocks, take it from first
249 block in first column*/
250 velocity_block_indices_t setFirstBlockIndices;
251 vmesh->getIndices(blocks[columnBlockOffsets[setColumnOffsets[setIndex]]],
252 setFirstBlockIndices[0], setFirstBlockIndices[1], setFirstBlockIndices[2]);
253 swapBlockIndices(setFirstBlockIndices, dimension);
254 /*compute the maximum starting point of the lagrangian (target) grid
255 (base level) within the 4 corner cells in this
256 block. Needed for computing maximum extent of target column*/
257
258 Realf max_intersectionMin = intersection +
259 (setFirstBlockIndices[0] * WID + 0) * intersection_di +
260 (setFirstBlockIndices[1] * WID + 0) * intersection_dj;
261 max_intersectionMin = std::max(max_intersectionMin,
263 (setFirstBlockIndices[0] * WID + 0) * intersection_di +
264 (setFirstBlockIndices[1] * WID + WID - 1) * intersection_dj);
265 max_intersectionMin = std::max(max_intersectionMin,
267 (setFirstBlockIndices[0] * WID + WID - 1) * intersection_di +
268 (setFirstBlockIndices[1] * WID + 0) * intersection_dj);
269 max_intersectionMin = std::max(max_intersectionMin,
271 (setFirstBlockIndices[0] * WID + WID - 1) * intersection_di +
272 (setFirstBlockIndices[1] * WID + WID - 1) * intersection_dj);
273
274 Realf min_intersectionMin = intersection +
275 (setFirstBlockIndices[0] * WID + 0) * intersection_di +
276 (setFirstBlockIndices[1] * WID + 0) * intersection_dj;
277 min_intersectionMin = std::min(min_intersectionMin,
279 (setFirstBlockIndices[0] * WID + 0) * intersection_di +
280 (setFirstBlockIndices[1] * WID + WID - 1) * intersection_dj);
281 min_intersectionMin = std::min(min_intersectionMin,
283 (setFirstBlockIndices[0] * WID + WID - 1) * intersection_di +
284 (setFirstBlockIndices[1] * WID + 0) * intersection_dj);
285 min_intersectionMin = std::min(min_intersectionMin,
287 (setFirstBlockIndices[0] * WID + WID - 1) * intersection_di +
288 (setFirstBlockIndices[1] * WID + WID - 1) * intersection_dj);
289
290 //now, record which blocks are target blocks
291 for(uint columnIndex = setColumnOffsets[setIndex]; columnIndex < setColumnOffsets[setIndex] + setNumColumns[setIndex] ; columnIndex ++){
292 const vmesh::LocalID n_cblocks = columnNumBlocks[columnIndex];
293 vmesh::GlobalID* cblocks = blocks + columnBlockOffsets[columnIndex]; //column blocks
294 velocity_block_indices_t firstBlockIndices;
295 velocity_block_indices_t lastBlockIndices;
296 vmesh->getIndices(cblocks[0],
297 firstBlockIndices[0], firstBlockIndices[1], firstBlockIndices[2]);
298 vmesh->getIndices(cblocks[n_cblocks -1],
299 lastBlockIndices[0], lastBlockIndices[1], lastBlockIndices[2]);
300 swapBlockIndices(firstBlockIndices, dimension);
301 swapBlockIndices(lastBlockIndices, dimension);
302
303 /*firstBlockV is in z the minimum velocity value of the lower
304 * edge in source grid.
305 *lastBlockV is in z the maximum velocity value of the upper
306 * edge in source grid. Added 1.01*dv to account for unexpected issues*/
307 Realf firstBlockMinV = (WID * firstBlockIndices[2]) * dv + v_min;
308 Realf lastBlockMaxV = (WID * (lastBlockIndices[2] + 1)) * dv + v_min;
309
310 /*gk is now the k value in terms of cells in target
311 grid. This distance between max_intersectionMin (so lagrangian
312 plan, well max value here) and V of source grid, divided by
313 intersection_dk to find out how many grid cells that is*/
314 const int firstBlock_gk = (int)((firstBlockMinV - max_intersectionMin)/intersection_dk);
315 const int lastBlock_gk = (int)((lastBlockMaxV - min_intersectionMin)/intersection_dk);
316
317 int firstBlockIndexK = firstBlock_gk/WID;
318 int lastBlockIndexK = lastBlock_gk/WID;
320 //now enforce mesh limits for target column blocks
321 firstBlockIndexK = (firstBlockIndexK >= 0) ? firstBlockIndexK : 0;
322 firstBlockIndexK = (firstBlockIndexK < max_v_length ) ? firstBlockIndexK : max_v_length - 1;
323 lastBlockIndexK = (lastBlockIndexK >= 0) ? lastBlockIndexK : 0;
324 lastBlockIndexK = (lastBlockIndexK < max_v_length ) ? lastBlockIndexK : max_v_length - 1;
325 if(firstBlockIndexK < wallmargin
326 || firstBlockIndexK >= max_v_length - wallmargin
327 || lastBlockIndexK < wallmargin
328 || lastBlockIndexK >= max_v_length - wallmargin
329 ) {
330 string message = "Some target blocks in acceleration are going to be less than ";
331 message += std::to_string(wallmargin);
332 message += " blocks away from the current velocity space walls for population ";
333 message += getObjectWrapper().particleSpecies[popID].name;
334 message += " at CellID ";
335 message += std::to_string(static_cast<int>(spatial_cell->parameters[CellParams::CELLID]));
336 message += ". Consider expanding velocity space for that population.";
337 bailout(true, message, __FILE__, __LINE__);
338 }
339
340 //store source blocks
341 for (uint blockK = firstBlockIndices[2]; blockK <= lastBlockIndices[2]; blockK++){
342 isSourceBlock[blockK] = true;
343 }
344
345 //store target blocks
346 for (uint blockK = firstBlockIndexK; (int)blockK <= lastBlockIndexK; blockK++){
347 isTargetBlock[blockK]=true;
348 }
349
350 //store also for each column firstBlockIndexK, and lastBlockIndexK
351 columnMinBlockK.push_back(firstBlockIndexK);
352 columnMaxBlockK.push_back(lastBlockIndexK);
353 }
354
355 //now add target blocks that do not yet exist and remove source blocks
356 //that are not target blocks
357 for (uint blockK = 0; blockK < MAX_BLOCKS_PER_DIM; blockK++){
358 if(isTargetBlock[blockK] && !isSourceBlock[blockK] ) {
359 const int targetBlock =
360 setFirstBlockIndices[0] * block_indices_to_id[0] +
361 setFirstBlockIndices[1] * block_indices_to_id[1] +
362 blockK * block_indices_to_id[2];
363 addVelocityBlock(targetBlock, vmesh, blockContainer);
364
365 }
366 if(!isTargetBlock[blockK] && isSourceBlock[blockK] ) {
367 const int targetBlock =
368 setFirstBlockIndices[0] * block_indices_to_id[0] +
369 setFirstBlockIndices[1] * block_indices_to_id[1] +
370 blockK * block_indices_to_id[2];
371
372 spatial_cell->remove_velocity_block(targetBlock, popID);
373 }
374 }
375
376 /*now store pointer to blocks, cannot do it at the same time as adding
377 them since they might move due to re-allocations or migrated when
378 removing blocks*/
379 for (int blockK = 0; blockK < MAX_BLOCKS_PER_DIM; blockK++){
380 if(isTargetBlock[blockK]) {
381 const int targetBlock =
382 setFirstBlockIndices[0] * block_indices_to_id[0] +
383 setFirstBlockIndices[1] * block_indices_to_id[1] +
384 blockK * block_indices_to_id[2];
385 const vmesh::LocalID tblockLID = vmesh->getLocalID(targetBlock);
386 // Get pointer to target block data.
387 blockIndexToBlockData[blockK] = blockContainer->getData(tblockLID);
388 }
389 }
390
391
392
393 // loop over columns in set and do the mapping
394 valuesColumnOffset = 0; //offset to values array for data in a column in this set
395 for(uint columnIndex = setColumnOffsets[setIndex]; columnIndex < setColumnOffsets[setIndex] + setNumColumns[setIndex] ; columnIndex ++){
396 const vmesh::LocalID n_cblocks = columnNumBlocks[columnIndex];
397 vmesh::GlobalID* cblocks = blocks + columnBlockOffsets[columnIndex]; //column blocks
398
399 // compute the common indices for this block column set
400 //First block in column
401 velocity_block_indices_t block_indices_begin;
402 vmesh->getIndices(cblocks[0],block_indices_begin[0],block_indices_begin[1],block_indices_begin[2]);
403
404 // Switch block indices according to dimensions, the algorithm has
405 // been written for integrating along z.
406 swapBlockIndices(block_indices_begin, dimension);
407
408 /* i,j,k are now relative to the order in which we copied data to the values array.
409 After this point in the k,j,i loops there should be no branches based on dimensions
410
411 Note that the i dimension is vectorized, and thus there are no loops over i
412 */
413 for (int j = 0; j < WID; j += VECL/WID){
414 // create vectors with the i and j indices in the vector position on the plane.
415 #if VECL == 4 && WID == 4
416 const Veci i_indices = Veci({0, 1, 2, 3});
417 const Veci j_indices = Veci({j, j, j, j});
418 #elif VECL == 4 && WID == 8
419 cerr << __FILE__ << ":" << __LINE__ << ": VECL == 4 && WID == 8 cannot work!" << endl;
420 abort();
421 #elif VECL == 8 && WID == 4
422 const Veci i_indices = Veci({0, 1, 2, 3,
423 0, 1, 2, 3});
424 const Veci j_indices = Veci({j, j, j, j,
425 j + 1, j + 1, j + 1, j + 1});
426 #elif VECL == 8 && WID == 8
427 const Veci i_indices = Veci({0, 1, 2, 3, 4, 5, 6, 7});
428 const Veci j_indices = Veci({j, j, j, j, j, j, j, j});
429 #elif VECL == 16 && WID == 4
430 const Veci i_indices = Veci({0, 1, 2, 3,
431 0, 1, 2, 3,
432 0, 1, 2, 3,
433 0, 1, 2, 3});
434 const Veci j_indices = Veci({j, j, j, j,
435 j + 1, j + 1, j + 1, j + 1,
436 j + 2, j + 2, j + 2, j + 2,
437 j + 3, j + 3, j + 3, j + 3});
438 #elif VECL == 16 && WID == 8
439 const Veci i_indices = Veci({0, 1, 2, 3, 4, 5, 6, 7,
440 0, 1, 2, 3, 4, 5, 6, 7});
441 const Veci j_indices = Veci({j, j, j, j, j, j, j, j,
442 j+1, j+1, j+1, j+1, j+1, j+1, j+1, j+1});
443 #elif VECL == 16 && WID == 16
444 const Veci i_indices = Veci({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
445 const Veci j_indices = Veci({j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j});
446 #elif VECL == 32 && WID == 4
447 cerr << __FILE__ << ":" << __LINE__ << ": VECL == 32 && WID == 4 cannot work, too long vector for one plane!" << endl;
448 abort();
449 #elif VECL == 32 && WID == 8
450 const Veci i_indices = Veci({0, 1, 2, 3, 4, 5, 6, 7,
451 0, 1, 2, 3, 4, 5, 6, 7,
452 0, 1, 2, 3, 4, 5, 6, 7,
453 0, 1, 2, 3, 4, 5, 6, 7});
454 const Veci j_indices = Veci({j, j, j, j, j, j, j, j,
455 j+1, j+1, j+1, j+1, j+1, j+1, j+1, j+1,
456 j+2, j+2, j+2, j+2, j+2, j+2, j+2, j+2,
457 j+3, j+3, j+3, j+3, j+3, j+3, j+3, j+3});
458 #elif VECL == 64 && WID == 4
459 cerr << __FILE__ << ":" << __LINE__ << ": VECL == 64 && WID == 4 cannot work, too long vector for one plane!" << endl;
460 abort();
461 #elif VECL == 64 && WID == 8
462 const Veci i_indices = Veci({0, 1, 2, 3, 4, 5, 6, 7,
463 0, 1, 2, 3, 4, 5, 6, 7,
464 0, 1, 2, 3, 4, 5, 6, 7,
465 0, 1, 2, 3, 4, 5, 6, 7,
466 0, 1, 2, 3, 4, 5, 6, 7,
467 0, 1, 2, 3, 4, 5, 6, 7,
468 0, 1, 2, 3, 4, 5, 6, 7,
469 0, 1, 2, 3, 4, 5, 6, 7});
470 const Veci j_indices = Veci({j, j, j, j, j, j, j, j,
471 j+1, j+1, j+1, j+1, j+1, j+1, j+1, j+1,
472 j+2, j+2, j+2, j+2, j+2, j+2, j+2, j+2,
473 j+3, j+3, j+3, j+3, j+3, j+3, j+3, j+3,
474 j+4, j+4, j+4, j+4, j+4, j+4, j+4, j+4,
475 j+5, j+5, j+5, j+5, j+5, j+5, j+5, j+5,
476 j+6, j+6, j+6, j+6, j+6, j+6, j+6, j+6,
477 j+7, j+7, j+7, j+7, j+7, j+7, j+7, j+7});
478 #else
479 cerr << __FILE__ << ":" << __LINE__ << ": Missing implementation for VECL=" << VECL << " and WID=" << WID << "!" << endl;
480 abort();
481 #endif
482
483 const Veci target_cell_index_common =
484 i_indices * cell_indices_to_id[0] +
485 j_indices * cell_indices_to_id[1];
486
487 /*
488 intersection_min is the intersection z coordinate (z after
489 swaps that is) of the lowest possible z plane for each i,j
490 index (i in vector)
491 */
492
493 const Vec intersection_min =
495 (block_indices_begin[0] * WID + to_realf(i_indices)) * intersection_di +
496 (block_indices_begin[1] * WID + to_realf(j_indices)) * intersection_dj;
497
498 /*compute some initial values, that are used to set up the
499 * shifting of values as we go through all blocks in
500 * order. See comments where they are shifted for
501 * explanations of their meaning*/
502 Vec v_r((WID * block_indices_begin[2]) * dv + v_min);
503 Vec lagrangian_v_r((v_r-intersection_min)/intersection_dk);
504#if VECTORCLASS_H >= 20000
505 Veci lagrangian_gk_r=truncatei(lagrangian_v_r);
506#else
507 Veci lagrangian_gk_r=truncate_to_int(lagrangian_v_r);
508#endif
509
510 /*compute location of min and max, this does not change for one
511 * column (or even for this set of intersections, and can be used
512 * to quickly compute max and min later on*/
513 //TODO, these can be computed much earlier, since they are
514 //identiacal for each set of intersections
515 int minGkIndex=0, maxGkIndex=0; // 0 for compiler
516 {
517 Real maxV = std::numeric_limits<Real>::min();
518 Real minV = std::numeric_limits<Real>::max();
519 for(int i = 0; i < VECL; i++) {
520 if ( lagrangian_v_r[i] > maxV) {
521 maxV = lagrangian_v_r[i];
522 maxGkIndex = i;
523 }
524 if ( lagrangian_v_r[i] < minV) {
525 minV = lagrangian_v_r[i];
526 minGkIndex = i;
527 }
528 }
529 }
530
531
532 // loop through all blocks in column and compute the mapping as integrals.
533 for (uint k=0; k < WID * n_cblocks; ++k ){
534 // Compute reconstructions
535 // values + i_pcolumnv(n_cblocks, -1, j, 0) is the starting point of the column data for fixed j
536 // k + WID is the index where we have stored k index, WID amount of padding.
537 #ifdef ACC_SEMILAG_PLM
538 Vec a[2];
539 compute_plm_coeff(values + valuesColumnOffset + i_pcolumnv(j, 0, -1, n_cblocks), k + WID , a, spatial_cell->getVelocityBlockMinValue(popID));
540 #endif
541 #ifdef ACC_SEMILAG_PPM
542 Vec a[3];
543 compute_ppm_coeff(values + valuesColumnOffset + i_pcolumnv(j, 0, -1, n_cblocks), h4, k + WID, a, spatial_cell->getVelocityBlockMinValue(popID));
544 #endif
545 #ifdef ACC_SEMILAG_PQM
546 Vec a[5];
547 compute_pqm_coeff(values + valuesColumnOffset + i_pcolumnv(j, 0, -1, n_cblocks), h8, k + WID, a, spatial_cell->getVelocityBlockMinValue(popID));
548 #endif
549
550 // set the initial value for the integrand at the boundary at v = 0
551 // (in reduced cell units), this will be shifted to target_density_1, see below.
552 Vec target_density_r(0.0);
553 // v_l, v_r are the left and right velocity coordinates of source cell. Left is the old right.
554 Vec v_l = v_r;
555 v_r += dv;
556
557 // left(l) and right(r) k values (global index) in the target
558 // Lagrangian grid, the intersecting cells. Again old right is new left.
559 const Veci lagrangian_gk_l = lagrangian_gk_r;
560#if VECTORCLASS_H >= 20000
561 lagrangian_gk_r = truncatei((v_r-intersection_min)/intersection_dk);
562#else
563 lagrangian_gk_r = truncate_to_int((v_r-intersection_min)/intersection_dk);
564#endif
565
566 //limits in lagrangian k for target column. Also take into
567 //account limits of target column
568 int minGk = std::max(int(lagrangian_gk_l[minGkIndex]), int(columnMinBlockK[columnIndex] * WID));
569 int maxGk = std::min(int(lagrangian_gk_r[maxGkIndex]), int((columnMaxBlockK[columnIndex] + 1) * WID - 1));
570
571 for(int gk = minGk; gk <= maxGk; gk++){
572 const int blockK = gk/WID;
573 const int gk_mod_WID = (gk - blockK * WID);
574
575
576 //cell indices in the target block (TODO: to be replaced by
577 //compile time generated scatter write operation)
578 const Veci target_cell(target_cell_index_common + gk_mod_WID * cell_indices_to_id[2]);
579
580 //the velocity between which we will integrate to put mass
581 //in the targe cell. If both v_r and v_l are in same cell
582 //then v_1,v_2 should be between v_l and v_r.
583 //v_1 and v_2 normalized to be between 0 and 1 in the cell.
584 //For vector elements where gk is already larger than needed (lagrangian_gk_r), v_2=v_1=v_r and thus the value is zero.
585 const Vec v_norm_r = ( min( max( (gk + 1) * intersection_dk + intersection_min, v_l), v_r) - v_l) * i_dv;
586 /*shift, old right is new left*/
587 const Vec target_density_l = target_density_r;
588
589 // compute right integrand
590 #ifdef ACC_SEMILAG_PLM
591 target_density_r =
592 v_norm_r * ( a[0] + v_norm_r * a[1] );
593 #endif
594 #ifdef ACC_SEMILAG_PPM
595 target_density_r =
596 v_norm_r * ( a[0] + v_norm_r * ( a[1] + v_norm_r * a[2] ) );
597
598 #endif
599 #ifdef ACC_SEMILAG_PQM
600 target_density_r =
601 v_norm_r * ( a[0] + v_norm_r * ( a[1] + v_norm_r * ( a[2] + v_norm_r * ( a[3] + v_norm_r * a[4] ) ) ) );
602 #endif
603
604 //store values, one element at a time. All blocks
605 //have been created by now.
606 //TODO replace by vector version & scatter & gather operation
607
608
609 if(dimension == 2) {
610 Realf* targetDataPointer = blockIndexToBlockData[blockK] + j * cell_indices_to_id[1] + gk_mod_WID * cell_indices_to_id[2];
611 Vec targetData;
612 targetData.load_a(targetDataPointer);
613 targetData += target_density_r - target_density_l;
614 targetData.store_a(targetDataPointer);
615 }
616 else{
617 // total value of integrand
618 const Vec target_density = target_density_r - target_density_l;
619 #pragma omp simd
620 for (int target_i=0; target_i < VECL; ++target_i) {
621 const Realf tval = target_density[target_i];
622 const uint tcell = target_cell[target_i];
623 blockIndexToBlockData[blockK][tcell] += tval;
624 } // for-loop over vector elements
625 }
626
627 } // for loop over target k-indices of current source block
628 } // for-loop over source blocks
629 } //for loop over j index
630 valuesColumnOffset += (n_cblocks + 2) * (WID3/VECL) ;// there are WID3/VECL elements of type Vec per block
631 } //for loop over columns
632
633 }
634 delete [] blocks;
635 return true;
636}
for i
Definition Dispersion.m:24
ARCH_HOSTDEV vmesh::LocalID push_back_and_zero()
ARCH_HOSTDEV vmesh::LocalID size() const
static vmesh::LocalID invalidLocalID()
void bailout(const bool condition, const std::string &message, const char *const file, const int line)
A function to stop the simulation if the boolean condition is true. Raises a flag which gets MPI_Redu...
Definition common.cpp:36
#define WID
Definition common.h:514
#define MAX_BLOCKS_PER_DIM
Definition common.h:73
const int WID3
Definition common.h:517
const int WID2
Definition common.h:516
static void compute_plm_coeff(const Vec *const values, const uint k, Vec a[2], const Realf threshold)
static void compute_ppm_coeff(const Vec *const values, const face_estimate_order order, const uint k, Vec a[3], const Realf threshold)
static void compute_pqm_coeff(const Vec *__restrict__ values, face_estimate_order order, uint k, Vec a[5], const Realf threshold)
void loadColumnBlockData(const vmesh::VelocityMesh *vmesh, vmesh::VelocityBlockContainer *blockContainer, const vmesh::GlobalID *blocks, const vmesh::LocalID n_blocks, const int dimension, Vec *__restrict__ values)
#define i_pcolumnv(j, k, k_block, num_k_blocks)
vmesh::LocalID addVelocityBlock(const vmesh::GlobalID &blockGID, vmesh::VelocityMesh *vmesh, vmesh::VelocityBlockContainer *blockContainer)
bool map_1d(SpatialCell *spatial_cell, const uint popID, Real in_intersection, Real in_intersection_di, Real in_intersection_dj, Real in_intersection_dk, const uint dimension)
void swapBlockIndices(velocity_block_indices_t &blockIndices, const uint dimension)
void sortBlocklistByDimension(const vmesh::VelocityMesh *vmesh, const uint dimension, uint *blocks, std::vector< uint > &columnBlockOffsets, std::vector< uint > &columnNumBlocks, std::vector< uint > &setColumnOffsets, std::vector< uint > &setNumColumns)
float Real
Definition definitions.h:41
float Realf
Definition definitions.h:33
const Realf intersection
const Realf intersection_dk
__shared__ int isTargetBlock[MAX_BLOCKS_PER_DIM]
__global__ void vmesh::VelocityMesh **__restrict__ ColumnOffsets split::SplitVector< vmesh::GlobalID > Hashinator::Hashmap< vmesh::GlobalID, vmesh::LocalID > const uint *__restrict__ const Realf const int const int const Realf v_min
const Realf intersection_di
__global__ void vmesh::VelocityMesh **__restrict__ ColumnOffsets split::SplitVector< vmesh::GlobalID > Hashinator::Hashmap< vmesh::GlobalID, vmesh::LocalID > const uint *__restrict__ const Realf const int const int const Realf const Realf dv
const uint setIndex
__global__ void vmesh::VelocityMesh **__restrict__ ColumnOffsets split::SplitVector< vmesh::GlobalID > Hashinator::Hashmap< vmesh::GlobalID, vmesh::LocalID > const uint *__restrict__ const Realf const int const int max_v_length
const Realf intersection_dj
__shared__ int isSourceBlock[MAX_BLOCKS_PER_DIM]
const int j
const int k
ObjectWrapper & getObjectWrapper()
Definition main.cpp:33
std::array< vmesh::LocalID, 3 > velocity_block_indices_t
uint32_t LocalID
Definition definitions.h:60
uint32_t GlobalID
Definition definitions.h:59
std::vector< species::Species > particleSpecies
static uint bailout_velocity_space_wall_margin
Definition parameters.h:188
An interface to a type with floating point values.
static ARCH_HOSTDEV VecSimple< T > min(VecSimple< T > const &l, VecSimple< T > const &r)
static ARCH_HOSTDEV void no_subnormals()
static ARCH_HOSTDEV VecSimple< T > max(VecSimple< T > const &l, VecSimple< T > const &r)
static ARCH_HOSTDEV VecSimple< int > truncate_to_int(VecSimple< T > const &a)