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 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 __init__(self,settings): super(FiniteDifferencesPropagator2D,self).__init__(settings) from _pypropagate import finite_difference_acF,finite_difference_a0F pde = settings.partial_differential_equation sb = settings.simulation_box self._2step = settings.get_numeric( pc.equal(pde.C, 0) ) != pc.S(True) sf = 0.5 if self._2step else 1 if self._2step: ra = settings.get_as(pde.ra*sf,complex) rc = settings.get_as(pde.rc*sf,complex) else: ra = pc.numpyfy(settings.get_unitless(pde.ra))(**{self._y.name + '_i':range(self._ny)}) z,dz = sb.coordinates[2].symbol,sb.coordinates[2].step evaluators = self._get_evaluators([ (pde.rf*sf), (pde.rf*sf).subs(z,z-dz*sf), pde.u_boundary, pde.u_boundary.subs(z,z-dz*sf) ], settings,return_type=pc.Types.Complex,compile_to_c = True,parallel=True) self.__rf = evaluators[:2] self.__u_boundary = evaluators[2:] self._solver = finite_difference_acF() if self._2step else finite_difference_a0F() self._solver.resize(self._nx,self._ny) if self._2step: self._solver.ra = ra self._solver.rc = rc else: self._solver.ra.as_numpy()[:] = ra d,u,l,r = [(self._get_x_coordinates(),np.zeros(self._nx,dtype = np.uint)), (self._get_x_coordinates(),np.ones(self._nx,dtype = np.uint)*(self._ny-1)), (np.zeros(self._ny,dtype = np.uint), self._get_y_coordinates()), (np.ones(self._ny,dtype = np.uint)*(self._nx-1),self._get_y_coordinates())] self.__boundary_values = [np.concatenate([v[0] for v in d,u,l,r]), np.concatenate([v[1] for v in d,u,l,r]), np.zeros(2*self._nx+2*self._ny,dtype=np.uint)] self._set_initial_field(settings) self._reset()
for i in range(len(ordered_types)): evaluator.add_rule(pc.DominantType(pc.Types.Imaginary,ordered_types[i]),pc.Types.Complex) evaluator.add_rule(pc.Type(ordered_types[i]),pc.Types.Type) for j in range(i): evaluator.add_rule(pc.DominantType(ordered_types[j],ordered_types[i]),ordered_types[i]) def eval_type_equality(m): tx = m[s.x] ty = m[s.y] if tx in ordered_types and ty in ordered_types: m[s.z] = tx == ty return True return False evaluator.add_rule(pc.equal(s.x,s.y),False,eval_type_equality) evaluator.add_rule(pc.Type(pc.Types.Imaginary*pc.Types.Complex),pc.Types.Complex) evaluator.add_rule(pc.DominantType(s.x,s.x),s.x) evaluator.add_rule(pc.Type(pc.Types.Imaginary),pc.Types.Type) evaluator.add_rule(pc.Type(pc.Type(s.x)),pc.Types.Type) evaluator.add_rule(pc.Type(True),pc.Types.Boolean) evaluator.add_rule(pc.Type(False),pc.Types.Boolean) evaluator.add_rule(pc.Type(s.x),pc.Types.Natural,condition=is_explicit_natural(s.x)) evaluator.add_rule(pc.Type(1/s.x),pc.DominantType(pc.Types.Rational,pc.Type(s.x))) evaluator.add_rule(pc.Type(s.x**s.y),pc.OperationType(pc.Type(s.x)**pc.Type(s.y))) evaluator.add_rule(pc.Type(s.x*s.y),pc.OperationType(pc.Type(s.x)*pc.Type(s.y)))
def is_even(x): return pc.equal(pc.mod(x, 2), 0)
binary_rule(lambda x, y: x**y if exp_length(x, y) < 100 else None), condition=are_explicit_numbers(s.x, s.y)) evaluator.add_rule(pc.mod(s.x, s.y), s.z, binary_rule(lambda x, y: x % y), condition=are_explicit_numbers(s.x, s.y)) evaluator.add_rule(pc.mod(s.x, -s.y), s.z, binary_rule(lambda x, y: x % (-y)), condition=are_explicit_numbers(s.x, s.y)) evaluator.add_rule(pc.mod(-s.x, s.y), s.z, binary_rule(lambda x, y: (-x) % (-y)), condition=are_explicit_numbers(s.x, s.y)) evaluator.add_rule(pc.equal(s.x, s.y), s.z, binary_rule(lambda x, y: x == y), condition=are_explicit_numbers(s.x, s.y)) evaluator.add_rule(pc.equal(s.x, -s.y), False, condition=are_explicit_numbers(s.x, s.y)) evaluator.add_rule(s.x < s.y, s.z, binary_rule(lambda x, y: x < y), condition=are_explicit_numbers(s.x, s.y)) evaluator.add_rule(s.x < -s.y, s.z, binary_rule(lambda x, y: x < -y), condition=are_explicit_numbers(s.x, s.y))
logic_evaluator.add_rule(pc.Not(True), False) logic_evaluator.add_rule(pc.Not(False), True) logic_evaluator.add_rule(pc.And(s.x, True), s.x) logic_evaluator.add_rule(pc.And(s.x, False), False) logic_evaluator.add_rule(pc.Or(s.x, True), True) logic_evaluator.add_rule(pc.Or(s.x, False), s.x) logic_evaluator.add_rule(pc.Not(pc.Not(s.x)), s.x) logic_evaluator.add_rule(pc.And(s.x, pc.Not(s.x)), False) logic_evaluator.add_rule(pc.Or(s.x, pc.Not(s.x)), True) logic_evaluator.add_rule(pc.And(s.x, s.x), s.x) logic_evaluator.add_rule(pc.Or(s.x, s.x), s.x) logic_evaluator.add_rule(pc.equal(s.x, s.x), True) logic_evaluator.add_rule(-s.x < -s.y, s.y < s.x) ''' logic_evaluator.add_rule(s.x<s.x,False); logic_evaluator.add_rule(-s.x<-s.y,s.y<s.x); logic_evaluator.add_rule(s.x<-s.x,False); logic_evaluator.add_rule(-s.x<s.x,False); logic_evaluator.add_rule(s.x<=s.x,True); logic_evaluator.add_rule(s.x>s.y,s.y<s.x); logic_evaluator.add_rule(s.x>=s.y,s.y<=s.x); logic_evaluator.add_rule(s.x<=s.y,pc.Or(s.x<s.y,equal(s.x,s.y))); logic_evaluator.add_rule(And(x<y,y<x),False);
logic_evaluator.add_rule(pc.Not(True),False); logic_evaluator.add_rule(pc.Not(False),True); logic_evaluator.add_rule(pc.And(s.x,True),s.x); logic_evaluator.add_rule(pc.And(s.x,False),False); logic_evaluator.add_rule(pc.Or(s.x,True),True); logic_evaluator.add_rule(pc.Or(s.x,False),s.x); logic_evaluator.add_rule(pc.Not(pc.Not(s.x)),s.x); logic_evaluator.add_rule(pc.And(s.x,pc.Not(s.x)),False); logic_evaluator.add_rule(pc.Or(s.x,pc.Not(s.x)),True); logic_evaluator.add_rule(pc.And(s.x,s.x),s.x); logic_evaluator.add_rule(pc.Or(s.x,s.x),s.x); logic_evaluator.add_rule(pc.equal(s.x,s.x),True); logic_evaluator.add_rule(-s.x<-s.y,s.x<s.y) ''' logic_evaluator.add_rule(s.x<s.x,False); logic_evaluator.add_rule(-s.x<-s.y,s.y<s.x); logic_evaluator.add_rule(s.x<-s.x,False); logic_evaluator.add_rule(-s.x<s.x,False); logic_evaluator.add_rule(s.x<=s.x,True); logic_evaluator.add_rule(s.x>s.y,s.y<s.x); logic_evaluator.add_rule(s.x>=s.y,s.y<=s.x); logic_evaluator.add_rule(s.x<=s.y,pc.Or(s.x<s.y,equal(s.x,s.y)));
] m[s.z] = pc.multiplication(*exponents) canonical_form.add_rule(pc.multiplication(s.x), s.x) canonical_form.add_rule(pc.addition(s.x), s.x) canonical_form.add_rule(pc.exponentiation(s.x), s.x) canonical_form.add_rule(1 / s.x, s.x**-1) canonical_form.add_rule(pc.exp(s.x), pc.e**s.x) canonical_form.add_rule(s.x**s.y, s.z, normalize_exponentiation, condition=pc.equal( pc.DominantType(pc.Type(s.y), pc.Types.Real), pc.Types.Real)) canonical_form.add_rule(pc.exp(s.x), pc.e**s.x) canonical_form.add_rule(pc.sqrt(s.x), s.x**(1 / pc.S(2))) canonical_form.add_rule(s.x > s.y, s.y < s.x) canonical_form.add_rule(s.x >= s.y, s.y <= s.x) canonical_form.add_rule(s.x <= s.y, pc.Or(s.x < s.y, pc.equal(s.x, s.y))) canonical_form.add_rule(pc.unequal(s.x, s.y), pc.Not(pc.equal(s.x, s.y))) canonical_form.add_rule(abs(s.x), pc.Max(s.x, -s.x), condition=pc.equal( pc.DominantType(pc.Type(s.x), pc.Types.Real), pc.Types.Real))
evaluator.add_rule(s.x * 1, s.x) evaluator.add_rule(s.x * 0, 0) evaluator.add_rule(s.x**1, s.x) evaluator.add_rule(s.x**0, 1) evaluator.add_rule(1**s.x, 1) evaluator.add_rule(0**s.x, 0, condition=s.x > 0) factor_evaluator.add_rule(s.x * s.x, s.x**2) evaluator.add_rule(s.x * s.x**-1, 1) evaluator.add_rule( (s.x**s.a)**s.b, s.x**(s.a * s.b), condition=pc.equal(pc.DominantType(pc.Type(s.b), pc.Types.Integer), pc.Types.Integer)) from .numeric_evaluator import is_even, is_uneven from .type_evaluator import issubtype evaluator.add_rule((s.x**s.a)**(s.a**-1), abs(s.x), condition=pc.And(issubtype(s.x, pc.Types.Real), is_even(s.a))) evaluator.add_rule((s.x**s.a)**(s.a**-1), s.x, condition=pc.And(issubtype(s.x, pc.Types.Real), is_uneven(s.a))) evaluator.add_rule((-s.x)**(s.a), s.x**s.a, condition=is_even(s.a)) evaluator.add_rule((-s.x)**(s.a), -(s.x)**s.a, condition=is_uneven(s.a))
def issubtype(x, t): return pc.equal(pc.DominantType(pc.Type(x), t), t)
evaluator.add_rule(pc.Type(ordered_types[i]), pc.Types.Type) for j in range(i): evaluator.add_rule(pc.DominantType(ordered_types[j], ordered_types[i]), ordered_types[i]) def eval_type_equality(m): tx = m[s.x] ty = m[s.y] if tx in ordered_types and ty in ordered_types: m[s.z] = tx == ty return True return False evaluator.add_rule(pc.equal(s.x, s.y), False, eval_type_equality) evaluator.add_rule(pc.Type(pc.Types.Imaginary * pc.Types.Complex), pc.Types.Complex) evaluator.add_rule(pc.DominantType(s.x, s.x), s.x) evaluator.add_rule(pc.Type(pc.Types.Imaginary), pc.Types.Type) evaluator.add_rule(pc.Type(pc.Type(s.x)), pc.Types.Type) evaluator.add_rule(pc.Type(True), pc.Types.Boolean) evaluator.add_rule(pc.Type(False), pc.Types.Boolean) evaluator.add_rule(pc.Type(s.x), pc.Types.Natural, condition=is_explicit_natural(s.x)) evaluator.add_rule(pc.Type(1 / s.x), pc.DominantType(pc.Types.Rational, pc.Type(s.x)))
def is_even(x): return pc.equal(pc.mod(x,2),0)
evaluator.add_rule(-s.x-s.y, -s.z, binary_rule(lambda x, y: x + y), condition=are_explicit_numbers(s.x, s.y)) evaluator.add_rule(s.x - s.y, s.z, binary_rule(lambda x, y: x - y), condition=are_explicit_numbers(s.x, s.y)) evaluator.add_rule(s.x * s.y, s.z, binary_rule(lambda x, y: x * y), condition=are_explicit_numbers(s.x, s.y)) evaluator.add_rule(s.x ** s.a * s.y ** s.a, s.z ** s.a, binary_rule(lambda x, y: x * y), condition=are_explicit_numbers(s.x, s.y)) def exp_length(a,b): import math as m return m.log10(a)*b evaluator.add_rule(s.x ** s.y, s.z, binary_rule(lambda x, y: x ** y if exp_length(x,y)<100 else None), condition=are_explicit_numbers(s.x, s.y)) evaluator.add_rule(s.x ** -s.y, s.z ** -1, binary_rule(lambda x, y: x ** y if exp_length(x,y)<100 else None), condition=are_explicit_numbers(s.x, s.y)) evaluator.add_rule(pc.mod(s.x,s.y), s.z, binary_rule(lambda x, y: x % y), condition=are_explicit_numbers(s.x, s.y)) evaluator.add_rule(pc.mod(s.x,-s.y), s.z, binary_rule(lambda x, y: x % (-y)), condition=are_explicit_numbers(s.x, s.y)) evaluator.add_rule(pc.mod(-s.x,s.y), s.z, binary_rule(lambda x, y: (-x) % (-y)), condition=are_explicit_numbers(s.x, s.y)) evaluator.add_rule(pc.equal(s.x,s.y), s.z, binary_rule(lambda x, y: x == y), condition=are_explicit_numbers(s.x, s.y)) evaluator.add_rule(pc.equal(s.x,-s.y), False, condition=are_explicit_numbers(s.x, s.y)) evaluator.add_rule(s.x < s.y, s.z, binary_rule(lambda x, y: x < y), condition=are_explicit_numbers(s.x, s.y)) evaluator.add_rule(s.x < -s.y, s.z, binary_rule(lambda x, y: x < -y), condition=are_explicit_numbers(s.x, s.y)) evaluator.add_rule(-s.x < s.y, s.z, binary_rule(lambda x, y: -x < y), condition=are_explicit_numbers(s.x, s.y)) #evaluator.add_rule(s.a**s.x*s.b**-s.x, (s.a*s.b**-1)**(s.x),condition=are_explicit_numbers(s.a, s.b)) def is_even(x): return pc.equal(pc.mod(x,2),0) from type_evaluator import issubtype def is_uneven(x):
def issubtype(x,t): return pc.equal(pc.DominantType(pc.Type(x),t),t)
e = m[s.y] exponents = [(arg.args[0]**arg.args[1])**e for arg in f.args if arg.function == pc.exponentiation] exponents += [arg ** e for arg in f.args if isinstance(arg.value, pc.Number) or arg == pc.I] if len(candidates) != len(f.args): exponents += [pc.multiplication(*[arg for arg in f.args if arg not in candidates])**e] m[s.z] = pc.multiplication(*exponents) canonical_form.add_rule(pc.multiplication(s.x),s.x) canonical_form.add_rule(pc.addition(s.x),s.x) canonical_form.add_rule(pc.exponentiation(s.x),s.x) canonical_form.add_rule(1/s.x, s.x**-1) canonical_form.add_rule(pc.exp(s.x), pc.e**s.x) canonical_form.add_rule(s.x**s.y, s.z, normalize_exponentiation,condition=pc.equal(pc.DominantType(pc.Type(s.y),pc.Types.Real),pc.Types.Real)) canonical_form.add_rule(pc.exp(s.x),pc.e**s.x) canonical_form.add_rule(pc.sqrt(s.x),s.x**(1/pc.S(2))) canonical_form.add_rule(s.x>s.y,s.y<s.x) canonical_form.add_rule(s.x>=s.y,s.y<=s.x) canonical_form.add_rule(s.x<=s.y,pc.Or(s.x<s.y,pc.equal(s.x,s.y))) canonical_form.add_rule(pc.unequal(s.x,s.y),pc.Not(pc.equal(s.x,s.y))); canonical_form.add_rule(abs(s.x),pc.Max(s.x,-s.x),condition=pc.equal(pc.DominantType(pc.Type(s.x),pc.Types.Real),pc.Types.Real)) canonical_form.add_rule(pc.Max(s.a,s.b),-pc.Min(-s.a,-s.b))
evaluator.add_rule(s.x+0, s.x) evaluator.add_rule(s.x-s.x, 0) evaluator.add_rule(s.x+s.x, 2*s.x) evaluator.add_rule(s.x*1, s.x) evaluator.add_rule(s.x*0, 0) evaluator.add_rule(s.x**1, s.x) evaluator.add_rule(s.x**0, 1) evaluator.add_rule(1**s.x, 1) evaluator.add_rule(0**s.x, 0,condition=s.x>0) factor_evaluator.add_rule(s.x*s.x, s.x**2) evaluator.add_rule(s.x*s.x**-1, 1) evaluator.add_rule((s.x**s.a)**s.b, s.x**(s.a*s.b),condition=pc.equal(pc.DominantType(pc.Type(s.b),pc.Types.Integer),pc.Types.Integer)) from .numeric_evaluator import is_even,is_uneven from .type_evaluator import issubtype evaluator.add_rule((s.x**s.a)**(s.a**-1), abs(s.x),condition=pc.And( issubtype(s.x,pc.Types.Real),is_even(s.a) ) ) evaluator.add_rule((s.x**s.a)**(s.a**-1), s.x,condition=pc.And( issubtype(s.x,pc.Types.Real),is_uneven(s.a))) evaluator.add_rule((-s.x)**(s.a), s.x**s.a ,condition=is_even(s.a)) evaluator.add_rule((-s.x)**(s.a), -(s.x)**s.a ,condition=is_uneven(s.a)) factor_evaluator.add_rule(s.x**s.n*s.y**-s.n,(s.x*s.y**-1)**s.n,condition=pc.Or(s.y>0,issubtype(s.n,pc.Types.Integer)))