Vlasiator ebf0dd394 on dev (v5.4.0 + 1054 commits)
Loading...
Searching...
No Matches
common_pitch_angle_diffusion.cpp
Go to the documentation of this file.
1/*
2 * This file is part of Vlasiator.
3 * Copyright 2010-2025 Finnish Meteorological Institute and University of Helsinki
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/*
24 In this file we define functions and variables that are used for both
25 CPU and GPU versions of pitchAngleDiffusion
26*/
27
28#include "../parameters.h"
29#include "../object_wrapper.h"
30#include <math.h>
31//#include <cmath> // NaN Inf checks
32#include <iostream>
33#include <fstream>
34#include <iomanip>
35#include <iterator>
36#include <Eigen/Geometry>
38
39/* Storage of Temperature anisotropy to beta parallel array for pitch-angle diffusion parametrization
40 see: Parametrization of coefficients for sub-grid modeling of pitch-angle diffusion in global
41 magnetospheric hybrid-Vlasov simulations, M. Dubart, M. Battarbee, U. Ganse, A. Osmane, F. Spanier,
42 J. Suni, G. Cozzani, K. Horaites, K. Papadakis, Y. Pfau-Kempf, V. Tarvus, and M. Palmroth,
43 Physics of Plasmas 30, 123903 (2023)
44 https://doi.org/10.1063/5.0176376
45 */
46std::vector<Real> betaParaArray;
47std::vector<Real> TanisoArray;
48std::vector<Real> nu0Array;
49size_t n_betaPara = 0;
50size_t n_Taniso = 0;
51bool nuArrayRead = false;
52
54 if (nuArrayRead) {
55 return;
56 }
57
58 // Read from NU0BOX.DAT (or other file if declared in parameters)
59 std::string PATHfile = Parameters::PADnu0;
60 std::ifstream FILEDmumu;
61 FILEDmumu.open(PATHfile);
62
63 // verify file access was successful
64 if (!FILEDmumu.is_open()) {
65 std::cerr<<"Error opening file "<<PATHfile<<"!"<<std::endl;
66 if (FILEDmumu.fail()) {
67 std::cerr<<strerror(errno)<<std::endl;
68 }
69 abort();
70 }
71
72 // Read betaPara strings from file
73 std::string lineBeta;
74 for (int i = 0; i < 2; i++) {
75 std::getline(FILEDmumu,lineBeta);
76 }
77 std::istringstream issBeta(lineBeta);
78 float numBeta;
79 while ((issBeta >> numBeta)) { // Stream read from issBeta into numBeta
80 betaParaArray.push_back(numBeta);
81 }
82
83 // Read Taniso strings from file
84 std::string lineTaniso;
85 for (int i = 0; i < 2; i++) {
86 std::getline(FILEDmumu,lineTaniso);
87 }
88 std::istringstream issTaniso(lineTaniso);
89 float numTaniso;
90 while ((issTaniso >> numTaniso)) { // Stream read from issTaniso into numTaniso
91 TanisoArray.push_back(numTaniso);
92 }
93
94 // Discard one line
95 std::string lineDUMP;
96 for (int i = 0; i < 1; i++) {
97 std::getline(FILEDmumu,lineDUMP);
98 }
99
100 // Read values of nu0 from file
101 std::string linenu0;
102 n_betaPara = betaParaArray.size();
103 n_Taniso = TanisoArray.size();
105
106 for (size_t i = 0; i < n_betaPara; i++) {
107 std::getline(FILEDmumu,linenu0);
108 std::istringstream issnu0(linenu0);
109 std::vector<Real> tempLINE;
110 float numTEMP;
111 while((issnu0 >> numTEMP)) {
112 tempLINE.push_back(numTEMP);
113 }
114 if (tempLINE.size() != n_Taniso) {
115 std::cerr<<"ERROR! line "<<i<<" entry in "<<PATHfile<<" has "<<tempLINE.size()<<" entries instead of expected "<<n_Taniso<<"!"<<std::endl;
116 abort();
117 }
118 for (size_t j = 0; j < n_Taniso; j++) {
119 nu0Array[i*n_Taniso+j] = tempLINE[j];
120 }
121 }
122
123 nuArrayRead = true;
124 FILEDmumu.close();
125}
126
127/* Linear interpolation of diffusion coefficient from above array
128 */
130 const Real Taniso_in,
131 const Real betaParallel_in
132 ) {
133 Real Taniso = Taniso_in;
134 Real betaParallel = betaParallel_in;
135 int betaIndx = -1;
136 int TanisoIndx = -1;
137 for (size_t i = 0; i < betaParaArray.size(); i++) {
138 if (betaParallel >= betaParaArray[i]) {
139 betaIndx = i;
140 }
141 }
142 for (size_t i = 0; i < TanisoArray.size() ; i++) {
143 if (Taniso >= TanisoArray[i] ) {
144 TanisoIndx = i;
145 }
146 }
147
148 if ( (betaIndx < 0) || (TanisoIndx < 0) ) {
149 // Values below table lower bounds; no diffusion required.
150 return 0.0;
151 } else {
152 // Interpolate values from table; if values are above bounds, cap to maximum value.
153 if (betaIndx >= (int)betaParaArray.size()-1) {
154 betaIndx = (int)betaParaArray.size()-2; // force last bin
155 betaParallel = betaParaArray[betaIndx+1]; // force interpolation to bin top
156 }
157 if (TanisoIndx >= (int)TanisoArray.size()-1) {
158 TanisoIndx = (int)TanisoArray.size()-2; // force last bin
159 Taniso = TanisoArray[TanisoIndx+1]; // force interpolation to bin top
160 }
161 // bi-linear interpolation with weighted mean to find nu0(betaParallel,Taniso)
162 const Real beta1 = betaParaArray[betaIndx];
163 const Real beta2 = betaParaArray[betaIndx+1];
164 const Real Taniso1 = TanisoArray[TanisoIndx];
165 const Real Taniso2 = TanisoArray[TanisoIndx+1];
166 const Real nu011 = nu0Array[betaIndx*n_Taniso+TanisoIndx];
167 const Real nu012 = nu0Array[betaIndx*n_Taniso+TanisoIndx+1];
168 const Real nu021 = nu0Array[(betaIndx+1)*n_Taniso+TanisoIndx];
169 const Real nu022 = nu0Array[(betaIndx+1)*n_Taniso+TanisoIndx+1];
170 // Weights
171 const Real w11 = (beta2 - betaParallel)*(Taniso2 - Taniso) / ( (beta2 - beta1)*(Taniso2-Taniso1) );
172 const Real w12 = (beta2 - betaParallel)*(Taniso - Taniso1) / ( (beta2 - beta1)*(Taniso2-Taniso1) );
173 const Real w21 = (betaParallel - beta1)*(Taniso2 - Taniso) / ( (beta2 - beta1)*(Taniso2-Taniso1) );
174 const Real w22 = (betaParallel - beta1)*(Taniso - Taniso1) / ( (beta2 - beta1)*(Taniso2-Taniso1) );
175 // Linear interpolation (with fudge factor divisor)
176 return (w11*nu011 + w12*nu012 + w21*nu021 + w22*nu022)/Parameters::PADfudge;
177 }
178}
179//CellIdx appears to be unused
181 SpatialCell& cell,
182 const uint popID, const size_t CellIdx, bool& currentSpatialLoopComplete,
183 Realf& sparsity, std::array<Real,3>& b, Real& nu0
184 ){
185
186 sparsity = 0.01 * cell.getVelocityBlockMinValue(popID);
187
188 currentSpatialLoopComplete = false;
189
190 // Diffusion coefficient to use in this cell
191 nu0 = 0.0;
192
193 // Compute b
194 const std::array<Real,3> B = {cell.parameters[CellParams::PERBXVOL] + cell.parameters[CellParams::BGBXVOL],
197 const Real Bnorm = sqrt(B[0]*B[0] + B[1]*B[1] + B[2]*B[2]);
198 b[0] = B[0]/Bnorm;
199 b[1] = B[1]/Bnorm;
200 b[2] = B[2]/Bnorm;
201
202 if (P::PADcoefficient >= 0) {
203 // User-provided single diffusion coefficient
204 nu0 = P::PADcoefficient;
205 } else {
206 // Use nu0 values based on Taniso and betaPara read from file
207 if (!nuArrayRead) {
208 std::cerr<<" ERROR! Attempting to interpolate nu0 value but file has not been read."<<std::endl;
209 abort();
210 }
211
212 // Perform Eigen rotation to find parallel and perpendicular pressure
213 Eigen::Matrix3d rot = Eigen::Quaterniond::FromTwoVectors(Eigen::Vector3d{b[0], b[1], b[2]}, Eigen::Vector3d{0, 0, 1}).normalized().toRotationMatrix();
214 Eigen::Matrix3d Ptensor {
218 };
219 Eigen::Matrix3d transposerot = rot.transpose();
220 Eigen::Matrix3d Pprime = rot * Ptensor * transposerot;
221
222 // Anisotropy
223 Real Taniso = 0.0;
224 if (Pprime(2, 2) > std::numeric_limits<Real>::min()) {
225 Taniso = (Pprime(0, 0) + Pprime(1, 1)) / (2 * Pprime(2, 2));
226 }
227 // Beta Parallel
228 Real betaParallel = 0.0;
229 if (Bnorm > 0) {
230 betaParallel = 2.0 * physicalconstants::MU_0 * Pprime(2, 2) / (Bnorm*Bnorm);
231 }
232 // Find anisotropy and beta parallel indexes from read table
233 nu0 = interpolateNuFromArray(Taniso,betaParallel);
234 }
235
236 // Enable nu0 disk output; skip cells where diffusion is not required (or diffusion coefficient is very small).
237 cell.parameters[CellParams::NU0] = nu0;
238 if (nu0 <= 0.001) {
239 currentSpatialLoopComplete = true;
240 }
241}
for i
Definition Dispersion.m:24
sqrt(1.0+vA *vA/(c *c))) % Ion-acoustic wave cS
Real getVelocityBlockMinValue(const uint popID) const
std::array< Real, CellParams::N_SPATIAL_CELL_PARAMS > parameters
Realf interpolateNuFromArray(const Real Taniso_in, const Real betaParallel_in)
void readNuArrayFromFile()
std::vector< Real > TanisoArray
std::vector< Real > nu0Array
std::vector< Real > betaParaArray
void computePitchAngleDiffusionParameters(SpatialCell &cell, const uint popID, const size_t CellIdx, bool &currentSpatialLoopComplete, Realf &sparsity, std::array< Real, 3 > &b, Real &nu0)
float Real
Definition definitions.h:41
float Realf
Definition definitions.h:33
const int j
const Real MU_0
Definition common.h:570
static Realf PADcoefficient
Definition parameters.h:238
static std::string PADnu0
Definition parameters.h:242
static Realf PADfudge
Definition parameters.h:243