def __init__(self, settings): super(Propagator, self).__init__(settings) coordinates = settings.partial_differential_equation.coordinates self._x, self._t = coordinates[0].symbol, coordinates[2].symbol if self.ndim > 1: self._y = coordinates[1].symbol self._nx, self._nt = self._get_as((coordinates[0].steps, coordinates[2].steps), int, settings) if self.ndim > 1: self._ny = self._get_as(coordinates[1].steps, int, settings) self._xmin, self._xmax, self._tmin, self._tmax = settings.get_numeric( (coordinates[0].min, coordinates[0].max, coordinates[2].min, coordinates[2].max)) if self.ndim > 1: self._ymin, self._ymax = settings.get_numeric((coordinates[1].min, coordinates[1].max)) import expresso.pycas as pc pe = settings.partial_differential_equation self._F_is_zero = settings.get_unitless(pe.F) == pc.Zero self._F_is_constant_in_z = settings.get_numeric(pc.derivative(pe.F, self._t)) == pc.Zero self._F_is_constant = self._F_is_constant_in_z and settings.get_numeric(pc.derivative(pe.F, self._x)) == pc.Zero if self.ndim > 1: self._F_is_constant &= settings.get_numeric(pc.derivative(pe.F, self._y)) == pc.Zero if self.ndim > 1: self.__coordinate_names = [c.index.name for c in coordinates] else: self.__coordinate_names = [c.index.name for c in (coordinates[0], coordinates[2])]
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'),(arg_attrs[1].min+arg_attrs[1].max)/2,info='Value to which the %s is set for 1D solvers' % y.name) pde.lock() return pde
def __init__(self,settings): super(Propagator,self).__init__(settings) coordinates = settings.partial_differential_equation.coordinates self._x,self._t = coordinates[0].symbol,coordinates[2].symbol if self.ndim > 1: self._y = coordinates[1].symbol self._nx,self._nt = self._get_as((coordinates[0].steps,coordinates[2].steps),int,settings) if self.ndim > 1: self._ny = self._get_as(coordinates[1].steps,int,settings) self._xmin,self._xmax,self._tmin,self._tmax = settings.get_numeric((coordinates[0].min,coordinates[0].max,coordinates[2].min,coordinates[2].max)) if self.ndim > 1: self._ymin,self._ymax = settings.get_numeric((coordinates[1].min,coordinates[1].max)) import expresso.pycas as pc pe = settings.partial_differential_equation self._F_is_zero = settings.get_unitless( pe.F ) == pc.Zero self._F_is_constant_in_z = settings.get_numeric(pc.derivative(pe.F, self._t )) == pc.Zero self._F_is_constant = self._F_is_constant_in_z and settings.get_numeric(pc.derivative(pe.F, self._x)) == pc.Zero if self.ndim > 1: self._F_is_constant &= settings.get_numeric(pc.derivative(pe.F, self._y )) == pc.Zero if self.ndim > 1: self.__coordinate_names = [c.index.name for c in coordinates] else: self.__coordinate_names = [c.index.name for c in (coordinates[0],coordinates[2])]
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
evaluator.add_rule(pc.OperationType(pc.Abs(pc.Types.Rational)),pc.Types.Rational) evaluator.add_rule(pc.OperationType(pc.Abs(pc.Types.Integer)),pc.Types.Natural) evaluator.add_rule(pc.OperationType(pc.Abs(pc.Types.Natural)),pc.Types.Natural) evaluator.add_rule(pc.Type(pc.real(s.x)),pc.Types.Real) evaluator.add_rule(pc.Type(pc.imag(s.x)),pc.Types.Real) evaluator.add_rule(pc.Type(pc.conjugate(s.x)),pc.Types.Complex) evaluator.add_rule(pc.Type(pc.Indicator(s.x)),pc.Types.Natural) evaluator.add_rule(pc.Type(pc.OuterPiecewise(s.x)),pc.Type(s.x)) evaluator.add_rule(pc.Type(pc.InnerPiecewise((s.a,s.b),s.x)),pc.DominantType(pc.Type(s.a),pc.Type(pc.InnerPiecewise(s.x)))) evaluator.add_rule(pc.Type(pc.InnerPiecewise((s.a,s.b))),pc.Type(s.a)) evaluator.add_rule(pc.Type(pc.derivative(s.x,s.y)),pc.Type(s.x)) evaluator.add_rule(pc.Type(pc.evaluated_at(s.x,s.y,s.z)),pc.DominantType(pc.Type(s.x),pc.Type(s.z))) evaluator.add_rule(pc.Type(pc.tmp(s.x)),pc.Type(s.x)) evaluator.add_rule(pc.Type(pc.sqrt(s.x)),pc.Type(s.x**(1/pc.S(2)))) evaluator.add_rule(pc.Type(pc.atan2(s.x,s.y)),pc.DominantType(pc.Type(s.x),pc.Type(s.x),pc.Types.Rational)) for f in [pc.exp,pc.log,pc.sin,pc.cos,pc.asin ,pc.acos,pc.tan,pc.atan,pc.cot,pc.acot,pc.sinh,pc.cosh,pc.asinh,pc.acosh,pc.tanh,pc.atanh,pc.coth,pc.acoth]: evaluator.add_rule(pc.Type(f(s.x)),pc.DominantType(pc.Type(s.x),pc.Types.Rational)) def issubtype(x,t): return pc.equal(pc.DominantType(pc.Type(x),t),t) from .logic_evaluator import is_mpmath from mpmath import mp
evaluator.add_rule(pc.InnerPiecewise((s.a,s.x),(s.b,s.x)),(s.a,s.x)) evaluator.add_rule(pc.InnerPiecewise((s.x,s.a),(s.x,s.b)),(s.x,pc.Or(s.a,s.b))) evaluator.add_rule(pc.InnerPiecewise(pc.InnerPiecewise(s.x)),pc.InnerPiecewise(s.x)) evaluator.add_rule(pc.OuterPiecewise((s.a,s.b)),s.a*pc.Indicator(s.b)) from .logic_evaluator import contains_atomic excluded_derivatives = {pc.InnerPiecewise,pc.Tuple} def check_if_excluded_derivative(m): return not m[s.y].function in excluded_derivatives evaluator.add_rule(pc.derivative(s.x,s.x),1) evaluator.add_rule(pc.derivative(s.y,s.x),0,check_if_excluded_derivative,condition=pc.Not(contains_atomic(s.y,s.x))); evaluator.add_rule(pc.derivative(s.a+s.b,s.x),pc.derivative(s.a,s.x)+pc.derivative(s.b,s.x)) evaluator.add_rule(pc.derivative(s.a*s.b,s.x),pc.derivative(s.a,s.x)*s.b+pc.derivative(s.b,s.x)*s.a) evaluator.add_rule(pc.derivative(-s.x,s.x),-1) evaluator.add_rule(pc.derivative(1/s.x,s.x),-s.x**-2) evaluator.add_rule(pc.derivative(pc.log(s.x),s.x),1/s.x) evaluator.add_rule(pc.derivative(pc.sin(s.x),s.x),pc.cos(s.x)) evaluator.add_rule(pc.derivative(pc.cos(s.x),s.x),-pc.sin(s.x)) # TODO: Add assumptions to expressions: the following is only valid if x != -1,1 or x != -i,i evaluator.add_rule(pc.derivative(pc.asin(s.x),s.x),1/pc.sqrt(1-s.x**2)) evaluator.add_rule(pc.derivative(pc.acos(s.x),s.x),-1/pc.sqrt(1-s.x**2))
(s.x, pc.Or(s.a, s.b))) evaluator.add_rule(pc.InnerPiecewise(pc.InnerPiecewise(s.x)), pc.InnerPiecewise(s.x)) evaluator.add_rule(pc.OuterPiecewise((s.a, s.b)), s.a * pc.Indicator(s.b)) from .logic_evaluator import contains_atomic excluded_derivatives = {pc.InnerPiecewise, pc.Tuple} def check_if_excluded_derivative(m): return not m[s.y].function in excluded_derivatives evaluator.add_rule(pc.derivative(s.x, s.x), 1) evaluator.add_rule(pc.derivative(s.y, s.x), 0, check_if_excluded_derivative, condition=pc.Not(contains_atomic(s.y, s.x))) evaluator.add_rule(pc.derivative(s.a + s.b, s.x), pc.derivative(s.a, s.x) + pc.derivative(s.b, s.x)) evaluator.add_rule( pc.derivative(s.a * s.b, s.x), pc.derivative(s.a, s.x) * s.b + pc.derivative(s.b, s.x) * s.a) evaluator.add_rule(pc.derivative(-s.x, s.x), -1) evaluator.add_rule(pc.derivative(1 / s.x, s.x), -s.x**-2) evaluator.add_rule(pc.derivative(pc.log(s.x), s.x), 1 / s.x) evaluator.add_rule(pc.derivative(pc.sin(s.x), s.x), pc.cos(s.x))
evaluator.add_rule(pc.OperationType(pc.Abs(pc.Types.Natural)), pc.Types.Natural) evaluator.add_rule(pc.Type(pc.real(s.x)), pc.Types.Real) evaluator.add_rule(pc.Type(pc.imag(s.x)), pc.Types.Real) evaluator.add_rule(pc.OperationType(abs(s.x)), pc.Types.Real) #evaluator.add_rule(pc.Type(pc.conjugate(s.x)),pc.Type(s.x)) evaluator.add_rule(pc.Type(pc.Indicator(s.x)), pc.Types.Natural) evaluator.add_rule(pc.Type(pc.OuterPiecewise(s.x)), pc.Type(s.x)) evaluator.add_rule( pc.Type(pc.InnerPiecewise((s.a, s.b), s.x)), pc.DominantType(pc.Type(s.a), pc.Type(pc.InnerPiecewise(s.x)))) evaluator.add_rule(pc.Type(pc.InnerPiecewise((s.a, s.b))), pc.Type(s.a)) evaluator.add_rule(pc.Type(pc.derivative(s.x, s.y)), pc.Type(s.x)) evaluator.add_rule(pc.Type(pc.evaluated_at(s.x, s.y, s.z)), pc.DominantType(pc.Type(s.x), pc.Type(s.z))) evaluator.add_rule(pc.Type(pc.tmp(s.x)), pc.Type(s.x)) evaluator.add_rule(pc.Type(pc.sqrt(s.x)), pc.Type(s.x**(1 / pc.S(2)))) evaluator.add_rule( pc.Type(pc.atan2(s.x, s.y)), pc.DominantType(pc.Type(s.x), pc.Type(s.x), pc.Types.Rational)) for f in [ pc.exp, pc.log, pc.sin, pc.cos, pc.asin, pc.acos, pc.tan, pc.atan, pc.cot, pc.acot, pc.sinh, pc.cosh, pc.asinh, pc.acosh, pc.tanh, pc.atanh, pc.coth, pc.acoth ]: