import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import os
os.chdir('..')
import proppy as pp
nr_particles = 1*10**4
source_pos = np.array([0.0, 0.0, 0.0], dtype=np.float32)
energy = 10**12 # eV
sphere = 10**14 # [m]
def point_source(nr_particles=nr_particles):
return pp.PointSourceIsotropic(energy, source_pos, nr_particles)
def sphere_source(nr_particles=nr_particles):
radius = sphere
source = pp.SphereSourceIsotropic(energy, source_pos, nr_particles, radius)
return source
step_size = 1.0*10**12
def propagator(nr_steps=1*10**4, step_size=step_size, diff=1.5*10**21):
speed_of_light = 3*10**8 # [m/s]
diffusion_coefficient = diff # [m^2/s]
mfp_iso = 3*diffusion_coefficient/speed_of_light
mfp = np.array([mfp_iso, mfp_iso, mfp_iso], dtype=np.float32) # [m]
prop = pp.IsotropicPropagator(mfp, nr_steps, step_size)
return prop
def time_evolution_observer(nr_steps):
substeps = [False, False, True] # observe only steps (no substeps)
min_step = 1
max_step = nr_steps
nr_obs_steps = 30
observer = pp.TimeEvolutionObserverLog(min_step, max_step, nr_obs_steps, substeps)
return observer
def sphere_observer(deactivate=True):
substeps = [False, False, True] # observe only steps (no substeps)
spheres = [sphere]
return pp.SphericalObserver(substeps, spheres, on_detection_deactivate=deactivate)
def run_simulation(source, observer, propagator, file_name):
sim = pp.Simulation()
sim.add_source(source)
sim.add_propagator(propagator)
sim.add_observer(observer)
%time sim.run_simulation()
sim.save_data(file_name)
def analyze(file_name, diff, nr_particles=nr_particles):
plt.figure(figsize=(5,3))
df = pd.read_pickle(file_name+'.pkl')
bins = 20
trajectory_lengths = df['d']
d = trajectory_lengths/10**14
hist, bins = np.histogram(d, bins=bins)
logbins = np.logspace(np.log10(min(d)),np.log10(max(d)),len(bins))
plt.hist(d, bins=logbins, alpha=0.5, label='$\kappa =$ {:.1e}m$^2$/s'.format(diff))
plt.axvline(x=1, color='k', ls='--', label='plasmoid radius')
plt.title('total # particles = {:.0e}'.format(nr_particles))
plt.xlabel('D/{:.0e}m'.format(sphere))
plt.ylabel('# particles')
plt.loglog()
plt.legend()
plt.show()
plt.figure(figsize=(5,3))
bins = 50
trajectory_lengths = df['d']
d = trajectory_lengths/10**14
hist, bins = np.histogram(d, bins=bins)
linbins = np.linspace((min(d)),(max(d)),len(bins))
plt.hist(d, bins=linbins, alpha=0.5, label='$\kappa =$ {:.1e}m$^2$/s'.format(diff))
plt.axvline(x=1, color='k', ls='--', label='plasmoid radius')
plt.title('total # particles = {:.0e}'.format(nr_particles))
plt.xlabel('D/{:.0e}m'.format(sphere))
plt.ylabel('# particles')
plt.legend()
plt.show()
All particles start in the center with isotropic directions (i,i,i), with i=-1 or i =1. Observe all particles n times (with log spacing time intervalls). At each observed time, the running diffusion coefficients (1. plot) and the particle distribution (2. and 3. plots) can be plottet. The latter show that particles start in the center and propagate in positive or negative direction (2. plot) and diffuse after some time (plateau in 1. plot) and Gaus-distribution in the 3. plot.
diff = 10**21 #[m^2/s]
file_0 = 'data/data_tut_5_point_time_kappa'
nr_steps = 3*10**3
run_simulation(point_source(nr_particles=10**3), time_evolution_observer(nr_steps=nr_steps), propagator(step_size=step_size, diff=diff, nr_steps=nr_steps), file_0)
df = pd.read_pickle(file_0+'.pkl')
sta = pp.Statistics(df)
df_kappas = sta.plot_diffusion_coefficients(n_points_plateau=5)
steps = sorted(list(set(df['i'])))
print('\n-----------------------------------')
print('particle distribution after '+str(int(steps[0]))+'. step')
sta.plot_distribution('x', steps[0], 50, None)
print('\n-----------------------------------')
print('particle distribution after last step')
sta.plot_distribution('x', steps[-1], 50, None)
df
Observer initialized Propagator initialized start simulation CPU times: user 6.18 s, sys: 14 ms, total: 6.2 s Wall time: 6.21 s saved data file data/data_tut_5_point_time_kappa.pkl init statistics plotting class
diffusion coefficients computed between 9.94e+14m and 3.00e+15m with 5 data points kappa_{xx}: 9.95e+20 m²/s +- 1.91e+19 m²/s kappa_{yy}: 9.06e+20 m²/s +- 1.53e+19 m²/s kappa_{zz}: 9.43e+20 m²/s +- 1.01e+19 m²/s ----------------------------------- particle distribution after 1. step
----------------------------------- particle distribution after last step
id | i | d | x | y | z | phi | pitch_angle | radius | sub_step | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0.0 | 1.0 | 1.000000e+12 | -5.773503e+11 | 5.773503e+11 | -5.773503e+11 | 2.228828 | 1.545519 | -1.0 | 2.0 |
1 | 0.0 | 2.0 | 2.000000e+12 | -1.154701e+12 | 1.154701e+12 | -1.154701e+12 | 2.228828 | 1.545519 | -1.0 | 2.0 |
2 | 0.0 | 3.0 | 3.000000e+12 | -1.732051e+12 | 5.773503e+11 | -1.732051e+12 | 2.228828 | 1.545519 | -1.0 | 2.0 |
3 | 0.0 | 5.0 | 5.000000e+12 | -2.886751e+12 | -5.773503e+11 | -2.886751e+12 | 2.228828 | 1.545519 | -1.0 | 2.0 |
4 | 0.0 | 6.0 | 6.000000e+12 | -2.309401e+12 | -1.154701e+12 | -3.464101e+12 | 2.228828 | 1.545519 | -1.0 | 2.0 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
26995 | 999.0 | 994.0 | 9.940000e+14 | 1.558852e+14 | -2.193930e+13 | 9.353090e+13 | 1.567741 | 2.267743 | -1.0 | 2.0 |
26996 | 999.0 | 1310.0 | 1.310000e+15 | 6.004442e+13 | 9.237605e+12 | 1.316363e+14 | 1.567741 | 2.267743 | -1.0 | 2.0 |
26997 | 999.0 | 1727.0 | 1.727000e+15 | -9.814945e+12 | 3.637307e+13 | 1.195118e+14 | 1.567741 | 2.267743 | -1.0 | 2.0 |
26998 | 999.0 | 2276.0 | 2.276000e+15 | -1.223986e+14 | 5.080682e+13 | 1.408740e+14 | 1.567741 | 2.267743 | -1.0 | 2.0 |
26999 | 999.0 | 3000.0 | 3.000000e+15 | -1.639681e+14 | -1.847520e+13 | 1.812888e+14 | 1.567741 | 2.267743 | -1.0 | 2.0 |
27000 rows × 10 columns
All particles start at a random position within a 3d sphere with isotropic directions (i,i,i), with i=-1 or i =1. Here, we show the initial particle distribution (after 1. step) and the final distribution. It shifts towards a Gaussian distribution over time. Effect is better visible with higher statistics.
file_1 = 'data/data_tut_5_source_time_distr'
nr_steps=3*10**3
run_simulation(sphere_source(nr_particles=10**3), time_evolution_observer(nr_steps=nr_steps), propagator(step_size=step_size, diff=diff, nr_steps=nr_steps), file_1)
df = pd.read_pickle(file_1+'.pkl')
sta = pp.Statistics(df)
steps = sorted(list(set(df['i'])))
print('\n-----------------------------------')
print('particle distribution after '+str(int(steps[0]))+'. step')
sta.plot_distribution('x', steps[0], 50, None)
print('\n-----------------------------------')
print('particle distribution after last step')
sta.plot_distribution('x', steps[-1], 50, None)
Observer initialized Propagator initialized start simulation CPU times: user 6.52 s, sys: 514 ms, total: 7.03 s Wall time: 7.28 s saved data file data/data_tut_5_source_time_distr.pkl init statistics plotting class ----------------------------------- particle distribution after 1. step
----------------------------------- particle distribution after last step
All particles start in the center with isotropic directions (i,i,i), with i=-1 or i =1. Observe particles only when they cross the spherical observer. Take observed particles out of the simulation, because they are treated as escaped. The plots show ne number of escaping particles per bin as a function of the travelled distance in plasmoid radii.
file_2 = 'data/data_tut_5_point_sphere_hist'
run_simulation(point_source(), sphere_observer(), propagator(step_size=step_size, diff=diff, nr_steps=1*10**4), file_2)
analyze(file_2, diff)
Observer initialized Propagator initialized start simulation CPU times: user 9.36 s, sys: 30.6 ms, total: 9.39 s Wall time: 9.41 s saved data file data/data_tut_5_point_sphere_hist.pkl
Same as above but with homogeneouse particle distribution within complete plasmoid.
file_3 = 'data/data_tut_5_sphere_sphere'
run_simulation(sphere_source(), sphere_observer(), propagator(step_size=step_size, diff=diff, nr_steps=1*10**4), file_3)
analyze(file_3, diff)
Observer initialized Propagator initialized start simulation CPU times: user 4.17 s, sys: 402 µs, total: 4.17 s Wall time: 4.17 s saved data file data/data_tut_5_sphere_sphere.pkl
Same as example "Point source with spherical observer" with one change: particles are not dectivated after observation and can therefore be observed several times.
file_4 = 'data/data_tut_5_sphere_sphere_active'
run_simulation(point_source(nr_particles=5), sphere_observer(deactivate=False), propagator(step_size=step_size, diff=diff, nr_steps=1*10**4), file_4)
analyze(file_4, diff, nr_particles=5)
Observer initialized Propagator initialized start simulation CPU times: user 213 ms, sys: 16.1 ms, total: 229 ms Wall time: 228 ms saved data file data/data_tut_5_sphere_sphere_active.pkl
Comparison between a point source and a sphere source. Note that particles need trajectory legths that are larger than the plasmoid radius to escape with a cantral point source.
colors = ['r', 'dodgerblue']
labels = ['point source', 'spherical source']
bins = 100
logbins = np.logspace(np.log10(step_size/sphere), np.log10(step_size*nr_steps/sphere),bins)
for i, file in enumerate([file_2, file_3]):
df = pd.read_pickle(file+'.pkl')
trajectory_lengths = df['d']
d = trajectory_lengths/sphere
plt.hist(d, bins=logbins, histtype=u'step', edgecolor=colors[i], linewidth=1., facecolor="None", label=labels[i])
plt.axvline(x=step_size/sphere, color='grey', ls='--', label='step length')
plt.axvline(x=1, color='k', ls='--', label='plasmoid radius')
plt.title('total # particles injected = {:.0e}'.format(nr_particles), size=14)
plt.xlabel('$l_\mathrm{traj}$'+' / {:.0e}m'.format(sphere), size=14)
plt.ylabel('# particles', size=14)
plt.loglog()
plt.legend(loc = "upper left")
#plt.savefig('traj_lengths_comparison_rwpropa.pdf')
plt.show()
The issues with the initial bins for the spherical source result is caused by the fixed step size which can't resolve the small scales shown in the log-scaling of the x-axis. See the same result in a lin-lin-plot below.
colors = ['r', 'dodgerblue']
labels = ['point source', 'spherical source']
bins = 100
linbins = np.linspace(step_size/sphere, (step_size*nr_steps/sphere),bins)
for i, file in enumerate([file_2, file_3]):
df = pd.read_pickle(file+'.pkl')
trajectory_lengths = df['d']
d = trajectory_lengths/sphere
plt.hist(d, bins=linbins, histtype=u'step', edgecolor=colors[i], linewidth=1., facecolor="None", label=labels[i])
plt.axvline(x=step_size/sphere, color='grey', ls='--', label='step length')
plt.axvline(x=1, color='k', ls='--', label='plasmoid radius')
plt.title('total # particles injected = {:.0e}'.format(nr_particles), size=14)
plt.xlabel('$l_\mathrm{traj}$'+' / {:.0e}m'.format(sphere), size=14)
plt.ylabel('# particles', size=14)
plt.legend(loc = "upper right")
plt.show()