def Report(self, basename, mks_length):
     wc, xc, yc, zc, wrms, xrms, yrms, zrms = BeamProfiler.Report(
         self, basename, mks_length)
     field_tool = caustic_tools.FourierTool(self.N, self.wave_band(wc),
                                            (xc, yc, zc),
                                            (self.Lx, self.Ly, self.Lz),
                                            self.cl)
     print('    constructing fields in eikonal plane...')
     E = np.zeros(self.N[:3] + (3, )).astype(np.complex)
     E[..., 0], dom3d = field_tool.GetBoundaryFields(self.xps, self.eiks, 1)
     E[..., 1], dom3d = field_tool.GetBoundaryFields(self.xps, self.eiks, 2)
     E[..., 2], dom3d = field_tool.GetBoundaryFields(self.xps, self.eiks, 3)
     np.save(basename + '_' + self.name + '_plane_eik', E)
     print('    constructing fields in wave zone...')
     A = np.zeros(self.N + (3, )).astype(np.complex)
     A[..., 0], dom4d = field_tool.GetFields(self.dz, E[..., 0])
     A[..., 1], dom4d = field_tool.GetFields(self.dz, E[..., 1])
     A[..., 2], dom4d = field_tool.GetFields(self.dz, E[..., 2])
     np.save(basename + '_' + self.name + '_plane_wave', A)
     np.save(basename + '_' + self.name + '_plane_plot_ext', dom4d)
Esempio n. 2
0
def track(cl, xp, eikonal, vg, vol_dict):
    '''Propagate unidirectional fully dispersive waves using eikonal data as a boundary condition.
	The volume must be oriented so the polarization axis is x (linear polarization only).

	:param numpy.array xp: ray phase space with shape (bundles,rays,8)
	:param numpy.array eikonal: ray eikonal data with shape (bundles,4)
	:param numpy.array vg: ray group velocity with shape (bundles,rays,4)
	:param dictionary vol_dict: input file dictionary for the volume'''
    band = vol_dict['frequency band']
    size = (band[1] - band[0], ) + vol_dict['size']
    N = vol_dict['wave grid']
    # N[3] is the number of diagnostic planes, including the initial plane
    diagnostic_steps = N[3] - 1
    subcycles = vol_dict['subcycles']
    steps = diagnostic_steps * subcycles
    field_planes = steps + 1

    powersof2 = [2**i for i in range(32)]
    if N[0] - 1 not in powersof2:
        raise ValueError('UPPE propagator requires 2**n+1 w-nodes')
    if N[1] not in powersof2:
        raise ValueError('UPPE propagator requires 2**n x-nodes')
    if N[2] not in powersof2:
        raise ValueError('UPPE propagator requires 2**n y-nodes')
    try:
        window_speed = vol_dict['window speed']
    except:
        window_speed = 1.0
    try:
        chi3 = vol_dict['chi3']
    except:
        chi3 = 0.0

    # Capture the rays
    if vol_dict['wave coordinates'] == 'cartesian':
        field_tool = caustic_tools.FourierTool(N, band, (0, 0, 0), size[1:],
                                               cl)
    else:
        field_tool = caustic_tools.BesselBeamTool(N, band, (0, 0, 0), size[1:],
                                                  cl)

    w_nodes, x1_nodes, x2_nodes, plot_ext = field_tool.GetGridInfo()
    A = np.zeros(N).astype(np.complex)
    J = np.zeros(N).astype(np.complex)
    ne = np.zeros(N).astype(np.complex)
    A0, dom3d = field_tool.GetBoundaryFields(xp[:, 0, :], eikonal, 1)

    # Setup the wave propagation domain
    chi = vol_dict['dispersion inside'].chi(w_nodes)
    try:
        ionizer = vol_dict['ionizer']
    except KeyError:
        ionizer = ionization.Ionization(1.0, 1.0, 1.0, 1.0)
    dens_nodes = grid_tools.cell_centers(-size[3] / 2, size[3] / 2, steps)
    field_walls = grid_tools.cell_walls(dens_nodes[0], dens_nodes[-1], steps)
    diagnostic_walls = np.linspace(-size[3] / 2, size[3] / 2, N[3])
    dz = field_walls[1] - field_walls[0]
    Dz = diagnostic_walls[1] - diagnostic_walls[0]
    dom4d = np.concatenate((dom3d, [field_walls[0], field_walls[-1]]))

    # Step through the domain
    # Strategy to get density plane is to re-use ray gather system
    # This works as long as the shape of xp is (*,*,8)
    xp_eff = np.zeros((N[1], N[2], 8))
    if vol_dict['wave coordinates'] == 'cartesian':
        xp_eff[..., 1] = np.outer(x1_nodes, np.ones(N[2]))
        xp_eff[..., 2] = np.outer(np.ones(N[1]), x2_nodes)
    else:
        xp_eff[..., 1] = np.outer(x1_nodes, np.cos(x2_nodes))
        xp_eff[..., 2] = np.outer(x1_nodes, np.sin(x2_nodes))
    A[..., 0] = A0
    J[..., 0] = 0.0
    ne[..., 0] = 0.0
    for k in range(diagnostic_steps):
        print('Advancing to diagnostic plane', k + 1)
        rhs_evals = 0
        for s in range(subcycles):
            if subcycles > 1:
                if s == 0:
                    print('  subcycling .', end='', flush=True)
                else:
                    print('.', end='', flush=True)
            xp_eff[..., 3] = dens_nodes[k * subcycles + s]
            dens = vol_dict['object'].GetDensity(xp_eff)
            A0, J0, ne0, evals = propagator(cl, field_tool, window_speed, A0,
                                            chi, chi3, dens, ionizer, dz)
            A0[:4, ...] = 0.0
            rhs_evals += evals
        print('', rhs_evals, 'evaluations of j(w,kx,ky)')
        A[..., k + 1] = A0
        J[..., k + 1] = J0
        ne[..., k + 1] = ne0

    # Finish by relaunching rays and returning UPPE data
    field_tool.RelaunchRays(xp, eikonal, vg, A[..., -1], size[3])
    return A, J, ne, dom4d
Esempio n. 3
0
def track(xp, eikonal, vg, vol_dict):
    '''Propagate unidirectional fully dispersive waves using eikonal data as a boundary condition.
	The volume must be oriented so the polarization axis is x (linear polarization only).

	:param numpy.array xp: ray phase space with shape (bundles,rays,8)
	:param numpy.array eikonal: ray eikonal data with shape (bundles,4)
	:param numpy.array vg: ray group velocity with shape (bundles,rays,4)
	:param dictionary vol_dict: input file dictionary for the volume'''
    band = vol_dict['frequency band']
    size = (band[1] - band[0], ) + vol_dict['size']
    N = vol_dict['wave grid']
    # N[3] is the number of diagnostic planes, including the initial plane
    diagnostic_steps = N[3] - 1
    subcycles = vol_dict['subcycles']
    steps = diagnostic_steps * subcycles
    field_planes = steps + 1
    Vol = vol_dict['object']

    try:
        window_speed = vol_dict['window speed']
    except:
        window_speed = 1.0
    try:
        chi3 = vol_dict['chi3']
    except:
        chi3 = 0.0

    # Capture the rays
    if vol_dict['wave coordinates'] == 'cartesian':
        field_tool = caustic_tools.FourierTool(N, band, (0, 0, 0), size[1:],
                                               Vol.queue, Vol.transform_k)
    else:
        field_tool = caustic_tools.BesselBeamTool(N, band, (0, 0, 0), size[1:],
                                                  Vol.queue, Vol.transform_k)

    w_nodes, x1_nodes, x2_nodes, plot_ext = field_tool.GetGridInfo()
    A = np.zeros(N).astype(np.complex)
    J = np.zeros(N).astype(np.complex)
    ne = np.zeros(N).astype(np.complex)
    A0, dom3d = field_tool.GetBoundaryFields(xp[:, 0, :], eikonal, 1)

    # Setup the wave propagation domain
    chi = vol_dict['dispersion inside'].chi(w_nodes)
    try:
        ionizer = vol_dict['ionizer']
    except KeyError:
        ionizer = ionization.Ionization(1.0, 1.0, 1.0, 1.0)
    dens_nodes = grid_tools.cell_centers(-size[3] / 2, size[3] / 2, steps)
    field_walls = grid_tools.cell_walls(dens_nodes[0], dens_nodes[-1], steps)
    diagnostic_walls = np.linspace(-size[3] / 2, size[3] / 2, N[3])
    dz = field_walls[1] - field_walls[0]
    Dz = diagnostic_walls[1] - diagnostic_walls[0]
    dom4d = np.concatenate((dom3d, [field_walls[0], field_walls[-1]]))

    # Step through the domain
    # Strategy to get density plane is to re-use ray gather system
    # This works as long as the shape of xp is (*,*,8)
    xp_eff = np.zeros((N[1], N[2], 8))
    if vol_dict['wave coordinates'] == 'cartesian':
        xp_eff[..., 1] = np.outer(x1_nodes, np.ones(N[2]))
        xp_eff[..., 2] = np.outer(np.ones(N[1]), x2_nodes)
    else:
        xp_eff[..., 1] = np.outer(x1_nodes, np.cos(x2_nodes))
        xp_eff[..., 2] = np.outer(x1_nodes, np.sin(x2_nodes))
    A[..., 0] = A0
    J[..., 0] = 0.0
    ne[..., 0] = 0.0
    for k in range(diagnostic_steps):
        print('Advancing to diagnostic plane', k + 1)
        for s in range(subcycles):
            xp_eff[..., 3] = dens_nodes[k * subcycles + s]
            dens = vol_dict['object'].GetDensity(xp_eff)
            A0, J0, ne0 = propagator(field_tool, window_speed, A0, chi, chi3,
                                     dens, ionizer, dz)
            try:
                A0 *= vol_dict['damping filter'](w_nodes)[:, np.newaxis,
                                                          np.newaxis]
            except KeyError:
                A0 = A0
        A[..., k + 1] = A0
        J[..., k + 1] = J0
        ne[..., k + 1] = ne0

    # Return the wave amplitude
    # Rays are re-launched externally
    return A, J, ne, dom4d
Esempio n. 4
0
def track(cl, xp, eikonal, vg, vol_dict):
    '''Propagate unidirectional fully dispersive waves using eikonal data as a boundary condition.
	The volume must be oriented so the polarization axis is x (linear polarization only).

	:param numpy.array xp: ray phase space with shape (bundles,rays,8)
	:param numpy.array eikonal: ray eikonal data with shape (bundles,4)
	:param numpy.array vg: ray group velocity with shape (bundles,rays,4)
	:param dictionary vol_dict: input file dictionary for the volume'''
    band = vol_dict['frequency band']
    NL_band = vol_dict['nonlinear band']
    size = (band[1] - band[0], ) + vol_dict['size']
    N = vol_dict['wave grid']
    # N[3] is the number of diagnostic planes, including the initial plane
    diagnostic_steps = N[3] - 1
    subcycles = vol_dict['subcycles']
    steps = diagnostic_steps * subcycles
    field_planes = steps + 1

    powersof2 = [2**i for i in range(32)]
    if N[0] - 1 not in powersof2:
        raise ValueError('UPPE propagator requires 2**n+1 w-nodes')
    if N[1] not in powersof2:
        raise ValueError('UPPE propagator requires 2**n x-nodes')
    if N[2] not in powersof2:
        raise ValueError('UPPE propagator requires 2**n y-nodes')
    try:
        window_speed = vol_dict['window speed']
    except KeyError:
        window_speed = 1.0
    try:
        chi3 = vol_dict['chi3']
    except KeyError:
        chi3 = 0.0
    try:
        full_relaunch = vol_dict['full relaunch']
    except KeyError:
        full_relaunch = False

    # Capture the rays
    if vol_dict['wave coordinates'] == 'cartesian':
        field_tool = caustic_tools.FourierTool(N, band, (0, 0, 0), size[1:],
                                               cl)
    else:
        field_tool = caustic_tools.BesselBeamTool(N, band, (0, 0, 0), size[1:],
                                                  cl, vol_dict['radial modes'])

    warnings.warn(
        'Polarization information is lost upon entering paraxial region.')
    w_nodes, x1_nodes, x2_nodes, plot_ext = field_tool.GetGridInfo()
    A = np.zeros(N).astype(np.complex)
    J = np.zeros(N).astype(np.complex)
    ne = np.zeros(N).astype(np.complex)
    A[..., 0], dom3d = field_tool.GetBoundaryFields(xp[:, 0, :], eikonal, 1)

    # Setup the wave propagation medium
    chi = vol_dict['dispersion inside'].chi(w_nodes).astype(np.complex)
    try:
        ionizer = ionization.Ionizer(vol_dict['ionizer'])
    except KeyError:
        ionizer = None
    mat = Material(cl.q, field_tool, N, vol_dict['wave coordinates'],
                   vol_dict['object'], chi, chi3,
                   vol_dict['density reference'], window_speed)

    # Setup the wave propagation domain
    dens_nodes = grid_tools.cell_centers(-size[3] / 2, size[3] / 2, steps)
    field_walls = grid_tools.cell_walls(dens_nodes[0], dens_nodes[-1], steps)
    diagnostic_walls = np.linspace(-size[3] / 2, size[3] / 2, N[3])
    dzmin = vol_dict['minimum step']
    Dz = diagnostic_walls[1] - diagnostic_walls[0]
    dom4d = np.concatenate((dom3d, [field_walls[0], field_walls[-1]]))

    # Step through the domain
    A0 = np.copy(A[..., 0])
    for k in range(diagnostic_steps):
        zi = diagnostic_walls[k]
        zf = diagnostic_walls[k + 1]
        print('Advancing to diagnostic plane', k + 1)
        A0, J0, ne0, evals = propagator(cl, field_tool, window_speed, A0, mat,
                                        ionizer, NL_band, subcycles, zi, zf,
                                        dzmin)
        print('', evals, 'evaluations of j(w,kx,ky)')
        A[..., k + 1] = A0
        J[..., k + 1] = J0
        ne[..., k + 1] = ne0

    # Finish by relaunching rays and returning UPPE data
    if full_relaunch:
        field_tool.RelaunchRays1(xp, eikonal, vg, A[..., -1], size[3],
                                 vol_dict['dispersion inside'])
    else:
        field_tool.RelaunchRays(xp, eikonal, vg, A[..., -1], size[3],
                                vol_dict['dispersion inside'])
    return A, J, ne, dom4d
Esempio n. 5
0
def track(cl, xp, eikonal, vg, vol_dict):
    '''Propagate paraxial waves using eikonal data as a boundary condition.
	The volume must be oriented so the polarization axis is x (linear polarization only).

	:param numpy.array xp: ray phase space with shape (bundles,rays,8)
	:param numpy.array eikonal: ray eikonal data with shape (bundles,4)
	:param numpy.array vg: ray group velocity with shape (bundles,rays,4)
	:param dictionary vol_dict: input file dictionary for the volume'''
    band = vol_dict['frequency band']
    size = (band[1] - band[0], ) + vol_dict['size']
    N = vol_dict['wave grid']
    # N[3] is the number of diagnostic planes, including the initial plane
    diagnostic_steps = N[3] - 1
    subcycles = vol_dict['subcycles']
    steps = diagnostic_steps * subcycles
    field_planes = steps + 1
    Vol = vol_dict['object']

    powersof2 = [2**i for i in range(32)]
    if N[0] not in powersof2:
        raise ValueError('Paraxial propagator requires 2**n w-nodes')
    if N[1] not in powersof2:
        raise ValueError('Paraxial propagator requires 2**n x-nodes')
    if N[2] not in powersof2:
        raise ValueError('Paraxial propagator requires 2**n y-nodes')
    try:
        window_speed = vol_dict['window speed']
    except:
        window_speed = 1.0
    try:
        chi3 = vol_dict['chi3']
    except:
        chi3 = 0.0

    # Capture the rays
    if vol_dict['wave coordinates'] == 'cartesian':
        field_tool = caustic_tools.FourierTool(N, band, (0, 0, 0), size[1:],
                                               cl)
    else:
        field_tool = caustic_tools.BesselBeamTool(N, band, (0, 0, 0), size[1:],
                                                  cl)

    w_nodes, x1_nodes, x2_nodes, plot_ext = field_tool.GetGridInfo()
    A = np.zeros(N).astype(np.complex)
    A0, dom3d = field_tool.GetBoundaryFields(xp[:, 0, :], eikonal, 1)
    n0 = np.mean(
        np.sqrt(np.einsum('...i,...i', xp[:, 0, 5:8], xp[:, 0, 5:8])) /
        xp[:, 0, 4])
    ng = 1.0 / np.mean(
        np.sqrt(np.einsum('...i,...i', vg[:, 0, 1:4], vg[:, 0, 1:4])))

    # Setup the wave propagation domain
    chi = vol_dict['dispersion inside'].chi(w_nodes)
    dens_nodes = grid_tools.cell_centers(-size[3] / 2, size[3] / 2, steps)
    field_walls = grid_tools.cell_walls(dens_nodes[0], dens_nodes[-1], steps)
    diagnostic_walls = np.linspace(-size[3] / 2, size[3] / 2, N[3])
    dz = field_walls[1] - field_walls[0]
    Dz = diagnostic_walls[1] - diagnostic_walls[0]
    dom4d = np.concatenate((dom3d, [field_walls[0], field_walls[-1]]))

    # Step through the domain
    # Strategy to get density plane is to re-use ray gather system
    # This works as long as the shape of xp is (*,*,8)
    xp_eff = np.zeros((N[1], N[2], 8))
    if vol_dict['wave coordinates'] == 'cartesian':
        xp_eff[..., 1] = np.outer(x1_nodes, np.ones(N[2]))
        xp_eff[..., 2] = np.outer(np.ones(N[1]), x2_nodes)
    else:
        xp_eff[..., 1] = np.outer(x1_nodes, np.cos(x2_nodes))
        xp_eff[..., 2] = np.outer(x1_nodes, np.sin(x2_nodes))
    A[..., 0] = A0
    for k in range(diagnostic_steps):
        print('Advancing to diagnostic plane', k + 1)
        for s in range(subcycles):
            xp_eff[..., 3] = dens_nodes[k * subcycles + s]
            dens = vol_dict['object'].GetDensity(xp_eff)
            A0 = propagator(field_tool, A0, chi, dens, n0, ng, dz, True)
            try:
                A0 *= vol_dict['damping filter'](w_nodes)[:, np.newaxis,
                                                          np.newaxis]
            except KeyError:
                A0 = A0
        A[..., k + 1] = A0

    # Finish by relaunching rays and returning wave data
    field_tool.RelaunchRays(xp, eikonal, vg, A[..., -1], size[3])
    return A, dom4d