Vlasiator ebf0dd394 on dev (v5.4.0 + 1054 commits)
Loading...
Searching...
No Matches
fluxfunction.py
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# */
22import numpy as np
23
24# Calculate fluxfunction by integrating along -z boundary first,
25# and then going along z-direction.
26def polar_computeFluxUp(BX,BY,BZ, dxdydz):
27 # Create fluxfunction-field to be the same shape as B
28 flux = np.zeros_like(BX)
29 sizes = np.array(BX.shape)
30 tmp_flux=0.
31 flux[sizes[0]-1,0,0] = tmp_flux
32
33 # First fill the z=0 cells in the -x direction
34 for x in np.arange(sizes[0]-2,-1,-1):
35 tmp_flux -= BZ[x,0,0] * dxdydz[0]
36 flux[x,0,0] = tmp_flux
37
38 # Now, for each column, integrate in +z-direction.
39 for x in np.arange(sizes[0]):
40 tmp_flux = flux[x,0,0]
41 for z in np.arange(1,sizes[2]):
42 tmp_flux -= BX[x,0,z]*dxdydz[2]
43 flux[x,0,z] = tmp_flux
44
45 return flux
46
47 # Calculate fluxfunction by integrating along +z boundary first,
48 # and then going along negative z-direction.
49def polar_computeFluxDown(BX,BY,BZ,dxdydz):
50 # Create fluxfunction-field to be the same shape as B
51 flux = np.zeros_like(BX)
52 sizes = np.array(BX.shape)
53 tmp_flux=0.
54 flux[sizes[0]-1,0,0] = tmp_flux
55
56 # First fill the x=xmax cells in the +z direction
57 for z in np.arange(1,sizes[2]):
58 tmp_flux -= BX[sizes[0]-1,0,z]*dxdydz[2]
59 flux[sizes[0]-1,0,z] = tmp_flux
60
61 # Then fill the z=max - 1 cells
62 for x in np.arange(sizes[0]-2,-1,-1):
63 tmp_flux -= BZ[x,0,sizes[2]-1] * dxdydz[0]
64 flux[x,0,sizes[2]-1] = tmp_flux
65
66 # Now, for each column, integrate in -z-direction.
67 for x in np.arange(sizes[0]-1):
68 tmp_flux = flux[x,0,sizes[2]-1]
69 for z in np.arange(sizes[2]-2,-1,-1):
70 tmp_flux += BX[x,0,z]*dxdydz[2]
71 flux[x,0,z] = tmp_flux
72
73 return flux
74
75
76# Calculate fluxfunction by integrating along -x from the right boundary
77def polar_computeFluxLeft(BX,BY,BZ,dxdydz):
78 # Create fluxfunction-field to be the same shape as B
79 flux = np.zeros_like(BX)
80 sizes = np.array(BX.shape)
81 tmp_flux=0.
82 flux[sizes[0]-1,0,0] = tmp_flux
83
84 # First fill the x=xmax cells in the +z direction
85 for z in np.arange(1,sizes[2]):
86 tmp_flux -= BX[sizes[0]-1,0,z]*dxdydz[2]
87 flux[sizes[0]-1,0,z] = tmp_flux
88
89 # Now, for each row, integrate in -x-direction.
90 for z in np.arange(0,sizes[2]):
91 tmp_flux = flux[sizes[0]-1,0,z]
92 for x in np.arange(sizes[0]-2,-1,-1):
93 tmp_flux -= BZ[x,0,z] * dxdydz[0]
94 flux[x,0,z] = tmp_flux
95
96 return flux
97
98# Calculate fluxfunction by integrating along +x from the left boundary
99def polar_computeFluxRight(BX,BY,BZ,dxdydz):
100 # Create fluxfunction-field to be the same shape as B
101 flux = np.zeros_like(BX)
102 sizes = np.array(BX.shape)
103 tmp_flux=0.
104 flux[sizes[0]-1,0,0] = tmp_flux
105
106 # First fill the z=0 cells in the -x direction
107 for x in np.arange(sizes[0]-2,-1,-1):
108 tmp_flux -= BZ[x,0,0]*dxdydz[0]
109 flux[x,0,0] = tmp_flux
110
111 # Then fill the x=0 cells in the +z direction
112 for z in np.arange(1,sizes[2]):
113 tmp_flux -= BX[x,0,0]*dxdydz[2]
114 flux[0,0,z] = tmp_flux
115
116 # Now, for each row, integrate in +x-direction.
117 for z in np.arange(1,sizes[2]):
118 tmp_flux = flux[0,0,z]
119 for x in np.arange(1,sizes[0]):
120 tmp_flux += BZ[x,0,z] * dxdydz[0]
121 flux[x,0,z] = tmp_flux
122
123 return flux
124
125
126# namespace Equatorialplane {
127# # Calculate fluxfunction by integrating along -y boundary first,
128# # and then going along y-direction.
129# std::vector<double> computeFluxUp(Field& B) {
130# # Create fluxfunction-field to be the same shape as B
131# std::vector<double> flux(B.dimension[0]->cells * B.dimension[1]->cells * B.dimension[2]->cells);
132
133# long double tmp_flux=0.;
134
135# # First, fill the y=3 cells
136# for(int x=B.dimension[0]->cells-2; x>0; x--) {
137# Vec3d bval = B.getCell(x,3,0);
138
139# tmp_flux -= bval[1] * B.dx[0];
140# flux[B.dimension[0]->cells * 3 + x] = tmp_flux;
141# }
142
143# # Now, for each row, integrate in y-direction.
144# for(int x=1; x< B.dimension[0]->cells-1; x++) {
145
146# tmp_flux = flux[B.dimension[0]->cells * 3 + x];
147# for(int y=4; y< B.dimension[1]->cells; y++) {
148# Vec3d bval = B.getCell(x,y,0);
149
150# tmp_flux -= bval[0]*B.dx[1];
151# flux[B.dimension[0]->cells * y + x] = tmp_flux;
152# }
153# }
154
155# return flux;
156# }
157
158
159
160# # Calculate fluxfunction by integrating along +y boundary first,
161# # and then going along negative y-direction.
162# std::vector<double> computeFluxDown(Field& B) {
163# # Create fluxfunction-field to be the same shape as B
164# std::vector<double> flux(B.dimension[0]->cells * B.dimension[1]->cells * B.dimension[2]->cells);
165
166# long double tmp_flux=0.;
167
168# # Calculate flux-difference between bottom and top edge
169# # of +x boundary (so that values are consistent with computeFluxUp)
170# for(int y=3; y<B.dimension[1]->cells-4; y++) {
171# Vec3d bval = B.getCell(B.dimension[0]->cells-2,y,0);
172
173# tmp_flux -= bval[0]*B.dx[1];
174# }
175
176# # First, fill the y=max - 4 cells
177# for(int x=B.dimension[0]->cells-2; x>0; x--) {
178# Vec3d bval = B.getCell(x,B.dimension[1]->cells-4,0);
179
180# tmp_flux -= bval[1] * B.dx[0];
181# flux[B.dimension[0]->cells * (B.dimension[1]->cells - 4) + x] = tmp_flux;
182# }
183
184# # Now, for each row, integrate in -y-direction.
185# for(int x=1; x< B.dimension[0]->cells-1; x++) {
186
187# tmp_flux = flux[B.dimension[0]->cells * (B.dimension[1]->cells - 4) + x];
188# for(int y=B.dimension[1]->cells-5; y > 0; y--) {
189# Vec3d bval = B.getCell(x,y,0);
190
191# tmp_flux += bval[0] * B.dx[1];
192# flux[B.dimension[0]->cells * y + x] = tmp_flux;
193# }
194# }
195
196# return flux;
197# }
198
199
200
201# # Calculate fluxfunction by integrating along -x from the right boundary
202# std::vector<double> computeFluxLeft(Field& B) {
203# # Create fluxfunction-field to be the same shape as B
204# std::vector<double> flux(B.dimension[0]->cells * B.dimension[1]->cells * B.dimension[2]->cells);
205
206# long double tmp_flux=0.;
207# long double bottom_right_flux=0.;
208
209# # Now, for each row, integrate in -y-direction.
210# for(int y=0; y < B.dimension[1]->cells; y++) {
211# Vec3d bval = B.getCell(B.dimension[0]->cells-1,y,0);
212# bottom_right_flux -= bval[0] * B.dx[1];
213# tmp_flux = bottom_right_flux;
214# for(int x=B.dimension[0]->cells-1; x>0; x--) {
215
216# bval = B.getCell(x,y,0);
217
218# tmp_flux -= bval[1] * B.dx[0];
219# flux[B.dimension[0]->cells * y + x] = tmp_flux;
220# }
221# }
222
223# return flux;
224# }
225
226# }
227
228
229# Get a median of 3 values (branch-free!)
230# static double median3(double a, double b, double c) {
231# return max(min(a,b), min(max(a,b),c));
232# }
233def median3(a, b, c):
234 return max(min(a,b), min(max(a,b),c))
235
236def median4(a, b, c, d):
237 # This actually drops the largest and smallest value and returns the mean of the remaining two
238 l = [a,b,c,d]
239 l.sort()
240 return np.mean(l[1:3])
241
242def mean4(a, b, c, d):
243 return np.mean([a,b,c,d])
244
245def calculate(BX,BY,BZ, dxdydz):
246 sizes = np.array(BX.shape)
247
248 if True: # polar plane
249 fluxUp = polar_computeFluxUp(BX,BY,BZ,dxdydz)
250 fluxDown = polar_computeFluxDown(BX,BY,BZ,dxdydz)
251 fluxLeft = polar_computeFluxLeft(BX,BY,BZ,dxdydz)
252 # else:
253 # fluxUp = Equatorialplane::computeFluxUp(B)
254 # fluxDown = Equatorialplane::computeFluxDown(B)
255 # fluxLeft = Equatorialplane::computeFluxLeft(B)
256
257 for x in np.arange(sizes[0]):
258 for y in np.arange(sizes[1]):
259 for z in np.arange(sizes[2]):
260 a = fluxUp[x,y,z]
261 b = fluxDown[x,y,z]
262 c = fluxLeft[x,y,z]
263 fluxUp[x,y,z] = median3(a,b,c)
264 return fluxUp
265
266
267def calculate4(BX,BY,BZ, dxdydz):
268 sizes = np.array(BX.shape)
269
270 if True: # polar plane
271 fluxUp = polar_computeFluxUp(BX,BY,BZ,dxdydz)
272 fluxDown = polar_computeFluxDown(BX,BY,BZ,dxdydz)
273 fluxLeft = polar_computeFluxLeft(BX,BY,BZ,dxdydz)
274 fluxRight = polar_computeFluxRight(BX,BY,BZ,dxdydz)
275 # else:
276 # fluxUp = Equatorialplane::computeFluxUp(B)
277 # fluxDown = Equatorialplane::computeFluxDown(B)
278 # fluxLeft = Equatorialplane::computeFluxLeft(B)
279
280 for x in np.arange(sizes[0]):
281 for y in np.arange(sizes[1]):
282 for z in np.arange(sizes[2]):
283 a = fluxUp[x,y,z]
284 b = fluxDown[x,y,z]
285 c = fluxLeft[x,y,z]
286 d = fluxRight[x,y,z]
287 fluxUp[x,y,z] = median4(a,b,c,d)
288 return fluxUp
289
290def calculate4mean(BX,BY,BZ, dxdydz):
291 sizes = np.array(BX.shape)
292
293 if True: # polar plane
294 fluxUp = polar_computeFluxUp(BX,BY,BZ,dxdydz)
295 fluxDown = polar_computeFluxDown(BX,BY,BZ,dxdydz)
296 fluxLeft = polar_computeFluxLeft(BX,BY,BZ,dxdydz)
297 fluxRight = polar_computeFluxRight(BX,BY,BZ,dxdydz)
298 # else:
299 # fluxUp = Equatorialplane::computeFluxUp(B)
300 # fluxDown = Equatorialplane::computeFluxDown(B)
301 # fluxLeft = Equatorialplane::computeFluxLeft(B)
302
303 for x in np.arange(sizes[0]):
304 for y in np.arange(sizes[1]):
305 for z in np.arange(sizes[2]):
306 a = fluxUp[x,y,z]
307 b = fluxDown[x,y,z]
308 c = fluxLeft[x,y,z]
309 d = fluxRight[x,y,z]
310 fluxUp[x,y,z] = mean4(a,b,c,d)
311 return fluxUp
median4(a, b, c, d)
calculate4mean(BX, BY, BZ, dxdydz)
polar_computeFluxDown(BX, BY, BZ, dxdydz)
median3(a, b, c)
polar_computeFluxUp(BX, BY, BZ, dxdydz)
calculate4(BX, BY, BZ, dxdydz)
mean4(a, b, c, d)
polar_computeFluxLeft(BX, BY, BZ, dxdydz)
calculate(BX, BY, BZ, dxdydz)
polar_computeFluxRight(BX, BY, BZ, dxdydz)
static ARCH_HOSTDEV VecSimple< T > min(VecSimple< T > const &l, VecSimple< T > const &r)
static ARCH_HOSTDEV VecSimple< T > max(VecSimple< T > const &l, VecSimple< T > const &r)