Vlasiator ebf0dd394 on dev (v5.4.0 + 1054 commits)
Loading...
Searching...
No Matches
copysphere.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 */
22
26
27#include <cstdlib>
28#include <iostream>
29
30#include "copysphere.h"
31#include "../projects/project.h"
38#include "../common.h"
39#include "../object_wrapper.h"
40
41#ifdef DEBUG_VLASIATOR
42#define DEBUG_COPYSPHERE
43#endif
44#ifdef DEBUG_SYSBOUNDARY
45#define DEBUG_COPYSPHERE
46#endif
47
48namespace SBC {
50
52
54 Readparameters::add("copysphere.centerX", "X coordinate of copysphere center (m)", 0.0);
55 Readparameters::add("copysphere.centerY", "Y coordinate of copysphere center (m)", 0.0);
56 Readparameters::add("copysphere.centerZ", "Z coordinate of copysphere center (m)", 0.0);
57 Readparameters::add("copysphere.radius", "Radius of copysphere (m).", 1.0e7);
58 Readparameters::add("copysphere.geometry", "Select the geometry of the copysphere, 0: inf-norm (diamond), 1: 1-norm (square), 2: 2-norm (circle, DEFAULT), 3: 2-norm cylinder aligned with y-axis, use with polar plane/line dipole.", 2);
59 Readparameters::add( "copysphere.precedence", "Precedence value of the copysphere system boundary condition (integer), the higher the stronger.", 2);
60 Readparameters::add("copysphere.reapplyUponRestart", "If 0 (default), keep going with the state existing in the restart file. If 1, calls again applyInitialState. Can be used to change boundary condition behaviour during a run.", 0);
61 Readparameters::add("copysphere.zeroPerB", "If 0 (default), normal copysphere behaviour of magnetic field at inner boundary. If 1, keep magnetic field static at the inner boundary", 0);
62
63 // Per-population parameters
64 for (uint i = 0; i < getObjectWrapper().particleSpecies.size(); i++) {
65 const std::string& pop = getObjectWrapper().particleSpecies[i].name;
66
67 Readparameters::add(pop + "_copysphere.rho", "Number density of the copysphere (m^-3)", 0.0);
68 Readparameters::add(pop + "_copysphere.T", "Temperature of the copysphere (K)", 0.0);
69 Readparameters::add(pop + "_copysphere.VX0", "Bulk velocity of copyspheric distribution function in X direction (m/s)", 0.0);
70 Readparameters::add(pop + "_copysphere.VY0", "Bulk velocity of copyspheric distribution function in X direction (m/s)", 0.0);
71 Readparameters::add(pop + "_copysphere.VZ0", "Bulk velocity of copyspheric distribution function in X direction (m/s)", 0.0);
72 Readparameters::add(pop + "_copysphere.fluffiness", "Inertia of boundary smoothing when copying neighbour's moments and velocity distributions (0=completely constant boundaries, 1=neighbours are interpolated immediately).", 0);
73 }
74 }
75
77
78 Readparameters::get("copysphere.centerX", this->center[0]);
79 Readparameters::get("copysphere.centerY", this->center[1]);
80 Readparameters::get("copysphere.centerZ", this->center[2]);
81 Readparameters::get("copysphere.radius", this->radius);
82 FieldTracing::fieldTracingParameters.innerBoundaryRadius = this->radius;
83 Readparameters::get("copysphere.geometry", this->geometry);
84 Readparameters::get("copysphere.precedence", this->precedence);
85 uint reapply;
86 Readparameters::get("copysphere.reapplyUponRestart", reapply);
87 this->applyUponRestart = false;
88 if (reapply == 1) {
89 this->applyUponRestart = true;
90 }
91 uint noperb;
92 Readparameters::get("copysphere.zeroPerB", noperb);
93 this->zeroPerB = false;
94 if (noperb == 1) {
95 this->zeroPerB = true;
96 }
97
98 for (uint i = 0; i < getObjectWrapper().particleSpecies.size(); i++) {
99 const std::string& pop = getObjectWrapper().particleSpecies[i].name;
101
102 Readparameters::get(pop + "_copysphere.rho", sP.rho);
103 Readparameters::get(pop + "_copysphere.VX0", sP.V0[0]);
104 Readparameters::get(pop + "_copysphere.VY0", sP.V0[1]);
105 Readparameters::get(pop + "_copysphere.VZ0", sP.V0[2]);
106 Readparameters::get(pop + "_copysphere.fluffiness", sP.fluffiness);
107 Readparameters::get(pop + "_copysphere.T", sP.T);
108
109 // Failsafe, if density or temperature is zero, read from Magnetosphere
110 // (compare the corresponding verbose handling in projects/Magnetosphere/Magnetosphere.cpp)
111 if (sP.T == 0) {
112 Readparameters::get(pop + "_Magnetosphere.T", sP.T);
113 }
114 if (sP.rho == 0) {
115 Readparameters::get(pop + "_Magnetosphere.rho", sP.rho);
116 }
117
118 speciesParams.push_back(sP);
119 }
120 }
121
124 dynamic = false;
125
126 // iniSysBoundary is only called once, generateTemplateCell must
127 // init all particle species
128 generateTemplateCell(project);
129 }
130
131 Real getR(creal x, creal y, creal z, uint geometry, Real center[3]) {
132
133 Real r;
134
135 switch (geometry) {
136 case 0:
137 // infinity-norm, result is a diamond/square with diagonals aligned on the axes in 2D
138 r = fabs(x - center[0]) + fabs(y - center[1]) + fabs(z - center[2]);
139 break;
140 case 1:
141 // 1-norm, result is is a grid-aligned square in 2D
142 r = max(max(fabs(x - center[0]), fabs(y - center[1])), fabs(z - center[2]));
143 break;
144 case 2:
145 // 2-norm (Cartesian), result is a circle in 2D
146 r = sqrt((x - center[0]) * (x - center[0]) + (y - center[1]) * (y - center[1]) +
147 (z - center[2]) * (z - center[2]));
148 break;
149 case 3:
150 // 2-norm (Cartesian) cylinder aligned on y-axis
151 r = sqrt((x - center[0]) * (x - center[0]) + (z - center[2]) * (z - center[2]));
152 break;
153 default:
154 abort_mpi("copysphere.geometry has to be 0, 1 or 2.", 1);
155 }
156
157 return r;
158 }
159
160 void Copysphere::assignSysBoundary(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
162 const vector<CellID>& cells = getLocalCells();
163 for (uint i = 0; i < cells.size(); i++) {
164 if (mpiGrid[cells[i]]->sysBoundaryFlag == sysboundarytype::DO_NOT_COMPUTE) {
165 continue;
166 }
167
168 const creal* const cellParams = &(mpiGrid[cells[i]]->parameters[0]);
169 creal dx = cellParams[CellParams::DX];
170 creal dy = cellParams[CellParams::DY];
171 creal dz = cellParams[CellParams::DZ];
172 creal x = cellParams[CellParams::XCRD] + 0.5 * dx;
173 creal y = cellParams[CellParams::YCRD] + 0.5 * dy;
174 creal z = cellParams[CellParams::ZCRD] + 0.5 * dz;
175
176 if (getR(x, y, z, this->geometry, this->center) < this->radius) {
177 mpiGrid[cells[i]]->sysBoundaryFlag = this->getIndex();
178 }
179 }
180 }
181
182 void Copysphere::applyInitialState(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
185 fsgrids::bgbspan bgb, Project& project) {
186 const vector<CellID>& cells = getLocalCells();
187 #pragma omp parallel for
188 for (uint i = 0; i < cells.size(); ++i) {
189 SpatialCell* cell = mpiGrid[cells[i]];
190 if (cell->sysBoundaryFlag != this->getIndex()) continue;
191 for (uint popID=0; popID<getObjectWrapper().particleSpecies.size(); ++popID) {
192 setCellFromTemplate(cell,popID);
193 #ifdef DEBUG_VLASIATOR
194 // Verify current mesh and blocks
195 if (!cell->checkMesh(popID)) {
196 printf("ERROR in vmesh check: %s at %d\n",__FILE__,__LINE__);
197 }
198 #endif
199 }
200 }
201 }
202
204 fsgrids::technicalspan technical,
206 cint i,
207 cint j,
208 cint k
209 ) {
210 std::array<Real, 3> normalDirection{{ 0.0, 0.0, 0.0 }};
211
212 static creal DIAG2 = 1.0 / sqrt(2.0);
213 static creal DIAG3 = 1.0 / sqrt(3.0);
214
215 const auto& gridSpacing = fsgrid.getGridSpacing();
216
217 creal dx = gridSpacing[0];
218 creal dy = gridSpacing[1];
219 creal dz = gridSpacing[2];
220 const std::array<fsgrid::FsSize_t, 3> globalIndices = fsgrid.localToGlobal(i, j, k);
221 creal x = P::xmin + (convert<Real>(globalIndices[0]) + 0.5) * dx;
222 creal y = P::ymin + (convert<Real>(globalIndices[1]) + 0.5) * dy;
223 creal z = P::zmin + (convert<Real>(globalIndices[2]) + 0.5) * dz;
224 creal xsign = divideIfNonZero(x, fabs(x));
225 creal ysign = divideIfNonZero(y, fabs(y));
226 creal zsign = divideIfNonZero(z, fabs(z));
227
228 Real length = 0.0;
229
230 if (Parameters::xcells_ini == 1) {
231 if (Parameters::ycells_ini == 1) {
232 if (Parameters::zcells_ini == 1) {
233 // X,Y,Z
234 abort_mpi(
235 "What do you expect to do with a single-cell simulation of copysphere boundary type? Stop kidding.", 1);
236 // end of X,Y,Z
237 } else {
238 // X,Y
239 normalDirection[2] = zsign;
240 // end of X,Y
241 }
242 } else if (Parameters::zcells_ini == 1) {
243 // X,Z
244 normalDirection[1] = ysign;
245 // end of X,Z
246 } else {
247 // X
248 switch (this->geometry) {
249 case 0:
250 normalDirection[1] = DIAG2 * ysign;
251 normalDirection[2] = DIAG2 * zsign;
252 break;
253 case 1:
254 if (fabs(y) == fabs(z)) {
255 normalDirection[1] = ysign * DIAG2;
256 normalDirection[2] = zsign * DIAG2;
257 break;
258 }
259 if (fabs(y) > (this->radius - dy)) {
260 normalDirection[1] = ysign;
261 break;
262 }
263 if (fabs(z) > (this->radius - dz)) {
264 normalDirection[2] = zsign;
265 break;
266 }
267 if (fabs(y) > (this->radius - 2.0 * dy)) {
268 normalDirection[1] = ysign;
269 break;
270 }
271 if (fabs(z) > (this->radius - 2.0 * dz)) {
272 normalDirection[2] = zsign;
273 break;
274 }
275 break;
276 case 2:
277 length = sqrt(y * y + z * z);
278 normalDirection[1] = y / length;
279 normalDirection[2] = z / length;
280 break;
281 default:
282 std::cerr << __FILE__ << ":" << __LINE__ << ":" << "copysphere.geometry has to be 0, 1 or 2 with this grid shape." << std::endl;
283 abort();
284 }
285 // end of X
286 }
287 } else if (Parameters::ycells_ini == 1) {
288 if (Parameters::zcells_ini == 1) {
289 // Y,Z
290 normalDirection[0] = xsign;
291 // end of Y,Z
292 } else {
293 // Y
294 switch (this->geometry) {
295 case 0:
296 normalDirection[0] = DIAG2 * xsign;
297 normalDirection[2] = DIAG2 * zsign;
298 break;
299 case 1:
300 if (fabs(x) == fabs(z)) {
301 normalDirection[0] = xsign * DIAG2;
302 normalDirection[2] = zsign * DIAG2;
303 break;
304 }
305 if (fabs(x) > (this->radius - dx)) {
306 normalDirection[0] = xsign;
307 break;
308 }
309 if (fabs(z) > (this->radius - dz)) {
310 normalDirection[2] = zsign;
311 break;
312 }
313 if (fabs(x) > (this->radius - 2.0 * dx)) {
314 normalDirection[0] = xsign;
315 break;
316 }
317 if (fabs(z) > (this->radius - 2.0 * dz)) {
318 normalDirection[2] = zsign;
319 break;
320 }
321 break;
322 case 2:
323 case 3:
324 length = sqrt(x * x + z * z);
325 normalDirection[0] = x / length;
326 normalDirection[2] = z / length;
327 break;
328 default:
329 std::cerr << __FILE__ << ":" << __LINE__ << ":" << "copysphere.geometry has to be 0, 1, 2 or 3 with this grid shape." << std::endl;
330 abort();
331 }
332 // end of Y
333 }
334 } else if (Parameters::zcells_ini == 1) {
335 // Z
336 switch (this->geometry) {
337 case 0:
338 normalDirection[0] = DIAG2 * xsign;
339 normalDirection[1] = DIAG2 * ysign;
340 break;
341 case 1:
342 if (fabs(x) == fabs(y)) {
343 normalDirection[0] = xsign * DIAG2;
344 normalDirection[1] = ysign * DIAG2;
345 break;
346 }
347 if (fabs(x) > (this->radius - dx)) {
348 normalDirection[0] = xsign;
349 break;
350 }
351 if (fabs(y) > (this->radius - dy)) {
352 normalDirection[1] = ysign;
353 break;
354 }
355 if (fabs(x) > (this->radius - 2.0 * dx)) {
356 normalDirection[0] = xsign;
357 break;
358 }
359 if (fabs(y) > (this->radius - 2.0 * dy)) {
360 normalDirection[1] = ysign;
361 break;
362 }
363 break;
364 case 2:
365 length = sqrt(x * x + y * y);
366 normalDirection[0] = x / length;
367 normalDirection[1] = y / length;
368 break;
369 default:
370 abort_mpi("copysphere.geometry has to be 0, 1 or 2 with this grid shape.", 1);
371 }
372 // end of Z
373 } else {
374 // 3D
375 switch (this->geometry) {
376 case 0:
377 normalDirection[0] = DIAG3 * xsign;
378 normalDirection[1] = DIAG3 * ysign;
379 normalDirection[2] = DIAG3 * zsign;
380 break;
381 case 1:
382 if (fabs(x) == fabs(y) && fabs(x) == fabs(z) && fabs(x) > this->radius - dx) {
383 normalDirection[0] = xsign * DIAG3;
384 normalDirection[1] = ysign * DIAG3;
385 normalDirection[2] = zsign * DIAG3;
386 break;
387 }
388 if (fabs(x) == fabs(y) && fabs(x) == fabs(z) && fabs(x) > this->radius - 2.0 * dx) {
389 normalDirection[0] = xsign * DIAG3;
390 normalDirection[1] = ysign * DIAG3;
391 normalDirection[2] = zsign * DIAG3;
392 break;
393 }
394 if (fabs(x) == fabs(y) && fabs(x) > this->radius - dx && fabs(z) < this->radius - dz) {
395 normalDirection[0] = xsign * DIAG2;
396 normalDirection[1] = ysign * DIAG2;
397 normalDirection[2] = 0.0;
398 break;
399 }
400 if (fabs(y) == fabs(z) && fabs(y) > this->radius - dy && fabs(x) < this->radius - dx) {
401 normalDirection[0] = 0.0;
402 normalDirection[1] = ysign * DIAG2;
403 normalDirection[2] = zsign * DIAG2;
404 break;
405 }
406 if (fabs(x) == fabs(z) && fabs(x) > this->radius - dx && fabs(y) < this->radius - dy) {
407 normalDirection[0] = xsign * DIAG2;
408 normalDirection[1] = 0.0;
409 normalDirection[2] = zsign * DIAG2;
410 break;
411 }
412 if (fabs(x) == fabs(y) && fabs(x) > this->radius - 2.0 * dx && fabs(z) < this->radius - 2.0 * dz) {
413 normalDirection[0] = xsign * DIAG2;
414 normalDirection[1] = ysign * DIAG2;
415 normalDirection[2] = 0.0;
416 break;
417 }
418 if (fabs(y) == fabs(z) && fabs(y) > this->radius - 2.0 * dy && fabs(x) < this->radius - 2.0 * dx) {
419 normalDirection[0] = 0.0;
420 normalDirection[1] = ysign * DIAG2;
421 normalDirection[2] = zsign * DIAG2;
422 break;
423 }
424 if (fabs(x) == fabs(z) && fabs(x) > this->radius - 2.0 * dx && fabs(y) < this->radius - 2.0 * dy) {
425 normalDirection[0] = xsign * DIAG2;
426 normalDirection[1] = 0.0;
427 normalDirection[2] = zsign * DIAG2;
428 break;
429 }
430 if (fabs(x) > (this->radius - dx)) {
431 normalDirection[0] = xsign;
432 break;
433 }
434 if (fabs(y) > (this->radius - dy)) {
435 normalDirection[1] = ysign;
436 break;
437 }
438 if (fabs(z) > (this->radius - dz)) {
439 normalDirection[2] = zsign;
440 break;
441 }
442 if (fabs(x) > (this->radius - 2.0 * dx)) {
443 normalDirection[0] = xsign;
444 break;
445 }
446 if (fabs(y) > (this->radius - 2.0 * dy)) {
447 normalDirection[1] = ysign;
448 break;
449 }
450 if (fabs(z) > (this->radius - 2.0 * dz)) {
451 normalDirection[2] = zsign;
452 break;
453 }
454 break;
455 case 2:
456 length = sqrt(x * x + y * y + z * z);
457 normalDirection[0] = x / length;
458 normalDirection[1] = y / length;
459 normalDirection[2] = z / length;
460 break;
461 case 3:
462 length = sqrt(x * x + z * z);
463 normalDirection[0] = x / length;
464 normalDirection[2] = z / length;
465 break;
466 default:
467 abort_mpi("copysphere.geometry has to be 0, 1, 2 or 3 with this grid shape.", 1);
468 }
469 // end of 3D
470 }
471 return normalDirection;
472 }
473
483 const std::array<Real, 3>& gridSpacing,
484 const std::array<fsgrid::FsSize_t, 3>& globalCoordinates,
485 const fsgrid::FsStencil& stencil, cuint component) {
486 const uint32_t perbComponent = fsgrids::bfield::PERBX + component;
487 const uint32_t bitfield = 1 << component;
488
489 // clang-format off
490 static constexpr std::array permutations = {
491 std::array {
492 0, 1, 2, 3, 4, 5,
493 },
494 std::array {
495 2, 3, 0, 1, 4, 5,
496 },
497 std::array {
498 4, 5, 0, 1, 2, 3,
499 },
500 };
501
502 const std::array permutation = permutations[component];
503
504 const std::array<size_t, 6> inds = {
505 stencil.moo(),
506 stencil.poo(),
507 stencil.omo(),
508 stencil.opo(),
509 stencil.oom(),
510 stencil.oop(),
511 };
512 // clang-format on
513
514 auto bitFieldSet = [&bitfield](auto& tech) { return (tech.SOLVE & bitfield) == bitfield; };
515 auto sbLayerIsOne = [](auto& tech) { return tech.sysBoundaryLayer == 1; };
516 auto averageNeigbours = [&technical, &b, &inds, &permutation, &perbComponent,
517 &bitFieldSet](auto begin, auto end, auto& sum, auto& nCells) {
518 for (size_t i = begin; i < end; i++) {
519 const auto j = inds[permutation[i]];
520 if (bitFieldSet(technical[j])) {
521 sum += b[j][perbComponent];
522 nCells++;
523 }
524 }
525 };
526
527 auto averageAllNeighbours = [&stencil, &technical, &b, &perbComponent](auto predicateLambda, auto& sum,
528 auto& nCells) {
529 for (const auto& i : stencil.indices()) {
530 if (predicateLambda(technical[i])) {
531 sum += b[i][perbComponent];
532 nCells++;
533 }
534 }
535 };
536
537 Real sum = 0.0;
538 uint nCells = 0;
539 if (this->zeroPerB == true) {
540 sum = b[stencil.ooo()][perbComponent];
541 nCells = 1;
542 } else {
543 if (sbLayerIsOne(technical[stencil.ooo()])) {
544 averageNeigbours(0ul, 2ul, sum, nCells);
545
546 if (nCells == 0) {
547 averageNeigbours(2ul, 6ul, sum, nCells);
548 }
549
550 if (nCells == 0) {
551 averageAllNeighbours(bitFieldSet, sum, nCells);
552 }
553 } else {
554 // L2 cells
555 averageAllNeighbours(sbLayerIsOne, sum, nCells);
556 }
557 }
558
559 if (nCells == 0) {
560 cerr << __FILE__ << ":" << __LINE__ << ": ERROR: this should not have fallen through." << endl;
561 sum = 0.0;
562 nCells = 1;
563 }
564
565 return sum / nCells;
566 }
567
569 const fsgrid::FsStencil& stencil, cuint component) {
570 e[stencil.ooo()][fsgrids::efield::EX + component] = 0.0;
571 }
572
574 const fsgrid::FsStencil& stencil, cuint component) {
575 std::array<Real, fsgrids::ehall::N_EHALL>& cp = ehall[stencil.ooo()];
576 switch (component) {
577 case 0:
582 break;
583 case 1:
588 break;
589 case 2:
594 break;
595 default:
596 cerr << __FILE__ << ":" << __LINE__ << ":" << " Invalid component" << endl;
597 }
598 }
599
601 fsgrids::egradpespan EGradPe, const fsgrid::FsStencil& stencil,
602 cuint component) {
603 EGradPe[stencil.ooo()][fsgrids::egradpe::EXGRADPE + component] = 0.0;
604 }
605
607 fsgrids::dmomentsspan dmoments,
608 const fsgrid::FsStencil& stencil, cuint RKCase, cuint component) {
609 this->setCellDerivativesToZero(dperb, dmoments, stencil, component);
610 }
611
613 const fsgrid::FsStencil& stencil, cuint component) {
614 // FIXME This should be OK as the BVOL derivatives are only used for Lorentz force JXB, which is not applied on the
615 // copy sphere cells.
616 this->setCellBVOLDerivativesToZero(vols, stencil, component);
617 }
618
619 void Copysphere::vlasovBoundaryCondition(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
620 const CellID& cellID, const uint popID, const bool calculate_V_moments) {
621 this->vlasovBoundaryFluffyCopyFromAllCloseNbrs(mpiGrid, cellID, popID, calculate_V_moments,
622 this->speciesParams[popID].fluffiness);
623 }
624
630 // WARNING not 0.0 here or the dipole() function fails miserably.
631 templateCell.sysBoundaryFlag = this->getIndex();
632 templateCell.sysBoundaryLayer = 1;
633 templateCell.parameters[CellParams::XCRD] = 1.0;
634 templateCell.parameters[CellParams::YCRD] = 1.0;
635 templateCell.parameters[CellParams::ZCRD] = 1.0;
636 templateCell.parameters[CellParams::DX] = 1;
637 templateCell.parameters[CellParams::DY] = 1;
638 templateCell.parameters[CellParams::DZ] = 1;
639
640 Real initRho, initT, initV0X, initV0Y, initV0Z;
641 // Loop over particle species
642 for (uint popID = 0; popID < getObjectWrapper().particleSpecies.size(); ++popID) {
643 templateCell.clear(popID, false); // clear, do not de-allocate memory
644 const CopysphereSpeciesParameters& sP = this->speciesParams[popID];
645 const Real mass = getObjectWrapper().particleSpecies[popID].mass;
646 initRho = sP.rho;
647 initT = sP.T;
648 initV0X = sP.V0[0];
649 initV0Y = sP.V0[1];
650 initV0Z = sP.V0[2];
651
652 // Find list of blocks to initialize.
653 const uint nRequested = SBC::findMaxwellianBlocksToInitialize(popID, templateCell, initRho, initT, initV0X, initV0Y, initV0Z);
654 // stores in vmesh->getGrid() (localToGlobalMap)
655 // with count in cell.get_population(popID).N_blocks
656
657 // Resize and populate mesh
658 templateCell.prepare_to_receive_blocks(popID);
659
660 // Set the reservation value (capacity is increased in add_velocity_blocks
661 const Realf minValue = templateCell.getVelocityBlockMinValue(popID);
662
663 // fills v-space into target
664
665 #ifdef USE_GPU
666 vmesh::VelocityMesh *vmesh = templateCell.dev_get_velocity_mesh(popID);
667 vmesh::VelocityBlockContainer* VBC = templateCell.dev_get_velocity_blocks(popID);
668 #else
669 vmesh::VelocityMesh* vmesh = templateCell.get_velocity_mesh(popID);
670 vmesh::VelocityBlockContainer* VBC = templateCell.get_velocity_blocks(popID);
671 #endif
672 // Loop over blocks
673 Realf rhosum = 0;
675 {WID, WID, WID, nRequested},
676 ARCH_LOOP_LAMBDA (const uint i, const uint j, const uint k, const uint initIndex, Realf *lsum ) {
677 vmesh::GlobalID *GIDlist = vmesh->getGrid()->data();
678 Realf* bufferData = VBC->getData();
679 const vmesh::GlobalID blockGID = GIDlist[initIndex];
680 // Calculate parameters for new block
681 Real blockCoords[6];
682 vmesh->getBlockInfo(blockGID,&blockCoords[0]);
683 creal vxBlock = blockCoords[0];
684 creal vyBlock = blockCoords[1];
685 creal vzBlock = blockCoords[2];
686 creal dvxCell = blockCoords[3];
687 creal dvyCell = blockCoords[4];
688 creal dvzCell = blockCoords[5];
689 ARCH_INNER_BODY(i, j, k, initIndex, lsum) {
690 creal vx = vxBlock + (i+0.5)*dvxCell - initV0X;
691 creal vy = vyBlock + (j+0.5)*dvyCell - initV0Y;
692 creal vz = vzBlock + (k+0.5)*dvzCell - initV0Z;
693 const Realf value = projects::MaxwellianPhaseSpaceDensity(vx,vy,vz,initT,initRho,mass);
694 bufferData[initIndex*WID3 + k*WID2 + j*WID + i] = value;
695 //lsum[0] += value;
696 };
697 }, rhosum);
698
699 #ifdef USE_GPU
700 // Set and apply the reservation value
701 templateCell.setReservation(popID,nRequested,true); // Force to this value
702 templateCell.applyReservation(popID);
703 #endif
704
705 //let's get rid of blocks not fulfilling the criteria here to save memory.
706 templateCell.adjustSingleCellVelocityBlocks(popID,true);
707
708 } // for-loop over particle species
709
710 calculateCellMoments(&templateCell, true, false, true);
711
712 // WARNING Time-independence assumed here. Normal moments computed in setProjectCell
729 }
730
731 void Copysphere::setCellFromTemplate(SpatialCell* cell, const uint popID) {
732 copyCellData(&templateCell, cell, false, popID, true); // copy also vdf, _V
733 copyCellData(&templateCell, cell, true, popID, false); // don't copy vdf again but copy _R now
734 #ifdef USE_GPU
735 cell->setReservation(popID, templateCell.getReservation(popID));
736 #endif
737 }
738
739 std::string Copysphere::getName() const { return "Copysphere"; }
740 void Copysphere::getFaces(bool* faces) {}
741
742 void Copysphere::updateState(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
745 fsgrids::bgbspan bgb, creal t) {}
746
748} // namespace SBC
for i
Definition Dispersion.m:24
dx
Definition Dispersion.m:38
sqrt(1.0+vA *vA/(c *c))) % Ion-acoustic wave cS
Parameters length
Definition Dispersion.m:36
#define ARCH_INNER_BODY(...)
#define ARCH_LOOP_LAMBDA
void calculateCellMoments(spatial_cell::SpatialCell *cell, const bool &computeSecond, const bool &computePopulationMomentsOnly, const bool &doNotSkip)
static void get(const std::string &name, std::string &value)
static void add(const std::string &name, const std::string &desc, const std::string &defValue)
virtual void updateState(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, fsgrids::perbspan perb, fsgrids::bgbspan bgb, creal t) override
spatial_cell::SpatialCell templateCell
Definition copysphere.h:119
void setCellFromTemplate(SpatialCell *cell, const uint popID)
virtual ~Copysphere()
virtual std::string getName() const override
void getFaces(bool *faces) override
virtual void fieldSolverBoundaryCondGradPeElectricField(fsgrids::egradpespan EGradPe, const fsgrid::FsStencil &stencil, cuint component) override
virtual Real fieldSolverBoundaryCondMagneticField(fsgrids::perbspan b, fsgrids::constbgbspan bgb, fsgrids::consttechnicalspan technical, const std::array< Real, 3 > &gridSpacing, const std::array< fsgrid::FsSize_t, 3 > &globalCoordinates, const fsgrid::FsStencil &stencil, cuint component) override
virtual void fieldSolverBoundaryCondHallElectricField(fsgrids::ehallspan ehall, const fsgrid::FsStencil &stencil, cuint component) override
static void addParameters()
virtual void assignSysBoundary(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid) override
virtual void getParameters() override
virtual void vlasovBoundaryCondition(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const CellID &cellID, const uint popID, const bool calculate_V_moments) override
virtual void fieldSolverBoundaryCondDerivatives(fsgrids::dperbspan dperb, fsgrids::dmomentsspan dmoments, const fsgrid::FsStencil &stencil, cuint RKCase, cuint component) override
std::vector< CopysphereSpeciesParameters > speciesParams
Definition copysphere.h:116
virtual void applyInitialState(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, fsgrids::perbspan perb, fsgrids::bgbspan bgb, Project &project) override
std::array< Real, 3 > fieldSolverGetNormalDirection(fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, cint i, cint j, cint k)
virtual void initSysBoundary(creal &t, Project &project) override
virtual void fieldSolverBoundaryCondBVOLDerivatives(fsgrids::volspan vols, const fsgrid::FsStencil &stencil, cuint component) override
virtual uint getIndex() const override
virtual void fieldSolverBoundaryCondElectricField(fsgrids::efieldspan e, const fsgrid::FsStencil &stencil, cuint component) override
static void setCellBVOLDerivativesToZero(fsgrids::volspan vols, const fsgrid::FsStencil &stencil, cuint component)
void vlasovBoundaryFluffyCopyFromAllCloseNbrs(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const CellID &cellID, const uint popID, const bool calculate_V_moments, creal fluffiness)
void copyCellData(const SpatialCell *from, SpatialCell *to, const bool copyMomentsOnly, const uint popID, const bool copy_V_moments)
static void setCellDerivativesToZero(fsgrids::dperbspan dperb, fsgrids::dmomentsspan dmoments, const fsgrid::FsStencil &stencil, cuint component)
bool checkMesh(const uint popID)
void setReservation(const uint popID, const vmesh::LocalID reservationsize, bool force=false)
void abort_mpi(const std::string str, const int err_type)
Definition common.cpp:90
const std::vector< CellID > & getLocalCells()
Definition main.cpp:39
#define WID
Definition common.h:514
const int WID3
Definition common.h:517
const int WID2
Definition common.h:516
const uint32_t cuint
Definition definitions.h:50
float Real
Definition definitions.h:41
const int cint
Definition definitions.h:45
uint64_t CellID
Definition definitions.h:54
T convert(const T &number)
Definition definitions.h:56
float Realf
Definition definitions.h:33
fsgrid::FsGrid< FS_STENCIL_WIDTH > FieldSolverGrid
Definition definitions.h:78
const float creal
Definition definitions.h:42
Real divideIfNonZero(creal numerator, creal denominator)
Helper function.
Definition fs_common.cpp:33
Definitions of the limiter functions used in the field solver.
const int j
const int k
ObjectWrapper & getObjectWrapper()
Definition main.cpp:33
FieldTracingParameters fieldTracingParameters
vmesh::LocalID findMaxwellianBlocksToInitialize(const uint popID, spatial_cell::SpatialCell &cell, creal &rho, creal &T, creal &VX0, creal &VY0, creal &VZ0)
SBC::findMaxwellianBlocksToInitialize returns a list of blocks to construct the VDF with.
Real getR(creal x, creal y, creal z, uint geometry, Real center[3])
static void parallel_reduce(const uint(&limits)[NDim], Lambda loop_body, T &sum)
std::span< std::array< Real, fsgrids::bfield::N_BFIELD > > perbspan
Definition common.h:434
@ EXGRADPE
Definition common.h:305
std::span< const std::array< Real, bgbfield::N_BGB > > constbgbspan
Definition common.h:445
std::span< std::array< Real, fsgrids::egradpe::N_EGRADPE > > egradpespan
Definition common.h:440
std::span< std::array< Real, fsgrids::dmoments::N_DMOMENTS > > dmomentsspan
Definition common.h:448
std::span< technical > technicalspan
Definition common.h:452
@ EZHALL_010_011
Definition common.h:295
@ EYHALL_101_111
Definition common.h:299
@ EYHALL_100_110
Definition common.h:292
@ EXHALL_010_110
Definition common.h:294
@ EZHALL_110_111
Definition common.h:296
@ EZHALL_000_001
Definition common.h:291
@ EYHALL_001_011
Definition common.h:298
@ EXHALL_001_101
Definition common.h:297
@ EYHALL_000_010
Definition common.h:290
@ EXHALL_000_100
Definition common.h:289
@ EXHALL_011_111
Definition common.h:300
@ EZHALL_100_101
Definition common.h:293
std::span< std::array< Real, bgbfield::N_BGB > > bgbspan
Definition common.h:444
std::span< std::array< Real, fsgrids::dperb::N_DPERB > > dperbspan
Definition common.h:442
std::span< const technical > consttechnicalspan
Definition common.h:453
std::span< std::array< Real, fsgrids::efield::N_EFIELD > > efieldspan
Definition common.h:436
@ PERBX
Definition common.h:275
std::span< std::array< Real, fsgrids::volfields::N_VOL > > volspan
Definition common.h:450
std::span< std::array< Real, fsgrids::ehall::N_EHALL > > ehallspan
Definition common.h:438
ARCH_HOSTDEV Realf MaxwellianPhaseSpaceDensity(creal &vx, creal &vy, creal &vz, creal &T, creal &rho, creal &mass)
Definition project.h:45
uint32_t GlobalID
Definition definitions.h:59
std::vector< species::Species > particleSpecies
static uint zcells_ini
Definition parameters.h:50
static Real ymin
Definition parameters.h:40
static uint ycells_ini
Definition parameters.h:49
static uint xcells_ini
Definition parameters.h:48
static Real xmin
Definition parameters.h:38
static Real zmin
Definition parameters.h:42
static ARCH_HOSTDEV VecSimple< T > max(VecSimple< T > const &l, VecSimple< T > const &r)