def get_a0( tseries: OpenPMDTimeSeries, t: Optional[float] = None, it: Optional[int] = None, coord="x", m="all", slicing_dir="y", theta=0.0, lambda0=0.8e-6, ) -> Tuple[float, float, float, float]: """ Compute z₀, a₀, w₀, cτ. :param tseries: whole simulation time series :param t: time (in seconds) at which to obtain the data :param it: time step at which to obtain the data :param coord: which component of the field to extract :param m: 'all' for extracting the sum of all the modes :param slicing_dir: the direction along which to slice the data eg., 'x', 'y' or 'z' :param theta: the angle of the plane of observation, with respect to the 'x' axis :param lambda0: laser wavelength (meters) :return: z₀, a₀, w₀, cτ """ # get E_x field in V/m electric_field_x, info_electric_field_x = tseries.get_field( field="E", coord=coord, t=t, iteration=it, m=m, theta=theta, slicing_dir=slicing_dir, ) # normalized vector potential e0 = electric_field_amplitude_norm(lambda0=lambda0) a0 = electric_field_x / e0 # get pulse envelope envelope = np.abs(hilbert(a0, axis=1)) envelope_z = envelope[envelope.shape[0] // 2, :] a0_max = np.amax(envelope_z) # index of peak z_idx = np.argmax(envelope_z) # pulse peak position z0 = info_electric_field_x.z[z_idx] # FWHM perpendicular size of beam, proportional to w0 fwhm_a0_w0 = (np.sum(np.greater_equal(envelope[:, z_idx], a0_max / 2)) * info_electric_field_x.dr) # FWHM longitudinal size of the beam, proportional to ctau fwhm_a0_ctau = (np.sum(np.greater_equal(envelope_z, a0_max / 2)) * info_electric_field_x.dz) return z0, a0_max, fwhm_a0_w0, fwhm_a0_ctau
def field_snapshot( tseries: OpenPMDTimeSeries, it: int, field_name: str, normalization_factor=1, coord: Optional[str] = None, m="all", theta=0.0, chop: Optional[List[float]] = None, path="./", **kwargs, ) -> None: """ Plot the ``field_name`` field from ``tseries`` at step ``iter``. :param path: path to output file :param tseries: whole simulation time series :param it: time step in the simulation :param field_name: which field to extract, eg. 'rho', 'E', 'B' or 'J' :param normalization_factor: normalization factor for the extracted field :param coord: which component of the field to extract, eg. 'r', 't' or 'z' :param m: 'all' for extracting the sum of all the azimuthal modes :param theta: the angle of the plane of observation, with respect to the 'x' axis :param chop: adjusting extent of simulation box plot :param kwargs: extra plotting arguments, eg. labels, data limits etc. :return: saves field plot image to disk """ if chop is None: # how much to cut out from simulation domain chop = [40, -20, 15, -15] # CHANGEME field, info = tseries.get_field(field=field_name, coord=coord, iteration=it, m=m, theta=theta) field *= normalization_factor plot = sliceplots.Plot2D( arr2d=field, h_axis=info.z * 1e6, v_axis=info.r * 1e6, xlabel=r"${} \;(\mu m)$".format(info.axes[1]), ylabel=r"${} \;(\mu m)$".format(info.axes[0]), extent=( info.zmin * 1e6 + chop[0], info.zmax * 1e6 + chop[1], info.rmin * 1e6 + chop[2], info.rmax * 1e6 + chop[3], ), cbar=True, text=f"iteration {it}", **kwargs, ) filename = os.path.join(path, f"{field_name}{it:06d}.png") plot.canvas.print_figure(filename)
def check_identical_fields( folder1, folder2 ): ts1 = OpenPMDTimeSeries( folder1 ) ts2 = OpenPMDTimeSeries( folder2 ) # Check the vector fields for field, coord in [("J", "z"), ("E","r"), ("E","z"), ("B","t")]: print("Checking %s%s" %(field, coord)) field1, info = ts1.get_field(field, coord, iteration=0) field2, info = ts2.get_field(field, coord, iteration=0) # For 0 fields, do not use allclose if abs(field1).max() == 0: assert abs(field2).max() == 0 else: assert np.allclose( field1/abs(field1).max(), field2/abs(field2).max() ) # Check the rho field print("Checking rho") field1, info = ts1.get_field("rho", iteration=0) field2, info = ts2.get_field("rho", iteration=0) assert np.allclose( field1/abs(field1).max(), field2/abs(field2).max() )
class Backend: ''' Use openPMD-viewer as the backend reader to read openPMD files ''' def __init__(self, filename): ''' Constructor: store the dataset object ''' self.dataset = OpenPMDTimeSeries(filename) def fields_list(self): ''' Return the list of fields defined on the grid ''' return self.dataset.avail_fields def species_list(self): ''' Return the list of species in the dataset ''' return self.dataset.avail_species def n_levels(self): ''' Return the number of MR levels in the dataset ''' return 1 def get_field_checksum(self, lev, field, test_name): ''' Calculate the checksum for a given field at a given level in the dataset ''' Q = self.dataset.get_field(field=field, iteration=self.dataset.iterations[-1])[0] return np.sum(np.abs(Q)) def get_species_attributes(self, species): ''' Return the list of attributes for a given species in the dataset ''' return self.dataset.avail_record_components[species] def get_species_checksum(self, species, attribute): ''' Calculate the checksum for a given attribute of a given species in the dataset ''' Q = self.dataset.get_particle(var_list=[attribute], species=species, iteration=self.dataset.iterations[-1]) # JSON complains with numpy integers, so if the quantity is a np.int64, convert to int checksum = np.sum(np.abs(Q)) if type(checksum) in [np.int64, np.uint64]: return int(checksum) return checksum
def check_theory_gaussian(): """ Check that the transverse E and B field are close to the high-gamma theory for a gaussian bunch """ ts = OpenPMDTimeSeries( os.path.join(temporary_dir, 'diags_serial/hdf5/') ) Ex, info = ts.get_field( 'E', 'x', iteration=0 ) By, info = ts.get_field( 'B', 'y', iteration=0 ) r, z = np.meshgrid( info.r, info.z, indexing='ij' ) # High-gamma theory for Gaussian bunch Eth = -Q/(2*np.pi)**1.5/sig_z/epsilon_0/r * \ (1 - np.exp(-0.5*r**2/sig_r**2)) * \ np.exp( -0.5*(z-zf)**2/sig_z**2) Bth = Eth/c # Check that the fields agree assert np.allclose( Ex, Eth, atol=0.1*Eth.max() ) assert np.allclose( By, Bth, atol=0.1*Bth.max() )
default='diags/hdf5', help='Path to the directory containing output files') args = parser.parse_args() ts = OpenPMDTimeSeries(args.output_dir) if args.norm_units: kp = 1. ne = 1. q_e = 1. else: kp = 1./10.e-6 ne = scc.c**2 / scc.e**2 * scc.m_e * scc.epsilon_0 * kp**2 q_e = scc.e rho_along_z, rho_meta = ts.get_field(field='rho', iteration=ts.iterations[-1], slice_across=['x','y'], slice_relative_position=[0,0]) zeta_array = rho_meta.z dzeta = rho_meta.dz nz = len(rho_meta.z) # generating the array with the beam density nb_array = np.zeros(nz) beam_starting_position = 1 / kp distance_to_start_pos = rho_meta.zmax - beam_starting_position index_beam_head = int(distance_to_start_pos / dzeta) beam_length = 2 / kp beam_length_i = int(beam_length / dzeta) if (args.gaussian_beam): sigma_z = 1.41 / kp peak_density = 0.01*ne nb_array = peak_density*np.sqrt(2*np.pi)*norm.pdf(np.linspace(-nz/2,nz/2,nz)*dzeta/sigma_z)
import matplotlib import sys import numpy as np import math import argparse from openpmd_viewer import OpenPMDTimeSeries parser = argparse.ArgumentParser( description='Script to analyze the equality of two simulations') parser.add_argument('--first', dest='first', required=True) parser.add_argument('--second', dest='second', required=True) args = parser.parse_args() # Replace the string below, to point to your data tss = OpenPMDTimeSeries(args.first) tsp = OpenPMDTimeSeries(args.second) iteration = 0 for field in ['Bx', 'By', 'Ez', 'ExmBy', 'EypBx']: Fs, ms = tss.get_field(iteration=iteration, field=field) Fp, mp = tsp.get_field(iteration=iteration, field=field) error = np.sum((Fp-Fs)**2) / np.sum(Fs**2) print(field, 'error = np.sum((Fp-Fs)**2) / np.sum(Fs**2) = ' +str(error)) assert(error<0.006)
# full IO and from a simulation with only slice IO import matplotlib.pyplot as plt import scipy.constants as scc import matplotlib import sys import numpy as np import math import argparse from openpmd_viewer import OpenPMDTimeSeries do_plot = False field = 'Ez' ts1 = OpenPMDTimeSeries('full_io') F_full = ts1.get_field(field=field, iteration=ts1.iterations[-1])[0] F_full = np.swapaxes(F_full, 0, 2) F_full_xz = (F_full[:, F_full.shape[1] // 2, :].squeeze() + F_full[:, F_full.shape[1] // 2 - 1, :].squeeze()) / 2. F_full_yz = (F_full[F_full.shape[0] // 2, :, :].squeeze() + F_full[F_full.shape[0] // 2 - 1, :, :].squeeze()) / 2. ts2 = OpenPMDTimeSeries('slice_io_xz') F_slice_xz = ts2.get_field(field=field, iteration=ts2.iterations[-1])[0].transpose() ts3 = OpenPMDTimeSeries('slice_io_yz') F_slice_yz = ts3.get_field(field=field, iteration=ts3.iterations[-1])[0].transpose() if do_plot:
def run_cpu_gpu_deposition(show=False, particle_shape='cubic'): # Skip this test if cuda is not installed if not cuda_installed: return # Perform deposition for a few timesteps, with both the CPU and GPU for hardware in ['cpu', 'gpu']: if hardware == 'cpu': use_cuda = False elif hardware == 'gpu': use_cuda = True # Initialize the simulation object sim = Simulation(Nz, zmax, Nr, rmax, Nm, dt, zmin=zmin, use_cuda=use_cuda, particle_shape=particle_shape) sim.ptcl = [] # Add an electron bunch (set the random seed first) np.random.seed(0) add_elec_bunch_gaussian(sim, sig_r, sig_z, n_emit, gamma0, sig_gamma, Q, N) # Add a field diagnostic sim.diags = [ FieldDiagnostic(diag_period, sim.fld, fieldtypes=['rho', 'J'], comm=sim.comm, write_dir=os.path.join('tests', hardware)) ] ### Run the simulation sim.step(N_step) # Check that the results are identical ts_cpu = OpenPMDTimeSeries('tests/cpu/hdf5') ts_gpu = OpenPMDTimeSeries('tests/gpu/hdf5') for iteration in ts_cpu.iterations: for field, coord in [('rho', ''), ('J', 'x'), ('J', 'z')]: # Jy is not tested because it is zero print('Testing %s at iteration %d' % (field + coord, iteration)) F_cpu, info = ts_cpu.get_field(field, coord, iteration=iteration) F_gpu, info = ts_gpu.get_field(field, coord, iteration=iteration) tolerance = 1.e-13 * (abs(F_cpu).max() + abs(F_gpu).max()) if not show: assert np.allclose(F_cpu, F_gpu, atol=tolerance) else: if not np.allclose(F_cpu, F_gpu, atol=tolerance): plot_difference(field, coord, iteration, F_cpu, F_gpu, info) # Remove the files used shutil.rmtree('tests/cpu') shutil.rmtree('tests/gpu')
rho0 = -scc.e * dens c = scc.c mu_0 = scc.mu_0 eps_0 = scc.epsilon_0 # Radius of the can beam R = 10.e-6 x_beam_mid = 2 y_beam_mid = -1 x_domain_len = 8 y_domain_len = 8 # Load HiPACE++ data for By in SI units Bx_sim, Bx_meta = ts.get_field( field='Bx', iteration=0, slice_across=['x', 'z'], slice_relative_position=[2 * x_beam_mid / x_domain_len, 0]) By_sim, By_meta = ts.get_field( field='By', iteration=0, slice_across=['y', 'z'], slice_relative_position=[2 * y_beam_mid / y_domain_len, 0]) jz_sim = ts.get_field( field='jz', iteration=0, slice_across=['y', 'z'], slice_relative_position=[2 * y_beam_mid / y_domain_len, 0])[0] rho_sim = ts.get_field( field='rho', iteration=0,
eps_0 = 1. R = 1. else: # Density of the can beam dens = 2.8239587008591567e23 # at this density, 1/kp = 10um, allowing for an easy comparison with normalized units # Define array for transverse coordinate and theory for By and Bx jz0 = - scc.e * scc.c * dens rho0 = - scc.e * dens c = scc.c mu_0 = scc.mu_0 eps_0 = scc.epsilon_0 # Radius of the can beam R = 10.e-6 # Load HiPACE++ data for By in SI units Bx_sim, Bx_meta = ts.get_field(field='Bx', iteration=0, slice_across=['x','z'], slice_relative_position=[0,0]) By_sim, By_meta = ts.get_field(field='By', iteration=0, slice_across=['y','z'], slice_relative_position=[0,0]) jz_sim = ts.get_field(field='jz', iteration=0, slice_across=['y','z'], slice_relative_position=[0,0])[0] rho_sim = ts.get_field(field='rho', iteration=0, slice_across=['y','z'], slice_relative_position=[0,0])[0] Ex_sim = ts.get_field(field='ExmBy', iteration=0, slice_across=['y','z'], slice_relative_position=[0,0])[0] + c*By_sim Ey_sim = ts.get_field(field='EypBx', iteration=0, slice_across=['x','z'], slice_relative_position=[0,0])[0] - c*Bx_sim y = Bx_meta.y x = By_meta.x By_th = mu_0 * jz0 * x / 2. By_th[abs(x)>=R] = mu_0 * jz0 * R**2/(2*x[abs(x)>R]) Ex_th = rho0 / eps_0 * x / 2. Ex_th[abs(x)>=R] = rho0 / eps_0 * R**2/(2*x[abs(x)>R]) Bx_th = -mu_0 * jz0 * y / 2. Bx_th[abs(y)>=R] = -mu_0 * jz0 * R**2/(2*y[abs(y)>R])
args = parser.parse_args() ts_norm = OpenPMDTimeSeries(args.norm_data) ts_si = OpenPMDTimeSeries(args.si_data) ts_si_fixed_weight = OpenPMDTimeSeries(args.si_fixed_weight_data) elec_density = 2.8239587008591567e23 # [1/m^3] # calculation of the plasma frequency omega_p = np.sqrt(elec_density * (scc.e**2) / (scc.epsilon_0 * scc.m_e)) E_0 = omega_p * scc.m_e * scc.c / scc.e kp = omega_p / scc.c # 1./10.e-6 # Load HiPACE++ data for Ez in both normalized and SI units Ez_along_z_norm, meta_norm = ts_norm.get_field(field='Ez', iteration=1, slice_across=['x', 'y'], slice_relative_position=[0, 0]) Ez_along_z_si, meta_si = ts_si.get_field(field='Ez', iteration=1, slice_across=['x', 'y'], slice_relative_position=[0, 0]) Ez_along_z_si_fixed_w, meta = ts_si_fixed_weight.get_field( field='Ez', iteration=1, slice_across=['x', 'y'], slice_relative_position=[0, 0]) zeta_norm = meta_norm.z zeta_si = meta_si.z if args.do_plot: fig, ax = plt.subplots()
# # This file is part of HiPACE++. # # Authors: MaxThevenet, Severin Diederichs # License: BSD-3-Clause-LBNL # This script calculates the sum of jz. # The beam current and the grid current should cancel each other. import argparse import numpy as np from openpmd_viewer import OpenPMDTimeSeries parser = argparse.ArgumentParser(description='Script to analyze the correctness of the beam in vacuum') parser.add_argument('--output-dir', dest='output_dir', default='diags/hdf5', help='Path to the directory containing output files') args = parser.parse_args() ts = OpenPMDTimeSeries(args.output_dir) # Load Hipace data for jz jz_sim, jz_info = ts.get_field(field='jz', iteration=1) # Assert that the grid current and the beam current cancel each other error_jz = np.sum( (jz_sim)**2) print("sum of jz**2: " + str(error_jz) + " (tolerance = 3e-3)") assert(error_jz < 3e-3)
import scipy.constants as scc import matplotlib import sys import numpy as np import math import argparse from openpmd_viewer import OpenPMDTimeSeries fields = ['Ez', 'ExmBy', 'EypBx'] ts1 = OpenPMDTimeSeries('fine_io') ts2 = OpenPMDTimeSeries('coarse_io') for field in fields: F_full = ts1.get_field(field=field, iteration=ts1.iterations[-1])[0] F_full_coarse = (F_full[2::5,1::4,1::3] + F_full[2::5,2::4,1::3])/2 F_coarse = ts2.get_field(field=field, iteration=ts2.iterations[-1])[0] print("F_full.shape =", F_full.shape) print("F_full_coarse.shape =", F_full_coarse.shape) print("F_coarse.shape =", F_coarse.shape) error = np.max(np.abs(F_coarse-F_full_coarse)) / np.max(np.abs(F_full_coarse)) print("error =", error) assert(error < 3.e-14) del ts1 del ts2
default='diags/hdf5', help='Path to the directory containing output files') args = parser.parse_args() ts_ref = OpenPMDTimeSeries('./REF_diags/hdf5/') ts = OpenPMDTimeSeries(args.output_dir) if do_plot: field = 'Bx' step = 20 ms = .1 plt.figure() F, meta = ts_ref.get_field(field=field, iteration=ts_ref.iterations[-1]) xp, yp, zp, uzp, wp = ts_ref.get_particle( species='beam', iteration=ts_ref.iterations[-1], var_list=['x', 'y', 'z', 'uz', 'w']) plt.subplot(221) plt.title('ref xz') extent = [meta.zmin, meta.zmax, meta.xmin, meta.xmax] plt.imshow(F[:, F.shape[1] // 2, :], extent=extent, aspect='auto', origin='lower', interpolation='nearest') plt.plot(zp[::step], xp[::step], '.', ms=ms)