aboutsummaryrefslogtreecommitdiff
path: root/Examples/Tests/langmuir/analysis_2d.py
diff options
context:
space:
mode:
Diffstat (limited to 'Examples/Tests/langmuir/analysis_2d.py')
-rwxr-xr-xExamples/Tests/langmuir/analysis_2d.py140
1 files changed, 140 insertions, 0 deletions
diff --git a/Examples/Tests/langmuir/analysis_2d.py b/Examples/Tests/langmuir/analysis_2d.py
new file mode 100755
index 000000000..e137d5022
--- /dev/null
+++ b/Examples/Tests/langmuir/analysis_2d.py
@@ -0,0 +1,140 @@
+#!/usr/bin/env python3
+
+# Copyright 2019 Jean-Luc Vay, Maxence Thevenet, Remi Lehe
+#
+#
+# This file is part of WarpX.
+#
+# License: BSD-3-Clause-LBNL
+#
+# This is a script that analyses the simulation results from
+# the script `inputs.multi.rt`. This simulates a 3D periodic plasma wave.
+# The electric field in the simulation is given (in theory) by:
+# $$ E_x = \epsilon \,\frac{m_e c^2 k_x}{q_e}\sin(k_x x)\cos(k_y y)\cos(k_z z)\sin( \omega_p t)$$
+# $$ E_y = \epsilon \,\frac{m_e c^2 k_y}{q_e}\cos(k_x x)\sin(k_y y)\cos(k_z z)\sin( \omega_p t)$$
+# $$ E_z = \epsilon \,\frac{m_e c^2 k_z}{q_e}\cos(k_x x)\cos(k_y y)\sin(k_z z)\sin( \omega_p t)$$
+import os
+import re
+import sys
+
+import matplotlib.pyplot as plt
+from mpl_toolkits.axes_grid1.axes_divider import make_axes_locatable
+import yt
+
+yt.funcs.mylog.setLevel(50)
+
+import numpy as np
+from scipy.constants import c, e, epsilon_0, m_e
+
+sys.path.insert(1, '../../../../warpx/Regression/Checksum/')
+import checksumAPI
+
+# this will be the name of the plot file
+fn = sys.argv[1]
+
+# Parse test name and check if current correction (psatd.current_correction=1) is applied
+current_correction = True if re.search( 'current_correction', fn ) else False
+
+# Parse test name and check if Vay current deposition (algo.current_deposition=vay) is used
+vay_deposition = True if re.search( 'Vay_deposition', fn ) else False
+
+# Parameters (these parameters must match the parameters in `inputs.multi.rt`)
+epsilon = 0.01
+n = 4.e24
+n_osc_x = 2
+n_osc_z = 2
+xmin = -20e-6; xmax = 20.e-6; Nx = 128
+zmin = -20e-6; zmax = 20.e-6; Nz = 128
+
+# Wave vector of the wave
+kx = 2.*np.pi*n_osc_x/(xmax-xmin)
+kz = 2.*np.pi*n_osc_z/(zmax-zmin)
+# Plasma frequency
+wp = np.sqrt((n*e**2)/(m_e*epsilon_0))
+
+k = {'Ex':kx, 'Ez':kz}
+cos = {'Ex': (0,1,1), 'Ez':(1,1,0)}
+
+def get_contribution( is_cos, k ):
+ du = (xmax-xmin)/Nx
+ u = xmin + du*( 0.5 + np.arange(Nx) )
+ if is_cos == 1:
+ return( np.cos(k*u) )
+ else:
+ return( np.sin(k*u) )
+
+def get_theoretical_field( field, t ):
+ amplitude = epsilon * (m_e*c**2*k[field])/e * np.sin(wp*t)
+ cos_flag = cos[field]
+ x_contribution = get_contribution( cos_flag[0], kx )
+ z_contribution = get_contribution( cos_flag[2], kz )
+
+ E = amplitude * x_contribution[:, np.newaxis ] \
+ * z_contribution[np.newaxis, :]
+
+ return( E )
+
+# Read the file
+ds = yt.load(fn)
+t0 = ds.current_time.to_value()
+data = ds.covering_grid(level = 0, left_edge = ds.domain_left_edge, dims = ds.domain_dimensions)
+edge = np.array([(ds.domain_left_edge[1]).item(), (ds.domain_right_edge[1]).item(), \
+ (ds.domain_left_edge[0]).item(), (ds.domain_right_edge[0]).item()])
+
+# Check the validity of the fields
+error_rel = 0
+for field in ['Ex', 'Ez']:
+ E_sim = data[('mesh',field)].to_ndarray()[:,:,0]
+ E_th = get_theoretical_field(field, t0)
+ max_error = abs(E_sim-E_th).max()/abs(E_th).max()
+ print('%s: Max error: %.2e' %(field,max_error))
+ error_rel = max( error_rel, max_error )
+
+# Plot the last field from the loop (Ez at iteration 40)
+fig, (ax1, ax2) = plt.subplots(1, 2, dpi = 100)
+# First plot
+vmin = E_sim.min()
+vmax = E_sim.max()
+cax1 = make_axes_locatable(ax1).append_axes('right', size = '5%', pad = '5%')
+im1 = ax1.imshow(E_sim, origin = 'lower', extent = edge, vmin = vmin, vmax = vmax)
+cb1 = fig.colorbar(im1, cax = cax1)
+ax1.set_xlabel(r'$z$')
+ax1.set_ylabel(r'$x$')
+ax1.set_title(r'$E_z$ (sim)')
+# Second plot
+vmin = E_th.min()
+vmax = E_th.max()
+cax2 = make_axes_locatable(ax2).append_axes('right', size = '5%', pad = '5%')
+im2 = ax2.imshow(E_th, origin = 'lower', extent = edge, vmin = vmin, vmax = vmax)
+cb2 = fig.colorbar(im2, cax = cax2)
+ax2.set_xlabel(r'$z$')
+ax2.set_ylabel(r'$x$')
+ax2.set_title(r'$E_z$ (theory)')
+# Save figure
+fig.tight_layout()
+fig.savefig('Langmuir_multi_2d_analysis.png', dpi = 200)
+
+tolerance_rel = 0.05
+
+print("error_rel : " + str(error_rel))
+print("tolerance_rel: " + str(tolerance_rel))
+
+assert( error_rel < tolerance_rel )
+
+# Check relative L-infinity spatial norm of rho/epsilon_0 - div(E)
+# with current correction (and periodic single box option) or with Vay current deposition
+if current_correction:
+ tolerance = 1e-9
+elif vay_deposition:
+ tolerance = 1e-3
+if current_correction or vay_deposition:
+ rho = data[('boxlib','rho')].to_ndarray()
+ divE = data[('boxlib','divE')].to_ndarray()
+ error_rel = np.amax( np.abs( divE - rho/epsilon_0 ) ) / np.amax( np.abs( rho/epsilon_0 ) )
+ print("Check charge conservation:")
+ print("error_rel = {}".format(error_rel))
+ print("tolerance = {}".format(tolerance))
+ assert( error_rel < tolerance )
+
+test_name = os.path.split(os.getcwd())[1]
+checksumAPI.evaluate_checksum(test_name, fn)