Source code for snowdrop.src.preprocessor.util

"""
Classes define user functions.

Created on Thu Mar 11 22:08:13 2021

@author: A.Goumilevski
"""
import os
import sympy as sp
#from numpy import abs as Abs,sign,exp
from sympy import Function,simplify,Abs,sign,exp,erf
from sympy import Ge,Gt,Le,Lt,Eq,N,Heaviside,Min,Max
from sympy.abc import x,y,z


# Positive = sp.lambdify(x, sign(x)+sign(Abs(x))) 
# Negative = sp.lambdify(x, -sign(x)+sign(Abs(x))) 

[docs] class Positive(Function): """Evaluate if expression is positive."""
[docs] @classmethod def eval(cls,x): """ Evaluate expression `x`. Parameters: cls : `Function` object Instance of `Function` class. x : float Expression value. Returns: f : float Returns one if x is non-negative and zero otherwise. """ cls.x = x if sign(x)+sign(Abs(x)): f = 1 else: f = 0 return f
[docs] @classmethod def fdiff(cls,argindex): """ Compute drivative of `a` or `b` expression. Parameters: cls : `Function` object Instance of `Function` class. argindex : int Indexes of the args, starting at 1 Returns: diff : Expression Returns zero. """ return 0
[docs] class Negative(Function): """Evaluate if expression is negative."""
[docs] @classmethod def eval(cls,x): """ Evaluate expression `x`. Parameters: cls : `Function` object Instance of `Function` class. x : float Expression value. Returns: f : float Returns one if x is negative and zero otherwise. """ if sign(x)+sign(Abs(x)): f = 0 else: f = 1 return f
[docs] @classmethod def fdiff(cls,argindex): """ Compute drivative of `a` or `b` expression. Parameters: cls : `Function` object Instance of `Function` class. argindex : int Indexes of the args, starting at 1 Returns: diff : Expression Returns zero. """ return 0
[docs] class PNORM(Function): """Evaluate Troll's normal function."""
[docs] @classmethod def eval(cls,x): """ Return value based on condition evaluation. Parameters: cls : `Function` object Instance of `Function` class. condition : float Expression value. x : float Expression value. Returns: f : float Returns `x` if `condition` is non-negative and zero otherwise. """ cls.x = x f = exp(-0.5*x*x) return f
[docs] @classmethod def fdiff(cls,z): """ Compute drivative of `z` expression. Parameters: cls : `Function` object Instance of `Function` class. z : symbol Take derivative w.r.t. symbol `z` Returns: diff : Expression Derivative w.r.t `z`. """ diff = -z*exp(-0.5*z*z) return diff
[docs] class IfThen(Function): """Evaluate codition and return value based on this condition."""
[docs] @classmethod def eval(cls,condition,x): """ Return value based on condition evaluation. Parameters: cls : `Function` object Instance of `Function` class. condition : float Expression value. x : float Expression value. Returns: f : float Returns `x` if `condition` is non-negative and zero otherwise. """ cls.condition = condition cls.x = x if Positive(condition): f = x else: f = 0 return f
[docs] @classmethod def fdiff(cls,argindex): """ Compute drivative of `x` expression. Parameters: cls : `Function` object Instance of `Function` class. argindex : int Indexes of the args, starting at 1 Returns: diff : Expression Derivative w.r.t `x` if `condition` is non-negative and zero otherwise. """ if Positive(cls.condition): diff = sp.diff(cls,cls.x) else: diff = 0 return diff
[docs] class IfThenElse(Function): """Evaluate codition and return value based on this condition."""
[docs] @classmethod def eval(cls,condition,a,b): """ Return value based on condition evaluation. Parameters: cls : `Function` object Instance of `Function` class. condition : float Expression value. a : float Expression value. b : float Expression value. Returns: f : float Returns `a` if `condition` is non-negative and `b` otherwise. """ cls.condition = condition cls.a = a cls.b = b if Positive(condition): return a else: return b
[docs] @classmethod def fdiff(cls,argindex): """ Compute drivative of `a` or `b` expression. Parameters: cls : `Function` object Instance of `Function` class. argindex : int Indexes of the args, starting at 1 Returns: diff : Expression Derivative w.r.t `a` if `condition` is non-negative and derivative w.r.t `b` otherwise. """ if argindex == 1: diff = 0 elif Positive(condition): if argindex == 2: diff = sp.diff(cls,cls.a) elif argindex == 3: diff = sp.diff(cls,cls.b) else: if argindex == 2: diff = sp.diff(cls,cls.b) elif argindex == 3: diff = sp.diff(cls,cls.a) return diff
[docs] class myzif(Function):
[docs] @classmethod def eval(cls,x): """ Return value based on user's function evaluation. Parameters: cls : `Function` object Instance of `Function` class. x : float Expression value. """ y = x*(1+erf(3.*x))/2. return y
[docs] class Min1(Function):
[docs] @classmethod def eval(cls,a,b): """ Return minimum of two values. Parameters: cls : `Function` object Instance of `Function` class. a : float Expression value. b : float Expression value. """ if a <= b: y = a else: y = b return y
[docs] class Max1(Function):
[docs] @classmethod def eval(cls,a,b): """ Return minimum of two values. Parameters: cls : `Function` object Instance of `Function` class. a : float Expression value. b : float Expression value. """ if a >= b: y = a else: y = b return y
[docs] def updateFiles(model,path): """ Update python generated files. Parameters: model : Model Model object. path : str Path to folder. """ try: src_dynamic = model.functions_src['f_dynamic_src'] src_sparse = model.functions_src['f_sparse_src'] src_ss = model.functions_src['f_steady_src'] src_jacob = model.functions_src['f_jacob_src'] src_rhs = model.functions_src['f_rhs_src'] file_path = os.path.abspath(os.path.join(path,'f_dynamic.py')) with open(file_path, 'w') as f: f.write(src_dynamic) if not src_sparse is None: file_path = os.path.abspath(os.path.join(path,'f_sparse.py')) with open(file_path, 'w') as f: f.write(src_sparse) file_path = os.path.abspath(os.path.join(path,'f_steady.py')) with open(file_path, 'w') as f: f.write(src_ss) file_path = os.path.abspath(os.path.join(path,'f_jacob.py')) with open(file_path, 'w') as f: f.write(src_jacob) file_path = os.path.abspath(os.path.join(path,'f_rhs.py')) with open(file_path, 'w') as f: f.write(src_rhs) except: pass
if __name__ == "__main__": "Test user functions." z = -1 # f = PNORM # s=f(x) # print(s) # s=sp.diff(f(x),x) # print(s) # f = sp.lambdify(x, x>0) # s = f(z) # print(s) # f = Positive # s = f(z) # print(s) # s = sp.diff(f(x),x) # print(s) # print() # f = Negative # s = f(z) # print(s) # s = sp.diff(f(x),x) # print(s) # print() # f = IfThen # s = f(z,x**2*(x+y)) # print(s) # s = sp.diff(f(z,x**2*(x+y)),x) # print(s) # s = sp.diff(f(z,x**2*(x+y)),y) # print(s) # print() # f = IfThenElse # s=f(z,x**2*(x+y),y**3) # print(s) # s=sp.diff(f(z,x**2*(x+y),y**3),x) # print(s) # s=sp.diff(f(z,x**2*(x+y),y**3),y) # print(s) # ns = {"IfThenElse":IfThenElse,"Positive":Positive,"z":z} # e = "IfThenElse(z,x**2*(x+y),y**3)" # eq = sp.sympify(e,locals=ns) # s = eq.diff(x) # print(s) # f = myzif # s=f(x) # print(s) # s=sp.diff(f(x),x) # print(s) # eq = Min(x**2*(x+y),y**3) # print(eq.diff(y)) # e = "Min(x**2*(x+y),y**3)" # eq = sp.sympify(e) # s = eq.diff(x) # print(s) # print(Min(1,2)) ns={"T":x,"T_rule":y,"T_ceiling":z} e = "T-Min(T_rule, T*T_ceiling)" #eq = sp.sympify(e) eq = sp.sympify(e,locals=ns) print(eq.diff(x))