Vlasiator ebf0dd394 on dev (v5.4.0 + 1054 commits)
Loading...
Searching...
No Matches
fieldtracing.h
Go to the documentation of this file.
1/*
2 * This file is part of Vlasiator.
3 *
4 *
5 * For details of usage, see the COPYING file and read the "Rules of the Road"
6 * at http://www.physics.helsinki.fi/vlasiator/
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23#ifndef FIELDTRACING_H
24#define FIELDTRACING_H
25
26#include <cstdlib>
27#include <array>
28#include "../common.h"
32#include "../logger.h"
33extern Logger logFile;
34
35// Used in full box + flux rope tracing, the others used in coupling should use Real as double probably.
36typedef float TReal;
37
38// Get the (integer valued) global fsgrid cell index (i,j,k) for the magnetic-field traced mapping point that node n is
39// associated with
40template <class T>
41std::array<fsgrid::FsSize_t, 3> getGlobalFsGridCellIndexForCoord(T& grid, const std::array<Real, 3>& x) {
42 return grid.physicalToGlobal(x[0], x[1], x[2]);
43}
44// Get the (integer valued) local fsgrid cell index (i,j,k) for the magnetic-field traced mapping point that node n is
45// associated with If the cell is not in our local domain, will return {-1,-1,-1}
46template <class T>
47std::array<fsgrid::FsIndex_t, 3> getLocalFsGridCellIndexForCoord(T& grid, const std::array<Real, 3>& x) {
48 std::array<fsgrid::FsSize_t, 3> globalInd = getGlobalFsGridCellIndexForCoord(grid, x);
49 std::array<fsgrid::FsIndex_t, 3> retval = grid.globalToLocal(globalInd[0], globalInd[1], globalInd[2]);
50 return retval;
51}
52// Get the (integer valued) local fsgrid cell index (i,j,k) for the magnetic-field traced mapping point that node n is
53// associated with This includes indices beyond local size (positive and negative) as we need to access ghost cells
54template <class T>
55std::array<fsgrid::FsIndex_t, 3> getLocalFsGridCellIndexWithGhostsForCoord(T& grid, const std::array<Real, 3>& x) {
56 std::array<fsgrid::FsSize_t, 3> globalInd = getGlobalFsGridCellIndexForCoord(grid, x);
57 const std::array<fsgrid::FsIndex_t, 3> localStart = grid.getLocalStart();
58 std::array<fsgrid::FsIndex_t, 3> retval = {(fsgrid::FsIndex_t)globalInd[0] - localStart[0],
59 (fsgrid::FsIndex_t)globalInd[1] - localStart[1],
60 (fsgrid::FsIndex_t)globalInd[2] - localStart[2]};
61 return retval;
62}
63// Get the fraction fsgrid cell index for the magnetic-field traced mapping point that node n is associated with.
64// Note that these are floating point values between 0 and 1
65template <class T> std::array<Real, 3> getFractionalFsGridCellForCoord(T& grid, const std::array<Real, 3>& x) {
66 return grid.physicalToCellFractional(x[0], x[1], x[2]);
67}
68
69namespace FieldTracing {
70
75
78 Euler, // Euler stepping (constant stepsize)
79 ADPT_Euler, // Adaptive Euler stepping (adaptive stepsize)
80 BS, // Bulirsch-Stoer Stepping (adaptive stepsize)
81 DPrince // Dormand-Prince Stepping (adaptive stepsize)
82};
83
108
110
119 UNPROCESSED, // Keep first for the reductions to work!
125};
126
146
148inline int ijk2Index(int i, int j, int k, std::array<int, 3> dims) { return i + j * dims[0] + k * dims[0] * dims[1]; }
149
151template <typename REAL>
152using TracingFieldFunction = std::function<bool(std::array<REAL, 3>&, const bool, std::array<REAL, 3>&)>;
153
154template <typename REAL>
157 fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, std::array<REAL, 3>& r,
158 const bool alongB, std::array<REAL, 3>& b) {
159
160 if ( r[0] > P::xmax - 2*P::dx_ini
161 || r[0] < P::xmin + 2*P::dx_ini
162 || r[1] > P::ymax - 2*P::dy_ini
163 || r[1] < P::ymin + 2*P::dy_ini
164 || r[2] > P::zmax - 2*P::dz_ini
165 || r[2] < P::zmin + 2*P::dz_ini
166 ) {
167 cerr << (string)("(fieldtracing) Error: fsgrid coupling trying to step outside of the global domain?\n");
168 return false;
169 }
170
171 // Get field direction
172 b[0] = SBC::ionosphereGrid.dipoleField(r[0], r[1], r[2], X, 0, X) + SBC::ionosphereGrid.BGB[0];
173 b[1] = SBC::ionosphereGrid.dipoleField(r[0], r[1], r[2], Y, 0, Y) + SBC::ionosphereGrid.BGB[1];
174 b[2] = SBC::ionosphereGrid.dipoleField(r[0], r[1], r[2], Z, 0, Z) + SBC::ionosphereGrid.BGB[2];
175
176 std::array<fsgrid::FsSize_t, 3> fsgridCellu =
178 std::array<fsgrid::FsIndex_t, 3> fsgridCell = {(fsgrid::FsIndex_t)fsgridCellu[0], (fsgrid::FsIndex_t)fsgridCellu[1],
179 (fsgrid::FsIndex_t)fsgridCellu[2]};
180 const auto& localStart = fsgrid.getLocalStart();
181 const auto* localSize = &fsgrid.getLocalSize()[0];
182 // Make the global index a local one, bypass the fsgrid function that yields (-1,-1,-1) also for ghost cells.
183 fsgridCell[0] -= localStart[0];
184 fsgridCell[1] -= localStart[1];
185 fsgridCell[2] -= localStart[2];
186
187 if ( fsgridCell[0] > localSize[0]
188 || fsgridCell[1] > localSize[1]
189 || fsgridCell[2] > localSize[2]
190 || fsgridCell[0] < -1
191 || fsgridCell[1] < -1
192 || fsgridCell[2] < -1
193 ) {
194 cerr << (string)("(fieldtracing) Error: fsgrid coupling trying to access local ID " + to_string(fsgridCell[0]) + " " + to_string(fsgridCell[1]) + " " + to_string(fsgridCell[2])
195 + " for local domain size " + to_string(localSize[0]) + " " + to_string(localSize[1]) + " " + to_string(localSize[2])
196 + " at position " + to_string(r[0]) + " " + to_string(r[1]) + " " + to_string(r[2]) + " radius " + to_string(sqrt(r[0] * r[0] + r[1] * r[1] + r[2] * r[2]))
197 + "\n");
198 abort();
199 return false;
200 } else {
201 const auto stencil = fsgrid.makeStencil(fsgridCell[0], fsgridCell[1], fsgridCell[2]);
202 if (technical[stencil.ooo()].sysBoundaryFlag == sysboundarytype::NOT_SYSBOUNDARY) {
203 const std::array<Real, 3> perB =
204 interpolatePerturbedB(perb, dperb, technical, fsgrid, fieldTracingParameters.reconstructionCoefficientsCache,
205 fsgridCell[0], fsgridCell[1], fsgridCell[2], {(Real)r[0], (Real)r[1], (Real)r[2]});
206 b[0] += perB[0];
207 b[1] += perB[1];
208 b[2] += perB[2];
209 }
210 }
211
212 // Normalize
213 REAL norm = 1. / sqrt(b[0]*b[0] + b[1]*b[1] + b[2]*b[2]);
214 for (int c = 0; c < 3; c++) {
215 b[c] = b[c] * norm;
216 }
217
218 // Make sure motion is outwards. Flip b if dot(r,b) < 0
219 if (!(std::isfinite(b[0]) && std::isfinite(b[1]) && std::isfinite(b[2]))) {
220 cerr << "(fieldtracing) Error: magnetic field is nan or inf in getRadialBfieldDirection at location "
221 << r[0] << ", " << r[1] << ", " << r[2] << ", with B = " << b[0] << ", " << b[1] << ", " << b[2] << endl;
222 b[0] = 0;
223 b[1] = 0;
224 b[2] = 0;
225 }
226 if (!alongB) { // In this function, outwards indicates whether we trace along (true) or against (false) the field
227 // direction
228 b[0] *= -1;
229 b[1] *= -1;
230 b[2] *= -1;
231 }
232 return true;
233}
234
235/*Modified Midpoint Method used by the Bulirsch Stoer integrations
236 * stepsize: initial step size
237 * r: initial position
238 * r1: new position
239 * n: number of substeps
240 * stepsize: big stepsize to use
241 * z0,zmid,z2: intermediate approximations
242 * */
243template <typename REAL>
244void modifiedMidpointMethod(std::array<REAL, 3> r, std::array<REAL, 3>& r1, int n, REAL stepSize,
245 TracingFieldFunction<REAL>& BFieldFunction, const bool outwards = true) {
246 // Allocate some memory.
247 std::array<REAL, 3> bunit, crd, z0, zmid, z1;
248 // Divide by number of sub steps
249 REAL h = stepSize / (REAL)n;
250
251 // First step
252 BFieldFunction(r, outwards, bunit);
253 z0 = r;
254 z1 = {r[0] + h * bunit[0], r[1] + h * bunit[1], r[2] + h * bunit[2]};
255 BFieldFunction(z1, outwards, bunit);
256
257 crd = {r[0] + h * bunit[0], r[1] + h * bunit[1], r[2] + h * bunit[2]};
258
259 for (int m = 0; m <= n; m++) {
260 zmid = {z0[0] + 2 * h * bunit[0], z0[1] + 2 * h * bunit[1], z0[2] + 2 * h * bunit[2]};
261 z0 = z1;
262 z1 = zmid;
263 crd = {crd[0] + h * bunit[0], crd[1] + h * bunit[1], crd[2] + h * bunit[2]};
264 BFieldFunction(crd, outwards, bunit);
265 }
266
267 // These are now are new position
268 for (int c = 0; c < 3; c++) {
269 r1[c] = 0.5 * (z0[c] + z1[c] + h * bunit[c]);
270 }
271}; // Modified Midpoint Method used by BS step
272
274template <typename REAL>
275void richardsonExtrapolation(int i, std::vector<REAL>& table, REAL& maxError, std::array<int, 3> dims) {
276 int k;
277 maxError = 0;
278 for (int dim = 0; dim < 3; dim++) {
279 for (k = 1; k < i + 1; k++) {
280
281 table.at(ijk2Index(i, k, dim, dims)) =
282 table.at(ijk2Index(i, k - 1, dim, dims)) +
283 (table.at(ijk2Index(i, k - 1, dim, dims)) - table.at(ijk2Index(i - 1, k - 1, dim, dims))) /
284 (std::pow(4, i) - 1);
285 }
286
287 REAL thisError =
288 fabs(table.at(ijk2Index(k - 1, k - 1, dim, dims)) - table.at(ijk2Index(k - 2, k - 2, dim, dims)));
289 if (thisError > maxError) {
290 maxError = thisError;
291 }
292 }
293
294}; // Richardson extrapolation method used by BS step
295
296template <typename REAL>
297bool bulirschStoerStep(std::array<REAL, 3>& r, std::array<REAL, 3>& b, REAL& stepSize, const REAL minStepSize,
298 const REAL maxStepSize, TracingFieldFunction<REAL>& BFieldFunction, const bool outwards = true) {
299 // Factors by which the stepsize is multiplied
300 REAL shrink = 0.95;
301 REAL grow = 1.2;
302 // Max substeps for midpoint method
303 int kMax = 8;
304 // Optimal row to converge at
305 int kOpt = 6;
306
307 const int ndim = kMax * kMax * 3;
308 std::array<int, 3> dims = {kMax, kMax, 3};
309 std::vector<REAL> table(ndim);
310 std::array<REAL, 3> rold, rnew, r1;
311 REAL error;
312
313 // Get B field unit vector in case we don't converge yet
314 BFieldFunction(r, outwards, b);
315
316 // Let's start things up with 2 substeps
317 int n = 2;
318 // Save old state
319 rold = r;
320 // Take a first Step
321 modifiedMidpointMethod(r, r1, n, stepSize, BFieldFunction, outwards);
322
323 // Save values in table
324 for (int c = 0; c < 3; ++c) {
325 table[ijk2Index(0, 0, c, dims)] = r1[c];
326 }
327
328 for (int i = 1; i < kMax; ++i) {
329
330 // Increment n by 2 at every iteration.
331 n += 2;
332 modifiedMidpointMethod(r, rnew, n, stepSize, BFieldFunction, outwards);
333
334 // Save values in table
335 for (int c = 0; c < 3; ++c) {
336 table[ijk2Index(i, 0, c, dims)] = rnew[c];
337 }
338
339 // Now let's perform a Richardson extrapolatation
340 richardsonExtrapolation(i, table, error, dims);
341
342 // Normalize error
343 error /= fieldTracingParameters.max_allowed_error;
344
345 // If we are below eps good, let's return but also let's modify the stepSize accordingly
346 if (error < 1. || stepSize == minStepSize) {
347 if (i > kOpt) {
348 stepSize *= shrink;
349 }
350 if (i < kOpt) {
351 stepSize *= grow;
352 }
353 // Make sure stepsize does not exceed maxStepsize
354 stepSize = stepSize > maxStepSize ? maxStepSize : stepSize;
355 stepSize = stepSize < minStepSize ? minStepSize : stepSize;
356 // Keep our new position
357 r = rnew;
358 // Evaluate B here
359 BFieldFunction(r, outwards, b);
360 return true;
361 }
362 }
363
364 // If we end up here it means our tracer did not converge so we need to reduce the stepSize all along and try again
365 stepSize *= shrink;
366 stepSize = stepSize < minStepSize ? minStepSize : stepSize;
367 return false;
368}; // Bulirsch Stoer step
369
370template <typename REAL>
371bool dormandPrinceStep(std::array<REAL, 3>& r, std::array<REAL, 3>& b, REAL& stepSize, const REAL minStepSize,
372 const REAL maxStepSize, TracingFieldFunction<REAL>& BFieldFunction, const bool outwards = true) {
373 // BFieldFunction can return false if it steps out of the "comfort zone"
374 bool proceed = true;
375 std::array<REAL, 7> kx, ky, kz;
376 std::array<REAL, 3> b_unit;
377 std::array<REAL, 3> _r{0, 0, 0};
378
379 // K1 slope
380 proceed = BFieldFunction(r, outwards, b_unit);
381 kx[0] = stepSize * b_unit[0];
382 ky[0] = stepSize * b_unit[1];
383 kz[0] = stepSize * b_unit[2];
384
385 // K2 slope
386 _r[0] = r[0] + (1. / 5.) * kx[0];
387 _r[1] = r[1] + (1. / 5.) * ky[0];
388 _r[2] = r[2] + (1. / 5.) * kz[0];
389 if (proceed) {
390 proceed = BFieldFunction(_r, outwards, b_unit);
391 }
392 kx[1] = stepSize * b_unit[0];
393 ky[1] = stepSize * b_unit[1];
394 kz[1] = stepSize * b_unit[2];
395
396 // K3 slope
397 _r[0] = r[0] + (3. / 10.) * kx[1];
398 _r[1] = r[1] + (3. / 10.) * ky[1];
399 _r[2] = r[2] + (3. / 10.) * kz[1];
400 if (proceed) {
401 proceed = BFieldFunction(_r, outwards, b_unit);
402 }
403 kx[2] = stepSize * b_unit[0];
404 ky[2] = stepSize * b_unit[1];
405 kz[2] = stepSize * b_unit[2];
406
407 // K4 slope
408 _r[0] = r[0] + (4. / 5.) * kx[2];
409 _r[1] = r[1] + (4. / 5.) * ky[2];
410 _r[2] = r[2] + (4. / 5.) * kz[2];
411 if (proceed) {
412 proceed = BFieldFunction(_r, outwards, b_unit);
413 }
414 kx[3] = stepSize * b_unit[0];
415 ky[3] = stepSize * b_unit[1];
416 kz[3] = stepSize * b_unit[2];
417
418 // K5 slope
419 _r[0] = r[0] + (8. / 9.) * kx[3];
420 _r[1] = r[1] + (8. / 9.) * ky[3];
421 _r[2] = r[2] + (8. / 9.) * kz[3];
422 if (proceed) {
423 proceed = BFieldFunction(_r, outwards, b_unit);
424 }
425 kx[4] = stepSize * b_unit[0];
426 ky[4] = stepSize * b_unit[1];
427 kz[4] = stepSize * b_unit[2];
428
429 // K6 slope
430 _r[0] = r[0] + kx[4];
431 _r[1] = r[1] + ky[4];
432 _r[2] = r[2] + kz[4];
433 if (proceed) {
434 proceed = BFieldFunction(_r, outwards, b_unit);
435 }
436 kx[5] = stepSize * b_unit[0];
437 ky[5] = stepSize * b_unit[1];
438 kz[5] = stepSize * b_unit[2];
439
440 // K7 slope
441 _r[0] = r[0] + kx[5];
442 _r[1] = r[1] + ky[5];
443 _r[2] = r[2] + kz[5];
444 if (proceed) {
445 proceed = BFieldFunction(_r, outwards, b_unit);
446 }
447 kx[6] = stepSize * b_unit[0];
448 ky[6] = stepSize * b_unit[1];
449 kz[6] = stepSize * b_unit[2];
450
451 REAL err = 0;
452 std::array<REAL, 3> rf;
453 if (proceed) {
454 // Error calculation
455 std::array<REAL, 3> error_xyz;
456 rf[0] = r[0] + (35. / 384.) * kx[0] + (500. / 1113.) * kx[2] + (125. / 192.) * kx[3] - (2187. / 6784.) * kx[4] + (11. / 84.) * kx[5];
457 rf[1] = r[1] + (35. / 384.) * ky[0] + (500. / 1113.) * ky[2] + (125. / 192.) * ky[3] - (2187. / 6784.) * ky[4] + (11. / 84.) * ky[5];
458 rf[2] = r[2] + (35. / 384.) * kz[0] + (500. / 1113.) * kz[2] + (125. / 192.) * kz[3] - (2187. / 6784.) * kz[4] + (11. / 84.) * kz[5];
459
460 error_xyz[0] = abs((71. / 57600.) * kx[0] - (71. / 16695.) * kx[2] + (71. / 1920.) * kx[3] - (17253. / 339200.) * kx[4] + (22. / 525.) * kx[5] - (1. / 40.) * kx[6]);
461 error_xyz[1] = abs((71. / 57600.) * ky[0] - (71. / 16695.) * ky[2] + (71. / 1920.) * ky[3] - (17253. / 339200.) * ky[4] + (22. / 525.) * ky[5] - (1. / 40.) * ky[6]);
462 error_xyz[2] = abs((71. / 57600.) * kz[0] - (71. / 16695.) * kz[2] + (71. / 1920.) * kz[3] - (17253. / 339200.) * kz[4] + (22. / 525.) * kz[5] - (1. / 40.) * kz[6]);
463
464 // Estimate proper stepsize
465 err = std::max(std::max(error_xyz[0], error_xyz[1]), error_xyz[2]);
466 REAL s = pow((fieldTracingParameters.max_allowed_error / (2 * err)), 1. / 5.);
467 stepSize = stepSize * s;
468 } else { // proceed is false, we probably stepped too far
469 stepSize /= 2;
470 }
471
472 stepSize = stepSize > maxStepSize ? maxStepSize : stepSize;
473 stepSize = stepSize < minStepSize ? minStepSize : stepSize;
474 if ((err > fieldTracingParameters.max_allowed_error && stepSize > minStepSize) || !proceed) {
475 return false;
476 }
477 // No explicit else so the compiler sees a return at the end of the non-void function.
478 // With the return in if it's the same.
479 // Evaluate B at the final stepping point to get the b vector of the fieldline
480 BFieldFunction(r, outwards, b);
481 r = rf;
482 return true;
483
484}; // Dormand Prince step
485
486template <typename REAL>
487bool adaptiveEulerStep(std::array<REAL, 3>& r, std::array<REAL, 3>& b, REAL& stepSize, const REAL minStepSize,
488 const REAL maxStepSize, TracingFieldFunction<REAL>& BFieldFunction, const bool outwards = true) {
489 // First evaluation
490 std::array<REAL, 3> r1;
491 BFieldFunction(r, outwards, b);
492
493 for (int c = 0; c < 3; c++) {
494 r1[c] = r[c] + stepSize * b[c];
495 }
496
497 // Second more accurate evaluation
498 std::array<REAL, 3> r2, b2;
499 for (int c = 0; c < 3; c++) {
500 r2[c] = r[c] + 0.5 * stepSize * b[c];
501 }
502
503 BFieldFunction(r2, outwards, b2);
504 for (int c = 0; c < 3; c++) {
505 r2[c] = r2[c] + 0.5 * stepSize * b2[c];
506 }
507
508 // Local error estimate
509 std::array<REAL, 3> error_xyz{fabs(r2[0] - r1[0]), fabs(r2[1] - r1[1]), fabs(r2[2] - r1[2])};
510
511 // Max Error and step adjustment
512 const REAL err = std::max(std::max(error_xyz[0], error_xyz[1]), error_xyz[2]);
513 stepSize = stepSize * sqrt(fieldTracingParameters.max_allowed_error / err);
514 stepSize = stepSize > maxStepSize ? maxStepSize : stepSize;
515 stepSize = stepSize < minStepSize ? minStepSize : stepSize;
516
517 if (err <= fieldTracingParameters.max_allowed_error || stepSize == minStepSize) {
518 // Note: B at r has been evaluated above so no need to do it here and we're not returning it anyway as it's not
519 // needed.
520 r = r2;
521 return true;
522 } else {
523 stepSize *= 0.9; // This is to avoid asymptotic convergence when the ratio above is very close to 1.
524 return false;
525 }
526}; // Adaptive Euler step
527
528template <typename REAL>
529void eulerStep(std::array<REAL, 3>& x, std::array<REAL, 3>& v, REAL& stepSize,
530 TracingFieldFunction<REAL>& BFieldFunction, const bool outwards = true) {
531 // Get field direction
532 BFieldFunction(x, outwards, v);
533
534 for (int c = 0; c < 3; c++) {
535 x[c] += stepSize * v[c];
536 }
537}; // Euler step
538
540template <typename REAL>
541void stepFieldLine(std::array<REAL, 3>& x, std::array<REAL, 3>& v, REAL& stepsize, const REAL minStepSize,
542 const REAL maxStepSize, TracingMethod method, TracingFieldFunction<REAL>& BFieldFunction,
543 const bool outwards) {
544 bool reTrace;
545 uint32_t attempts = 0;
546 switch (method) {
547 case Euler:
548 eulerStep(x, v, stepsize, BFieldFunction, outwards);
549 break;
550 case ADPT_Euler:
551 do {
552 reTrace = !adaptiveEulerStep(x, v, stepsize, minStepSize, maxStepSize, BFieldFunction, outwards);
553 attempts++;
554 } while (reTrace && attempts <= fieldTracingParameters.max_field_tracer_attempts);
555 if (reTrace) {
556 logFile << "(fieldtracing) Warning: Adaptive Euler field line tracer exhausted all available attempts and "
557 "still did not converge."
558 << std::endl;
559 }
560 break;
561 case BS:
562 do {
563 reTrace = !bulirschStoerStep(x, v, stepsize, minStepSize, maxStepSize, BFieldFunction, outwards);
564 attempts++;
565 } while (reTrace && attempts <= fieldTracingParameters.max_field_tracer_attempts);
566 break;
567 case DPrince:
568 do {
569 reTrace = !dormandPrinceStep(x, v, stepsize, minStepSize, maxStepSize, BFieldFunction, outwards);
570 attempts++;
571 } while (reTrace && attempts <= fieldTracingParameters.max_field_tracer_attempts);
572 if (reTrace) {
573 logFile << "(fieldtracing) Warning: Dormand Prince field line tracer exhausted all available attempts and "
574 "still did not converge..."
575 << std::endl;
576 }
577 break;
578 default:
579 std::cerr << "(fieldtracing) Error: No field line tracing method defined." << std::endl;
580 abort();
581 break;
582 }
583} // stepFieldLine
584
586inline void resetReconstructionCoefficientsCache() { fieldTracingParameters.reconstructionCoefficientsCache.clear(); }
587
592 std::vector<SBC::SphericalTriGrid::Node>& nodes, creal radius);
593
595std::array<std::pair<int, Real>, 3>
596calculateIonosphereVlasovGridCoupling(std::array<Real, 3> x, std::vector<SBC::SphericalTriGrid::Node>& nodes,
597 creal couplingRadius);
598
603 std::vector<SBC::SphericalTriGrid::Node>& nodes);
604
610 dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid);
611
615 dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
616 std::vector<SBC::SphericalTriGrid::Node>& nodes);
617
618} // namespace FieldTracing
619
620#endif
for i
Definition Dispersion.m:24
sqrt(1.0+vA *vA/(c *c))) % Ion-acoustic wave cS
Constants c
Definition Dispersion.m:45
float Real
Definition definitions.h:41
fsgrid::FsGrid< FS_STENCIL_WIDTH > FieldSolverGrid
Definition definitions.h:78
const float creal
Definition definitions.h:42
std::array< fsgrid::FsIndex_t, 3 > getLocalFsGridCellIndexWithGhostsForCoord(T &grid, const std::array< Real, 3 > &x)
std::array< Real, 3 > getFractionalFsGridCellForCoord(T &grid, const std::array< Real, 3 > &x)
float TReal
std::array< fsgrid::FsIndex_t, 3 > getLocalFsGridCellIndexForCoord(T &grid, const std::array< Real, 3 > &x)
std::array< fsgrid::FsSize_t, 3 > getGlobalFsGridCellIndexForCoord(T &grid, const std::array< Real, 3 > &x)
std::array< Real, 3 > interpolatePerturbedB(fsgrids::perbspan perb, fsgrids::constdperbspan dperb, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, std::map< std::array< int, 3 >, std::array< Real, Rec::N_REC_COEFFICIENTS > > &reconstructionCoefficientsCache, cint i, cint j, cint k, const std::array< Real, 3 > x)
@ Y
Definition functions.hpp:28
@ X
Definition functions.hpp:28
@ Z
Definition functions.hpp:28
Logger logFile
Definition main.cpp:25
const int j
const int k
void resetReconstructionCoefficientsCache()
int ijk2Index(int i, int j, int k, std::array< int, 3 > dims)
void traceOpenClosedConnection(fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, fsgrids::perbspan perb, fsgrids::constdperbspan dperb, std::vector< SBC::SphericalTriGrid::Node > &nodes)
void traceFullBoxConnectionAndFluxRopes(fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, fsgrids::perbspan perb, fsgrids::constdperbspan dperb, dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid)
void richardsonExtrapolation(int i, std::vector< REAL > &table, REAL &maxError, std::array< int, 3 > dims)
void calculateIonosphereFsgridCoupling(fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, fsgrids::perbspan perb, fsgrids::constdperbspan dperb, std::vector< SBC::SphericalTriGrid::Node > &nodes, creal couplingRadius)
bool bulirschStoerStep(std::array< REAL, 3 > &r, std::array< REAL, 3 > &b, REAL &stepSize, const REAL minStepSize, const REAL maxStepSize, TracingFieldFunction< REAL > &BFieldFunction, const bool outwards=true)
void stepFieldLine(std::array< REAL, 3 > &x, std::array< REAL, 3 > &v, REAL &stepsize, const REAL minStepSize, const REAL maxStepSize, TracingMethod method, TracingFieldFunction< REAL > &BFieldFunction, const bool outwards)
bool dormandPrinceStep(std::array< REAL, 3 > &r, std::array< REAL, 3 > &b, REAL &stepSize, const REAL minStepSize, const REAL maxStepSize, TracingFieldFunction< REAL > &BFieldFunction, const bool outwards=true)
bool traceFullFieldFunction(fsgrids::perbspan perb, fsgrids::constdperbspan dperb, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, std::array< REAL, 3 > &r, const bool alongB, std::array< REAL, 3 > &b)
void modifiedMidpointMethod(std::array< REAL, 3 > r, std::array< REAL, 3 > &r1, int n, REAL stepSize, TracingFieldFunction< REAL > &BFieldFunction, const bool outwards=true)
std::function< bool(std::array< REAL, 3 > &, const bool, std::array< REAL, 3 > &)> TracingFieldFunction
bool adaptiveEulerStep(std::array< REAL, 3 > &r, std::array< REAL, 3 > &b, REAL &stepSize, const REAL minStepSize, const REAL maxStepSize, TracingFieldFunction< REAL > &BFieldFunction, const bool outwards=true)
void reduceData(fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, fsgrids::perbspan perb, fsgrids::constdperbspan dperb, dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, std::vector< SBC::SphericalTriGrid::Node > &nodes)
FieldTracingParameters fieldTracingParameters
void eulerStep(std::array< REAL, 3 > &x, std::array< REAL, 3 > &v, REAL &stepSize, TracingFieldFunction< REAL > &BFieldFunction, const bool outwards=true)
std::array< std::pair< int, Real >, 3 > calculateIonosphereVlasovGridCoupling(std::array< Real, 3 > x, std::vector< SBC::SphericalTriGrid::Node > &nodes, creal couplingRadius)
SphericalTriGrid ionosphereGrid
std::span< std::array< Real, fsgrids::bfield::N_BFIELD > > perbspan
Definition common.h:434
std::span< technical > technicalspan
Definition common.h:452
std::span< const std::array< Real, fsgrids::dperb::N_DPERB > > constdperbspan
Definition common.h:443
std::map< std::array< int, 3 >, std::array< Real, Rec::N_REC_COEFFICIENTS > > reconstructionCoefficientsCache
static Real ymax
Definition parameters.h:41
static Real dz_ini
Definition parameters.h:46
static Real dx_ini
Definition parameters.h:44
static Real xmax
Definition parameters.h:39
static Real zmax
Definition parameters.h:43
static Real ymin
Definition parameters.h:40
static Real xmin
Definition parameters.h:38
static Real zmin
Definition parameters.h:42
static Real dy_ini
Definition parameters.h:45
static ARCH_HOSTDEV VecSimple< T > abs(const VecSimple< T > &l)