Vlasiator ebf0dd394 on dev (v5.4.0 + 1054 commits)
Loading...
Searching...
No Matches
Dispersion.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2import glob
3import numpy as np
4import analysator
5import matplotlib.pyplot as plt
6import os
7import sys
8
9if len(sys.argv) > 1:
10 dirname = sys.argv[1]
11else:
12 dirname = "."
13
14ptnoninteractive = int(os.environ.get('PTNOINTERACTIVE', '0'))
15
16if ptnoninteractive == 0: # interactive mode
17 try:
18 from tqdm import tqdm
19 have_tqdm = True
20 except ImportError:
21 print("WARNING: Could not import tqdm")
22 have_tqdm = False
23else:
24 have_tqdm = False
25if not have_tqdm:
26 tqdm = lambda x : x
27
28# can be "none", "spatial", "temporal" or "both"
29do_windowing="both"
30
31
32class SI:
33 e = 1.6022e-19 #C
34 mp = 1.6726e-27 #kg
35 me = 9.1094e-31 #kg
36 eps0 = 8.8542e-12 # F/m
37 mu0 = 4.*np.pi*1e-7 # H/m
38 kB = 1.3807e-23 # J/K
39 c = 2.9979e8 # m/s
40
41timesteps = []
42for filename in glob.glob(dirname+"/bulk*vlsv"):
43 parts = filename.split("/")[-1].split(".")
44 if len(parts) == 3:
45 timesteps.append(int(parts[1]))
46timesteps.sort()
47tsize = len(timesteps)
48print("Found "+str(tsize)+" timesteps in directory "+dirname)
49
50if tsize <= 0:
51 sys.exit(1)
52
53for i,t in enumerate(timesteps[:1]):
54 f = analysator.vlsvfile.VlsvReader(dirname+"/bulk."+"{:07d}".format(t)+".vlsv")
55 [xsize, ysize, zsize] = map(int,f.get_fsgrid_mesh_size()) # uint64t makes some other stuff unhappy
56 fg_b = f.read_fsgrid_variable("fg_b")
57 B0vec = np.array([np.average(fg_b[:,0]), np.average(fg_b[:,1]), np.average(fg_b[:,2])])
58 B0 = np.sqrt(np.sum(B0vec**2))
59
60print("Found field grid with "+str(xsize)+"x"+str(ysize)+"x"+str(zsize)+" cells")
61print("Found "+str(tsize)+" timesteps")
62print("B_0 = "+str(B0)+" T")
63
64config=f.get_config()
65dt = f.read_parameter("dt")
66print("dt = "+str(dt)+" s")
67dtout = float(config["io"]["system_write_t_interval"][0])
68print("dtout = "+str(dtout)+" s")
69xmin = f.read_parameter("xmin")
70xmax = f.read_parameter("xmax")
71dx = (xmax-xmin)/xsize
72print("dx = "+str(dx)+" m")
73ni = float(config["proton_Dispersion"]["rho"][0])
74print("n_p = "+str(ni)+" m^-3")
75Ti = float(config["proton_Dispersion"]["Temperature"][0])
76print("T_p = "+str(Ti)+" K")
77ne, Te = ni, Ti # wild assumption!
78Wci = SI.e * B0 / SI.mp
79print("W_ci = "+str(Wci)+" 1/s")
80Wce = SI.e * B0 / SI.me
81print("W_ce = "+str(Wce)+" 1/s")
82wpi = np.sqrt(ni * SI.e**2 / SI.mp / SI.eps0)
83print("w_pi = "+str(wpi)+" 1/s")
84wpe = np.sqrt(ne * SI.e**2 / SI.me / SI.eps0)
85print("w_pe = "+str(wpe)+" 1/s")
86vthi = np.sqrt(2.*SI.kB * Ti / SI.mp)
87print("v_thi = "+str(vthi)+" m/s")
88vA = B0 / np.sqrt(SI.mu0 * (SI.me*ne + SI.mp*ni))
89print("v_A = "+str(vA)+" m/s")
90vthe = np.sqrt(2.*SI.kB * Te / SI.me)
91print("v_the = "+str(vthe)+" m/s")
92di = SI.c / wpi
93print("d_i = "+str(di)+" m")
94de = SI.c / wpe
95print("d_e = "+str(de)+" m")
96ri = vthi / Wci
97print("r_i = "+str(ri)+" m")
98re = vthe / Wce
99print("r_e = "+str(re)+" m")
100lD = vthe / wpe
101print("l_D = "+str(lD)+" m")
102
103
104B = np.zeros( (len(timesteps), xsize, 5) , dtype=complex) # time, space, field component (including left and right handed)
105
106print("Loading data")
107for i in tqdm(range(len(timesteps))):
108 t = timesteps[i]
109 if not have_tqdm:
110 print("Output step "+str(i)+" at time "+str(t))
111 f = analysator.vlsvfile.VlsvReader(dirname+"/bulk."+"{:07d}".format(t)+".vlsv")
112 fg_b = f.read_fsgrid_variable("fg_b")
113 B[i,:,:3] = fg_b
114
115# from left and right handed circular component by complex addition
116B[:,:,3] = B[:,:,1] - complex("j")*B[:,:,2]
117B[:,:,4] = B[:,:,1] + complex("j")*B[:,:,2]
118
119if do_windowing=="spatial" or do_windowing=="both":
120 spatial_window = np.hamming(xsize)
121else:
122 spatial_window = np.ones(xsize)
123if do_windowing=="temporal" or do_windowing=="both":
124 temporal_window = np.hamming(tsize)
125else:
126 temporal_window = np.ones(tsize)
127
128window = np.outer(spatial_window, temporal_window).T
129
130componentnames = ["x","y","z", "left", "right"]
131
132print("Plotting data")
133
134with tqdm(total=3+5+5) as pbar:
135 for c in range(len(componentnames)):
136 # plot x-t space
137 if c < 3:
138 plt.figure("B"+componentnames[c])
139 X = np.linspace(xmin, xmax, xsize)
140 T = np.linspace(timesteps[0], timesteps[-1], len(timesteps))
141 vmax = np.amax(abs(B[2:,:,c]))
142 im = plt.pcolormesh(X/ri, T*Wci, np.real(B[:,:,c]), shading="gouraud", vmin=-vmax, vmax=vmax)
143 plt.colorbar(im, label="B_{"+componentnames[c]+"} / T")
144 plt.xlabel("x / r_i")
145 plt.ylabel("t * W_ci")
146 plt.tight_layout()
147 plt.savefig(dirname+"/B"+componentnames[c]+".png")
148 plt.close()
149 pbar.update()
150
151 # plot k-omega power
152 plt.figure("kB"+componentnames[c])
153 kB = np.fft.fftshift(np.fft.fft2(B[:,:,c]*window))
154 w = 2.*np.pi*np.fft.fftshift(np.fft.fftfreq(tsize, d=dtout))
155 kx = 2.*np.pi*np.fft.fftshift(np.fft.fftfreq(xsize, d=dx))
156 kleft = 1./SI.c * np.sqrt(w**2 - wpe**2/(1.+Wce/w) - wpi**2/(1.-Wci/w))
157 kright = 1./SI.c * np.sqrt(w**2 - wpe**2/(1.-Wce/w) - wpi**2/(1.+Wci/w))
158 #kleft = w/SI.c * np.sqrt(1. - (wpe**2+wpi**2)/((1.+Wce)*(1.-Wci)))
159 #kright = w/SI.c * np.sqrt(1. - (wpe**2+wpi**2)/((1.-Wce)*(1.+Wci)))
160
161 powerB = kB.real**2 + kB.imag**2
162
163 vmax = np.ceil(np.log10(np.amax(powerB)))
164 vmin = vmax - 7
165
166 im = plt.pcolormesh(kx*ri, w/Wci, np.log10(powerB), shading='gouraud', vmin=vmin, vmax=vmax)
167 plt.colorbar(im, label="log |~B_{"+componentnames[c]+"}|^2")
168 plt.plot( kleft*ri, w/Wci, color="C0", linestyle=":", label="L")
169 plt.plot(-kleft*ri, w/Wci, color="C0", linestyle=":")
170 plt.plot( kright*ri, w/Wci, color="C1", linestyle=":", label="R")
171 plt.plot(-kright*ri, w/Wci, color="C1", linestyle=":")
172 plt.plot( kx*ri, abs(vA*kx/Wci), color="C2", linestyle=":", label="vA")
173 plt.plot( kx*ri, abs(vthi*kx/Wci), color="C3", linestyle=":", label="vthi")
174 plt.axhline(Wci/Wci, color="C4", linewidth=0.5, label="W_ci")
175 plt.xlabel("k_x r_i")
176 plt.ylabel("w / Wci")
177 #plt.xlim(-np.pi/ri*ri, np.pi/ri*ri)
178 #plt.ylim( 0., 3.*Wci/Wci)
179 plt.xlim(-0.2, 0.2)
180 plt.ylim( 0.0, 1.2)
181 plt.legend()
182 plt.tight_layout()
183 plt.savefig(dirname+"/kB"+componentnames[c]+".png")
184 plt.close()
185 pbar.update()
186
187 # plot t-k power
188 plt.figure("sB"+componentnames[c])
189 sB = np.fft.fftshift(np.fft.fft(B[:,:,c]*window, axis=1), axes=1) # compute the fft only over the x->kx direction
190 spowerB = sB.real**2 + sB.imag**2
191 mask = kx>=0.
192 im = plt.pcolormesh(T*Wci, kx[mask]*ri, np.log10(spowerB[:,mask].T), shading='gouraud')
193 plt.colorbar(im, label="log |~B_{"+componentnames[c]+"}|^2")
194 plt.xlabel("t * W_ci")
195 plt.ylabel("k_x r_i")
196 plt.tight_layout()
197 plt.savefig(dirname+"/sB"+componentnames[c]+".png")
198 plt.close()
199 pbar.update()
200
static ARCH_HOSTDEV VecSimple< T > abs(const VecSimple< T > &l)