コード例 #1
0
def init_fields(sim, w, ctau, k0, z0, zf, E0, m=1):
    """
    Imprints the appropriate profile on the fields of the simulation.

    Parameters
    ----------
    sim: Simulation object from fbpic

    w : float
       The initial waist of the laser (in microns)

    ctau : float
       The initial temporal waist of the laser (in microns)

    k0 : flat
       The central wavevector of the laser (in microns^-1)

    z0 : float
       The position of the centroid on the z axis

    zf : float
       The position of the focal plane

    E0 : float
       The initial E0 of the pulse

    m: int, optional
        The mode on which to imprint the profile
        For m = 1 : gaussian profile, linearly polarized beam
        For m = 0 : annular profile, polarized in E_theta
    """
    # Initialize the fields
    a0 = E0 * e / (m_e * c**2 * k0)
    tau = ctau / c
    lambda0 = 2 * np.pi / k0
    # Create the relevant laser profile
    if m == 0:
        # Build a radially-polarized pulse from 2 Laguerre-Gauss profiles
        profile = LaguerreGaussLaser( 0, 1, 0.5*a0, w, tau, z0, zf=zf,
                    lambda0=lambda0, theta_pol=0., theta0=0. ) \
                + LaguerreGaussLaser( 0, 1, 0.5*a0, w, tau, z0, zf=zf,
                    lambda0=lambda0, theta_pol=np.pi/2, theta0=np.pi/2 )
    elif m == 1:
        profile = GaussianLaser(a0=a0,
                                waist=w,
                                tau=tau,
                                lambda0=lambda0,
                                z0=z0,
                                zf=zf)
    elif m == 2:
        profile = LaguerreGaussLaser(0,
                                     1,
                                     a0=a0,
                                     waist=w,
                                     tau=tau,
                                     lambda0=lambda0,
                                     z0=z0,
                                     zf=zf)
    # Add the profiles to the simulation
    add_laser_pulse(sim, profile)
コード例 #2
0
ファイル: simulation.py プロジェクト: EZoni/fbpic
    def add_laser(self, laser, injection_method):
        # Call method of parent class
        PICMI_Simulation.add_laser(self, laser, injection_method)

        # Handle injection method
        assert type(injection_method) == PICMI_LaserAntenna
        # Handle laser profile method
        if type(laser) == PICMI_GaussianLaser:
            assert laser.propagation_direction[0] == 0.
            assert laser.propagation_direction[1] == 0.
            assert (laser.zeta is None) or (laser.zeta == 0)
            assert (laser.beta is None) or (laser.beta == 0)
            phi2_chirp = laser.phi2
            if phi2_chirp is None:
                phi2_chirp = 0
            polarization_angle = np.arctan2(laser.polarization_direction[1],
                                            laser.polarization_direction[0])
            laser_profile = GaussianLaser(a0=laser.a0,
                                          waist=laser.waist,
                                          z0=laser.centroid_position[-1],
                                          zf=laser.focal_position[-1],
                                          tau=laser.duration,
                                          theta_pol=polarization_angle,
                                          phi2_chirp=phi2_chirp)
        else:
            raise ValueError('Unknown laser profile: %s' %
                             type(injection_method))

        # Inject the laser
        add_laser_pulse(self.fbpic_sim,
                        laser_profile,
                        method='antenna',
                        z0_antenna=injection_method.position[-1],
                        gamma_boost=self.gamma_boost)
コード例 #3
0
def test_laser_periodic(show=False):
    """
    Function that is run by py.test, when doing `python setup.py test`
    Test the propagation of a laser in a periodic box.
    """
    # Propagate the pulse in a single step
    dt = zfoc * 1. / c

    # Initialize the simulation object
    sim = Simulation(Nz,
                     zmax,
                     Nr,
                     rmax,
                     Nm,
                     dt,
                     zmin=zmin,
                     boundaries={
                         'z': 'periodic',
                         'r': 'reflective'
                     })

    # Initialize the laser fields
    profile = FewCycleLaser(a0=a0, waist=w0, tau_fwhm=tau_fwhm, z0=0, zf=zfoc)
    add_laser_pulse(sim, profile)

    # Propagate the pulse
    compare_fields(sim.fld.interp[1], sim.time, profile, show)
    sim.step(1)
    compare_fields(sim.fld.interp[1], sim.time, profile, show)
コード例 #4
0
def test_laser_periodic(show=False):
    """
    Function that is run by py.test, when doing `python setup.py test`
    Test the propagation of a laser in a periodic box.
    """
    # Propagate the pulse in a single step
    dt = Lprop * 1. / c

    # Initialize the simulation object
    sim = Simulation(Nz,
                     zmax,
                     Nr,
                     rmax,
                     Nm,
                     dt,
                     n_order=n_order,
                     zmin=zmin,
                     boundaries={
                         'z': 'periodic',
                         'r': 'reflective'
                     })

    # Initialize the laser fields
    profile = FlattenedGaussianLaser(a0=a0,
                                     w0=w0,
                                     N=N,
                                     tau=ctau / c,
                                     z0=0,
                                     zf=zfoc)
    add_laser_pulse(sim, profile)

    # Propagate the pulse
    sim.step(1)

    # Check the validity of the transverse field profile
    # (Take the RMS field in order to suppress the laser oscillations)
    trans_profile = np.sqrt(np.average(sim.fld.interp[1].Er.real**2, axis=0))
    # Calculate the theortical profile out-of-focus
    Zr = k0 * w0**2 / 2
    w_th = w0 * (Lprop - zfoc) / Zr
    r = sim.fld.interp[1].r
    th_profile = trans_profile[0] * flat_gauss(r / w_th, N)
    # Plot the profile, if requested by the user
    if show:
        import matplotlib.pyplot as plt
        plt.plot(1.e6 * r, trans_profile, label='Simulated')
        plt.plot(1.e6 * r, th_profile, label='Theoretical')
        plt.legend(loc=0)
        plt.xlabel('r (microns)')
        plt.title('Transverse profile out-of-focus')
        plt.tight_layout()
        plt.show()
    # Check the validity
    assert np.allclose(th_profile, trans_profile, atol=rtol * th_profile[0])
コード例 #5
0
def test_linear_wakefield(Nm=1, show=False):
    """
    Run a simulation of linear laser-wakefield and compare the fields
    with the analytical solution.

    Parameters
    ----------
    Nm: int
        The number of azimuthal modes used in the simulation (Use 1, 2 or 3)
        This also determines the profile of the driving laser:
        - Nm=1: azimuthally-polarized annular laser 
          (laser in mode m=0, wakefield in mode m=0)
        - Nm=2: linearly-polarized Gaussian laser
          (laser in mode m=1, wakefield in mode m=0)
        - Nm=3: linearly-polarized Laguerre-Gauss laser
          (laser in mode m=0 and m=2, wakefield in mode m=0 and m=2, 

    show: bool
        Whether to have pop-up windows show the comparison between
        analytical and simulated results
    """
    # Automatically choose higher number of macroparticles along theta
    p_nt = 2 * Nm
    # Initialize the simulation object
    sim = Simulation(Nz,
                     zmax,
                     Nr,
                     rmax,
                     Nm,
                     dt,
                     p_zmin,
                     p_zmax,
                     p_rmin,
                     p_rmax,
                     p_nz,
                     p_nr,
                     p_nt,
                     n_e,
                     use_cuda=use_cuda,
                     boundaries={
                         'z': 'open',
                         'r': 'reflective'
                     })

    # Create the relevant laser profile
    if Nm == 1:
        # Build an azimuthally-polarized pulse from 2 Laguerre-Gauss profiles
        profile = LaguerreGaussLaser( 0, 1, a0=a0, waist=w0, tau=tau, z0=z0,
                                      theta_pol=np.pi/2, theta0=0. ) \
                + LaguerreGaussLaser( 0, 1, a0=a0, waist=w0, tau=tau, z0=z0,
                                      theta_pol=0., theta0=-np.pi/2 )
    elif Nm == 2:
        profile = GaussianLaser(a0=a0,
                                waist=w0,
                                tau=tau,
                                z0=z0,
                                theta_pol=np.pi / 2)
    elif Nm == 3:
        profile = LaguerreGaussLaser(0,
                                     1,
                                     a0=a0,
                                     waist=w0,
                                     tau=tau,
                                     z0=z0,
                                     theta_pol=np.pi / 2)
    add_laser_pulse(sim, profile)

    # Configure the moving window
    sim.set_moving_window(v=c)

    # Add diagnostics
    if write_fields:
        sim.diags.append(FieldDiagnostic(diag_period, sim.fld, sim.comm))
    if write_particles:
        sim.diags.append(
            ParticleDiagnostic(diag_period, {'electrons': sim.ptcl[0]},
                               sim.comm))

    # Prevent current correction for MPI simulation
    if sim.comm.size > 1:
        correct_currents = False
    else:
        correct_currents = True

    # Run the simulation
    sim.step(N_step, correct_currents=correct_currents)

    # Compare the fields
    compare_fields(sim, Nm, show)
コード例 #6
0
                                                       phi2_chirp=phi2_chirp)
        trans_prof = FlattenedGaussianTransverseProfile(w0=w0, N=30, zf=zfoc)
    elif case == 'donut_chirped':
        long_prof = GaussianChirpedLongitudinalProfile(tau=ctau / c,
                                                       z0=0.,
                                                       phi2_chirp=phi2_chirp)
        trans_prof = DonutLikeLaguerreGaussTransverseProfile(waist=w0,
                                                             zf=zfoc,
                                                             p=2,
                                                             m=1)
    else:
        raise ValueError('Unknown case')
    # Construct Paraxial Approximation Laser
    profile = ParaxialApproximationLaser(long_prof, trans_prof, E_laser)
    # Initialize the laser fields
    add_laser_pulse(sim, profile)

    # Plot and compare with reference pulse
    if reference_profile is not None:
        r_2d, z_2d = np.meshgrid(sim.fld.interp[0].r,
                                 sim.fld.interp[0].z,
                                 indexing='ij')
        Ex_reference = reference_profile.E_field(r_2d, 0, z_2d, 0)[0]
    if plot:
        import matplotlib.pyplot as plt
        plt.subplot(211)
        plt.imshow(2 * sim.fld.interp[1].Er.real.T)
        plt.colorbar()
        if reference_profile is not None:
            plt.subplot(212)
            plt.imshow(Ex_reference)
コード例 #7
0
        n_emit=0,  #initial emittance is 0
        gamma0=gamma0,
        sig_gamma=sig_gamma,
        n_physical_particles=Qtot / e,
        n_macroparticles=5000,
        zf=L0,
        tf=(L0 - z0Beam) / c,
        z_injection_plane=L0)

    # Load initial fields
    # Add a laser to the fields of the simulation
    #add_laser( sim, a0, w0, ctau, z0 )
    #add_laser_pulse(sim,PulseTrain_profile,method="antenna",z0_antenna=z0Antenna,v_antenna=0) #fw_propagating=True
    add_laser_pulse(sim,
                    UniformPulseTrainN(NumberOfPulses, UniformPulseSpacing),
                    method="antenna",
                    z0_antenna=z0Antenna,
                    v_antenna=0)  #fw_propagating=True

    if use_restart is False:
        # Track electrons if required (species 0 correspond to the electrons)
        if track_electrons:
            elec.track(sim.comm)
    else:
        # Load the fields and particles from the latest checkpoint file
        restart_from_checkpoint(sim)

    # Configure the moving window
    sim.set_moving_window(v=v_window)

    # Add diagnostics
コード例 #8
0
def run_fbpic(job: Job) -> None:
    """
    This ``signac-flow`` operation runs a ``fbpic`` simulation.

    :param job: the job instance is a handle to the data of a unique statepoint
    """
    from fbpic.main import Simulation
    from fbpic.lpa_utils.laser import add_laser_pulse, GaussianLaser
    from fbpic.openpmd_diag import FieldDiagnostic, ParticleDiagnostic

    # The density profile
    def dens_func(z: np.ndarray, r: np.ndarray) -> np.ndarray:
        """Returns relative density at position z and r.

        :param z: longitudinal positions, 1d array
        :param r: radial positions, 1d array
        :return: a 1d array ``n`` containing the density (between 0 and 1) at the given positions (z, r)
        """
        # Allocate relative density
        n = np.ones_like(z)

        # Make linear ramp
        n = np.where(
            z < job.sp.ramp_start + job.sp.ramp_length,
            (z - job.sp.ramp_start) / job.sp.ramp_length,
            n,
        )

        # Supress density before the ramp
        n = np.where(z < job.sp.ramp_start, 0.0, n)

        return n

    # plot density profile for checking
    all_z = np.linspace(job.sp.zmin, job.sp.p_zmax, 1000)
    dens = dens_func(all_z, 0.0)

    width_inch = job.sp.p_zmax / 1e-5
    major_locator = pyplot.MultipleLocator(10)
    minor_locator = pyplot.MultipleLocator(5)
    major_locator.MAXTICKS = 10000
    minor_locator.MAXTICKS = 10000

    def mark_on_plot(*, ax, parameter: str, y=1.1):
        ax.annotate(s=parameter,
                    xy=(job.sp[parameter] * 1e6, y),
                    xycoords="data")
        ax.axvline(x=job.sp[parameter] * 1e6, linestyle="--", color="red")
        return ax

    fig, ax = pyplot.subplots(figsize=(width_inch, 4.8))
    ax.plot(all_z * 1e6, dens)
    ax.set_xlabel(r"$%s \;(\mu m)$" % "z")
    ax.set_ylim(-0.1, 1.2)
    ax.set_xlim(job.sp.zmin * 1e6 - 20, job.sp.p_zmax * 1e6 + 20)
    ax.set_ylabel("Density profile $n$")
    ax.xaxis.set_major_locator(major_locator)
    ax.xaxis.set_minor_locator(minor_locator)

    mark_on_plot(ax=ax, parameter="zmin")
    mark_on_plot(ax=ax, parameter="zmax")
    mark_on_plot(ax=ax, parameter="p_zmin", y=0.9)
    mark_on_plot(ax=ax, parameter="z0", y=0.8)
    mark_on_plot(ax=ax, parameter="zf", y=0.6)
    mark_on_plot(ax=ax, parameter="ramp_start", y=0.7)
    mark_on_plot(ax=ax, parameter="L_interact")
    mark_on_plot(ax=ax, parameter="p_zmax")

    ax.annotate(s="ramp_start + ramp_length",
                xy=(job.sp.ramp_start * 1e6 + job.sp.ramp_length * 1e6, 1.1),
                xycoords="data")
    ax.axvline(x=job.sp.ramp_start * 1e6 + job.sp.ramp_length * 1e6,
               linestyle="--",
               color="red")

    ax.fill_between(all_z * 1e6, dens, alpha=0.5)

    fig.savefig(job.fn("check_density.png"))

    # redirect stdout to "stdout.txt"
    orig_stdout = sys.stdout
    f = open(job.fn("stdout.txt"), "w")
    sys.stdout = f

    # Initialize the simulation object
    sim = Simulation(
        job.sp.Nz,
        job.sp.zmax,
        job.sp.Nr,
        job.sp.rmax,
        job.sp.Nm,
        job.sp.dt,
        n_e=None,  # no electrons
        zmin=job.sp.zmin,
        boundaries={
            "z": "open",
            "r": "reflective"
        },
        n_order=-1,
        use_cuda=True,
        verbose_level=2,
    )

    # Create a Gaussian laser profile
    laser_profile = GaussianLaser(a0=job.sp.a0,
                                  waist=job.sp.w0,
                                  tau=job.sp.ctau / c_light,
                                  z0=job.sp.z0,
                                  zf=job.sp.zf,
                                  theta_pol=0.,
                                  lambda0=job.sp.lambda0,
                                  cep_phase=0.,
                                  phi2_chirp=0.,
                                  propagation_direction=1)

    # Add it to the simulation
    add_laser_pulse(sim,
                    laser_profile,
                    gamma_boost=None,
                    method='direct',
                    z0_antenna=None,
                    v_antenna=0.)

    # Create the plasma electrons
    elec = sim.add_new_species(q=-q_e,
                               m=m_e,
                               n=job.sp.n_e,
                               dens_func=dens_func,
                               p_zmin=job.sp.p_zmin,
                               p_zmax=job.sp.p_zmax,
                               p_rmax=job.sp.p_rmax,
                               p_nz=job.sp.p_nz,
                               p_nr=job.sp.p_nr,
                               p_nt=job.sp.p_nt)

    # Track electrons, useful for betatron radiation
    # elec.track(sim.comm)

    # Configure the moving window
    sim.set_moving_window(v=c_light)

    # Add diagnostics
    write_dir = os.path.join(job.ws, "diags")
    sim.diags = [
        FieldDiagnostic(job.sp.diag_period,
                        sim.fld,
                        comm=sim.comm,
                        write_dir=write_dir,
                        fieldtypes=["rho", "E"]),
        ParticleDiagnostic(job.sp.diag_period, {"electrons": elec},
                           select={"uz": [1., None]},
                           comm=sim.comm,
                           write_dir=write_dir,
                           particle_data=["momentum", "weighting"]),
    ]

    # Plot the Ex component of the laser
    # Get the fields in the half-plane theta=0 (Sum mode 0 and mode 1)
    gathered_grids = [
        sim.comm.gather_grid(sim.fld.interp[m]) for m in range(job.sp.Nm)
    ]

    rgrid = gathered_grids[0].r
    zgrid = gathered_grids[0].z

    # construct the Er field for theta=0
    Er = gathered_grids[0].Er.T.real

    for m in range(1, job.sp.Nm):
        # There is a factor 2 here so as to comply with the convention in
        # Lifschitz et al., which is also the convention adopted in Warp Circ
        Er += 2 * gathered_grids[m].Er.T.real

    e0 = electric_field_amplitude_norm(lambda0=job.sp.lambda0)

    fig = pyplot.figure(figsize=(8, 8))
    sliceplots.Plot2D(
        fig=fig,
        arr2d=Er / e0,
        h_axis=zgrid * 1e6,
        v_axis=rgrid * 1e6,
        zlabel=r"$E_r/E_0$",
        xlabel=r"$z \;(\mu m)$",
        ylabel=r"$r \;(\mu m)$",
        extent=(
            zgrid[0] * 1e6,  # + 40
            zgrid[-1] * 1e6,  # - 20
            rgrid[0] * 1e6,
            rgrid[-1] * 1e6,  # - 15,
        ),
        cbar=True,
        vmin=-3,
        vmax=3,
        hslice_val=0.0,  # do a 1D slice through the middle of the simulation box
    )
    fig.savefig(job.fn('check_laser.png'))

    # set deterministic random seed
    np.random.seed(0)

    # Run the simulation
    sim.step(job.sp.N_step, show_progress=False)

    # redirect stdout back and close "stdout.txt"
    sys.stdout = orig_stdout
    f.close()
コード例 #9
0
# - Mode 0: Build a radially-polarized pulse from 2 Laguerre-Gauss profiles
profile0 = LaguerreGaussLaser( 0, 1, 0.5*a0, w0, tau, z0, zf=zf,
            lambda0=lambda0, theta_pol=0., theta0=0. ) \
         + LaguerreGaussLaser( 0, 1, 0.5*a0, w0, tau, z0, zf=zf,
            lambda0=lambda0, theta_pol=np.pi/2, theta0=np.pi/2 )
# - Mode 1: Use a regular linearly-polarized pulse
profile1 = GaussianLaser(a0=a0,
                         waist=w0,
                         tau=tau,
                         lambda0=lambda0,
                         z0=z0,
                         zf=zf)

if not restart:
    # Add the profiles to the simulation
    add_laser_pulse(sim, profile0)
    add_laser_pulse(sim, profile1)
else:
    restart_from_checkpoint(sim)

# Calculate the total number of steps
N_step = int(round(L_prop / (c * dt)))
diag_period = int(round(N_step / N_diag))

# Add openPMD diagnostics
sim.diags = [
    FieldDiagnostic(diag_period, sim.fld, fieldtypes=["E"], comm=sim.comm)
]

set_periodic_checkpoint(sim, N_step // 2)
コード例 #10
0
# NB: The code below is only executed when running the script,
# (`python lwfa_script.py`), but not when importing it (`import lwfa_script`).
if __name__ == '__main__':

    # Initialize the simulation object
    sim = Simulation( Nz, zmax, Nr, rmax, Nm, dt, n_e=None, zmin=zmin,
            boundaries={"z":"open", "r":"reflective"}, n_order=n_order, use_cuda=use_cuda, verbose_level=2, )

    # Create a Gaussian laser profile
    laser_profile = GaussianLaser(a0=a0, waist=w0, tau=ctau / c, z0=z0,
                                  zf=None, theta_pol=0., lambda0=lambda0,
                                  cep_phase=0., phi2_chirp=0.,
                                  propagation_direction=1)

    # Add it to the simulation
    add_laser_pulse(sim, laser_profile, gamma_boost=None, method='direct', z0_antenna=None, v_antenna=0.)

    # Create the plasma electrons
    elec = sim.add_new_species( q=-e, m=m_e, n=n_e,
        dens_func=dens_func, p_zmin=p_zmin, p_zmax=p_zmax, p_rmax=p_rmax,
        p_nz=p_nz, p_nr=p_nr, p_nt=p_nt )

    if use_restart is False:
        # Track electrons if required (species 0 correspond to the electrons)
        if track_electrons:
            elec.track( sim.comm )
    else:
        # Load the fields and particles from the latest checkpoint file
        restart_from_checkpoint( sim )

    # Configure the moving window