Vlasiator ebf0dd394 on dev (v5.4.0 + 1054 commits)
Loading...
Searching...
No Matches
gpu_1d_pqm.hpp
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#ifndef GPU_1D_PQM_H
24#define GPU_1D_PQM_H
25
29
30/*
31 Define functions for Realf instead of Vec
32*/
33
34/*make sure quartic polynomial is monotonic*/
35static ARCH_DEV inline void filter_pqm_monotonicity(const Realf* __restrict__ values, int k, Realf &fv_l, Realf &fv_r, Realf &fd_l, Realf &fd_r, const int index, const int stride) {
36 /*fixed values give to roots clearly outside [0,1], or nonexisting ones*/
37
38 /*second derivative coefficients, eq 23 in white et al.*/
39 const Realf b0 = (Realf)(60.0) * values[k*stride+index] - (Realf)(24.0) * fv_r - (Realf)(36.0) * fv_l + (Realf)(3.0) * (fd_r - (Realf)(3.0) * fd_l);
40 const Realf b1 = (Realf)(-360.0) * values[k*stride+index] + (Realf)(36.0) * fd_l - (Realf)(24.0) * fd_r + (Realf)(168.0) * fv_r + (Realf)(192.0) * fv_l;
41 const Realf b2 = (Realf)(360.0) * values[k*stride+index] + (Realf)(30.0) * (fd_r - fd_l) - (Realf)(180.0) * (fv_l + fv_r);
42 /*let's compute sqrt value to be used for computing roots. If we
43 take sqrt of negaitve numbers, then we instead set a value that
44 will make the root to be +-100 which is well outside range
45 of[0,1]. We do not catch FP exceptions, so sqrt(negative) are okish (add
46 a max(val_to_sqrt,0) if not*/
47 const Realf val_to_sqrt = b1 * b1 - (Realf)(4.0) * b0 * b2;
48 const Realf sqrt_val = (val_to_sqrt < (Realf)(0.0)) ?
49 b1 + (Realf)(200.0) * b2 :
50 sqrt(val_to_sqrt);
51 //compute roots. Division is safe with vectorclass (=inf)
52 const Realf root1 = (b2 != (Realf)(0.0)) ? (-b1 + sqrt_val) / ((Realf)(2.0) * b2) : (Realf)(0.0);
53 const Realf root2 = (b2 != (Realf)(0.0)) ? (-b1 - sqrt_val) / ((Realf)(2.0) * b2) : (Realf)(0.0);
54
55 /*PLM slope, MC limiter*/
56 const Realf plm_slope_l = (Realf)(2.0) * (values[k*stride+index] - values[(k-1)*stride+index]);
57 const Realf plm_slope_r = (Realf)(2.0) * (values[(k+1)*stride+index] - values[k*stride+index]);
58 const Realf slope_sign = plm_slope_l + plm_slope_r; //it also has some magnitude, but we will only use its sign.
59 /*first derivative coefficients*/
60 const Realf c0 = fd_l;
61 const Realf c1 = b0;
62 const Realf c2 = b1 / (Realf)(2.0);
63 const Realf c3 = b2 / (Realf)(3.0);
64 //compute both slopes at inflexion points, at least one of these
65 //is with [0..1]. If the root is not in this range, we
66 //simplify later if statements by setting it to the plm slope
67 //sign
68 const Realf root1_slope = (root1 >= (Realf)(0.0) && root1 <= (Realf)(1.0)) ?
69 c0 + root1 * ( c1 + root1 * (c2 + root1 * c3 ) ) :
70 slope_sign;
71 const Realf root2_slope = (root2 >= (Realf)(0.0) && root2 <= (Realf)(1.0)) ?
72 c0 + root2 * ( c1 + root2 * (c2 + root2 * c3 ) ) :
73 slope_sign;
74 const bool fixInflexion = root1_slope * slope_sign < (Realf)(0.0) || root2_slope * slope_sign < (Realf)(0.0);
75
76 if(fixInflexion) {
77 const Realf valuesa = values[k*stride+index];
78 Realf fva_l = fv_l;
79 Realf fva_r = fv_r;
80 Realf fda_l = fd_l;
81 Realf fda_r = fd_r;
82 const Realf slope_signa = slope_sign;
83 //need to collapse, point has wrong sign
84
85 if(fabs(plm_slope_l) <= fabs(plm_slope_r))
86 {
87 //collapse to left edge (eq 21)
88 fda_l = (Realf)(1.0 / 3.0) * ( (Realf)(10.0) * valuesa - (Realf)(2.0) * fva_r - (Realf)(8.0) * fva_l);
89 fda_r = (Realf)(-10.0) * valuesa + (Realf)(6.0) * fva_r + (Realf)(4.0) * fva_l;
90 //check if PLM slope is consistent (eq 28 & 29)
91 if (slope_signa * fda_l < (Realf)(0.0))
92 {
93 fda_l = (Realf)(0.0);
94 fva_r = (Realf)(5.0) * valuesa - (Realf)(4.0) * fva_l;
95 fda_r = (Realf)(20.0) * (valuesa - fva_l);
96 }
97 else if (slope_signa * fda_r < (Realf)(0.0))
98 {
99 fda_r = (Realf)(0.0);
100 fva_l = (Realf)(0.5) * ((Realf)(5.0) * valuesa - (Realf)(3.0) * fva_r);
101 fda_l = (Realf)(10.0 / 3.0) * (-valuesa + fva_r);
102 }
103 }
104 else
105 {
106 //collapse to right edge (eq 21)
107 fda_l = (Realf)(10.0) * valuesa - (Realf)(6.0) * fva_l - (Realf)(4.0) * fva_r;
108 fda_r = (Realf)(1.0 / 3.0) * ( (Realf)(- 10.0) * valuesa + (Realf)(2.0) * fva_l + (Realf)(8.0) * fva_r);
109 //check if PLM slope is consistent (eq 28 & 29)
110 if (slope_signa * fda_l < (Realf)(0.0))
111 {
112 fda_l = (Realf)(0.0);
113 fva_r = (Realf)(0.5) * ( (Realf)(5.0) * valuesa - (Realf)(3.0) * fva_l);
114 fda_r = (Realf)(10.0 / 3.0) * (valuesa - fva_l);
115 }
116 else if (slope_signa * fda_r < (Realf)(0.0))
117 {
118 fda_r = (Realf)(0.0);
119 fva_l = (Realf)(5.0) * valuesa - (Realf)(4.0) * fva_r;
120 fda_l = (Realf)(20.0) * ( - valuesa + fva_r);
121 }
122 }
123 fv_l = (Realf)fva_l;
124 fd_l = (Realf)fda_l;
125 fv_r = (Realf)fva_r;
126 fd_r = (Realf)fda_r;
127 }
128}
129
130static ARCH_DEV inline void compute_pqm_coeff(const Realf* __restrict__ values, face_estimate_order order, int k, Realf a[5], const Realf threshold, const int index, const int stride)
131{
132 Realf fv_l; /*left face value*/
133 Realf fv_r; /*right face value*/
134 Realf fd_l; /*left face derivative*/
135 Realf fd_r; /*right face derivative*/
136
137 compute_filtered_face_values_derivatives(values, k, order, fv_l, fv_r, fd_l, fd_r, threshold, index, stride);
138 filter_pqm_monotonicity(values, k, fv_l, fv_r, fd_l, fd_r, index, stride);
139 //Fit a second order polynomial for reconstruction see, e.g., White
140 //2008 (PQM article) (note additional integration factors built in,
141 //contrary to White (2008) eq. 4
142 a[0] = fv_l;
143 a[1] = fd_l/(Realf)(2.0);
144 a[2] = (Realf)(10.0) * values[k*stride+index] - (Realf)(4.0) * fv_r - (Realf)(6.0) * fv_l + (Realf)(0.5) * (fd_r - (Realf)(3.0) * fd_l);
145 a[3] = (Realf)(-15.0) * values[k*stride+index] + (Realf)(1.5) * fd_l - fd_r + (Realf)(7.0) * fv_r + (Realf)(8.0) * fv_l;
146 a[4] = (Realf)(6.0) * values[k*stride+index] + (Realf)(0.5) * (fd_r - fd_l) - (Realf)(3.0) * (fv_l + fv_r);
147}
148
149
150#endif
sqrt(1.0+vA *vA/(c *c))) % Ion-acoustic wave cS
#define ARCH_DEV
face_estimate_order
void compute_filtered_face_values_derivatives(const Vec *const values, const uint k, const face_estimate_order order, Vec &fv_l, Vec &fv_r, Vec &fd_l, Vec &fd_r, const Realf threshold)
float Realf
Definition definitions.h:33
static ARCH_DEV void compute_pqm_coeff(const Realf *__restrict__ values, face_estimate_order order, int k, Realf a[5], const Realf threshold, const int index, const int stride)
static ARCH_DEV void filter_pqm_monotonicity(const Realf *__restrict__ values, int k, Realf &fv_l, Realf &fv_r, Realf &fd_l, Realf &fd_r, const int index, const int stride)
const int k
__global__ void const Realf const uint *__restrict__ const uint *__restrict__ const vmesh::GlobalID *__restrict__ const uint const uint const uint const Realf threshold
#define index(i, j, k)