def get_full_christoffel(psi, p_expo): """ This computes and returns the "second" Christoffel symbols (i.e. Gamma^i_jk) built from the original, "full," nonconformal metric (called gamma_ij most of the time). It will compute the second Christoffels (C2) built from the conformal metric it they have not already been computed. The notation should be understood such that for C3[i,j,k] the first index (i) is the "up" index and the last two (j,k) are the "down" indices. As this uses the metric, it assumes the metric has been set, e.g., dendro_ccz4.set_metric(gt); """ global metric, inv_metric, undef, C1, C2, C3, d #global metric, inv_metric, undef, C2, C3, d if C3 == undef: C3 = MutableDenseNDimArray(range(27), (3, 3, 3)) if C2 == undef: get_second_christoffel() for k in e_i: for j in e_i: for i in e_i: # C3[i, j, k] = C2[i, j, k] - 1/(2*chi)*(KroneckerDelta(i, j) * d(k, chi) + #C3[i, j, k] = C2[i, j, k] + 0.5*p_expo*(psi**(p_expo))*(KroneckerDelta(i, j) * d(k, psi) + C3[i, j, k] = C2[i, j, k] + 0.5*p_expo/psi*(KroneckerDelta(i, j) * d(k, psi) + KroneckerDelta(i, k) * d(j, psi) - metric[j, k]*sum([inv_metric[i, m]*d(m, psi) for m in e_i]) ) return C3
def test_complicated_derivative_with_Indexed(): x, y = symbols("x,y", cls=IndexedBase) sigma = symbols("sigma") i, j, k = symbols("i,j,k") m0, m1, m2, m3, m4, m5 = symbols("m0:6") f = Function("f") expr = f((x[i] - y[i])**2 / sigma) _xi_1 = symbols("xi_1", cls=Dummy) assert expr.diff(x[m0]).dummy_eq( (x[i] - y[i])*KroneckerDelta(i, m0)*\ 2*Subs( Derivative(f(_xi_1), _xi_1), (_xi_1,), ((x[i] - y[i])**2/sigma,) )/sigma ) assert expr.diff(x[m0]).diff(x[m1]).dummy_eq( 2*KroneckerDelta(i, m0)*\ KroneckerDelta(i, m1)*Subs( Derivative(f(_xi_1), _xi_1), (_xi_1,), ((x[i] - y[i])**2/sigma,) )/sigma + \ 4*(x[i] - y[i])**2*KroneckerDelta(i, m0)*KroneckerDelta(i, m1)*\ Subs( Derivative(f(_xi_1), _xi_1, _xi_1), (_xi_1,), ((x[i] - y[i])**2/sigma,) )/sigma**2 )
def apply(given, i=None, j=None): assert given.is_Equality x_set_comprehension, interval = given.args n = interval.max() + 1 assert interval.min() == 0 assert len(x_set_comprehension.limits) == 1 k, a, b = x_set_comprehension.limits[0] assert b - a == n - 1 x = LAMBDA(x_set_comprehension.function.arg, *x_set_comprehension.limits).simplify() if j is None: j = Symbol.j(domain=[0, n - 1], integer=True, given=True) if i is None: i = Symbol.i(domain=[0, n - 1], integer=True, given=True) assert j >= 0 and j < n assert i >= 0 and i < n index = index_function(n) di = index[i](x[:n]) dj = index[j](x[:n]) return Equality(KroneckerDelta(di, dj), KroneckerDelta(i, j), given=given)
def _eval_derivative(self, v): from sympy import Sum, symbols, Dummy if not isinstance(v, MatrixElement): from sympy import MatrixBase if isinstance(self.parent, MatrixBase): return self.parent.diff(v)[self.i, self.j] return S.Zero M = self.args[0] if M == v.args[0]: return KroneckerDelta(self.args[1], v.args[1])*KroneckerDelta(self.args[2], v.args[2]) if isinstance(M, Inverse): i, j = self.args[1:] i1, i2 = symbols("z1, z2", cls=Dummy) Y = M.args[0] r1, r2 = Y.shape return -Sum(M[i, i1]*Y[i1, i2].diff(v)*M[i2, j], (i1, 0, r1-1), (i2, 0, r2-1)) if self.has(v.args[0]): return None return S.Zero
def _eval_innerproduct_JzBra(self, bra, **hints): result = KroneckerDelta(self.j, bra.j) if bra.dual_class() is not self.__class__: result *= self._represent_JzOp(None)[bra.j-bra.m] else: result *= KroneckerDelta(self.j, bra.j) * KroneckerDelta(self.m, bra.m) return result
def get_complete_christoffel(chi): """ Computes and returns the second Christoffel Symbols. Assumes the metric has been set. Will compute the first/second Christoffel if not already computed. e.g., dendro.set_metric(gt); C2_spatial = dendro.get_complete_christoffel(); """ global metric, inv_metric, undef, C1, C2, C3, d if C3 == undef: C3 = MutableDenseNDimArray(range(27), (3, 3, 3)) if C2 == undef: get_second_christoffel() for k in e_i: for j in e_i: for i in e_i: # C3[i, j, k] = C2[i, j, k] - 1/(2*chi)*(KroneckerDelta(i, j) * d(k, chi) + C3[i, j, k] = C2[i, j, k] - 0.5/(chi)*(KroneckerDelta(i, j) * d(k, chi) + KroneckerDelta(i, k) * d(j, chi) - metric[j, k]*sum([inv_metric[i, m]*d(m, chi) for m in e_i]) ) return C3
def test_matrixelement_diff(): dexpr = diff((D*w)[k,0], w[p,0]) assert w[k, p].diff(w[k, p]) == 1 assert w[k, p].diff(w[0, 0]) == KroneckerDelta(0, k, (0, n-1))*KroneckerDelta(0, p, (0, 0)) _i_1 = Dummy("_i_1") assert dexpr.dummy_eq(Sum(KroneckerDelta(_i_1, p, (0, n-1))*D[k, _i_1], (_i_1, 0, n - 1))) assert dexpr.doit() == D[k, p]
def _check_varsh_872_9(term_list): # Sum( CG(a,alpha,b,beta,c,gamma)*CG(a,alpha',b,beta',c,gamma), (gamma, -c, c), (c, abs(a-b), a+b)) a, alpha, alphap, b, beta, betap, c, gamma, lt = map( Wild, ('a', 'alpha', 'alphap', 'b', 'beta', 'betap', 'c', 'gamma', 'lt')) # Case alpha==alphap, beta==betap # For numerical alpha,beta expr = lt * CG(a, alpha, b, beta, c, gamma)**2 simp = 1 sign = lt / abs(lt) x = abs(a - b) y = abs(alpha + beta) build_expr = a + b + 1 - Piecewise((x, x > y), (0, Eq(x, y)), (y, y > x)) index_expr = a + b - c term_list, other1 = _check_cg_simp(expr, simp, sign, lt, term_list, (a, alpha, b, beta, c, gamma, lt), (a, alpha, b, beta), build_expr, index_expr) # For symbolic alpha,beta x = abs(a - b) y = a + b build_expr = (y + 1 - x) * (x + y + 1) index_expr = (c - x) * (x + c) + c + gamma term_list, other2 = _check_cg_simp(expr, simp, sign, lt, term_list, (a, alpha, b, beta, c, gamma, lt), (a, alpha, b, beta), build_expr, index_expr) # Case alpha!=alphap or beta!=betap # Note: this only works with leading term of 1, pattern matching is unable to match when there is a Wild leading term # For numerical alpha,alphap,beta,betap expr = CG(a, alpha, b, beta, c, gamma) * CG(a, alphap, b, betap, c, gamma) simp = KroneckerDelta(alpha, alphap) * KroneckerDelta(beta, betap) sign = sympify(1) x = abs(a - b) y = abs(alpha + beta) build_expr = a + b + 1 - Piecewise((x, x > y), (0, Eq(x, y)), (y, y > x)) index_expr = a + b - c term_list, other3 = _check_cg_simp( expr, simp, sign, sympify(1), term_list, (a, alpha, alphap, b, beta, betap, c, gamma), (a, alpha, alphap, b, beta, betap), build_expr, index_expr) # For symbolic alpha,alphap,beta,betap x = abs(a - b) y = a + b build_expr = (y + 1 - x) * (x + y + 1) index_expr = (c - x) * (x + c) + c + gamma term_list, other4 = _check_cg_simp( expr, simp, sign, sympify(1), term_list, (a, alpha, alphap, b, beta, betap, c, gamma), (a, alpha, alphap, b, beta, betap), build_expr, index_expr) return term_list, other1 + other2 + other4
def column_transformation(*limits): n = limits[0][-1] + 1 (i, *_), (j, *_) = limits # return Identity(n) + LAMBDA[j:n, i:n](Piecewise((0, i < n - 1), (KroneckerDelta(j, n - 1) - 1, True))) # return Identity(n) + LAMBDA[j:n, i:n](Piecewise((KroneckerDelta(j, n - 1) - 1, Equality(i, n - 1)), (0, True))) return Identity(n) + LAMBDA[j:n, i:n](KroneckerDelta(i, n - 1) * (KroneckerDelta(j, n - 1) - 1)) return LAMBDA( Piecewise((KroneckerDelta(i, j), i < n - 1), (2 * KroneckerDelta(j, n - 1) - 1, True)), *limits)
def test_codegen_array_parse(): expr = M[i, j] assert _codegen_array_parse(expr) == (M, (i, j)) expr = M[i, j] * N[k, l] assert _codegen_array_parse(expr) == (CodegenArrayTensorProduct(M, N), (i, j, k, l)) expr = M[i, j] * N[j, k] assert _codegen_array_parse(expr) == (CodegenArrayDiagonal( CodegenArrayTensorProduct(M, N), (1, 2)), (i, k, j)) expr = Sum(M[i, j] * N[j, k], (j, 0, k - 1)) assert _codegen_array_parse(expr) == (CodegenArrayContraction( CodegenArrayTensorProduct(M, N), (1, 2)), (i, k)) expr = M[i, j] + N[i, j] assert _codegen_array_parse(expr) == (CodegenArrayElementwiseAdd(M, N), (i, j)) expr = M[i, j] + N[j, i] assert _codegen_array_parse(expr) == (CodegenArrayElementwiseAdd( M, CodegenArrayPermuteDims(N, Permutation([1, 0]))), (i, j)) expr = M[i, j] + M[j, i] assert _codegen_array_parse(expr) == (CodegenArrayElementwiseAdd( M, CodegenArrayPermuteDims(M, Permutation([1, 0]))), (i, j)) expr = (M * N * P)[i, j] assert _codegen_array_parse(expr) == (CodegenArrayContraction( CodegenArrayTensorProduct(M, N, P), (1, 2), (3, 4)), (i, j)) expr = expr.function # Disregard summation in previous expression ret1, ret2 = _codegen_array_parse(expr) assert ret1 == CodegenArrayDiagonal(CodegenArrayTensorProduct(M, N, P), (1, 2), (3, 4)) assert str(ret2) == "(i, j, _i_1, _i_2)" expr = KroneckerDelta(i, j) * M[i, k] assert _codegen_array_parse(expr) == (M, ({i, j}, k)) expr = KroneckerDelta(i, j) * KroneckerDelta(j, k) * M[i, l] assert _codegen_array_parse(expr) == (M, ({i, j, k}, l)) expr = KroneckerDelta(j, k) * (M[i, j] * N[k, l] + N[i, j] * M[k, l]) assert _codegen_array_parse(expr) == (CodegenArrayDiagonal( CodegenArrayElementwiseAdd( CodegenArrayTensorProduct(M, N), CodegenArrayPermuteDims(CodegenArrayTensorProduct(M, N), Permutation(0, 2)(1, 3))), (1, 2)), (i, l, frozenset({j, k}))) expr = KroneckerDelta(j, m) * KroneckerDelta( m, k) * (M[i, j] * N[k, l] + N[i, j] * M[k, l]) assert _codegen_array_parse(expr) == (CodegenArrayDiagonal( CodegenArrayElementwiseAdd( CodegenArrayTensorProduct(M, N), CodegenArrayPermuteDims(CodegenArrayTensorProduct(M, N), Permutation(0, 2)(1, 3))), (1, 2)), (i, l, frozenset({j, m, k}))) expr = KroneckerDelta(i, j) * KroneckerDelta(j, k) * KroneckerDelta( k, m) * M[i, 0] * KroneckerDelta(m, n) assert _codegen_array_parse(expr) == (M, ({i, j, k, m, n}, 0)) expr = M[i, i] assert _codegen_array_parse(expr) == (CodegenArrayDiagonal(M, (0, 1)), (i, ))
def apply(W): n = W.shape[0] k = Symbol.k(integer=True) return Equality( Concatenate( Concatenate(W.T, ZeroMatrix(n)).T, LAMBDA[k:n + 1](KroneckerDelta(k, n))), Concatenate( Concatenate(W, ZeroMatrix(n)).T, LAMBDA[k:n + 1](KroneckerDelta(k, n))).T)
def _eval_derivative(self, v): if not isinstance(v, MatrixElement): from sympy import MatrixBase if isinstance(self.parent, MatrixBase): return self.parent.diff(v)[self.i, self.j] return S.Zero if self.args[0] != v.args[0]: return S.Zero return KroneckerDelta(self.args[1], v.args[1])*KroneckerDelta(self.args[2], v.args[2])
def test_arrayexpr_convert_index_to_array_support_function(): expr = M[i, j] assert _convert_indexed_to_array(expr) == (M, (i, j)) expr = M[i, j] * N[k, l] assert _convert_indexed_to_array(expr) == (ArrayTensorProduct(M, N), (i, j, k, l)) expr = M[i, j] * N[j, k] assert _convert_indexed_to_array(expr) == (ArrayDiagonal( ArrayTensorProduct(M, N), (1, 2)), (i, k, j)) expr = Sum(M[i, j] * N[j, k], (j, 0, k - 1)) assert _convert_indexed_to_array(expr) == (ArrayContraction( ArrayTensorProduct(M, N), (1, 2)), (i, k)) expr = M[i, j] + N[i, j] assert _convert_indexed_to_array(expr) == (ArrayAdd(M, N), (i, j)) expr = M[i, j] + N[j, i] assert _convert_indexed_to_array(expr) == (ArrayAdd( M, PermuteDims(N, Permutation([1, 0]))), (i, j)) expr = M[i, j] + M[j, i] assert _convert_indexed_to_array(expr) == (ArrayAdd( M, PermuteDims(M, Permutation([1, 0]))), (i, j)) expr = (M * N * P)[i, j] assert _convert_indexed_to_array(expr) == (_array_contraction( ArrayTensorProduct(M, N, P), (1, 2), (3, 4)), (i, j)) expr = expr.function # Disregard summation in previous expression ret1, ret2 = _convert_indexed_to_array(expr) assert ret1 == ArrayDiagonal(ArrayTensorProduct(M, N, P), (1, 2), (3, 4)) assert str(ret2) == "(i, j, _i_1, _i_2)" expr = KroneckerDelta(i, j) * M[i, k] assert _convert_indexed_to_array(expr) == (M, ({i, j}, k)) expr = KroneckerDelta(i, j) * KroneckerDelta(j, k) * M[i, l] assert _convert_indexed_to_array(expr) == (M, ({i, j, k}, l)) expr = KroneckerDelta(j, k) * (M[i, j] * N[k, l] + N[i, j] * M[k, l]) assert _convert_indexed_to_array(expr) == (_array_diagonal( _array_add( ArrayTensorProduct(M, N), _permute_dims(ArrayTensorProduct(M, N), Permutation(0, 2)(1, 3))), (1, 2)), (i, l, frozenset({j, k}))) expr = KroneckerDelta(j, m) * KroneckerDelta( m, k) * (M[i, j] * N[k, l] + N[i, j] * M[k, l]) assert _convert_indexed_to_array(expr) == (_array_diagonal( _array_add( ArrayTensorProduct(M, N), _permute_dims(ArrayTensorProduct(M, N), Permutation(0, 2)(1, 3))), (1, 2)), (i, l, frozenset({j, m, k}))) expr = KroneckerDelta(i, j) * KroneckerDelta(j, k) * KroneckerDelta( k, m) * M[i, 0] * KroneckerDelta(m, n) assert _convert_indexed_to_array(expr) == (M, ({i, j, k, m, n}, 0)) expr = M[i, i] assert _convert_indexed_to_array(expr) == (ArrayDiagonal(M, (0, 1)), (i, ))
def get_complete_christoffel(chi): """Computes and returns the complete Christoffel Symbols This function will take the metric, inverse metric, first derivative, and then calculate the complete Christoffel Symbols. It will store these symbols internally for other calculations as well. If the second Christoffel Symbols were not already computed, it will compute them and store them internally. If these complete Christoffel Symbols were already computed, it will just return the already-stored Symbols. Parameters ---------- chi : sympy.Scalar The input scalar used in the calculation Returns ------- sympy.Matrix The 3x3 matrix returned is the complete Christoffel Symbols Example ------- >>> C3 = dendrosym.nr.get_complete_christoffel() """ global metric, inv_metric, undef, C1, C2, C3, d if C3 == undef: C3 = sym.tensor.array.MutableDenseNDimArray(range(27), (3, 3, 3)) if C2 == undef: get_second_christoffel() for kk in e_i: for jj in e_i: for ii in e_i: # C3[i, j, k] = C2[i, j, k] - \ # 1/(2*chi)*(KroneckerDelta(i, j) * d(k, chi) + C3[ii, jj, kk] = C2[ii, jj, kk] - 0.5 / (chi) * ( KroneckerDelta(ii, jj) * d(kk, chi) + KroneckerDelta(ii, kk) * d(jj, chi) - metric[jj, kk] * sum([inv_metric[ii, mm] * d(mm, chi) for mm in e_i])) return C3
def _eval_derivative(self, wrt): if self == wrt: return S.One elif isinstance( wrt, IndexedFunc.IndexedFuncValue) and wrt.base == self.base: if len(self.indices) != len(wrt.indices): msg = "Different # of indices: d({!s})/d({!s})".format( self, wrt) raise IndexException(msg) elif self.functional_form != wrt.functional_form: msg = "Different function form d({!s})/d({!s})".format( self.functional_form, wrt.functional_form) raise IndexException(msg) result = S.One for index1, index2 in zip(self.indices, wrt.indices): result *= KroneckerDelta(index1, index2) return result else: # f(x).diff(s) -> x.diff(s) * f.fdiff(1)(s) i = 0 l = [] funcof = self._get_iter_func() for a in funcof: i += 1 da = a.diff(wrt) if da is S.Zero: continue df = self._get_df(a, wrt) l.append(df * da) return Add(*l)
def _entry(self, i, j): eq = Eq(i, j) if eq is S.false: return S.Zero elif eq is S.true: return self.arg[i, i] return self.arg[i, j]*KroneckerDelta(i, j)
def test_SHOKet(): assert SHOKet('k').dual_class() == SHOBra assert SHOBra('b').dual_class() == SHOKet assert InnerProduct(b, k).doit() == KroneckerDelta(k.n, b.n) assert k.hilbert_space == ComplexSpace(S.Infinity) assert k3_rep[k3.n, 0] == Integer(1) assert b3_rep[0, b3.n] == Integer(1)
def test_states(): assert PIABKet(n).dual_class() == PIABBra assert PIABKet(n).hilbert_space ==\ L2(Interval(S.NegativeInfinity,S.Infinity)) assert represent(PIABKet(n)) == sqrt(2 / L) * sin(n * pi * x / L) assert (PIABBra(i) * PIABKet(j)).doit() == KroneckerDelta(i, j) assert PIABBra(n).dual_class() == PIABKet
def _entry(self, i, j, **kwargs): eq = Eq(i, j) if eq is S.true: return S.One elif eq is S.false: return S.Zero return KroneckerDelta(i, j)
def _check_varsh_sum_872_4(e): a = Wild('a') alpha = Wild('alpha') b = Wild('b') beta = Wild('beta') c = Wild('c') cp = Wild('cp') gamma = Wild('gamma') gammap = Wild('gammap') match1 = e.match(Sum(CG(a,alpha,b,beta,c,gamma)*CG(a,alpha,b,beta,cp,gammap),(alpha,-a,a),(beta,-b,b))) if match1 is not None and len(match1) == 8: return (KroneckerDelta(c,cp)*KroneckerDelta(gamma,gammap)).subs(match1) match2 = e.match(Sum(CG(a,alpha,b,beta,c,gamma)**2,(alpha,-a,a),(beta,-b,b))) if match2 is not None and len(match2) == 6: return 1 return e
def _check_varsh_sum_871_2(e): a = Wild('a') alpha = symbols('alpha') c = Wild('c') match = e.match(Sum((-1)**(a-alpha)*CG(a,alpha,a,-alpha,c,0),(alpha,-a,a))) if match is not None and len(match) == 2: return (sqrt(2*a+1)*KroneckerDelta(c,0)).subs(match) return e
def _check_varsh_sum_871_1(e): a = Wild('a') alpha = symbols('alpha') b = Wild('b') match = e.match(Sum(CG(a, alpha, b, 0, a, alpha), (alpha, -a, a))) if match is not None and len(match) == 2: return ((2 * a + 1) * KroneckerDelta(b, 0)).subs(match) return e
def _entry(self, i, j, **kwargs): if self._iscolumn: result = self._vector._entry(i, 0, **kwargs) else: result = self._vector._entry(0, j, **kwargs) if i != j: result *= KroneckerDelta(i, j) return result
def _check_varsh_871_2(term_list): # Sum((-1)**(a-alpha)*CG(a,alpha,a,-alpha,c,0),(alpha,-a,a)) a, alpha, c, lt = map(Wild, ('a', 'alpha', 'c', 'lt')) expr = lt*CG(a, alpha, a, -alpha, c, 0) simp = sqrt(2*a + 1)*KroneckerDelta(c, 0) sign = (-1)**(a - alpha)*lt/abs(lt) build_expr = 2*a + 1 index_expr = a + alpha return _check_cg_simp(expr, simp, sign, lt, term_list, (a, alpha, c, lt), (a, c), build_expr, index_expr)
def _check_varsh_871_1(term_list): # Sum( CG(a,alpha,b,0,a,alpha), (alpha, -a, a)) == KroneckerDelta(b,0) a, alpha, b, lt = map(Wild, ('a', 'alpha', 'b', 'lt')) expr = lt*CG(a, alpha, b, 0, a, alpha) simp = (2*a + 1)*KroneckerDelta(b, 0) sign = lt/abs(lt) build_expr = 2*a + 1 index_expr = a + alpha return _check_cg_simp(expr, simp, sign, lt, term_list, (a, alpha, b, lt), (a, b), build_expr, index_expr)
def _check_varsh_sum_872_4(e): alpha = symbols('alpha') beta = symbols('beta') a = Wild('a') b = Wild('b') c = Wild('c') cp = Wild('cp') gamma = Wild('gamma') gammap = Wild('gammap') cg1 = CG(a, alpha, b, beta, c, gamma) cg2 = CG(a, alpha, b, beta, cp, gammap) match1 = e.match(Sum(cg1 * cg2, (alpha, -a, a), (beta, -b, b))) if match1 is not None and len(match1) == 6: return (KroneckerDelta(c, cp) * KroneckerDelta(gamma, gammap)).subs(match1) match2 = e.match(Sum(cg1**2, (alpha, -a, a), (beta, -b, b))) if match2 is not None and len(match2) == 4: return S.One return e
def Lij(l, a, b, axis): if axis == "z": return KroneckerDelta(a, b) * b elif axis == "x": return (1. / 2) * (Lij(l, a, b, "Lp") + Lij(l, a, b, "Lm")) elif axis == "y": return (-1j / 2) * (Lij(l, a, b, "Lp") - Lij(l, a, b, "Lm")) elif axis == "Lp": if b == l: return 0 else: return KroneckerDelta(a, b + 1) * np.sqrt((l - b) * (l + b + 1)) elif axis == "Lm": if b == -l: return 0 else: return KroneckerDelta(a, b - 1) * np.sqrt((l + b) * (l - b + 1)) else: return None
def test_cg_simp_sum(): x, a, b, c, cp, alpha, beta, gamma, gammap = symbols( 'x a b c cp alpha beta gamma gammap') # Varshalovich 8.7.1 Eq 1 assert cg_simp(x * Sum(CG(a, alpha, b, 0, a, alpha), (alpha, -a, a) )) == x*(2*a + 1)*KroneckerDelta(b, 0) assert cg_simp(x * Sum(CG(a, alpha, b, 0, a, alpha), (alpha, -a, a)) + CG(1, 0, 1, 0, 1, 0)) == x*(2*a + 1)*KroneckerDelta(b, 0) + CG(1, 0, 1, 0, 1, 0) assert cg_simp(2 * Sum(CG(1, alpha, 0, 0, 1, alpha), (alpha, -1, 1))) == 6 # Varshalovich 8.7.1 Eq 2 assert cg_simp(x*Sum((-1)**(a - alpha) * CG(a, alpha, a, -alpha, c, 0), (alpha, -a, a))) == x*sqrt(2*a + 1)*KroneckerDelta(c, 0) assert cg_simp(3*Sum((-1)**(2 - alpha) * CG( 2, alpha, 2, -alpha, 0, 0), (alpha, -2, 2))) == 3*sqrt(5) # Varshalovich 8.7.2 Eq 4 assert cg_simp(Sum(CG(a, alpha, b, beta, c, gamma)*CG(a, alpha, b, beta, cp, gammap), (alpha, -a, a), (beta, -b, b))) == KroneckerDelta(c, cp)*KroneckerDelta(gamma, gammap) assert cg_simp(Sum(CG(a, alpha, b, beta, c, gamma)*CG(a, alpha, b, beta, c, gammap), (alpha, -a, a), (beta, -b, b))) == KroneckerDelta(gamma, gammap) assert cg_simp(Sum(CG(a, alpha, b, beta, c, gamma)*CG(a, alpha, b, beta, cp, gamma), (alpha, -a, a), (beta, -b, b))) == KroneckerDelta(c, cp) assert cg_simp(Sum(CG( a, alpha, b, beta, c, gamma)**2, (alpha, -a, a), (beta, -b, b))) == 1 assert cg_simp(Sum(CG(2, alpha, 1, beta, 2, gamma)*CG(2, alpha, 1, beta, 2, gammap), (alpha, -2, 2), (beta, -1, 1))) == KroneckerDelta(gamma, gammap)
def _eval_derivative(self, wrt): if isinstance(wrt, Indexed) and wrt.base == self.base: if len(self.indices) != len(wrt.indices): msg = "Different # of indices: d({!s})/d({!s})".format( self, wrt) raise IndexException(msg) result = S.One for index1, index2 in zip(self.indices, wrt.indices): result *= KroneckerDelta(index1, index2) return result else: return S.Zero
def _entry(self, i, j): if self.diagonal_length is not None: if Ge(i, self.diagonal_length) is S.true: return S.Zero elif Ge(j, self.diagonal_length) is S.true: return S.Zero eq = Eq(i, j) if eq is S.true: return self.arg[i, i] elif eq is S.false: return S.Zero return self.arg[i, j]*KroneckerDelta(i, j)