def add_dissipations(self, w, z): """ Add dissipative components with variable :math:`\\mathbf{w}` and \ dissipative function :math:`\\mathrm{z}(\\mathbf{w})`. * Variable :math:`\\mathbf{w}` is appended to the current list of \ variables symbols :code:`core.w`, * Expression :math:`\\mathrm{z}` is appended to the current list of \ dissipative functions :code:`core.z`. Parameters ---------- w: one or several pyphs.symbols Variable symbols. Can be a single symbol or a list of symbols. z: one or several sympy.Expr Must be a valid dissipative function with respect to the variable \ :math:`\\mathbf{w}` with :math:`\\nabla\\mahtrm z(\\mathbf{w}) \succeq 0`. """ try: w = _assert_vec(w) z = _assert_vec(z) assert len(w) == len(z), 'w and z should have same dimension.' except: _assert_expr(w) _assert_expr(w) w = (w, ) z = (z, ) self.w += list(w) self.z += list(map(simplify, list(z)))
def add_storages(self, x, H): """ Add storage components with state :math:`\\mathbf{x}` and energy \ :math:`\\mathrm{H}(\\mathbf{x}) \geq 0`. * State :math:`\\mathbf{x}` is appended to the current list of \ states symbols :code:`core.x`, * Expression :math:`\\mathrm{H}` is added to the current expression \ of the Hamiltonian :code:`core.H`. Parameters ---------- x: one or several pyphs.symbols State symbols. Can be a single symbol or a list of symbols. H: sympy.Expr Must be a valid storage function with respect to the state \ :math:`\\mathbf{x}` with :math:`\\nabla^2\\mahtrm H(\\mathbf{x}) \succeq 0`. """ try: hasattr(x, 'index') x = _assert_vec(x) except: _assert_expr(x) x = (x, ) self.x += list(x) self.H += H self.H.simplify()
def _append_funcs_init(nums, files, objlabel): title = "\n\n// Functions Results Initialisation\n" files['cpp']['init'] += title for name in nums.names: if name in nums.method.funcs_names: expr = getattr(nums.method, name + '_expr') try: _assert_expr(expr) cpp = _str_scal_func_init_cpp(name) except AssertionError: cpp = _str_mat_func_init_cpp(nums.method, name) files['cpp']['init'] += cpp
def _append_funcs_defs(nums, files): title = "\n\n// Functions Results Definitions\n" files['h']['private'] += title for name in nums.names: if name in nums.method.funcs_names: expr = getattr(nums.method, name + '_expr') try: _assert_expr(expr) files['h']['private'] += '\ndouble _{0};'.format(name) except AssertionError: mat = sympy.Matrix(getattr(nums.method, name + '_expr')) mtype = matrix_type(mat.shape[0], mat.shape[1]) files['h']['private'] += '\n{0} _{1};'.format(mtype, name)
def _append_funcs_get(nums, files, objlabel): title = "\n\n// Functions Results Accessors\n" files['h']['public'] += title files['cpp']['public'] += title for name in nums.names: if name in nums.method.funcs_names: expr = getattr(nums.method, name + '_expr') try: _assert_expr(expr) h, cpp = _str_scal_func_get(name, objlabel) except AssertionError: h, cpp = _str_mat_func_get(nums.method, name, objlabel) files['h']['public'] += h files['cpp']['public'] += cpp
def form(name, obj): """ Pyphs formating of argument format 'obj' to a symbol Parameters ---------- argname : str argobj : {str, float, (str, float)} Outputs ------- symb : PHSCore.symbol subs : PHSCore.subs """ if isinstance(obj, tuple): assert isinstance(obj[0], str), 'for tupple parameter, \ first element should be a str, got {0!s}'.format(type(obj[0])) try: assert isinstance(obj[1], (float, int)), 'for tupple parameter, \ second element should be numeric, got\ {0!s}'.format(type(obj[1])) except AssertionError: _assert_expr(obj[1]) string = obj[0] symb = symbols(string) sub = {symb: obj[1]} par = None elif isinstance(obj, (float, int)): string = name symb = symbols(string) sub = {symb: obj} par = None elif isinstance(obj, str): string = obj symb = symbols(string) sub = {} par = symb else: _assert_expr(obj) string = name symb = symbols(string) sub = {symb: obj} par = None return symb, sub, par
def discrete_gradient(H, x, dx, numtol=EPS): """ Symbolic computation here. Return the discrete gradient of scalar function\ H between x and x+dx, with H separable with respect to x: H = sum_i[H_i(x_i)]. Parameters ----------- H : sympy.expression Scalar function of x. x : list or sympy.Matrix 1 dimensional array of sympy symbols. dx : list or sympy.Matrix 1 dimensional array of sympy symbols. Output ------- gradd : list discrete gradient of H with 'gradd[i] = H.diff(x) if norm(dx[i]) < numtol else \ (H(x+dx[i])-H(x))/dx[i]' """ x = _assert_vec(x) dx = _assert_vec(dx) _assert_expr(H) nx = len(x) assert len(dx) == nx, \ 'dim(dx)={0!s} is not equal to dim(x)={1!s}'.format(len(dx), nx) dxHd = [] for i in range(nx): Hpost = H.subs(x[i], x[i] + dx[i]) dxh = simplify((Hpost - H) / dx[i]) dxh0 = simplify(H.diff(x[i]).doit()) dxhi = sympy.Piecewise((dxh, dx[i] < -numtol), (dxh0, dx[i] < numtol), (dxh, True)) dxHd.append(dxhi) return simplify(dxHd)
def gradient_theta(H, x, dx, theta=0.): """ Symbolic computation here. Return the evaluation of the gradient of scalar\ function H at x+theta*dx. Parameters ----------- H : sympy.expression Scalar function of x. x : list or sympy.Matrix 1 dimensional array of sympy symbols. dx : list or sympy.Matrix 1 dimensional array of sympy symbols. Output ------- gradd : list discrete gradient of H with 'gradd[i] = [H.diff(x).subs(x, x+theta*dx)]_i' """ x = _assert_vec(x) dx = _assert_vec(dx) _assert_expr(H) nx = len(x) assert len(dx) == nx, \ 'dim(dx)={0!s} is not equal to dim(x)={1!s}'.format(len(dx), nx) dxHd = gradient(H, x) subs = {} for i, (xi, dxi) in enumerate(zip(x, dx)): subs[xi] = xi + theta * dxi for i, dxh in enumerate(dxHd): dxHd[i] = dxh.subs(subs) return simplify(dxHd)
def add_parameters(self, p): """ Add a continuously varying parameter. Usage ----- core.add_parameters(p) Parameter ---------- p: sympy.Symbol or list of sympy.Symbol Single symbol or list of symbol associated with continuously \ varying parameter(s). """ try: hasattr(p, '__len__') p = _assert_vec(p) except: _assert_expr(p) p = (p, ) self.p += list(p)
def add_ports(self, u, y): """ Add one or several ports with input u and output y. Parameters ---------- u : str, symbol, or list of y : str, symbol, or list of """ if hasattr(u, '__len__'): u = _assert_vec(u) y = _assert_vec(y) assert len(u) == len(y), 'u and y should have same dimension.' else: _assert_expr(u) _assert_expr(y) u = (u, ) y = (y, ) self.u += list(u) self.y += list(y)
def add_storages(self, x, H): """ Add a storage component with state x and energy H. * State x is append to the current list of states symbols, * Expression H is added to the current expression of Hamiltonian. Parameters ---------- x : str, symbol, or list of H : sympy.Expr """ try: hasattr(x, 'index') x = _assert_vec(x) except: _assert_expr(x) x = (x, ) self.x += list(x) self.H += H self.H.simplify()
def add_dissipations(self, w, z): """ Add a dissipative component with dissipation variable w and \ dissipation function z. Parameters ---------- w : str, symbol, or list of z : sympy.Expr or list of """ try: w = _assert_vec(w) z = _assert_vec(z) assert len(w) == len(z), 'w and z should have same dimension.' except: _assert_expr(w) _assert_expr(w) w = (w, ) z = (z, ) self.w += list(w) self.z += map(simplify, list(z))
def gradient(scalar_func, vars_, dosimplify=True): """ Symbolic computation here. Return the gradient of scalar function H w.r.t. vector variable x. Parameters ----------- scalar_func : sympy.Expr Scalar function. vars_ : list or sympy.Matrix array of sympy symbols for variables dosimplify : bool Apply simplification Output ------- grad : list gradient of H with grad[i] = H.diff(x[i]) """ vars_ = _assert_vec(vars_) _assert_expr(scalar_func) nvars = len(vars_) grad = [0, ]*nvars for i in range(nvars): grad[i] = scalar_func.diff(vars_[i]).doit() if dosimplify: grad = simplify(grad) return grad