def build_orthogonal_basis(n, p): # Build a basis from total degree monomials monomial_basis = [] x = [Symbol('x%d' % k) for k in range(1,n+1)] for alpha in MultiIndex(n, p): term = 1 for j in range(n): term *= x[j]**alpha[j] monomial_basis.append(term) # Now build the corresponding mass matrix M = zeros(len(monomial_basis), len(monomial_basis)) for i, psi1 in enumerate(monomial_basis): for j, psi2 in enumerate(monomial_basis): if i <= j: out = psi1*psi2 for k in range(n): out = integrate(out, (x[k], -1,1)) M[i,j] = out M[j,i] = out R = M.cholesky().inv() # Now build our orthogonal basis basis_terms = [] basis = [] for i in range(len(monomial_basis)): term = 0 for j, psi in enumerate(monomial_basis): term += R[i,j]*psi basis.append(term) # Make the sparse version term = Poly(term, x) term = [ (alpha, float(term.coeff_monomial(alpha)) ) for alpha in term.monoms()] basis_terms.append(term) # Now build the derivatives basis_terms_der = [] for i in range(n): basis_terms_der_curr = [] for psi in basis: # Make the sparse version term = Poly(diff(psi, x[i]), x) term = [ (alpha, float(term.coeff_monomial(alpha)) ) for alpha in term.monoms()] basis_terms_der_curr.append(term) basis_terms_der.append(basis_terms_der_curr) return basis_terms, basis_terms_der
def _simpsol(soleq): lhs = soleq.lhs sol = soleq.rhs sol = powsimp(sol) gens = list(sol.atoms(exp)) p = Poly(sol, *gens, expand=False) gens = [factor_terms(g) for g in gens] if not gens: gens = p.gens syms = [Symbol('C1'), Symbol('C2')] terms = [] for coeff, monom in zip(p.coeffs(), p.monoms()): coeff = piecewise_fold(coeff) if type(coeff) is Piecewise: coeff = Piecewise(*((ratsimp(coef).collect(syms), cond) for coef, cond in coeff.args)) else: coeff = ratsimp(coeff).collect(syms) monom = Mul(*(g**i for g, i in zip(gens, monom))) terms.append(coeff * monom) return Eq(lhs, Add(*terms))