def AssembleNonLinearTerms(self): print("Assembling Non-Linear terms...") starttime = ti.time() i = 0 w = self.w phi = self.phi dxphi = self.dxphi dyphi = self.dyphi A = syp.MutableDenseNDimArray(zeros((self.N, self.N))) B = syp.MutableDenseNDimArray(zeros((self.N, self.N))) while i < self.N: weight_func = w[i] for j in range(self.N): phi1 = phi[j] for k in range(self.N): A[i, j] += self.a_sym[k] * integrate( weight_func * phi1 * dxphi[k] * self.orthW, self.wx, self.x_int, self.wy, self.y_int) B[i, j] += self.a_sym[k] * integrate( weight_func * phi1 * dyphi[k] * self.orthW, self.wx, self.x_int, self.wy, self.y_int) i += 1 print("Done") print("that took:", ti.time() - starttime, "s") return syp.lambdify([self.a_sym], A), syp.lambdify([self.a_sym], B)
def AssembleNonLinearTerms(self): print("Assembling Non-Linear terms...") starttime = ti.time() i = 0 w = array(self.w) phi = array(self.phi) dxphi = array(self.dxphi) dyphi = array(self.dyphi) A = syp.MutableDenseNDimArray(zeros((self.N, self.N))) B = syp.MutableDenseNDimArray(zeros((self.N, self.N))) while i < self.N: weight_func = w[i] for j in range(self.N): for k in range(self.N): A[i, j] += self.a_sym[k] * integrate( weight_func * dyphi[j] * dxphi[k] * self.orthW, wx, x_int, wy, y_int) B[i, j] += self.a_sym[k] * integrate( weight_func * dxphi[j] * dyphi[k] * self.orthW, wx, x_int, wy, y_int) #while i < self.N: # weight_func = w[i]; # for j in range(self.N): # A[i, j] = integrate(weight_func*syp.diff(self.phi[j], xi)*comm1, wx, x_int, wy, y_int); # B[i, j] = integrate(weight_func*syp.diff(self.phi[j], yi)*comm2, wx, x_int, wy, y_int); i += 1 print("Done") print("that took:", ti.time() - starttime, "s") return syp.lambdify([self.a_sym], A * c), syp.lambdify([self.a_sym], B * c)
def Error_test_Momentum(self, mu): t_sym = syp.symbols("t_sym") fakeSolnx = syp.exp(-t_sym) * self.phi[0] fakeSolny = syp.exp(-t_sym) * self.phi[0] fx = syp.lambdify([self.x, self.y, t_sym], fakeSolnx, "numpy") fy = syp.lambdify([self.x, self.y, t_sym], fakeSolny, "numpy") SourceTermx = syp.diff(fakeSolnx, t_sym) + fakeSolnx * syp.diff( fakeSolnx, self.x) + fakeSolny * syp.diff( fakeSolnx, self.y) - mu * (syp.diff(syp.diff(fakeSolnx, self.x), self.x) + syp.diff(syp.diff(fakeSolnx, self.y), self.y)) SourceTermy = syp.diff(fakeSolny, t_sym) + fakeSolnx * syp.diff( fakeSolny, self.x) + fakeSolny * syp.diff( fakeSolny, self.y) - mu * (syp.diff(syp.diff(fakeSolny, self.x), self.x) + syp.diff(syp.diff(fakeSolny, self.y), self.y)) source_x = syp.MutableDenseNDimArray(zeros((1, self.N))[0]) source_y = syp.MutableDenseNDimArray(zeros((1, self.N))[0]) self.a_error[0, 0] = 1.0 self.b_error[0, 0] = 1.0 for i in range(self.N): source_x[i] = integrate(SourceTermx * self.phi[i] * self.orthW, self.wx, self.x_int, self.wy, self.y_int) source_y[i] = integrate(SourceTermy * self.phi[i] * self.orthW, self.wx, self.x_int, self.wy, self.y_int) return fx, fy, syp.lambdify([t_sym], source_x), syp.lambdify([t_sym], source_y)
def init_chr(self): """ Christoffel symbols of the metric. The first index is the upper index. """ self.inv = self.tensor.inv() # Metric inverse chr = sp.MutableDenseNDimArray(np.zeros((self.dim,)*3)) # Initializing symbols dg = sp.MutableDenseNDimArray(np.zeros((self.dim,)*3)) # derivative of metric w.r.t. variables for mu in range(self.dim): dg[:,:,mu] = sp.diff(self.tensor, self.variables[mu]) for nu in range(self.dim): chr[:,:,nu] = 1/2*( self.inv*dg[:,:,nu] + self.inv*dg[:,nu,:] - self.inv*(sp.Matrix(dg[:,nu,:]).transpose())) self.chr = sp.simplify(chr) # store christoffel symbols in object
def init_riemann(self): """ Riemann tensor of the metric, which is a 4-index tensor. """ riemann = sp.MutableDenseNDimArray(np.zeros((self.dim,)*4)) # Inizializing 4-index tensor dchr = sp.MutableDenseNDimArray(np.zeros((self.dim,)*4)) # Derivative of Christoffel symbols if isinstance(self.chr, type(None)): self.init_chr() # Initialize Christoffel symbols (if not already done) for mu in range(self.dim): dchr[:,:,:,mu] = sp.diff(self.chr, self.variables[mu]) for sigma in range(self.dim): for rho in range(self.dim): riemann[rho,sigma,:,:] = dchr[rho,:,sigma,:].transpose() - dchr[rho,:,sigma,:] \ + sp.tensorcontraction(sp.tensorproduct(self.chr[rho,:,:], self.chr[:,:,sigma]),(1,2)) \ - (sp.tensorcontraction(sp.tensorproduct(self.chr[rho,:,:], self.chr[:,:,sigma]),(1,2))).transpose() self.riemann = sp.simplify(riemann)
def as_array(self): dim = len(self.stencil[0]) assert (dim == 2 or dim == 3), "Only 2D or 3D matrix representations are available" max_offset = max( max(abs(e) for e in direction) for direction in self.stencil) shape_list = [] for i in range(dim): shape_list.append(2 * max_offset + 1) number_of_elements = np.prod(shape_list) shape = tuple(shape_list) result = sp.MutableDenseNDimArray([0] * number_of_elements, shape) if dim == 2: for direction, weight in zip(self.stencil, self.weights): result[max_offset - direction[1], max_offset + direction[0]] = weight if dim == 3: for direction, weight in zip(self.stencil, self.weights): result[max_offset - direction[1], max_offset + direction[0], max_offset + direction[2]] = weight return result
def __computeDDG(self): """ G is a list of lenght (m) this function calculates the double gradient of G As we have (n) variables (X), the double gradient of G is: [DDG]_{ijk} = d2(G_i)/d(X_j)d(X_k) """ if self.G is None: self.DDG = None self._DDG0 = np.zeros((0, self.n, self.n)) self.isDDGconst = True else: self.DDG = np.zeros((self.m, self.n, self.n)) self.DDG = sp.MutableDenseNDimArray(self.DDG) for i, g in enumerate(self.G): for j, xj in enumerate(self.X): for k, xk in enumerate(self.X): self.DDG[i, j, k] = sp.diff(g, xj, xk) self.DDG = sp.Array(self.DDG) self.isDDGconst = isMatrixConstant(self.DDG, self.X) if not self.isDDGconst: self._DDG0 = None else: self._DDG0 = np.array(self.DDG, dtype="float32")
def init_ricci(self): """ Ricci tensor of the metric, which is a (dim x dim) tensor. """ self.ricci = sp.MutableDenseNDimArray(np.zeros((self.dim,)*2)) if isinstance(self.riemann, type(None)): self.init_riemann() # Initialize Riemann tensor (if not already done) for mu in range(self.dim): self.ricci += self.riemann[mu,:,mu,:] # Contracting first (upper) and third (lower) indices self.ricci = sp.Matrix(sp.simplify(self.ricci))
def __init__(self, basis_funcs, basis_funcs_p, weighting_funcs, x, y, int_vals, tn): self.phi = basis_funcs self.phi_p = basis_funcs_p self.w = weighting_funcs self.wx, self.x_int, self.wy, self.y_int = int_vals self.x = x self.y = y self.orthW = 1 / (syp.sqrt(1 - x**2) * syp.sqrt(1 - y**2)) self.N = len(basis_funcs) # Number of basis functions self.a_sym = syp.symbols("a_sym0:%d" % self.N) self.b_sym = syp.symbols("b_sym0:%d" % self.N) self.UV = syp.lambdify([self.a_sym, self.x, self.y], array(self.phi).dot(self.a_sym), 'numpy') P = array(self.phi_p).dot(self.a_sym) self.P = syp.lambdify([self.a_sym, self.x, self.y], P, 'numpy') self.a = zeros((self.N, tn)) # Weights for u self.b = zeros((self.N, tn)) # Weights for v self.a_error = zeros((self.N, tn)) # Weights for u_error self.b_error = zeros((self.N, tn)) # Weights for v_error self.p_error = zeros((self.N, tn)) # Weights for p_error self.p = zeros((self.N, tn)) # Weights for p self.p_error = zeros((self.N, tn)) # Weights for p_error self.S_m = syp.MutableDenseNDimArray(zeros((1, self.N))[0]) # Source Term for pressure self.S_mf = 0 # Source Term function for pressure self.dxphi = [] * len(self.phi) # Derivatives of basis functions self.dxphi_p = [] * len(self.phi) self.dyphi = [] * len(self.phi) self.dyphi_p = [] * len(self.phi) print("Computing derivatives of basis functions") for i in range(len(self.phi)): self.dxphi.append(syp.diff(self.phi[i], x)) self.dxphi_p.append(syp.diff(self.phi_p[i], x)) self.dyphi.append(syp.diff(self.phi[i], y)) self.dyphi_p.append(syp.diff(self.phi_p[i], y)) print("Done") self.vorticity = syp.lambdify([self.a_sym, self.b_sym, self.x, self.y], array(self.dyphi).dot(self.a_sym) - array(self.dxphi).dot(self.b_sym), 'numpy') self.grad_v = syp.lambdify([self.a_sym, self.b_sym, self.x, self.y], array(self.dxphi).dot(self.a_sym) + array(self.dyphi).dot(self.b_sym), "numpy")
def Error_test_Pressure(self): t_sym = syp.symbols("t_sym") fakeSoln = syp.exp(-t_sym) * self.phi_p[0] fP = syp.lambdify([self.x, self.y, t_sym], fakeSoln, "numpy") SourceTerm = syp.diff(fakeSoln, t_sym) source = syp.MutableDenseNDimArray(zeros((1, self.N))[0]) self.p_error[0, 0] = 1 for i in range(self.N): source[i] = integrate(SourceTerm * self.phi_p[i] * self.orthW, self.wx, self.x_int, self.wy, self.y_int) return fP, syp.lambdify([t_sym], source, "numpy")
def exterior_derivative(f, basis): r""" :param f: :param basis: :return: """ df = None # Handle the (0)-grade case if isinstance(f, sympy.Expr): n = len(basis) df = [0] * len(basis) for ii in range(n): df[ii] = sympy.diff(f, basis[ii]) df = sympy.MutableDenseNDimArray(df) # Handle the (1+)-grade cases if isinstance(f, sympy.Array) or isinstance(f, sympy.Matrix) or isinstance( f, sympy.MutableDenseNDimArray): n = (len(basis), ) + f.shape df = sympy.MutableDenseNDimArray(sympy.zeros(*n)) if len(n) == 2: for ii in range(df.shape[0]): for jj in range(df.shape[1]): if ii == jj: df[ii, jj] = 0 if ii < jj: df[ii, jj] += sympy.diff(f[jj], basis[ii]) df[ii, jj] += -sympy.diff(f[ii], basis[jj]) df[jj, ii] += -sympy.diff(f[jj], basis[ii]) df[jj, ii] += sympy.diff(f[ii], basis[jj]) # TODO Check if this is valid statement if len(n) > 2: raise NotImplementedError('Grade greater than 2 not implemeted') return df
def pb(f, g, prob): r""" :param f: :param g: :param prob: :return: """ if f is None and g is not None: omega = prob.omega.tomatrix() h = sympy.MutableDenseNDimArray([0] * omega.shape[0]) for i, states_i in enumerate(prob.states + prob.costates): for j, states_j in enumerate(prob.states + prob.costates): h[(i, )] += omega[i, j] * total_derivative( g.expr, states_j.sym) return h raise NotImplementedError
def make_standard_symplectic_form(states, costates): r""" Makes the standard symplectic form. :param states: A list of state variables, :math:`x`. :param costates: A list of co-state variables, :math:`\lambda`. :return: :math:`\omega`, the standard symplectic form """ if len(states) != len(costates): raise ValueError('Number of states and costates must be equal.') n = len(states) omega = sympy.zeros(2 * n, 2 * n) omega = sympy.MutableDenseNDimArray(omega) for ii in range(2 * n): for jj in range(2 * n): if jj - ii == n: omega[ii, jj] = 1 if ii - jj == n: omega[ii, jj] = -1 return omega
def __init__(self, basis_funcs, weighting_funcs, x, y): self.phi = basis_funcs self.w = weighting_funcs self.N = len(basis_funcs) # Number of basis functions self.a_sym = syp.symbols("a_sym0:%d" % self.N) self.a = zeros((self.N, tn)) # Weights for w self.b = zeros((self.N, tn)) # Weights for psi self.S_m = syp.MutableDenseNDimArray(zeros((1, self.N))) # Source Term for Stream Function self.S_mf = 0 # Source Term function for Stream Function self.dxphi = [] * len(self.phi) # Derivatives of basis functions self.dyphi = [] * len(self.phi) self.orthW = 1 / (syp.sqrt(1 - x**2) * syp.sqrt(1 - y**2)) print("Computing derivatives of basis functions") for i in range(len(self.phi)): self.dxphi.append(syp.diff(self.phi[i], x)) self.dyphi.append(syp.diff(self.phi[i], y)) print("Done")
def Source(self): t_sym = syp.symbols("t_sym") a = 0.0001 SourceTermx = (syp.exp(-t_sym**2 / a**2) + syp.exp( -(t_sym - 0.3)**2 / a**2) + syp.exp(-(t_sym - 0.6)**2 / a**2)) * ( 2 * self.phi[0] + 6.7 * self.phi[1] - 3.5 * self.phi[2] + 1.4 * self.phi[3]) source_x = syp.MutableDenseNDimArray(zeros((1, self.N))[0]) for i in range(self.N): source_x[i] = integrate(SourceTermx * self.phi[i] * self.orthW, self.wx, self.x_int, self.wy, self.y_int) return syp.lambdify([t_sym], source_x, "numpy") #def SourceTerm(self, t): # u = self.UV(self.a[:, t], x_mesh, y_mesh); # v = self.UV(self.b[:, t], x_mesh, y_mesh); # b = zeros_like(u); # b[1: -1, 1: -1] = (rho*(1/dt*((u[1: -1, 2:] - u[1: -1, 0: -2])/(2*dx) + (v[2:, 1: -1] - v[0: -2, 1: -1])/(2*dy)) - ((u[1: -1, 2:] - u[1: -1, 0: -2])/(2*dx))**2 - # 2*((u[2:, 1: -1] - u[0: -2, 1: -1])/(2*dy)*(v[1: -1, 2:] - v[1: -1, 0: -2])/(2*dx)) - ((v[2:, 1: -1] - v[0: -2, 1: -1])/(2*dy))**2)); # return b; #def Pressure_Update(p, t, iter_max = 50): # iter = 1; # b = self.SourceTerm(t); # while iter <= iter_max: # pn = p.copy(); # p[1: -1, 1: -1] = (((pn[1: -1, 2:] + pn[1: -1, 0: -2])*dy**2 + (pn[2:, 1: -1] + pn[0: -2, 1: -1])*dx**2)/(2*(dx**2 + dy**2)) - # dx**2*dy**2/(2*(dx**2 + dy**2))*b[1: -1, 1: -1]); # # Wall BC # p[:, -1] = p[:, -2]; # @ x = 1 # p[0, :] = p[1, :]; # @ y = -1 # p[:, 0] = p[:, 1]; # @ x = -1 # p[-1, :] = p[-2, :]; # @ y = 1 # iter += 1 # return p;
#gdown = sym.diag(1/(1+u[0]**2+u[1]**2),1/(1+u[0]**2+u[1]**2)) #gdown = sym.diag(1/(1+u[0]**2+u[1]**2)**2,1/(1+u[0]**2+u[1]**2)**2) #gdown = sym.Matrix([[1/(u[0]**2+u[1]**2+1), 1/(u[0]**2+u[1]**2+1)/2],[1/(u[0]**2+u[1]**2+1)/2, 1/(u[0]**2+u[1]**2+1)]]) gup = gdown**-1 detg = gdown.det() def connection_down(i, j, k): return (sym.diff(gdown[i, j], u[k]) + sym.diff(gdown[i, k], u[j]) - sym.diff(gdown[j, k], u[i])) / 2 ##allocate space to save connections gam_down = sym.MutableDenseNDimArray(range(dim**3), shape=(dim, dim, dim)) gam_up = sym.MutableDenseNDimArray(range(dim**3), shape=(dim, dim, dim)) #compute connection \Gamma_{ijk} for i in range(dim): for j in range(dim): for k in range(j + 1): gam_down[i, j, k] = connection_down(i, j, k) if (j != k): gam_down[i, k, j] = gam_down[i, j, k] def connection_up(i, j, k): gam = 0 for l in range(dim): gam += gam_down[l, j, k] * gup[l, i]
def transformation(self, prob: Problem) -> Problem: if not is_symplectic(prob.omega): logging.warning('BVP is not symplectic. Skipping reduction.') return prob constant_of_motion = prob.constants_of_motion[self.com_index] state_syms = extract_syms(prob.states) costates_syms = extract_syms(prob.costates) parameter_syms = extract_syms(prob.parameters) constant_syms = extract_syms(prob.constants) fn_p = prob.lambdify( [state_syms, costates_syms, parameter_syms, constant_syms], constant_of_motion.expr) states_and_costates = prob.states + prob.costates atoms = constant_of_motion.expr.atoms() atoms2 = set() for atom in atoms: if isinstance(atom, sympy.Symbol) and (atom not in { item.sym for item in prob.parameters + prob.constants }): atoms2.add(atom) atoms = atoms2 solve_for_p = sympy.solve(constant_of_motion.expr - constant_of_motion.sym, atoms, dict=True, simplify=False) if len(solve_for_p) > 1: raise ValueError parameter_index, symmetry, replace_p = 0, 0, None for parameter in solve_for_p[0].keys(): symmetry, symmetry_unit = noether(prob, constant_of_motion) replace_p = parameter for idx, state in enumerate(states_and_costates): if state.sym == parameter: parameter_index = idx prob.parameters.append( NamedDimensionalStruct(constant_of_motion.name, constant_of_motion.units)) symmetry_index = parameter_index - len(prob.states) # Derive the quad # Evaluate int(pdq) = int(PdQ) n = len(prob.quads) symmetry_symbol = sympy.Symbol('_q_{}'.format(n)) _lhs = constant_of_motion.expr / constant_of_motion.sym * symmetry lhs = 0 for idx, state in enumerate(states_and_costates): lhs += sympy.integrate(_lhs[idx], state.sym) lhs, _ = recursive_sub(lhs, solve_for_p[0]) state_syms = extract_syms(prob.states) costates_syms = extract_syms(prob.costates) parameter_syms = extract_syms(prob.parameters) constant_syms = extract_syms(prob.constants) # the_p = [constant_of_motion.sym] fn_q = prob.lambdify( [state_syms, costates_syms, parameter_syms, constant_syms], lhs) replace_q = states_and_costates[symmetry_index].sym solve_for_q = sympy.solve(lhs - symmetry_symbol, replace_q, dict=True, simplify=False) # Evaluate X_H(pi(., c)), pi = O^sharp omega = prob.omega.tomatrix() rvec = sympy.Matrix(([0] * len(states_and_costates))) for ii, state_1 in enumerate(states_and_costates): for jj, state_2 in enumerate(states_and_costates): rvec[ii] += omega[ii, jj] * sympy.diff(constant_of_motion.expr, state_2.sym) symmetry_eom = sym_zero for idx, state in enumerate(states_and_costates): symmetry_eom += state.eom * rvec[idx] # TODO: Figure out how to find units of the quads. This is only works in some specialized cases. symmetry_unit = states_and_costates[symmetry_index].units prob.quads.append( DynamicStruct(str(symmetry_symbol), symmetry_eom, symmetry_unit, local_compiler=prob.local_compiler)) for idx, state in enumerate(states_and_costates): state.eom, _ = recursive_sub(state.eom, solve_for_p[0]) state.eom, _ = recursive_sub(state.eom, solve_for_q[0]) for idx, bc in enumerate(prob.constraints['initial'] + prob.constraints['terminal']): bc.expr, _ = recursive_sub(bc.expr, solve_for_p[0]) bc.expr, _ = recursive_sub(bc.expr, solve_for_q[0]) for idx, law in enumerate(prob.control_law): for jj, symbol in enumerate(law.keys()): prob.control_law[idx][symbol], _ = recursive_sub( prob.sympify(law[symbol]), solve_for_p[0]) # prob.control_law[idx][symbol] = law[symbol] prob.control_law[idx][symbol], _ = recursive_sub( prob.sympify(law[symbol]), solve_for_q[0]) # prob.control_law[idx][symbol] = law[symbol] for idx, com in enumerate(prob.constants_of_motion): if idx != self.com_index: com.expr, _ = recursive_sub(com.expr, solve_for_p[0]) com.expr, _ = recursive_sub(com.expr, solve_for_q[0]) remove_parameter = states_and_costates[parameter_index] remove_symmetry = states_and_costates[symmetry_index] remove_parameter_dict = {'location': None, 'index': None} if remove_parameter in prob.states: remove_parameter_dict = { 'location': 'states', 'index': prob.states.index(remove_parameter) } prob.states.remove(remove_parameter) if remove_parameter in prob.costates: remove_parameter_dict = { 'location': 'costates', 'index': prob.costates.index(remove_parameter) } prob.costates.remove(remove_parameter) remove_symmetry_dict = {'location': None, 'index': None} if remove_symmetry in prob.states: remove_symmetry_dict = { 'location': 'states', 'index': prob.states.index(remove_symmetry) } prob.states.remove(remove_symmetry) if remove_symmetry in prob.costates: remove_symmetry_dict = { 'location': 'costates', 'index': prob.costates.index(remove_symmetry) } prob.costates.remove(remove_symmetry) omega = prob.omega.tomatrix() if parameter_index > symmetry_index: omega.row_del(parameter_index) omega.col_del(parameter_index) omega.row_del(symmetry_index) omega.col_del(symmetry_index) else: omega.row_del(symmetry_index) omega.col_del(symmetry_index) omega.row_del(parameter_index) omega.col_del(parameter_index) prob.omega = sympy.MutableDenseNDimArray(omega) del prob.constants_of_motion[self.com_index] state_syms = extract_syms(prob.states) costates_syms = extract_syms(prob.costates) parameter_syms = extract_syms(prob.parameters) constant_syms = extract_syms(prob.constants) quad_syms = extract_syms(prob.quads) fn_q_inv = prob.lambdify([ state_syms, costates_syms, quad_syms, parameter_syms, constant_syms ], solve_for_q[0][replace_q]) fn_p_inv = prob.lambdify( [state_syms, costates_syms, parameter_syms, constant_syms], solve_for_p[0][replace_p]) prob.sol_map_chain.append( MF(remove_parameter_dict, remove_symmetry_dict, fn_p, fn_q, fn_p_inv, fn_q_inv)) return prob
crR13Uc = smarr.MutableDenseNDimArray([crR13Uc_x, crR13Uc_y, crR13Uc_z]) crR02Uc = smarr.MutableDenseNDimArray([crR02Uc_x, crR02Uc_y, crR02Uc_z]) crR02R13 = smarr.MutableDenseNDimArray([crR02R13_x, crR02R13_y, crR02R13_z]) for cc in range(3): Der = Der.subs(eq_crR02Uc[cc], crR02Uc[cc]) Der = Der.subs(eq_crR13Uc[cc], crR13Uc[cc]) Der = Der.subs(eq_crR02R13[cc], crR02R13[cc]) norm_crR02R13 = sm.symbols('norm_crR02R13', real=True) cub_crR02R13 = sm.symbols('cub_crR02R13', real=True) Der = Der.subs(sm.sqrt(crR02R13_x**2 + crR02R13_y**2 + crR02R13_z**2), norm_crR02R13) Der = Der.subs(norm_crR02R13**3, cub_crR02R13) # other products eq_Acr = linfunc.cross_product(crR02R13, R13) Acr_x, Acr_y, Acr_z = sm.symbols('Acr_x Acr_y Acr_z', real=True) Acr = sm.MutableDenseNDimArray([Acr_x, Acr_y, Acr_z]) for cc in range(3): Der = Der.subs(eq_Acr[cc], Acr[cc]) eq_Bcr = linfunc.cross_product(crR02R13, R02) Bcr_x, Bcr_y, Bcr_z = sm.symbols('Bcr_x Bcr_y Bcr_z', real=True) Bcr = sm.MutableDenseNDimArray([Bcr_x, Bcr_y, Bcr_z]) for cc in range(3): Der = Der.subs(eq_Bcr[cc], Bcr[cc]) eq_Cdot = linfunc.scalar_product(crR02R13, Uc) Cdot = sm.symbols('Cdot', real=True) Der = Der.subs(eq_Cdot, Cdot)
def MatrixSymbolicFunction2(name, n, m): M = np.zeros((n, n), dtype="object") for i in range(n): for j in range(m): M[i, j] = sp.Function(f"{name}{i}{j}") return sp.MutableDenseNDimArray(M)
def MatrixSymbolicFunction1(name, n): M = np.zeros(n, dtype="object") for i in range(n): M[i] = sp.Function(f"{name}{i}") return sp.MutableDenseNDimArray(M)