def gauss_to_string(l, m, numeric=False): """Return string representation of the generalized gaussian:: _____ 2 m / 1 l! l+3/2 -a r l m g (x,y,z) = / ----- --------- (4 a) e r Y (x,y,z) l \/ 4 pi (2l + 1)! l numeric=True/False indicates whether the normalization constant should be written as a number or an algebraic expression. """ norm, xyzs = Y_collect(l, m) ng = Q(2**(2 * l + 3) * factorial(l), 2 * factorial(2 * l + 1)) norm.multiply(ng) string = to_string(l, xyzs) string = (' * ' + string) * (string != '1') if numeric: snorm = repr(eval(repr(norm.norm))) else: snorm = repr(norm.norm) string = 'sqrt(a**%s*%s)/pi' % (2 * l + 3, snorm) + string string += ' * exp(-a*r2)' return string
def legendre(l, m): """Determine z dependence of spherical harmonic. Returns vector, where the p'th element is the coefficient of z^p r^(l-|m|-p). """ # Check if requested has already been calculated if (l, m) in Y_lp[0]: return Y_lp[0][(l, m)] m = abs(m) assert l >= 0 and 0 <= m <= l result = np.zeros(l - m + 1, 'O') if l == m == 0: """Use that 0 P (z) = 1 0 """ result[0] = Q(1) elif l == m: """Use the recursion relation m m-1 P (z) = (2m-1) P (z) m m-1 """ result[:] += (2 * m - 1) * legendre(l - 1, m - 1) elif l == m + 1: """Use the recursion relation l-1 l-1 P (z) = (2l-1)z P (z) l l-1 """ result[1:] += (2 * l - 1) * legendre(l - 1, l - 1) else: """Use the recursion relation m 2l-1 m l+m-1 2 m P (z)= ---- z P (z) - ----- r P (z) l l-m l-1 l-m l-2 """ result[1:] += np.multiply(legendre(l - 1, m), Q(2 * l - 1, l - m)) result[:(l - 2) - m + 1] -= np.multiply(legendre(l - 2, m), Q(l + m - 1, l - m)) # Store result in global dictionary Y_lp[0][(l, m)] = result return result
def gauss_potential_to_string(l, m, numeric=False): """Return string representation of the potential of a generalized gaussian. The potential is determined by:: m m ^ _ m ^ v [g (r) Y (r) ](r) = v (r) Y (r) l l l l l l where:: 4 pi / -l-1 /r l+2 l /oo 1-l \ v (r) = ---- | r | dx x g (r) + r | dx x g (r) | l 2l+1 \ /0 l /r l / """ v_l = [ [Q(4, 1), 1], [Q(4, 3), 1, 2], [Q(4, 15), 3, 6, 4], [Q(4, 105), 15, 30, 20, 8], [Q(4, 945), 105, 210, 140, 56, 16], [Q(4, 10395), 945, 1890, 1260, 504, 144, 32], ] norm, xyzs = Y_collect(l, m) norm.multiply(v_l[l][0]) string = txt_sqrt(norm.norm, numeric) + '*' + (l != 0) * '(' if numeric: string += repr(v_l[l][1] * sqrt(pi)) else: string += str(v_l[l][1]) + '*sqrt(pi)' string += '*erf(sqrt(a)*r)' if len(v_l[l]) > 2: string += '-(' for n, coeff in enumerate(v_l[l][2:]): if n == 0: string += str(coeff) else: string += '+' + str(coeff) + '*(sqrt(a)*r)**%d' % (2 * n) string += ')*sqrt(a)*r*exp(-a*r2)' if l == 0: string += '/r' elif l == 1: string += ')/r/r2*' + to_string(l, xyzs) else: string += ')/r/r2**%d*' % l + to_string(l, xyzs) return string
def simplify(xyzs): """Rescale coefficients to smallest integer value""" norm = Q(1) numxyz = np.array(xyzs.values()) # up-scale all 'xyz' coefficients to integers for xyz in numxyz: numxyz *= xyz.denom norm /= xyz.denom # determine least common divisor for 'xyz' coefficients dmax = 1 num_max = max(abs(np.floor(numxyz))) for d in range(2, num_max + 1): test = numxyz / d if np.alltrue(test == np.floor(test)): dmax = d # Update simplified dictionary norm *= dmax for i, xyz in enumerate(xyzs): xyzs[xyz] = numxyz[i] / dmax return norm
def __init__(self, l, m): m = abs(m) if m == 0: self.norm = Q(2 * l + 1, 4) else: self.norm = Q((2 * l + 1) * factorial(l - m), 2 * factorial(l + m))