def transform_to_uncoupled(self): F = self.F mF = self.mF F1 = self.F1 J = self.J I1 = self.I1 I2 = self.I2 mF1s = np.arange(-F1, F1 + 1, 1) mJs = np.arange(-J, J + 1, 1) m1s = np.arange(-I1, I1 + 1, 1) m2s = np.arange(-I2, I2 + 1, 1) uncoupled_state = State() for mF1 in mF1s: for mJ in mJs: for m1 in m1s: for m2 in m2s: amp = CG(J, mJ, I1, m1, F1, mF1).doit() * CG( F1, mF1, I2, m2, F, mF).doit() basis_state = UncoupledBasisState( J, mJ, I1, m1, I2, m2) uncoupled_state = uncoupled_state + State( [(amp, basis_state)]) return uncoupled_state.normalize()
def calc_beta(self): ''' Method to calculate beta array to convert from blm to alm ''' ## initialize beta array beta_vals = np.zeros( (self.alm_size, 2 * self.blm_size - self.blmax - 1, 2 * self.blm_size - self.blmax - 1)) for ii in range(beta_vals.shape[0]): for jj in range(beta_vals.shape[1]): for kk in range(beta_vals.shape[2]): l1, m1 = self.idxtoalm(self.blmax, jj) l2, m2 = self.idxtoalm(self.blmax, kk) L, M = self.idxtoalm(self.almax, ii) ## clebs gordon coeffcients cg0 = (CG(l1, 0, l2, 0, L, 0).doit()).evalf() cg1 = (CG(l1, m1, l2, m2, L, M).doit()).evalf() beta_vals[ii, jj, kk] = np.sqrt( (2 * l1 + 1) * (2 * l2 + 1) / ((4 * np.pi) * (2 * L + 1))) * cg0 * cg1 self.beta_vals = beta_vals
def transform_to_uncoupled(self): F = self.F mF = self.mF F1 = self.F1 J = self.J I1 = self.I1 I2 = self.I2 electronic_state = self.electronic_state P = self.P Omega = self.Omega mF1s = np.arange(-F1,F1+1,1) mJs = np.arange(-J,J+1,1) m1s = np.arange(-I1,I1+1,1) m2s = np.arange(-I2,I2+1,1) uncoupled_state = State() for mF1 in mF1s: for mJ in mJs: for m1 in m1s: for m2 in m2s: amp = (complex(CG(J, mJ, I1, m1, F1, mF1).doit() *CG(F1, mF1, I2, m2, F, mF).doit())) basis_state = UncoupledBasisState(J, mJ, I1, m1, I2, m2, P = P, Omega=Omega, electronic_state = electronic_state) uncoupled_state = uncoupled_state + State([(amp, basis_state)]) return uncoupled_state.normalize()
def calc_component(self, j, mj, l, ml, s, ms): def _r1(rm, p, p1, p2): if self.p1 == 0: return 0., 0. k = rm.dot(p1) kn = np.vdot(k, k) theta = np.arccos(k[2]/kn) phi = np.arctan2(k[1], k[0]) return theta, phi _s1, _s2 = int(2*self.s1+1), int(2*self.s2+1) # sympy uses its on version of float, convert to normal floats c1 = float(CG(s, ms, l, ml, j, mj).doit()) res = np.zeros((self.mlength,_s1, _s2), dtype=complex) for m1, m2 in it.product(range(_s1), range(_s2)): c2 = float(CG(self.s1, m1-self.s1, self.s2, m2-self.s2, s, ms).doit()) #for i, ang in zip(self.rot_index[0], self.angles): # res[i,m1,m2] += c2*sp.sph_harm(ml, l, ang[0], ang[1]).conj() for i, q in enumerate(self.elements): #rm = q.rotation_matrix(inv=True) for j, pvecs in enumerate(self.allmomenta): #theta, phi = _r1(rm, *pvecs) _r = self.rot_index[j, i] theta, phi = self.angles[j,i] res[_r,m1,m2] += c2*sp.sph_harm(ml, l, theta, phi).conj() return c1*res
def overlap_mpmq(pp, theta, Ms, MJ, phi, lam): #overlap of -p-q/2 if lam == 100: return math.sqrt(2./Pi)* sum( sph_harmY(L, MJ-Ms, theta_prime2(pp, theta), phi+Pi)*\ float(CG(S(L), S(MJ - Ms), S(1), S(Ms), 1, MJ).doit())*(I**L)*\ psi_interpolated[L](np.sqrt(pp**2 + pp* qq* np.cos(theta)+ qq**2/4))/norm for L in range(0,3,2) ) if lam == 2: return math.sqrt(2./Pi)* sum( sph_harmY(L, MJ-Ms, theta_prime2(pp, theta), phi+Pi)*\ float(CG(S(L), S(MJ - Ms), S(1), S(Ms), 1, MJ).doit())*(I**L)*\ psi_interpolated2[L](np.sqrt(pp**2 + pp* qq* np.cos(theta)+ qq**2/4))/norm2 for L in range(0,3,2) )
def comp_sph_harm_to_relativistic_harm(dim_ms): '''transformation matrix from spin-complex spherical harmonics (orbital fast) to relativistic harmonics ''' csh2relh = np.zeros((dim_ms, dim_ms), dtype=complex) dim_m = dim_ms // 2 l = dim_m // 2 # set the orbital index iy = range(dim_m) for i in range(l): iy += [iy.pop(0)] # add slow spin index # for spin: up, then dn. wien2k convention. iys = {0.5: iy, -0.5: [iy[i] + dim_m for i in range(dim_m)]} # j=l-1/2 block # relativistic_harmonics index i_jm = -1 for i in [-0.5, 0.5]: _j = l + i for mj in np.arange(-_j, _j + 1): i_jm += 1 for s in [-0.5, 0.5]: csh2relh[iys[s][int(round(mj-s))], i_jm] = \ CG(l,mj-s,0.5,s,_j,mj).doit() return csh2relh
def _cg(l1, l2, L): """Computes CG coefficients from sympy <l1 m1; l2 m2| L M> and converts them to numerical values. Returns a full (2 * l1 + 1, 2 * l2 + 1, 2 * L + 1) array, which is mostly zeros. """ try: from sympy.physics.quantum.cg import CG except ModuleNotFoundError: raise ModuleNotFoundError( "Calculation of Clebsch-Gordan coefficients requires a sympy installation" ) rcg = np.zeros((2 * l1 + 1, 2 * l2 + 1, 2 * L + 1), dtype=np.double) if np.abs(l1 - l2) > L or np.abs(l1 + l2) < L: return rcg for m1 in range(-l1, l1 + 1): for m2 in range(-l2, l2 + 1): if np.abs(m1 + m2) > L: continue rcg[l1 + m1, l2 + m2, L + (m1 + m2)] += np.double( CG(l1, m1, l2, m2, L, m1 + m2).doit() ) return rcg
def get_coefficients(j3, m3, cutoff=3): """Reverse Clebsch-Gordan coupling This function returns a list of a list with all quantum numbers and coefficients leading to a fixed J,M combination Arguments --------- j3, m3: integers, Right hand side of CG-coefficients: <j1 j2 m1 m2|j3 m3> cutoff: (optional) integer, cutoff where to stop looking for couplings Returns ------- sqm: a list of lists for each combination j1,j2,m1,m2, CG-coeff found for j3 and m3 """ # Perhaps a 2d numpy array is better suited, no that needs to be fixed # length # List of lists: Each inner list holds j1,j2,m1,m2 and the coefficient sqm = [] for j1 in range(0, cutoff): for j2 in range(0, cutoff): #Check boundaries of j3 if np.abs(j1 - j2) <= j3 and j1 + j2 >= j3: for m1 in range(-j1, j1 + 1): for m2 in range(-j2, j2 + 1): if m1 + m2 == m3: sqm.append([ j1, j2, m1, m2, CG(j1, m1, j2, m2, j3, m3).doit() ]) return sqm
def Clebsch(j1, m1, j2, m2, J, M) : """ Return Clebsch-Gordan coefficient. Note that all arguments should be multiplied by 2 (e.g. 1 for spin 1/2, 2 for spin 1 etc.). Needs sympy. """ from sympy.physics.quantum.cg import CG from sympy import Rational return CG(Rational(j1,2), Rational(m1,2), Rational(j2,2), Rational(m2,2), Rational(J,2), Rational(M,2) ).doit().evalf()
def _clebsch_gordan_coefficient(recipe: dict) -> float: return (CG( recipe["j1"], recipe["m1"], recipe["j2"], recipe["m2"], recipe["J"], recipe["M"], ).doit().evalf())
def cg_coef(jb, jc, mb, mc, ja, ma): """ It returns the CG coefficient :math:`\\langle j_bm_bj_cm_c|j_am_a\\rangle`, as in a decay from particle *a* to *b* and *c*. It will either call **sympy.physics.quantum.cg()** or **get_cg_coef()**. """ if has_sympy: return float(CG(jb, mb, jc, mc, ja, ma).doit().evalf()) else: return get_cg_coef(jb, jc, mb, mc, ja, ma)
def test_doit(): assert (Wigner3j(S.Half, Rational(-1, 2), S.Half, S.Half, 0, 0).doit() == -sqrt(2) / 2) assert Wigner6j(1, 2, 3, 2, 1, 2).doit() == sqrt(21) / 105 assert Wigner6j(3, 1, 2, 2, 2, 1).doit() == sqrt(21) / 105 assert (Wigner9j(2, 1, 1, Rational(3, 2), S.Half, 1, S.Half, S.Half, 0).doit() == sqrt(2) / 12) assert CG(S.Half, S.Half, S.Half, Rational(-1, 2), 1, 0).doit() == sqrt(2) / 2
def test_doit(): assert Wigner3j(1 / 2, -1 / 2, 1 / 2, 1 / 2, 0, 0).doit() == -sqrt(2) / 2 assert Wigner6j(1, 2, 3, 2, 1, 2).doit() == sqrt(21) / 105 assert Wigner9j(2, 1, 1, S(3) / 2, S(1) / 2, 1, S(1) / 2, S(1) / 2, 0).doit() == sqrt(2) / 12 assert CG(1 / 2, 1 / 2, 1 / 2, -1 / 2, 1, 0).doit() == sqrt(2) / 2
def get_decay_part(decay, ls, lambda_list, symbol_list): """ .. math:: \\sqrt{\\frac{ 2 l + 1 }{ 2 j_a + 1 }} \\langle j_b, j_c, \\lambda_b, - \\lambda_c | s, \\lambda_b - \\lambda_c \\rangle \\langle l, s, 0, \\lambda_b - \\lambda_c | j_a, \\lambda_b - \\lambda_c \\rangle .. math:: D_{\\lambda_a, \\lambda_b - \\lambda_c}^{J_{A}*} (\\phi, \\theta, 0) """ a = decay.core b, c = decay.outs l, s = ls lambda_list = {k: spin_int(v) for k, v in lambda_list.items()} delta = lambda_list[b] - lambda_list[c] if abs(delta) > a.J: return 0 d_part = WignerD( spin_int(a.J), lambda_list[a], delta, symbol_list[decay]["alpha"], symbol_list[decay]["beta"], 0, ) # print(lambda_list) cg_part = sym.sqrt((2 * l + 1)) / sym.sqrt((2 * spin_int(a.J) + 1)) cg_part = cg_part * CG(l, 0, spin_int(s), delta, spin_int(a.J), delta) cg_part = cg_part * CG( spin_int(b.J), lambda_list[b], spin_int(c.J), -lambda_list[c], spin_int(s), delta, ) return simplify(d_part.conjugate() * cg_part)
def cg_prod(jmag, jpol, mpol, fac=2, log=None): r'''Compute a single coefficient :math:`<\vec{j}\vec{m}|\vec{j}\vec{j}^\prime>`, where :math:`\sum_k j_k^\prime=j_{\rm{tot}}`, :math:`\sum_k m_k=m_{\rm{tot}}`, and :math:`-j_{\rm{tot}}\le m_{\rm{tot}}\le j_{\rm{tot}}` by multiplying Clebsch-Gordan coefficients. Args: jmag: list of N nonnegative spin magnitudes, :math:`\vec{j}` jpol: list of N spin magnitude couplings from left to right Must have jcoup[0] == jmag[0] and sum (jcoup[:k]) >= 0 for all k<N mpol: list of N spin polarizations, -sum (jcoup) <= sum (mpol) <= sum(jcoup) Kwargs: fac: integer Divide jmag, jpol, and mpol by this to get the actual quantum #s. Default (2) means that you actually provided 2*j, 2*m, etc., so as to avoid data type ambiguities and floating-point rounding issues with half-integer quantum numbers. (Internally, everything is multiplied by 2 until we get to the actual Clebsch-Gordan cruncher.) log: PySCF logger object For logging output Returns: coeff: floating-point ''' ### Throat-clearing ### fac = 2 // fac jmag = np.around(np.asarray(jmag) * fac).astype(np.int32) jpol = np.around(np.asarray(jpol) * fac).astype(np.int32) mpol = np.around(np.asarray(mpol) * fac).astype(np.int32) _assert_j2m2(jmag, jpol, True) _assert_j2m2(jmag, mpol, False) mtot = mpol.sum() jtot = jpol.sum() assert (mtot in range(-jtot, jtot + 1, 2)), 'mpol and jpol mismatch' if log is None: log = logger.Logger(verbose=logger.DEBUG4) coeff = S(1) jrun = np.cumsum(jpol) mrun = np.cumsum(mpol) for i in range(1, len(jmag)): coeff *= CG( S(jrun[i - 1]) / 2, S(mrun[i - 1]) / 2, # j1, m1 S(jmag[i]) / 2, S(mpol[i]) / 2, # j2, m2 S(jrun[i]) / 2, S(mrun[i]) / 2).doit() # j3, m3 = m1 + m2 return coeff.evalf()
def _recurse(m2a_str, coeffs_in, j2, m2c_max, m2c_min): m2c_str = [] coeffs_out = [] logger.debug4( log, 'Entering _recurse with {} strings, {} coeffs, and {} <= m2c <= {}' .format(len(m2a_str), len(coeffs_in), m2c_min, m2c_max)) for m2a_vec, coeff in zip(m2a_str, coeffs_in): m2a = m2a_vec.sum() m2b_max = min(m2c_max - m2a, j2[1]) m2b_min = max(m2c_min - m2a, -j2[1]) logger.debug4( log, 'For this string, {} <= m2b <= {}'.format(m2b_min, m2b_max)) for m2b in range(m2b_min, m2b_max + 1, 2): m2c = m2a + m2b m2 = np.array([m2a, m2b, m2c]) cgfac = CG( S(j2[0]) / 2, S(m2a) / 2, S(j2[1]) / 2, S(m2b) / 2, S(j2[2]) / 2, S(m2c) / 2).doit() logger.debug4( log, 'Computing <{},{};{},{}|{},{}> = {}'.format( str(S(j2[0]) / 2), str(S(m2a) / 2), str(S(j2[1]) / 2), str(S(m2b) / 2), str(S(j2[2]) / 2), str(S(m2c) / 2), str(cgfac))) m2c_str.append(np.append(m2a_vec, m2b)) try: coeffs_out.append(float(coeff * cgfac.evalf())) except TypeError as e: assert (j2.sum() % 2 == 0), 'Coupling parity error? {}'.format(j2) return m2c_str, coeffs_out
def cg_matrix(n_l): """ Returns the Clebsch-Gordan coefficients for maximum angular momentum n_l-1 """ lmax = n_l - 1 cgs = np.zeros([n_l, 2 * lmax + 1, n_l, 2 * lmax + 1, n_l, 2 * lmax + 1], dtype=complex) for l in range(n_l): for l1 in range(n_l): for l2 in range(n_l): for m in range(-n_l, n_l + 1): for m1 in range(-n_l, n_l + 1): for m2 in range(-n_l, n_l + 1): # cgs[l1,l2,l,m1,m2,m] = N(CG(l1,l2,l,m1,m2,m).doit()) cgs[l1, m1, l2, m2, l, m] = N(CG(l1, m1, l2, m2, l, m).doit()) return cgs
def clebsch2(j1, m1, j2, m2, j3, m3): """ Computes <j1 m1 j2 m2 | j3 m3>, where all spins are given as double their values (contrary to the usual convention in this code). """ # https://docs.sympy.org/latest/modules/physics/quantum/cg.html # https://mattpap.github.io/scipy-2011-tutorial/html/numerics.html # This is kind of silly, using a symbolic math package to compute these things numerically, but I couldn't find a convenient # numerical routine for this that was licensed appropriately and packaged for ubuntu. # Performance is actually fine, because this is memoized. We take a ~1 second hit in startup time just from loading sympy. # Looking for a better alternative: https://scicomp.stackexchange.com/questions/32744/plug-and-go-clebsch-gordan-computation-in-python return CG( sympy.S(j1) / 2, sympy.S(m1) / 2, sympy.S(j2) / 2, sympy.S(m2) / 2, sympy.S(j3) / 2, sympy.S(m3) / 2).doit().evalf()
def CalcTensor(Cx, l, l1, l2): Ten = [[0 for x in range(1)] for x in range(2 * l + 1)] result = 0 #if (l>(l1+l2) or l<abs(l1-l2)): # print('Invalid tensor') # Ten = -1 if (l1 == 0): s1 = 1 elif (l1 == 2): s1 = 4 elif (l1 == 4): s1 = 11 elif (l1 == 6): s1 = 22 elif (l1 == 8): s1 = 37 if (l2 == 0): s2 = 1 elif (l2 == 2): s2 = 4 elif (l2 == 4): s2 = 11 elif (l2 == 6): s2 = 22 elif (l2 == 8): s2 = 37 #column of length 2l+1 jj = 0 for m in range(-l, l + 1): for m1 in range(-l1, l1 + 1): for m2 in range(-l2, l2 + 1): el = float(CG(l1, m1, l2, m2, l, m).doit()) Ten[jj][0] = Ten[jj][0] + el * np.conjugate( Cx[m1 + s1 - 1]) * np.conjugate(Cx[m2 + s2 - 1]) jj = jj + 1 return Ten
def compute_cg_matrix(k, l): """ Computes the matrix that block-diagonilizes the Kronecker product of Wigner D matrices of degree k and l respectively Output size (2k+1)(2l+1)x(2k+1)(2l+1) """ c_kl = np.zeros([(2 * k + 1) * (2 * l + 1), (2 * k + 1) * (2 * l + 1)]) n_off = 0 for J in range(abs(k - l), k + l + 1): m_off = 0 for m1_i in range(2 * k + 1): m1 = m1_i - k for m2_i in range(2 * l + 1): m2 = m2_i - l for n_i in range(2 * J + 1): n = n_i - J if m1 + m2 == n: c_kl[m_off + m2_i, n_off + n_i] = CG(k, m1, l, m2, J, m1 + m2).doit() m_off = m_off + 2 * l + 1 n_off = n_off + 2 * J + 1 return c_kl
def CGmatrix_to_file(SA,SB,S,directory): ##Define a ClebschGordan matrix using sympy library, returns an array of tuples, (p,q,CG(SA,MA[q],SB,MB[q],S,M[p])) ##which can be converted into the desired matrix matrix that changes for |S,M> basis to |SA,MA;SB,MB> if S > SA+SB: raise Exception('S should be less than SA+SB') ##directory='data/CGmats/' if not os.path.exists(directory): os.makedirs(directory) filename=directory+'CGmat_SA_'+str(float(SA))+'_SB_'+str(float(SB))+'_S_'+str(float(S))+'.hdf5' if not os.path.exists(filename): cgmat_data=[] MAarr=np.matlib.repmat(np.linspace(-SA,SA,int(2*SA+1)),1,int(2*SB+1))[0,:] MBarr=np.reshape(np.matlib.repmat(np.linspace(-SB,SB,int(2*SB+1)),int(2*SA+1),1),(1,int((2*SA+1)*(2*SB+1))),order='F')[0,:] Marr=np.linspace(-S,S,int(2*S+1)) for p in range(np.size(Marr)): Msumlist=np.where(MAarr+MBarr==Marr[p])[0] #print(p, end='\r', flush=True) for q in Msumlist: cgmat_data.append([p,q,CG(SA,MAarr[q],SB,MBarr[q],S,Marr[p]).doit().evalf()]) cgmat_datanp=np.array([cgmat_data_i for cgmat_data_i in cgmat_data]) cgmat_datanpf=cgmat_datanp.astype(float) print("Saving to file: "+filename) with h5py.File(filename, "w") as f: f.create_dataset("cgmat_data", cgmat_datanpf.shape, dtype=cgmat_datanpf.dtype, data=cgmat_datanpf)
def couple(tp): """ Couple an uncoupled spin states This function can be used to couple an uncoupled tensor product of spin states. All of the eigenstates to be coupled must be of the same class. It will return a linear combination of eigenstates that are subclasses of CoupledSpinState. Parameters ========== tp: TensorProduct TensorProduct of spin states to be coupled Examples ======== Couple a tensor product of numerical states: >>> from sympy.physics.quantum.spin import JzKet, couple >>> from sympy.physics.quantum.tensorproduct import TensorProduct >>> couple(TensorProduct(JzKet(1,0), JzKet(1,1))) -sqrt(2)*|1,1,1,1>/2 + sqrt(2)*|2,1,1,1>/2 Couple a tensor product of symbolic states: >>> from sympy import symbols >>> j1,m1,j2,m2 = symbols('j1 m1 j2 m2') >>> couple(TensorProduct(JzKet(j1,m1), JzKet(j2,m2))) Sum(CG(j1, m1, j2, m2, j, m1 + m2)*|j,m1 + m2>, (j, 0, j1 + j2)) """ states = tp.args evect = states[0].__class__ if not all([arg.__class__ is evect for arg in states]): raise TypeError('All operands must be of the same class') evect = evect.coupled_class() if all(state.j.is_number for state in states): # Numerical coupling vect = TensorProduct(*[state._represent() for state in states]) maxj = states[0].j + states[1].j j1, j2 = states[0].j, states[1].j if maxj == int(maxj): minj = 0 else: minj = S(1) / 2 result = [] for i in range(maxj - minj + 1): j = maxj - i for k in range(2 * j + 1): m = j - k max_m1 = min(j1, m + j2) min_m1 = max(-j1, m - j2) min_m2 = m - max_m1 result.append( Add(*[ vect[(j1 - (max_m1 - l)) * (2 * j2 + 1) + (j2 - (min_m2 + l)), 0] * CG(j1, max_m1 - l, j2, min_m2 + l, j, m) * evect(j, m, j1, j2) for l in range(max_m1 - min_m1 + 1) ])) if all(state.m.is_number for state in states): return Add(*result).doit() else: return Add(*result) else: # Symbolic coupling maxj = Add(*[state.j for state in states]) m = Add(*[state.m for state in states]) j = symbols('j') if not maxj.is_number or maxj == int(maxj): minj = 0 else: minj = S(1) / 2 j1 = states[0].j j2 = states[1].j m1 = states[0].m m2 = states[1].m return Sum(CG(j1, m1, j2, m2, j, m) * evect(j, m), (j, minj, maxj))
def uncouple(*args): """ Uncouple a coupled spin state Gives the uncoupled representation of a coupled spin state. Arguments must be either a spin state that is a subclass of CoupledSpinState or a spin state that is a subclass of SpinState and an array giving the j values of the spaces that are to be coupled Parameters ========== args: CoupledSpinState or SpinState The state that is to be coupled. If a subclass of SpinState is used, the state must be followed by the j values of the spaces that are to be coupled. Examples ======== Uncouple a numerical state using a CoupledSpinState state: >>> from sympy.physics.quantum.spin import JzKetCoupled, uncouple >>> from sympy import S >>> uncouple(JzKetCoupled(1, 0, S(1)/2, S(1)/2)) sqrt(2)*|1/2,-1/2>x|1/2,1/2>/2 + sqrt(2)*|1/2,1/2>x|1/2,-1/2>/2 Perform the same calculation using a SpinState state: >>> from sympy.physics.quantum.spin import JzKet >>> uncouple(JzKet(1, 0), S(1)/2, S(1)/2) sqrt(2)*|1/2,-1/2>x|1/2,1/2>/2 + sqrt(2)*|1/2,1/2>x|1/2,-1/2>/2 Uncouple a symbolic state using a CoupledSpinState state: >>> from sympy import symbols >>> j,m,j1,j2 = symbols('j m j1 j2') >>> uncouple(JzKetCoupled(j, m, j1, j2)) Sum(CG(j1, m1, j2, m2, j, m)*|j1,m1>x|j2,m2>, (m1, -j1, j1), (m2, -j2, j2)) Perform the same calculation using a SpinState state >>> uncouple(JzKet(j, m), j1, j2) Sum(CG(j1, m1, j2, m2, j, m)*|j1,m1>x|j2,m2>, (m1, -j1, j1), (m2, -j2, j2)) """ if len(args) == 3: state, j1, j2 = args evect = state.__class__ elif len(args) == 1: state = args[0] evect = state.uncoupled_class() j1, j2 = state.jvals state = evect(state.j, state.m) else: raise TypeError j = state.j m = state.m if state.j.is_number and state.m.is_number: result = [] for i_m1 in range(2 * j1 + 1): m1 = j1 - i_m1 for i_m2 in range(2 * j2 + 1): m2 = j2 - i_m2 result.append( CG(j1, m1, j2, m2, j, m).doit() * TensorProduct(evect(j1, m1), evect(j2, m2))) return Add(*result) else: m1, m2, mi = symbols('m1 m2 mi') # Hack to get rotation angles angles = (evect(0, mi)._represent())[0].args[3:6] out_state = TensorProduct(evect(j1, m1), evect(j2, m2)) if angles == (0, 0, 0): lt = CG(j1, m1, j2, m2, state.j, state.m) return Sum(lt * out_state, (m1, -j1, j1), (m2, -j2, j2)) else: lt = CG(j1, m1, j2, m2, state.j, mi) * Rotation.D( state.j, mi, state.m, *angles) return Sum(lt * out_state, (mi, -state.j, state.j), (m1, -j1, j1), (m2, -j2, j2))
def get_zT_prefactor(Ji,Ti,Tiz,dT,dTz,Tf,Tfz): cg = CG(Ti,Tiz,dT,dTz,Tf,Tfz) return ((math.sqrt(2*dT+1))/(math.sqrt(2*Ji+1)*math.sqrt(2*Tf+1)))*float(cg.doit())
def test_cg_simp_add(): j, m1, m1p, m2, m2p = symbols('j m1 m1p m2 m2p') # Test Varshalovich 8.7.1 Eq 1 a = CG(S(1) / 2, S(1) / 2, 0, 0, S(1) / 2, S(1) / 2) b = CG(S(1) / 2, -S(1) / 2, 0, 0, S(1) / 2, -S(1) / 2) c = CG(1, 1, 0, 0, 1, 1) d = CG(1, 0, 0, 0, 1, 0) e = CG(1, -1, 0, 0, 1, -1) assert cg_simp(a + b) == 2 assert cg_simp(c + d + e) == 3 assert cg_simp(a + b + c + d + e) == 5 assert cg_simp(a + b + c) == 2 + c assert cg_simp(2 * a + b) == 2 + a assert cg_simp(2 * c + d + e) == 3 + c assert cg_simp(5 * a + 5 * b) == 10 assert cg_simp(5 * c + 5 * d + 5 * e) == 15 assert cg_simp(-a - b) == -2 assert cg_simp(-c - d - e) == -3 assert cg_simp(-6 * a - 6 * b) == -12 assert cg_simp(-4 * c - 4 * d - 4 * e) == -12 a = CG(S(1) / 2, S(1) / 2, j, 0, S(1) / 2, S(1) / 2) b = CG(S(1) / 2, -S(1) / 2, j, 0, S(1) / 2, -S(1) / 2) c = CG(1, 1, j, 0, 1, 1) d = CG(1, 0, j, 0, 1, 0) e = CG(1, -1, j, 0, 1, -1) assert cg_simp(a + b) == 2 * KroneckerDelta(j, 0) assert cg_simp(c + d + e) == 3 * KroneckerDelta(j, 0) assert cg_simp(a + b + c + d + e) == 5 * KroneckerDelta(j, 0) assert cg_simp(a + b + c) == 2 * KroneckerDelta(j, 0) + c assert cg_simp(2 * a + b) == 2 * KroneckerDelta(j, 0) + a assert cg_simp(2 * c + d + e) == 3 * KroneckerDelta(j, 0) + c assert cg_simp(5 * a + 5 * b) == 10 * KroneckerDelta(j, 0) assert cg_simp(5 * c + 5 * d + 5 * e) == 15 * KroneckerDelta(j, 0) assert cg_simp(-a - b) == -2 * KroneckerDelta(j, 0) assert cg_simp(-c - d - e) == -3 * KroneckerDelta(j, 0) assert cg_simp(-6 * a - 6 * b) == -12 * KroneckerDelta(j, 0) assert cg_simp(-4 * c - 4 * d - 4 * e) == -12 * KroneckerDelta(j, 0) # Test Varshalovich 8.7.1 Eq 2 a = CG(S(1) / 2, S(1) / 2, S(1) / 2, -S(1) / 2, 0, 0) b = CG(S(1) / 2, -S(1) / 2, S(1) / 2, S(1) / 2, 0, 0) c = CG(1, 1, 1, -1, 0, 0) d = CG(1, 0, 1, 0, 0, 0) e = CG(1, -1, 1, 1, 0, 0) assert cg_simp(a - b) == sqrt(2) assert cg_simp(c - d + e) == sqrt(3) assert cg_simp(a - b + c - d + e) == sqrt(2) + sqrt(3) assert cg_simp(a - b + c) == sqrt(2) + c assert cg_simp(2 * a - b) == sqrt(2) + a assert cg_simp(2 * c - d + e) == sqrt(3) + c assert cg_simp(5 * a - 5 * b) == 5 * sqrt(2) assert cg_simp(5 * c - 5 * d + 5 * e) == 5 * sqrt(3) assert cg_simp(-a + b) == -sqrt(2) assert cg_simp(-c + d - e) == -sqrt(3) assert cg_simp(-6 * a + 6 * b) == -6 * sqrt(2) assert cg_simp(-4 * c + 4 * d - 4 * e) == -4 * sqrt(3) a = CG(S(1) / 2, S(1) / 2, S(1) / 2, -S(1) / 2, j, 0) b = CG(S(1) / 2, -S(1) / 2, S(1) / 2, S(1) / 2, j, 0) c = CG(1, 1, 1, -1, j, 0) d = CG(1, 0, 1, 0, j, 0) e = CG(1, -1, 1, 1, j, 0) assert cg_simp(a - b) == sqrt(2) * KroneckerDelta(j, 0) assert cg_simp(c - d + e) == sqrt(3) * KroneckerDelta(j, 0) assert cg_simp( a - b + c - d + e) == sqrt(2) * KroneckerDelta(j, 0) + sqrt(3) * KroneckerDelta(j, 0) assert cg_simp(a - b + c) == sqrt(2) * KroneckerDelta(j, 0) + c assert cg_simp(2 * a - b) == sqrt(2) * KroneckerDelta(j, 0) + a assert cg_simp(2 * c - d + e) == sqrt(3) * KroneckerDelta(j, 0) + c assert cg_simp(5 * a - 5 * b) == 5 * sqrt(2) * KroneckerDelta(j, 0) assert cg_simp(5 * c - 5 * d + 5 * e) == 5 * sqrt(3) * KroneckerDelta(j, 0) assert cg_simp(-a + b) == -sqrt(2) * KroneckerDelta(j, 0) assert cg_simp(-c + d - e) == -sqrt(3) * KroneckerDelta(j, 0) assert cg_simp(-6 * a + 6 * b) == -6 * sqrt(2) * KroneckerDelta(j, 0) assert cg_simp(-4 * c + 4 * d - 4 * e) == -4 * sqrt(3) * KroneckerDelta(j, 0) # Test Varshalovich 8.7.2 Eq 9 # alpha=alphap,beta=betap case # numerical a = CG(S(1) / 2, S(1) / 2, S(1) / 2, -S(1) / 2, 1, 0)**2 b = CG(S(1) / 2, S(1) / 2, S(1) / 2, -S(1) / 2, 0, 0)**2 c = CG(1, 0, 1, 1, 1, 1)**2 d = CG(1, 0, 1, 1, 2, 1)**2 assert cg_simp(a + b) == 1 assert cg_simp(c + d) == 1 assert cg_simp(a + b + c + d) == 2 assert cg_simp(4 * a + 4 * b) == 4 assert cg_simp(4 * c + 4 * d) == 4 assert cg_simp(5 * a + 3 * b) == 3 + 2 * a assert cg_simp(5 * c + 3 * d) == 3 + 2 * c assert cg_simp(-a - b) == -1 assert cg_simp(-c - d) == -1 # symbolic a = CG(S(1) / 2, m1, S(1) / 2, m2, 1, 1)**2 b = CG(S(1) / 2, m1, S(1) / 2, m2, 1, 0)**2 c = CG(S(1) / 2, m1, S(1) / 2, m2, 1, -1)**2 d = CG(S(1) / 2, m1, S(1) / 2, m2, 0, 0)**2 assert cg_simp(a + b + c + d) == 1 assert cg_simp(4 * a + 4 * b + 4 * c + 4 * d) == 4 assert cg_simp(3 * a + 5 * b + 3 * c + 4 * d) == 3 + 2 * b + d assert cg_simp(-a - b - c - d) == -1 a = CG(1, m1, 1, m2, 2, 2)**2 b = CG(1, m1, 1, m2, 2, 1)**2 c = CG(1, m1, 1, m2, 2, 0)**2 d = CG(1, m1, 1, m2, 2, -1)**2 e = CG(1, m1, 1, m2, 2, -2)**2 f = CG(1, m1, 1, m2, 1, 1)**2 g = CG(1, m1, 1, m2, 1, 0)**2 h = CG(1, m1, 1, m2, 1, -1)**2 i = CG(1, m1, 1, m2, 0, 0)**2 assert cg_simp(a + b + c + d + e + f + g + h + i) == 1 assert cg_simp(4 * (a + b + c + d + e + f + g + h + i)) == 4 assert cg_simp(a + b + 2 * c + d + 4 * e + f + g + h + i) == 1 + c + 3 * e assert cg_simp(-a - b - c - d - e - f - g - h - i) == -1 # alpha!=alphap or beta!=betap case # numerical a = CG(S(1) / 2, S(1) / 2, S(1) / 2, -S(1) / 2, 1, 0) * CG( S(1) / 2, -S(1) / 2, S(1) / 2, S(1) / 2, 1, 0) b = CG(S(1) / 2, S(1) / 2, S(1) / 2, -S(1) / 2, 0, 0) * CG( S(1) / 2, -S(1) / 2, S(1) / 2, S(1) / 2, 0, 0) c = CG(1, 1, 1, 0, 2, 1) * CG(1, 0, 1, 1, 2, 1) d = CG(1, 1, 1, 0, 1, 1) * CG(1, 0, 1, 1, 1, 1) assert cg_simp(a + b) == 0 assert cg_simp(c + d) == 0 # symbolic a = CG(S(1) / 2, m1, S(1) / 2, m2, 1, 1) * CG(S(1) / 2, m1p, S(1) / 2, m2p, 1, 1) b = CG(S(1) / 2, m1, S(1) / 2, m2, 1, 0) * CG(S(1) / 2, m1p, S(1) / 2, m2p, 1, 0) c = CG(S(1) / 2, m1, S(1) / 2, m2, 1, -1) * CG(S(1) / 2, m1p, S(1) / 2, m2p, 1, -1) d = CG(S(1) / 2, m1, S(1) / 2, m2, 0, 0) * CG(S(1) / 2, m1p, S(1) / 2, m2p, 0, 0) assert cg_simp(a + b + c + d) == KroneckerDelta(m1, m1p) * KroneckerDelta(m2, m2p) a = CG(1, m1, 1, m2, 2, 2) * CG(1, m1p, 1, m2p, 2, 2) b = CG(1, m1, 1, m2, 2, 1) * CG(1, m1p, 1, m2p, 2, 1) c = CG(1, m1, 1, m2, 2, 0) * CG(1, m1p, 1, m2p, 2, 0) d = CG(1, m1, 1, m2, 2, -1) * CG(1, m1p, 1, m2p, 2, -1) e = CG(1, m1, 1, m2, 2, -2) * CG(1, m1p, 1, m2p, 2, -2) f = CG(1, m1, 1, m2, 1, 1) * CG(1, m1p, 1, m2p, 1, 1) g = CG(1, m1, 1, m2, 1, 0) * CG(1, m1p, 1, m2p, 1, 0) h = CG(1, m1, 1, m2, 1, -1) * CG(1, m1p, 1, m2p, 1, -1) i = CG(1, m1, 1, m2, 0, 0) * CG(1, m1p, 1, m2p, 0, 0) assert cg_simp(a + b + c + d + e + f + g + h + i) == KroneckerDelta(m1, m1p) * KroneckerDelta(m2, m2p)
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 kappa(nu, l, lp): return Piecewise(((-sqrt(factorial(nu - 2)/factorial(nu + 2)) * CG(l, 1, lp, 1, nu, 2) / CG(l, 1, lp, -1, nu, 0)), ((nu > 1) & (nu < l + lp + 1))), (0, True))
def test_cg(): cg = CG(1, 2, 3, 4, 5, 6) wigner3j = Wigner3j(1, 2, 3, 4, 5, 6) wigner6j = Wigner6j(1, 2, 3, 4, 5, 6) wigner9j = Wigner9j(1, 2, 3, 4, 5, 6, 7, 8, 9) assert str(cg) == 'CG(1, 2, 3, 4, 5, 6)' ascii_str = \ """\ 5,6 \n\ C \n\ 1,2,3,4\ """ ucode_str = \ u"""\ 5,6 \n\ C \n\ 1,2,3,4\ """ assert pretty(cg) == ascii_str assert upretty(cg) == ucode_str assert latex(cg) == r'C^{5,6}_{1,2,3,4}' sT( cg, "CG(Integer(1), Integer(2), Integer(3), Integer(4), Integer(5), Integer(6))" ) assert str(wigner3j) == 'Wigner3j(1, 2, 3, 4, 5, 6)' ascii_str = \ """\ /1 3 5\\\n\ | |\n\ \\2 4 6/\ """ ucode_str = \ u"""\ ⎛1 3 5⎞\n\ ⎜ ⎟\n\ ⎝2 4 6⎠\ """ assert pretty(wigner3j) == ascii_str assert upretty(wigner3j) == ucode_str assert latex(wigner3j) == \ r'\left(\begin{array}{ccc} 1 & 3 & 5 \\ 2 & 4 & 6 \end{array}\right)' sT( wigner3j, "Wigner3j(Integer(1), Integer(2), Integer(3), Integer(4), Integer(5), Integer(6))" ) assert str(wigner6j) == 'Wigner6j(1, 2, 3, 4, 5, 6)' ascii_str = \ """\ /1 2 3\\\n\ < >\n\ \\4 5 6/\ """ ucode_str = \ u"""\ ⎧1 2 3⎫\n\ ⎨ ⎬\n\ ⎩4 5 6⎭\ """ assert pretty(wigner6j) == ascii_str assert upretty(wigner6j) == ucode_str assert latex(wigner6j) == \ r'\left\{\begin{array}{ccc} 1 & 2 & 3 \\ 4 & 5 & 6 \end{array}\right\}' sT( wigner6j, "Wigner6j(Integer(1), Integer(2), Integer(3), Integer(4), Integer(5), Integer(6))" ) assert str(wigner9j) == 'Wigner9j(1, 2, 3, 4, 5, 6, 7, 8, 9)' ascii_str = \ """\ /1 2 3\\\n\ | |\n\ <4 5 6>\n\ | |\n\ \\7 8 9/\ """ ucode_str = \ u"""\ ⎧1 2 3⎫\n\ ⎪ ⎪\n\ ⎨4 5 6⎬\n\ ⎪ ⎪\n\ ⎩7 8 9⎭\ """ assert pretty(wigner9j) == ascii_str assert upretty(wigner9j) == ucode_str assert latex(wigner9j) == \ r'\left\{\begin{array}{ccc} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{array}\right\}' sT( wigner9j, "Wigner9j(Integer(1), Integer(2), Integer(3), Integer(4), Integer(5), Integer(6), Integer(7), Integer(8), Integer(9))" )
def test_sympy__physics__quantum__cg__CG(): from sympy.physics.quantum.cg import CG from sympy import S assert _test_args(CG(S(3) / 2, S(3) / 2, S(1) / 2, -S(1) / 2, 1, 1))
def cg(l0, l, m): return CG(l0, 0, l, m, l, m).doit()
def test_doit(): assert Wigner3j(1 / 2, -1 / 2, 1 / 2, 1 / 2, 0, 0).doit() == -sqrt(2) / 2 assert CG(1 / 2, 1 / 2, 1 / 2, -1 / 2, 1, 0).doit() == sqrt(2) / 2