Vlasiator ebf0dd394 on dev (v5.4.0 + 1054 commits)
Loading...
Searching...
No Matches
derivatives.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
23#include <cstdlib>
24
25#include "fs_common.h"
26#include "derivatives.hpp"
27#include "fs_limiters.h"
28#include <Eigen/Geometry>
29
30template <typename T, size_t N> struct DerivativesData {
31 const std::array<T, N>& ooo = {};
32 const std::array<T, N>& poo = {};
33 const std::array<T, N>& moo = {};
34 const std::array<T, N>& opo = {};
35 const std::array<T, N>& omo = {};
36 const std::array<T, N>& oop = {};
37 const std::array<T, N>& oom = {};
38};
39
41 fsgrids::dmomentsspan dmoments,
42 const fsgrid::FsStencil& stencil, const bool atSysBoundary) {
43 using dmo = fsgrids::dmoments;
44 using mom = fsgrids::moments;
45
46 std::array<Real, dmo::N_DMOMENTS>& dMoments = dmoments[stencil.ooo()];
47
48 auto computeDiff = [](const auto& i, const auto& right, const auto& left) { return 0.5 * (right[i] - left[i]); };
49
50 auto computeLimiter = [](const auto& i, const auto& right, const auto& left, const auto& center) {
51 return limiter(left[i], center[i], right[i]);
52 };
53
54 // Constants for electron pressure derivatives, see also ldz_gradpe.cpp
55 // Calculate anchor point constants: First the pressure, then a derived constant.
57 const Real Pe_const = Pe_anchor * pow(Parameters::electronDensity, -Parameters::electronPTindex);
58 auto computeGradPeLimiter = [=](const auto& right, const auto& left, const auto& center) {
59 // pres_e = const * np.power(rho_e, index)
60 return Pe_const * limiter(pow(left[mom::RHOQ] / physicalconstants::CHARGE, Parameters::electronPTindex),
63 };
64
65 auto computeGradPeDiff = [=](const auto& right, const auto& left) {
66 return Pe_const * 0.5 * (pow(right[mom::RHOQ] / physicalconstants::CHARGE, Parameters::electronPTindex) - pow(left[mom::RHOQ] / physicalconstants::CHARGE, Parameters::electronPTindex));
67 };
68
69 const DerivativesData momData{
70 moments[stencil.ooo()],
71 moments[stencil.poo()], moments[stencil.moo()],
72 moments[stencil.opo()], moments[stencil.omo()],
73 moments[stencil.oop()], moments[stencil.oom()],
74 };
75
76 {
77#ifdef DEBUG_SOLVERS
78 const auto& cv = momData.ooo[mom::RHOM];
79 if (cv <= 0) {
80 std::cerr << __FILE__ << ":" << __LINE__ << (cv < 0 ? " Negative" : " Zero") << " density in fsgrid cell " << stencil.indexFromOffset( 0,0,0) << std::endl;
81 abort();
82 }
83
84 const auto& lv = momData.moo[mom::RHOM];
85 if (lv <= 0) {
86 std::cerr << __FILE__ << ":" << __LINE__ << (lv < 0 ? " Negative" : " Zero") << " density in fsgrid cell " << stencil.indexFromOffset(-1,0,0) << std::endl;
87 abort();
88 }
89
90 const auto& rv = momData.poo[mom::RHOM];
91 if (rv <= 0) {
92 std::cerr << __FILE__ << ":" << __LINE__ << (rv < 0 ? " Negative" : " Zero") << " density in fsgrid cell " << stencil.indexFromOffset( 1,0,0) << std::endl;
93 abort();
94 }
95#endif
96 }
97
98 static constexpr std::array moms{mom::RHOM, mom::RHOQ, mom::P_11, mom::P_22, mom::P_33, mom::VX, mom::VY, mom::VZ};
99 static constexpr std::array dmix{dmo::drhomdx, dmo::drhoqdx, dmo::dp11dx, dmo::dp22dx, dmo::dp33dx, dmo::dVxdx, dmo::dVydx, dmo::dVzdx};
100 static constexpr std::array dmiy{dmo::drhomdy, dmo::drhoqdy, dmo::dp11dy, dmo::dp22dy, dmo::dp33dy, dmo::dVxdy, dmo::dVydy, dmo::dVzdy};
101 static constexpr std::array dmiz{dmo::drhomdz, dmo::drhoqdz, dmo::dp11dz, dmo::dp22dz, dmo::dp33dz, dmo::dVxdz, dmo::dVydz, dmo::dVzdz};
102
104 for (size_t i = 0; i < moms.size(); i++) {
105 dMoments[dmix[i]] = computeDiff(moms[i], momData.poo, momData.moo);
106 dMoments[dmiy[i]] = computeDiff(moms[i], momData.opo, momData.omo);
107 dMoments[dmiz[i]] = computeDiff(moms[i], momData.oop, momData.oom);
108 }
109 dMoments[dmo::dPedx] = computeGradPeDiff(momData.poo, momData.moo);
110 dMoments[dmo::dPedy] = computeGradPeDiff(momData.opo, momData.omo);
111 dMoments[dmo::dPedz] = computeGradPeDiff(momData.oop, momData.oom);
112 } else {
113 for (size_t i = 0; i < moms.size(); i++) {
114 dMoments[dmix[i]] = computeLimiter(moms[i], momData.poo, momData.moo, momData.ooo);
115 dMoments[dmiy[i]] = computeLimiter(moms[i], momData.opo, momData.omo, momData.ooo);
116 dMoments[dmiz[i]] = computeLimiter(moms[i], momData.oop, momData.oom, momData.ooo);
117 }
118 dMoments[dmo::dPedx] = computeGradPeLimiter(momData.poo, momData.moo, momData.ooo);
119 dMoments[dmo::dPedy] = computeGradPeLimiter(momData.opo, momData.omo, momData.ooo);
120 dMoments[dmo::dPedz] = computeGradPeLimiter(momData.oop, momData.oom, momData.ooo);
121 }
122}
123
125 fsgrids::dperbspan dperb, const fsgrid::FsStencil& stencil,
126 bool dontCompute2ndDerivatives, bool atSysBoundary, cuint sysBoundaryFlag) {
127 using dpb = fsgrids::dperb;
128 using bfi = fsgrids::bfield;
129 std::array<Real, dpb::N_DPERB>& dPerB = dperb[stencil.ooo()];
130
131 auto computeDiff = [](const auto& i, const auto& right, const auto& left) { return 0.5 * (right[i] - left[i]); };
132
133 auto computeLimiter = [](const auto& i, const auto& right, const auto& left, const auto& center) {
134 return limiter(left[i], center[i], right[i]);
135 };
136 const DerivativesData perbData{
137 perb[stencil.ooo()], perb[stencil.poo()], perb[stencil.moo()], perb[stencil.opo()],
138 perb[stencil.omo()], perb[stencil.oop()], perb[stencil.oom()],
139 };
140
142 dPerB[dpb::dPERBydx] = computeDiff(bfi::PERBY, perbData.poo, perbData.moo);
143 dPerB[dpb::dPERBzdx] = computeDiff(bfi::PERBZ, perbData.poo, perbData.moo);
144 dPerB[dpb::dPERBxdy] = computeDiff(bfi::PERBX, perbData.opo, perbData.omo);
145 dPerB[dpb::dPERBzdy] = computeDiff(bfi::PERBZ, perbData.opo, perbData.omo);
146 dPerB[dpb::dPERBxdz] = computeDiff(bfi::PERBX, perbData.oop, perbData.oom);
147 dPerB[dpb::dPERBydz] = computeDiff(bfi::PERBY, perbData.oop, perbData.oom);
148 } else {
149 dPerB[dpb::dPERBydx] = computeLimiter(bfi::PERBY, perbData.poo, perbData.moo, perbData.ooo);
150 dPerB[dpb::dPERBzdx] = computeLimiter(bfi::PERBZ, perbData.poo, perbData.moo, perbData.ooo);
151 dPerB[dpb::dPERBxdy] = computeLimiter(bfi::PERBX, perbData.opo, perbData.omo, perbData.ooo);
152 dPerB[dpb::dPERBzdy] = computeLimiter(bfi::PERBZ, perbData.opo, perbData.omo, perbData.ooo);
153 dPerB[dpb::dPERBxdz] = computeLimiter(bfi::PERBX, perbData.oop, perbData.oom, perbData.ooo);
154 dPerB[dpb::dPERBydz] = computeLimiter(bfi::PERBY, perbData.oop, perbData.oom, perbData.ooo);
155 }
156
157 if (dontCompute2ndDerivatives) {
158 dPerB[dpb::dPERBydxx] = 0.0;
159 dPerB[dpb::dPERBzdxx] = 0.0;
160 dPerB[dpb::dPERBxdyy] = 0.0;
161 dPerB[dpb::dPERBzdyy] = 0.0;
162 dPerB[dpb::dPERBxdzz] = 0.0;
163 dPerB[dpb::dPERBydzz] = 0.0;
164 dPerB[dpb::dPERBxdyz] = 0.0;
165 dPerB[dpb::dPERBydxz] = 0.0;
166 dPerB[dpb::dPERBzdxy] = 0.0;
167 } else {
168 auto compute2ndDerivative = [](auto i, const auto& right, const auto& left, const auto& center) {
169 return left[i] + right[i] - 2.0 * center[i];
170 };
171 dPerB[dpb::dPERBydxx] = compute2ndDerivative(bfi::PERBY, perbData.poo, perbData.moo, perbData.ooo);
172 dPerB[dpb::dPERBzdxx] = compute2ndDerivative(bfi::PERBZ, perbData.poo, perbData.moo, perbData.ooo);
173 dPerB[dpb::dPERBxdyy] = compute2ndDerivative(bfi::PERBX, perbData.opo, perbData.omo, perbData.ooo);
174 dPerB[dpb::dPERBzdyy] = compute2ndDerivative(bfi::PERBZ, perbData.opo, perbData.omo, perbData.ooo);
175 dPerB[dpb::dPERBxdzz] = compute2ndDerivative(bfi::PERBX, perbData.oop, perbData.oom, perbData.ooo);
176 dPerB[dpb::dPERBydzz] = compute2ndDerivative(bfi::PERBY, perbData.oop, perbData.oom, perbData.ooo);
177
178 if (sysBoundaryFlag == sysboundarytype::NOT_SYSBOUNDARY) {
179 auto crossDerivative = [&perb](auto bl, auto br, auto tl, auto tr, auto i) {
180 const auto& botLeft = perb[bl];
181 const auto& botRght = perb[br];
182 const auto& topLeft = perb[tl];
183 const auto& topRght = perb[tr];
184 return FOURTH * (botLeft[i] + topRght[i] - botRght[i] - topLeft[i]);
185 };
186
187 dPerB[dpb::dPERBxdyz] = crossDerivative(stencil.omm(), stencil.opm(), stencil.omp(), stencil.opp(), bfi::PERBX);
188 dPerB[dpb::dPERBydxz] = crossDerivative(stencil.mom(), stencil.pom(), stencil.mop(), stencil.pop(), bfi::PERBY);
189 dPerB[dpb::dPERBzdxy] = crossDerivative(stencil.mmo(), stencil.pmo(), stencil.mpo(), stencil.ppo(), bfi::PERBZ);
190 }
191 }
192}
193
211 fsgrids::dperbspan dperb,
212 fsgrids::dmomentsspan dmoments,
213 const fsgrid::FsStencil& stencil, cuint sysBoundaryFlag, cuint sysBoundaryLayer,
214 const bool doMoments) {
215 /*
216 * For sysBoundaryLayer 1 or 2, we are near a boundary, and we wish to use regular centered differences instead of
217 * slope limiter-adjusted values. This is to minimize oscillations as a smooth behaviour is required near artificial
218 * boundaries, unlike at boundaries and shocks inside the simulation domain.
219 */
220 const bool atSysBoundary = sysBoundaryLayer == 1 || (sysBoundaryLayer == 2 && sysBoundaryFlag == sysboundarytype::NOT_SYSBOUNDARY);
221 const bool dontCompute2ndDerivatives = Parameters::ohmHallTerm < 2 || sysBoundaryLayer == 1;
222
223 if (doMoments) {
224 computeMomentsDerivatives(moments, dmoments, stencil, atSysBoundary);
225 }
226
227 computePerbDerivatives(perb, dperb, stencil, dontCompute2ndDerivatives, atSysBoundary, sysBoundaryFlag);
228
229 if (sysBoundaryFlag != sysboundarytype::NOT_SYSBOUNDARY) {
230 SBC::SysBoundaryCondition::setCellDerivativesToZero(dperb, dmoments, stencil, 3);
231 SBC::SysBoundaryCondition::setCellDerivativesToZero(dperb, dmoments, stencil, 4);
232 SBC::SysBoundaryCondition::setCellDerivativesToZero(dperb, dmoments, stencil, 5);
233 }
234}
235
255 fsgrids::momentsspan moments,
256 fsgrids::dperbspan dperb,
257 fsgrids::dmomentsspan dmoments,
259 const bool doMoments) {
260 phiprof::Timer derivativesTimer{"Calculate face derivatives"};
261 const size_t numCells = fsgrid.getNumCells();
262
263 phiprof::Timer mpiTimer{"FS derivatives ghost updates MPI", {"MPI"}};
264 fsgrid.updateGhostCells(perb);
265 if (doMoments) {
266 fsgrid.updateGhostCells(moments);
267 }
268 mpiTimer.stop();
269
270 // Calculate derivatives
271 fsgrid.parallel_for([](int timerId) -> phiprof::Timer { return phiprof::Timer{timerId}; },
272 phiprof::initializeTimer("FS derivatives compute cells"), technical,
273 [=](const fsgrid::Coordinates &coordinates, const fsgrid::FsStencil& stencil, cuint sysBoundaryFlag, cuint sysBoundaryLayer) {
274 calculateDerivatives(perb, moments, dperb, dmoments, stencil, sysBoundaryFlag, sysBoundaryLayer, doMoments);
275 });
276
277 derivativesTimer.stop(numCells, "Spatial Cells");
278}
279
294
296 fsgrids::consttechnicalspan technical, const fsgrid::FsStencil& stencil) {
297 const auto& tech = technical[stencil.ooo()];
298
299 cuint sysBoundaryFlag = tech.sysBoundaryFlag;
300 cuint sysBoundaryLayer = tech.sysBoundaryLayer;
301 const bool atSysBoundary =
302 sysBoundaryLayer == 1 || (sysBoundaryLayer == 2 && sysBoundaryFlag == sysboundarytype::NOT_SYSBOUNDARY);
303
304 using vf = fsgrids::volfields;
305
306 auto computeDiff = [](const auto& i, const auto& right, const auto& left) { return 0.5 * (right[i] - left[i]); };
307
308 auto computeLimiter = [](const auto& i, const auto& right, const auto& left, const auto& center) {
309 return limiter(left[i], center[i], right[i]);
310 };
311
312 auto& volCenter = vol[stencil.ooo()];
313 const auto poo = stencil.poo();
314 const auto moo = stencil.moo();
316 volCenter[vf::dPERBXVOLdx] = computeDiff(vf::PERBXVOL, vol[poo], vol[moo]);
317 volCenter[vf::dPERBYVOLdx] = computeDiff(vf::PERBYVOL, vol[poo], vol[moo]);
318 volCenter[vf::dPERBZVOLdx] = computeDiff(vf::PERBZVOL, vol[poo], vol[moo]);
319 } else {
320 volCenter[vf::dPERBXVOLdx] = computeLimiter(vf::PERBXVOL, vol[poo], vol[moo], volCenter);
321 volCenter[vf::dPERBYVOLdx] = computeLimiter(vf::PERBYVOL, vol[poo], vol[moo], volCenter);
322 volCenter[vf::dPERBZVOLdx] = computeLimiter(vf::PERBZVOL, vol[poo], vol[moo], volCenter);
323 }
324
325 const auto opo = stencil.opo();
326 const auto omo = stencil.omo();
328 volCenter[vf::dPERBXVOLdy] = computeDiff(vf::PERBXVOL, vol[opo], vol[omo]);
329 volCenter[vf::dPERBYVOLdy] = computeDiff(vf::PERBYVOL, vol[opo], vol[omo]);
330 volCenter[vf::dPERBZVOLdy] = computeDiff(vf::PERBZVOL, vol[opo], vol[omo]);
331 } else {
332 volCenter[vf::dPERBXVOLdy] = computeLimiter(vf::PERBXVOL, vol[opo], vol[omo], volCenter);
333 volCenter[vf::dPERBYVOLdy] = computeLimiter(vf::PERBYVOL, vol[opo], vol[omo], volCenter);
334 volCenter[vf::dPERBZVOLdy] = computeLimiter(vf::PERBZVOL, vol[opo], vol[omo], volCenter);
335 }
336
337 const auto oop = stencil.oop();
338 const auto oom = stencil.oom();
340 volCenter[vf::dPERBXVOLdz] = computeDiff(vf::PERBXVOL, vol[oop], vol[oom]);
341 volCenter[vf::dPERBYVOLdz] = computeDiff(vf::PERBYVOL, vol[oop], vol[oom]);
342 volCenter[vf::dPERBZVOLdz] = computeDiff(vf::PERBZVOL, vol[oop], vol[oom]);
343 } else {
344 volCenter[vf::dPERBXVOLdz] = computeLimiter(vf::PERBXVOL, vol[oop], vol[oom], volCenter);
345 volCenter[vf::dPERBYVOLdz] = computeLimiter(vf::PERBYVOL, vol[oop], vol[oom], volCenter);
346 volCenter[vf::dPERBZVOLdz] = computeLimiter(vf::PERBZVOL, vol[oop], vol[oom], volCenter);
347 }
348}
349
363 phiprof::Timer derivsTimer{"Calculate volume derivatives"};
364 const size_t numCells = fsgrid.getNumCells();
365
366 phiprof::Timer commTimer{"BVOL derivatives ghost updates MPI", {"MPI"}};
367 fsgrid.updateGhostCells(vol);
368 commTimer.stop(numCells, "Spatial Cells");
369
370 // Calculate derivatives
371 fsgrid.parallel_for([](int timerId) -> phiprof::Timer { return phiprof::Timer{timerId}; },
372 phiprof::initializeTimer("FS derivatives BVOL compute cells"), technical,
373 [=](const fsgrid::Coordinates &coordinates, const fsgrid::FsStencil& stencil, cuint sysBoundaryFlag, cuint sysBoundaryLayer) {
374 calculateBVOLDerivatives(vol, technical, stencil);
375 });
376
377 derivsTimer.stop(numCells, "Spatial Cells");
378}
379
392
395 const fsgrid::FsStencil& stencil, const std::array<Real, 3>& gridSpacing) {
396 auto normalize = [&vol, &bgb](auto i) -> std::array<Real, 3> {
397 const auto& b = bgb[i];
398 const auto& v = vol[i];
402 const Real bnorm = sqrt(bx*bx + by*by + bz*bz);
403
404 return {
405 bx / bnorm,
406 by / bnorm,
407 bz / bnorm,
408 };
409 };
410
411 const auto [bx, by, bz] = normalize(stencil.ooo());
412 const auto [left_x_bx, left_x_by, left_x_bz] = normalize(stencil.moo());
413 const auto [rght_x_bx, rght_x_by, rght_x_bz] = normalize(stencil.poo());
414 const auto [left_y_bx, left_y_by, left_y_bz] = normalize(stencil.omo());
415 const auto [rght_y_bx, rght_y_by, rght_y_bz] = normalize(stencil.opo());
416 const auto [left_z_bx, left_z_by, left_z_bz] = normalize(stencil.oom());
417 const auto [rght_z_bx, rght_z_by, rght_z_bz] = normalize(stencil.oop());
418
419 auto& volCenter = vol[stencil.ooo()];
420 volCenter[fsgrids::volfields::CURVATUREX] = bx * 0.5 * (rght_x_bx - left_x_bx) / gridSpacing[0] +
421 by * 0.5 * (rght_y_bx - left_y_bx) / gridSpacing[1] +
422 bz * 0.5 * (rght_z_bx - left_z_bx) / gridSpacing[2];
423 volCenter[fsgrids::volfields::CURVATUREY] = bx * 0.5 * (rght_x_by - left_x_by) / gridSpacing[0] +
424 by * 0.5 * (rght_y_by - left_y_by) / gridSpacing[1] +
425 bz * 0.5 * (rght_z_by - left_z_by) / gridSpacing[2];
426 volCenter[fsgrids::volfields::CURVATUREZ] = bx * 0.5 * (rght_x_bz - left_x_bz) / gridSpacing[0] +
427 by * 0.5 * (rght_y_bz - left_y_bz) / gridSpacing[1] +
428 bz * 0.5 * (rght_z_bz - left_z_bz) / gridSpacing[2];
429}
430
443 phiprof::Timer curvatureTimer{"Calculate curvature"};
444 const size_t numCells = fsgrid.getNumCells();
445
446 phiprof::Timer commTimer{"Calculate curvature ghost updates MPI", {"MPI"}};
447 fsgrid.updateGhostCells(vol);
448 commTimer.stop(numCells, "Spatial Cells");
449
450 fsgrid.parallel_for([](int timerId) -> phiprof::Timer { return phiprof::Timer{timerId}; },
451 phiprof::initializeTimer("Calculate curvature compute cells"), technical,
452 [=](const fsgrid::Coordinates &coordinates, const fsgrid::FsStencil& stencil, cuint sysBoundaryFlag, cuint sysBoundaryLayer) {
453 const bool compute = (sysBoundaryFlag == sysboundarytype::NOT_SYSBOUNDARY &&
454 sysBoundaryLayer != 1 && sysBoundaryLayer != 2);
455 if (compute) {
456 calculateCurvature(vol, bgb, stencil, coordinates.physicalGridSpacing);
457 }
458 });
459 curvatureTimer.stop(numCells, "Spatial Cells");
460}
461
465[[maybe_unused]] static std::array<Real, 3> getPerBVol(SpatialCell* cell) {
466 return std::array<Real, 3>{{cell->parameters[CellParams::PERBXVOL],
469}
470
474static std::array<Real, 3> getBVol(SpatialCell* cell) {
475 return std::array<Real, 3>{{cell->parameters[CellParams::BGBXVOL] + cell->parameters[CellParams::PERBXVOL],
478}
479
483static std::array<Real, 3> getMomentumDensity(SpatialCell* cell) {
484 Real rho = cell->parameters[CellParams::RHOM];
485 return std::array<Real, 3>{{rho * cell->parameters[CellParams::VX],
486 rho * cell->parameters[CellParams::VY],
487 rho * cell->parameters[CellParams::VZ]}};
488}
489
494 Real rho = cell->parameters[CellParams::RHOM];
495 std::array<Real, 3> p = getMomentumDensity(cell);
496 std::array<Real, 3> B = getBVol(cell);
497 return (pow(B[0],2) + pow(B[1],2) + pow(B[2],2)) / (2.0 * physicalconstants::MU_0) + // Magnetic field energy
498 (rho > EPS ? (pow(p[0],2) + pow(p[1],2) + pow(p[2],2)) / (2.0 * cell->parameters[CellParams::RHOM]) : 0.0); // Kinetic energy
499}
500
505static Real calculateAnisotropy(const Eigen::Matrix3d& rot, const std::array<Real, 6>& P) {
506 // Now, rotation matrix to get parallel and perpendicular pressure
507 // Eigen::Quaterniond q {Quaterniond::FromTwoVectors(Eigen::vector3d{0, 0, 1}, Eigen::vector3d{myB[0], myB[1], myB[2]})};
508 // Eigen::Matrix3d rot = q.toRotationMatrix();
509 Eigen::Matrix3d Ptensor{
510 {P[0], P[5], P[4]},
511 {P[5], P[1], P[3]},
512 {P[4], P[3], P[2]},
513 };
514
515 Eigen::Matrix3d transposerot = rot.transpose();
516 Eigen::Matrix3d Pprime = rot * Ptensor * transposerot;
517
518 Real Panisotropy{0.0};
519 if (Pprime(2, 2) > EPS) {
520 Panisotropy = (Pprime(0, 0) + Pprime(1, 1)) / (2 * Pprime(2, 2));
521 }
522
523 return Panisotropy;
524}
525
535void calculateScaledDeltas(SpatialCell* cell, std::vector<SpatialCell*>& neighbors) {
536 Real dRho{0};
537 Real dU{0};
538 Real dPsq{0};
539 Real dBsq{0};
540 Real dB{0};
541
542 Real myRho{cell->parameters[CellParams::RHOM]};
543 Real myU{calculateU(cell)};
544 Real myV{std::sqrt(std::pow(cell->parameters[CellParams::VX], 2) +
545 std::pow(cell->parameters[CellParams::VY], 2) +
546 std::pow(cell->parameters[CellParams::VZ], 2))};
547 Real maxV{myV};
548 std::array<Real, 3> myP = getMomentumDensity(cell);
549 std::array<Real, 3> myB = getBVol(cell);
550 for (SpatialCell* neighbor : neighbors) {
551 Real otherRho = neighbor->parameters[CellParams::RHOM];
552 Real otherU = calculateU(neighbor);
553 Real otherV{std::sqrt(std::pow(neighbor->parameters[CellParams::VX], 2) +
554 std::pow(neighbor->parameters[CellParams::VY], 2) +
555 std::pow(neighbor->parameters[CellParams::VZ], 2))};
556 std::array<Real, 3> otherP = getMomentumDensity(neighbor);
557 std::array<Real, 3> otherB = getBVol(neighbor);
558 Real deltaBsq = pow(myB[0]-otherB[0], 2) + pow(myB[1]-otherB[1], 2) + pow(myB[2]-otherB[2], 2);
559
560 if (myV < EPS) {
561 maxV = std::max(maxV, otherV);
562 }
563 Real maxRho = std::max(myRho, otherRho);
564 if (maxRho > EPS) {
565 dRho = std::max(fabs(myRho - otherRho) / maxRho, dRho);
566 }
567 Real maxU = std::max(myU, otherU);
568 if (maxU > EPS) {
569 dU = std::max(fabs(myU - otherU) / maxU, dU);
570 dBsq = std::max(deltaBsq / (2 * physicalconstants::MU_0 * maxU), dBsq);
571 if (myRho > EPS) {
572 dPsq = std::max((pow(myP[0]-otherP[0], 2) + pow(myP[1]-otherP[1], 2) + pow(myP[2] - otherP[2], 2)) / (2 * myRho * maxU), dPsq);
573 }
574 }
575 Real maxB = sqrt(std::max(pow(myB[0], 2) + pow(myB[1], 2) + pow(myB[2], 2), pow(otherB[0], 2) + pow(otherB[1], 2) + pow(otherB[2], 2)));
576 if (maxB > EPS) {
577 dB = std::max(sqrt(deltaBsq) / maxB, dB);
578 }
579 }
580
581 Real alpha{0.0};
582 alpha = std::max(alpha, dRho * P::alphaDRhoWeight);
583 alpha = std::max(alpha, dU * P::alphaDUWeight);
584 alpha = std::max(alpha, dPsq * P::alphaDPSqWeight);
585 alpha = std::max(alpha, dBsq * P::alphaDBSqWeight);
586 alpha = std::max(alpha, dB * P::alphaDBWeight);
587
594
595 // Note missing factor of mu_0, since we want B and J in same units later
596 myB = getBVol(cell); // Redundant, but this makes sure we use total B here
597 std::array<Real, 3> myJ = {dBZdy - dBYdz, dBXdz - dBZdx, dBYdx - dBXdy};
598 Real BdotJ{0.0};
599 Real Bsq{0.0};
600 Real J{0.0};
601 for (int i = 0; i < 3; ++i) {
602 BdotJ += myB[i] * myJ[i];
603 Bsq += myB[i] * myB[i];
604 J += myJ[i] * myJ[i];
605 }
606 J = std::sqrt(J);
607
608 Real Bperp{0.0};
609 if (Bsq > EPS) {
610 for (int i = 0; i < 3; ++i) {
611 Bperp += std::pow(myB[i] * (1 - BdotJ / Bsq), 2);
612 }
613 Bperp = std::sqrt(Bperp);
614 }
615
616 // Vorticity
623 Real vorticity {std::sqrt(std::pow(dVzdy - dVydz, 2) + std::pow(dVxdz - dVzdx, 2 ) + std::pow(dVydx - dVxdy, 2))};
624 //Real vA {std::sqrt(Bsq / (physicalconstants::MU_0 * myRho))};
625 Real amr_vorticity {-1.0}; // Error value
626 if (maxV > EPS) {
627 amr_vorticity = vorticity * cell->parameters[CellParams::DX] / maxV;
628 }
629
630 std::array<Real, 6> myPressure{cell->parameters[CellParams::P_11], cell->parameters[CellParams::P_22],
633 Eigen::Matrix3d rot =
634 Eigen::Quaterniond::FromTwoVectors(Eigen::Vector3d{myB[0], myB[1], myB[2]}, Eigen::Vector3d{0, 0, 1})
635 .normalized()
636 .toRotationMatrix();
637 Real Panisotropy{calculateAnisotropy(rot, myPressure)};
638 for (const auto& pop : cell->get_populations()) {
639 // TODO I hate this. Change all this crap to std::vectors?
640 std::array<Real, 6> popP{pop.P[0], pop.P[1], pop.P[2], pop.P[3], pop.P[4], pop.P[5]};
641 Real popPanisotropy{calculateAnisotropy(rot, popP)};
642 // low value refines
643 Panisotropy = std::min(Panisotropy, popPanisotropy);
644 }
645
646 cell->parameters[CellParams::AMR_DRHO] = dRho;
647 cell->parameters[CellParams::AMR_DU] = dU;
648 cell->parameters[CellParams::AMR_DPSQ] = dPsq;
649 cell->parameters[CellParams::AMR_DBSQ] = dBsq;
650 cell->parameters[CellParams::AMR_DB] = dB;
651 cell->parameters[CellParams::AMR_ALPHA1] = alpha;
652 cell->parameters[CellParams::AMR_ALPHA2] = cell->parameters[CellParams::DX] * J / (Bperp + EPS); // Epsilon in denominator so we don't get infinities
653 cell->parameters[CellParams::P_ANISOTROPY] = Panisotropy;
654 // Experimental, current scaling is bulk velocity
655 cell->parameters[CellParams::AMR_VORTICITY] = amr_vorticity;
656}
657
663
664void calculateScaledDeltasSimple(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid) {
665 const vector<CellID>& cells = getLocalCells();
666 int N_cells = cells.size();
667 phiprof::Timer gradientsTimer{"Calculate volume gradients"};
668 int computeTimerId{phiprof::initializeTimer("Calculate volume gradients compute cells")};
669
670 phiprof::Timer commTimer{"Calculate volume gradients ghost updates MPI", {"MPI"}};
671 // We only need nearest neighbourhood and spatial data here
673 mpiGrid.update_copies_of_remote_neighbors(Neighborhoods::NEAREST);
674 commTimer.stop(N_cells, "Spatial Cells");
675
676 // Calculate derivatives
677 #pragma omp parallel
678 {
679 phiprof::Timer computeTimer{computeTimerId};
680 #pragma omp for
681 for (uint i = 0; i < cells.size(); ++i) {
682 CellID id = cells[i];
683 SpatialCell* cell = mpiGrid[id];
684 std::vector<SpatialCell*> neighbors;
685 for (const auto& [neighbor, dir] : mpiGrid.get_face_neighbors_of(id)) {
686 neighbors.push_back(mpiGrid[neighbor]);
687 }
688 calculateScaledDeltas(cell, neighbors);
689 }
690 computeTimer.stop(N_cells, "Spatial Cells");
691 }
692
693 gradientsTimer.stop(N_cells, "Spatial Cells");
694}
for i
Definition Dispersion.m:24
sqrt(1.0+vA *vA/(c *c))) % Ion-acoustic wave cS
static void setCellDerivativesToZero(fsgrids::dperbspan dperb, fsgrids::dmomentsspan dmoments, const fsgrid::FsStencil &stencil, cuint component)
std::array< Real, vderivatives::N_V_DERIVATIVES > derivativesV
static void set_mpi_transfer_type(const uint64_t type, bool atSysBoundaries=false)
std::vector< Population > & get_populations()
std::array< Real, bvolderivatives::N_BVOL_DERIVATIVES > derivativesBVOL
std::array< Real, CellParams::N_SPATIAL_CELL_PARAMS > parameters
const std::vector< CellID > & getLocalCells()
Definition main.cpp:39
Parameters P
const uint32_t cuint
Definition definitions.h:50
float Real
Definition definitions.h:41
uint64_t CellID
Definition definitions.h:54
fsgrid::FsGrid< FS_STENCIL_WIDTH > FieldSolverGrid
Definition definitions.h:78
void calculateBVOLDerivativesSimple(fsgrids::volspan vol, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid)
High-level derivative calculation wrapper function.
void calculateCurvatureSimple(fsgrids::volspan vol, fsgrids::constbgbspan bgb, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid)
High-level curvature calculation wrapper function.
void calculateDerivatives(fsgrids::perbspan perb, fsgrids::constmomentsspan moments, fsgrids::dperbspan dperb, fsgrids::dmomentsspan dmoments, const fsgrid::FsStencil &stencil, cuint sysBoundaryFlag, cuint sysBoundaryLayer, const bool doMoments)
Low-level spatial derivatives calculation.
void calculateDerivativesSimple(fsgrids::perbspan perb, fsgrids::momentsspan moments, fsgrids::dperbspan dperb, fsgrids::dmomentsspan dmoments, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, const bool doMoments)
High-level derivative calculation wrapper function.
static std::array< Real, 3 > getBVol(SpatialCell *cell)
Returns volumetric B of cell.
void computePerbDerivatives(fsgrids::perbspan perb, fsgrids::dperbspan dperb, const fsgrid::FsStencil &stencil, bool dontCompute2ndDerivatives, bool atSysBoundary, cuint sysBoundaryFlag)
static Real calculateU(SpatialCell *cell)
Calculates energy density for spatial cell.
void calculateScaledDeltasSimple(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid)
High-level scaled gradient calculation wrapper function.
void calculateCurvature(fsgrids::volspan vol, fsgrids::constbgbspan bgb, const fsgrid::FsStencil &stencil, const std::array< Real, 3 > &gridSpacing)
Low-level curvature calculation.
static Real calculateAnisotropy(const Eigen::Matrix3d &rot, const std::array< Real, 6 > &P)
Calculates pressure anistotropy from B and Pi.
static std::array< Real, 3 > getPerBVol(SpatialCell *cell)
Returns perturbed volumetric B of cell.
void calculateScaledDeltas(SpatialCell *cell, std::vector< SpatialCell * > &neighbors)
Low-level scaled gradients calculation.
void calculateBVOLDerivatives(fsgrids::volspan vol, fsgrids::consttechnicalspan technical, const fsgrid::FsStencil &stencil)
Low-level spatial derivatives calculation.
static std::array< Real, 3 > getMomentumDensity(SpatialCell *cell)
Calculates momentum density of cell.
void computeMomentsDerivatives(fsgrids::constmomentsspan moments, fsgrids::dmomentsspan dmoments, const fsgrid::FsStencil &stencil, const bool atSysBoundary)
static creal EPS
Definition fs_common.h:61
const Real FOURTH
Definition fs_common.h:53
Definitions of the limiter functions used in the field solver.
T limiter(const T &left, const T &cent, const T &rght)
Definition fs_limiters.h:85
@ dVzdx
Definition gridGlue.hpp:45
@ dVydx
Definition gridGlue.hpp:42
@ dVydz
Definition gridGlue.hpp:44
@ dVxdy
Definition gridGlue.hpp:40
@ dVxdz
Definition gridGlue.hpp:41
@ dVzdy
Definition gridGlue.hpp:46
@ AMR_ALPHA2
Definition common.h:221
@ P_ANISOTROPY
Definition common.h:222
@ AMR_ALPHA1
Definition common.h:220
@ AMR_VORTICITY
Definition common.h:223
@ BGBYVOL
Definition common.h:379
@ BGBXVOL
Definition common.h:378
@ BGBZVOL
Definition common.h:380
std::span< std::array< Real, fsgrids::bfield::N_BFIELD > > perbspan
Definition common.h:434
std::span< const std::array< Real, bgbfield::N_BGB > > constbgbspan
Definition common.h:445
std::span< const std::array< Real, fsgrids::moments::N_MOMENTS > > constmomentsspan
Definition common.h:447
std::span< std::array< Real, fsgrids::moments::N_MOMENTS > > momentsspan
Definition common.h:446
std::span< std::array< Real, fsgrids::dmoments::N_DMOMENTS > > dmomentsspan
Definition common.h:448
std::span< technical > technicalspan
Definition common.h:452
std::span< std::array< Real, fsgrids::dperb::N_DPERB > > dperbspan
Definition common.h:442
std::span< const technical > consttechnicalspan
Definition common.h:453
volfields
Definition common.h:403
@ PERBYVOL
Definition common.h:405
@ CURVATUREZ
Definition common.h:421
@ CURVATUREX
Definition common.h:419
@ PERBXVOL
Definition common.h:404
@ CURVATUREY
Definition common.h:420
@ PERBZVOL
Definition common.h:406
std::span< std::array< Real, fsgrids::volfields::N_VOL > > volspan
Definition common.h:450
const Real CHARGE
Definition common.h:572
const Real K_B
Definition common.h:571
const Real MU_0
Definition common.h:570
static const uint64_t ALL_SPATIAL_DATA
const std::array< T, N > & oom
const std::array< T, N > & poo
const std::array< T, N > & opo
const std::array< T, N > & omo
const std::array< T, N > & oop
const std::array< T, N > & moo
const std::array< T, N > & ooo
static Real alphaDRhoWeight
Definition parameters.h:213
static Real alphaDBSqWeight
Definition parameters.h:216
static uint ohmHallTerm
Definition parameters.h:142
static bool fieldSolverFiniteDifferencingAtBoundaries
Definition parameters.h:154
static Real alphaDBWeight
Definition parameters.h:217
static Real electronDensity
Definition parameters.h:149
static Real alphaDUWeight
Definition parameters.h:214
static Real alphaDPSqWeight
Definition parameters.h:215
static Real electronTemperature
Definition parameters.h:146
static Real electronPTindex
Definition parameters.h:150