def periodic_envelope_propagation(field,omega0,s=1,z=None,omega=None,t=None): import numpy as np import expresso.pycas as pc from .. import units if z is None: z = pc.Symbol('z') if t is None: t = pc.Symbol('t') if omega is None: omega = pc.Symbol('omega') zindex = field.get_axis_index(z) omegaindex = field.get_axis_index(omega) omegamin,omegamax = field.bounds[omegaindex] zmin, zmax = field.bounds[zindex] sz = zmax - zmin ukmin = float(field.evaluate( (omegamin-omega0)/units.c*sz )) ukmax = float(field.evaluate( (omegamax-omega0)/units.c*sz )) uzmin = 0 uzmax = 1 nz,ik = np.meshgrid(np.linspace(uzmin,uzmax,field.shape[zindex]),np.linspace(1j*ukmin,1j*ukmax,field.shape[omegaindex])) factor = np.exp(-ik*nz/float(s)) del nz,ik transform = field * factor del factor tdfield = fourier_transform(transform, omega, t, inverse=True) del transform tdfield.bounds[omegaindex] = [(b - tdfield.bounds[omegaindex][0]).evaluate() for b in tdfield.bounds[omegaindex]] return tdfield
def __init__(self, settings, thread_count=1): import expresso.pycas as pc super(Fresnel2D, self).__init__(settings) self._thread_count = thread_count self._set_initial_field(settings) pe = settings.partial_differential_equation x, y, z = settings.partial_differential_equation.coordinates R, = self._get_evaluators([pc.exp(pe.F * z.step)], settings, return_type=pc.Types.Complex) D = pc.numpyfy( self._evaluate(pc.exp(-pe.A * z.step * (pc.Symbol('kx')**2)), settings)) if self._F_is_constant_in_z: self.__R_step = R(*self._get_indices()) else: self.__R = R import numpy as np fx = 2 * np.pi / (self._nx * self._get_as(x.step, float, settings)) kx = fx * (self._nx / 2. - np.abs(np.arange(self._nx) - self._nx / 2.)) self.__D_step = D(kx=kx, **self._get_indices_dict())
def __init__(self, sb, name): self.name = name self.symbol = getattr(sb, name) self.min = getattr(sb, name + 'min') self.max = getattr(sb, name + 'max') self.step = getattr(sb, 'd' + name) self.steps = getattr(sb, 'N' + name) self.size = getattr(sb, 's' + name) self.index = pc.Symbol('%s_i' % name, type=pc.Types.Natural)
def add_partial_differential_equation_category(settings, coordinates=None): import expresso.pycas as pc sb = settings.simulation_box pde = settings.create_category( 'partial_differential_equation', short_name='PDE', info="parameters of the partial differential equation") arg_attrs = [sb.coordinate_dict[x] for x in coordinates ] if coordinates is not None else sb.coordinates pde.add_attribute('coordinates', arg_attrs) x, y, z = [a.symbol for a in arg_attrs] dx, dy, dz = [s.step for s in arg_attrs] args = (x, y, z) pde.create_function('A', args) pde.create_function('C', args, pde.A) pde.create_function('F', args) pde.create_function('ra', args, pde.A * dz / dx**2, info="finite difference paramter") pde.create_function('rc', args, pde.C * dz / dy**2, info="finite difference paramter") pde.create_function('rf', args, pde.F * dz / 2, info="finite difference paramter") pde.create_function('u', args, info='solution to the PDE') pde.lock('u') pde.add_attribute( 'equation', pc.equal( pc.derivative(pde.u, z), pde.A * pc.derivative(pc.derivative(pde.u, x), x) + pde.C * pc.derivative(pc.derivative(pde.u, y), y) + pde.F * pde.u)) pde.create_key('u0', pc.Function('u_0_PDE')(*args), info="field initial condition") pde.create_function('u_boundary', args, info="field boundary condition") pde.create_key(arg_attrs[1].name + '0', pc.Symbol(y.name + '_0_PDE'), 0, info='Value to which the %s is set for 1D solvers' % y.name) pde.lock() return pde
def plot(arg, *args, **kwargs): """ Simple plot function for 1D and 2D coordinate arrays. If the data is complex, the absolute square value of the data will be plottted. Parameters ----------- arg: coordinate array the input data **kwargs: additional parameters to be passed to the plot functions Returns -------- plot: output of ax.plot for 1D and ax.imshow for 2D arrays """ import expresso.pycas import numpy as np from coordinate_ndarray import CoordinateNDArray if isinstance(arg, expresso.pycas.Expression): from .settings import Settings if len(args) > 0 and isinstance(args[0], Settings): settings = args[0] args = list(args) del args[0] else: settings = kwargs.get('settings') if not settings: raise ValueError( 'cannot plot expression: no settings provided') del kwargs['settings'] arg = expression_to_array(arg, settings) if isinstance(arg, (float, complex)): print arg return elif not isinstance(arg, CoordinateNDArray): if isinstance(arg, np.ndarray): pc = expresso.pycas arg = CoordinateNDArray( arg, [(pc.S(0), pc.S(n)) for n in arg.shape], [pc.Symbol('x_%i' % i) for i in range(len(arg.shape))]) else: raise ValueError( 'cannot plot non CoordinateNDArray object. For plotting regular arrays please use the matplotlib.pyplot module.' ) if not np.can_cast(arg.data.dtype, np.float128): if np.all(arg.data.imag == 0): arg = arg.real else: arg = abs(arg)**2 if len(arg.axis) == 1: return line_plot(arg, *args, **kwargs) elif len(arg.axis) == 2: return image_plot(arg, *args, **kwargs) else: raise ValueError("input array must be one or two dimensional")
def create_unit(name): u = pc.Symbol("SI base unit " + name, type=pc.Types.Real, positive=True, latex=r'\mathrm{%s}' % name, repr=name) globals()[name] = u base_units.add(u) add_metric_prefixes(name)
def __init__(self, settings, thread_count=None): super(Fresnel3D, self).__init__(settings) if thread_count == None: import multiprocessing thread_count = multiprocessing.cpu_count() self._thread_count = thread_count pe = settings.partial_differential_equation x, y, z = settings.partial_differential_equation.coordinates import expresso.pycas as pc R, = self._get_evaluators([pc.exp(pe.F * z.step)], settings, return_type=pc.Types.Complex, parallel=not self._F_is_constant_in_z) if self._F_is_constant_in_z: self.__R_step = R(*self._get_indices()) else: self.__R = R D = pc.numpyfy( self._evaluate( pc.exp( -z.step * (pe.A * pc.Symbol('kx')**2 + pe.C * pc.Symbol('ky')**2)), settings)) import numpy as np fx = 2 * np.pi / (self._nx * self._get_as(x.step, float, settings)) fy = 2 * np.pi / (self._ny * self._get_as(y.step, float, settings)) ky, kx = np.meshgrid( fy * (self._ny / 2. - np.abs(np.arange(self._ny) - self._ny / 2.)), fx * (self._nx / 2. - np.abs(np.arange(self._nx) - self._nx / 2.))) self.__C_is_zero = settings.get_numeric(pe.C) == pc.S(0) self.__D_step = D(kx=kx, ky=ky, **self._get_indices_dict()) self._set_initial_field(settings)
def __init__(self, settings, thread_count=1): import expresso.pycas as pc import numpy as np pe = settings.partial_differential_equation x, y, z = settings.partial_differential_equation.coordinates xi = getattr(settings.simulation_box, x.name + 'i') self.__ximin = float(settings.get_unitless(xi.subs(x.symbol, 0))) self.__ximax = float(settings.get_unitless(xi.subs(x.symbol, x.max))) self.__sx = self.__ximax - self.__ximin super(FresnelCS, self).__init__(settings) self._thread_count = thread_count self._set_initial_field(settings) R, = self._get_evaluators([pc.exp(pe.F * z.step)], settings, return_type=pc.Types.Complex) D = pc.numpyfy( self._evaluate(pc.exp(-pe.A * z.step * (pc.Symbol('kx')**2)), settings)) if self._F_is_constant_in_z: self.__R_step = R(*self._get_indices()) else: self.__R = R kx = hankel_freq(self._nx) * ((self._nx - 1) * 1. / self.__sx) self.__D_step = D(kx=kx, **self._get_indices_dict()) self.__hankel_resample_matrix = hankel_resample_matrix( self._nx, (np.arange(self._nx) - self.__ximin) * (self._nx * 1. / self.__sx), cache_key=(self._nx, self.__ximin, self.__sx), xmax=self._nx)
def add_coordinate(settings, category, name): import expresso.pycas as pc x = category.create_key(name, pc.Symbol(name, type=pc.Types.Real), info='coordinate') xmin = category.create_key('%smin' % name, pc.Symbol('%s_min' % name), info='minimum value') xmax = category.create_key('%smax' % name, pc.Symbol('%s_max' % name), info='maximum value') xi = pc.Symbol('%s_i' % name, type=pc.Types.Natural) xif = category.create_key('%si' % name, pc.Function('%s_i' % name)(x), info='numerical index') Nx = category.create_key('N%s' % name, pc.Symbol('N_%s' % name, type=pc.Types.Natural), info='numerical steps') sx = category.create_key('s%s' % name, pc.Symbol('s_%s' % name), info='total size') dx = category.create_key('d%s' % name, pc.Symbol('Delta %s' % name), info='step size') setattr(category, name, xmin + xi * dx) setattr(category, '%si' % name, (x - xmin) / dx) setattr(category, 's%s' % name, xmax - xmin) setattr(category, 'd%s' % name, sx / (Nx - 1)) category.lock(name, 'defined by %si' % name) category.lock('s%s' % name, 'defined by %smin and %smax' % (name, name)) category.lock('d%s' % name, 'defined by s%s and N%s' % (name, name)) settings.unitless.add_key('%s_coordinate' % name, x)
def create_2D_frequency_settings_from(settings): import expresso.pycas as pc from .. import units from ..plot import expression_to_array from ..coordinate_ndarray import CoordinateNDArray import numpy as np settings.initialize() settings = settings.copy() sb = settings.simulation_box we = settings.wave_equation omega0 = settings.get_numeric(we.omega) we.unlock('omega') we.omega = None freq_settings = create_paraxial_settings() pde = freq_settings.partial_differential_equation freq_settings.simulation_box.unlock() freq_settings.simulation_box.remove_name('y') omega = freq_settings.simulation_box.create_key('y', pc.Symbol('omega')) fsb = freq_settings.simulation_box freq_settings.simulation_box.y = fsb.ymin + fsb.yi * fsb.dy n = settings.get_numeric(we.n.subs(sb.y, 0)).subs(omega, abs(omega - omega0)) p = freq_settings.create_category('paramters', short_name="p") p.create_function('n', (sb.x, sb.y, sb.z, omega), n) p.create_symbol('k', (omega - omega0) / units.c) p.create_symbol('k_0', omega0 / units.c) pde.A = 1j / (2 * p.k_0) pde.C = 0 pde.F = 1j / (2 * p.k_0) * (p.n**2 * p.k**2 - p.k_0**2) xmin = settings.get_numeric(sb.xmin) xmax = settings.get_numeric(sb.xmax) freq_settings.simulation_box.xmin = xmin freq_settings.simulation_box.xmax = xmax freq_settings.simulation_box.Nx = settings.get_as(sb.Nx, int) omegamin = settings.get_numeric(-2 * pc.pi * sb.Nt / sb.st) omegamax = settings.get_numeric(2 * pc.pi * sb.Nt / sb.st) freq_settings.simulation_box.ymin = omegamin freq_settings.simulation_box.ymax = omegamax freq_settings.simulation_box.Ny = settings.get_as(sb.Nt, int) freq_settings.simulation_box.zmin = settings.get_numeric(sb.zmin) freq_settings.simulation_box.zmax = settings.get_numeric(sb.zmax) freq_settings.simulation_box.Nz = settings.get_as(sb.Nz, int) freq_settings.unitless.create_key( 's', units.s, settings.get_as(2 / (omegamax - omegamin) / units.s, float)) u0 = expression_to_array(settings.wave_equation.u0.subs([(sb.y, 0), (sb.z, sb.zmin)]), settings, axes=(sb.x, sb.t)) u0hat = CoordinateNDArray( np.fft.fftshift(np.fft.fft(u0.data, axis=1), axes=(1, )), [(xmin, xmax), (omegamin, omegamax)], [sb.x, omega]) set_initial(freq_settings, u0hat) freq_settings.partial_differential_equation.u_boundary = 0 return freq_settings
def create_symbol(name, value=None, info=None, **kwargs): prefix = '_'.join(cat_path) return cat.create_key( name, pc.Symbol("%s_%s" % (name, prefix), **kwargs), value, info)