def pade_m(coef, e, m): # Calculation of analitical function on a arbitrary mesh for a given Pade coefficient # and first known momenta of function # e - energy mesh (can be complex or real) # coef - Pade coefficients # m - first three momenta of function nlines = len(e) r = len(coef) / 2 f = mp.zeros(nlines, 1) pq = mp.ones(r * 2 + 1, 1) # for i in range(0, r): # pq[i] = coef[i] # pq[i + r] = coef[i + r] for iw in range(0, nlines): p = mp.mpc(0.0) q = mp.mpc(0.0) for i in range(0, r): p += coef[i] * e[iw]**i for i in range(0, r + 1): q += coef[i + r] * e[iw]**i f[iw] = fdiv(p, q) # f[iw] = np.divide(p, q) f[iw] /= e[iw]**3 f[iw] += m[0] / e[iw] + m[1] / (e[iw]**2) + m[2] / (e[iw]**3) f = fp.matrix(f) return f
def pade(coef, e): # Calculation of analitical function on a arbitrary mesh for a given Pade coefficient # e - energy mesh (can be complex or real) # coef - Pade coefficients nlines = len(e) r = len(coef) // 2 f = mp.zeros(nlines, 1) # pq = mp.ones(r * 2 + 1, 1) # for i in range(0, r): # pq[i] = coef[i] # pq[i + r] = coef[i + r] for iw in range(0, nlines): p = mp.mpc(0.0) q = mp.mpc(0.0) for i in range(0, r): p += coef[i] * e[iw]**i for i in range(0, r): # print(i, r, i+r) q += coef[i + r] * e[iw]**i # f[iw] = np.divide(p, q) f[iw] = fdiv(p, q) f = fp.matrix(f) return f
def Ht_AFE_B(z, t): """ This is the much more accurate approx functional eqn posted by Terry at https://terrytao.wordpress.com/2018/02/02/polymath15-second-thread-generalising-the-riemann-siegel-approximate-functional-equation/#comment-492182 :param z: point at which H_t is computed :param t: the "time" parameter :return: the B part in Ht """ z, t = mp.mpc(z), mp.mpc(t) s = (1 + 1j * z.real - z.imag) / 2 tau = mp.sqrt(s.imag / (2 * mp.pi())) M = int(tau) B_pre = (1 / 16.0) * s * (s - 1) * mp.power(mp.pi(), 0.5 * (s - 1)) * mp.gamma(0.5 * (1 - s)) B_sum = 0.0 for m in range(1, M + 1): if t.real > 0: B_sum += mp.exp( (t / 16.0) * mp.power(mp.log( (5 - s) / (2 * mp.pi() * m * m)), 2)) / mp.power(m, 1 - s) else: B_sum += 1 / mp.power(m, 1 - s) return B_pre * B_sum
def Ht_AFE_A(z, t): """ This is the much more accurate approx functional eqn posted by Terry at https://terrytao.wordpress.com/2018/02/02/polymath15-second-thread-generalising-the-riemann-siegel-approximate-functional-equation/#comment-492182 :param z: point at which H_t is computed :param t: the "time" parameter :return: the A part in Ht """ z, t = mp.mpc(z), mp.mpc(t) s = (1 + 1j * z.real - z.imag) / 2 tau = mp.sqrt(s.imag / (2 * mp.pi())) N = int(tau) A_pre = (1/16) * s * (s-1) \ * mp.power(mp.pi(), -1*s/2) * mp.gamma(s/2) A_sum = 0.0 for n in range(1, N + 1): if t.real > 0: A_sum += mp.exp( (t / 16) * mp.power(mp.log( (s + 4) / (2 * mp.pi() * n * n)), 2)) / mp.power(n, s) else: A_sum += 1 / mp.power(n, s) return A_pre * A_sum
def Ht_AFE(z, t): z, t = mp.mpc(z), mp.mpc(t) f_arg1 = (1 + 1j * z.real - z.imag) / 2.0 f_arg2 = (1 + 1j * z.real + z.imag) / 2.0 if z.imag == 0: result = 0.5 * (Ft(f_arg1, t).real) else: result = 0.25 * (Ft(f_arg1, t) + Ft(f_arg2, t).conjugate()) return result
def fft( b, invert=False) : a=[mp.mpc(0)]*len(b); a[0:len(b)]=b; n=len(a); if (n == 1): return a; a0=[mp.mpc(0)]*(n//2); a1=[mp.mpc(0)]*(n//2); for i in range(n//2) : a0[i] = mp.mpc(a[2*i]); a1[i] = mp.mpc(a[2*i+1]); a0=fft(a0, invert); a1=fft(a1, invert); factor=[-1,1]; ang = (mp.mpf(2) * mp.pi / n) * factor[int(invert)]; w=mp.mpc(1); wn=mp.exp(mp.mpc(real=0,imag=ang)); for i in range(n//2) : a[i] = a0[i] + w * a1[i]; a[i + n//2] = a0[i] - w * a1[i]; if (invert) : a[i] /= mp.mpc(2); a[i + n//2] /= mp.mpc(2); w *= wn; return a;
def Ht_Effective(z, t): """ This uses the effective approximation of H_t from Terry's blog :param z: point at which H_t is computed :param t: the "time" parameter :return: H_t as a sum of two terms that are analogous to A and B, but now also with an efffective error bound (returned as percentage of |H_t| """ z, t = mp.mpc(z), mp.mpc(t) sigma = (1 - z.imag) / 2.0 T = (z.real) / 2.0 Tdash = T + t * mp.pi() / 8.0 s1 = sigma + 1j * T s2 = 1 - sigma + 1j * T N = int((mp.sqrt(Tdash / (2 * mp.pi()))).real) alph1 = alpha1(s1) alph2 = alpha1(s2).conjugate() A0_expo = (t / 4.0) * alph1 * alph1 B0_expo = (t / 4.0) * alph2 * alph2 H01_est1 = H01(s1) H01_est2 = H01(s2).conjugate() #begin main estimate block A0 = mp.exp(A0_expo) * H01_est1 B0 = mp.exp(B0_expo) * H01_est2 A_sum = 0.0 B_sum = 0.0 for n in range(1, N + 1): A_sum += 1 / mp.power(n, s1 + (t / 2.0) * alph1 - (t / 4.0) * mp.log(n)) B_sum += 1 / mp.power( n, 1 - s1 + (t / 2.0) * alph2 - (t / 4.0) * mp.log(n)) A = A0 * A_sum B = B0 * B_sum H = (A + B) / 8.0 #end main estimate block #begin error block A0_err_expo = (t / 4.0) * (abs(alph1)**2) #A0_expo.real may also work B0_err_expo = (t / 4.0) * (abs(alph2)**2) #B0_expo.real may also work epserr_1 = mp.exp(A0_err_expo) * abs(H01_est1) * abs(eps_err(s1, t)) / ( (T - 3.33) * 8.0) epserr_2 = mp.exp(B0_err_expo) * abs(H01_est2) * abs(eps_err(s2, t)) / ( (T - 3.33) * 8.0) epserr = epserr_1 + epserr_2 C0 = mp.sqrt(mp.pi()) * mp.exp(-1 * (t / 64.0) * (mp.pi()**2)) * mp.power( Tdash, 1.5) * mp.exp(-1 * mp.pi() * T / 4.0) C = C0 * vwf_err(s1, t) / 8.0 toterr = epserr + C #print(epserr_1, epserr_2, C0, vwf_err(s1, t), C, toterr.real) #end error block if z.imag == 0: return (H.real, toterr.real / abs(H.real)) else: return (H, toterr.real / abs(H))
def Ht_complex_integrand(u, z, t): """ Computes the integrand of H_t(u) in Terry' blog at https://terrytao.wordpress.com/2018/02/02/polymath15-second-thread-generalising-the-riemann-siegel-approximate-functional-equation/ :param u: integration parameter :param z: point at which H_t is computed :param t: the "time" parameter :return: integrand of H_t(z) """ u, z, t = mp.mpc(u), mp.mpc(z), mp.mpc(t) return mp.exp(t * u * u) * phi_decay(u) * mp.cos(z * u)
def precise_kahan_zeros_to_poly(zeros): poly_size = len(zeros) + 1 poly = np.array([mp.mpc(1) for _ in range(1)], dtype=np.object) c = np.array([mp.mpc(0) for _ in range(poly_size)], dtype=np.object) for zero in zeros: y = - zero * poly - c[:poly.shape[0]] y = np.pad(y, (1, 0), 'constant', constant_values=mp.mpc(0)) t = np.pad(poly, (0, 1), 'constant', constant_values=mp.mpc(0)) + y c[:poly.shape[0]+1] = ( t - np.pad(poly, (0, 1), 'constant', constant_values=mp.mpc(0)) ) - y poly = t return poly
def create_simple_lattice(L, T, kind='rnd'): #-------------------------------------------------------------------------- # forming adjacency matrix basis_x = np.tile(np.arange(L), T) basis_y = np.repeat(np.arange(T), L) X, Y = np.meshgrid(basis_x, basis_y) adj_matrix = AND(np.abs(X - X.T) == 1, np.abs(Y - Y.T) == 0) adj_matrix += AND(np.abs(X - X.T) == 0, np.abs(Y - Y.T) == 1) adj_matrix += np.triu((X - X.T) * (Y - Y.T) == 1 * (2 * (Y % 2) - 1)) adj_matrix = adj_matrix + adj_matrix.T #-------------------------------------------------------------------------- # setting couplings matrix if kind == 'rnd': R = np.random.normal(0, 1, size=(L * T, L * T)) J_matrix = np.float_(adj_matrix) * (R + R.T) + 0j if kind == 'frm': J_matrix = -1.0 * np.float_(adj_matrix) + 0j if kind == 'afm': J_matrix = +1.0 * np.float_(adj_matrix) + 0j #-------------------------------------------------------------------------- # transformation to j_i = exp(-J_i), in mpc format E = mp.mpc(0) j_matrix = mp.matrix(np.exp(-J_matrix).tolist()) return E, j_matrix
def Aminus_1lnum_factor(k, d, l, nu, m, wig_1llp1_000, wig_1llm1_000, wig_1llp1_1m10, wig_1llm1_1m10): #the A^-_{l',l,\nu,m} factor for expressing off origin spherical waves in term of on origin spherical waves #we are concerned with dipole fields, so l=1; the l' in the analytical expressions are #represented by l here #also for our purposes m=-1,0,1 and the list of wigner coeffs. are passed in as arguments #we assume that the elongation of the Wigner3j lists happen outside the function if (l == nu): return 0 #the Wigner3j (1 l l ; 0 0 0)==0 and the entire A factor reduces to 0 sign = (-1)**abs(m) mpimag = mp.mpc(1j) ans = sign * mpimag**(1 - l - nu) * (2 * nu + 1) * mp.sqrt(3 * mp.one * (2 * l + 1) / (2 * l * (l + 1))) if nu > l: if m == 0: ans *= wig_1llp1_000[l - 1]**2 else: ans *= wig_1llp1_000[l - 1] * wig_1llp1_1m10[l - 1] #note that for the Wigner3j symbols (j1 j2 j3 ; m1 m2 m3) = (-1)^(j1+j2+j3)*(j1 j2 j3 ; -m1 -m2 -m3) #here j1=1, j2=l, j3=nu=l \pm 1 so j1+j2+j3 is always even else: if m == 0: ans *= wig_1llm1_000[l - 1]**2 else: ans *= wig_1llm1_000[l - 1] * wig_1llm1_1m10[l - 1] return ans * mp_spherical_hn(nu, k * d)
def adjusted_AB_analysis(z, t): z, t = mp.mpc(z), mp.mpc(t) s = (1 + 1j * z.real - z.imag) / 2 tau = mp.sqrt(s.imag / (2 * mp.pi())) N = int(tau) M = int(tau) s_like1 = (s + 4) / 2 s_like2 = (5 - s) / 2 initial_term = (1 / 4) * mp.sqrt(2 * mp.pi()) A_pre = initial_term * mp.power(mp.pi(), -1 * s / 2) * mp.exp( (s_like1 - 0.5) * mp.log(s_like1) - s_like1) A_sum = 0.0 for n in range(1, N + 1): if t.real > 0: A_sum += mp.exp( (t / 16) * mp.power(mp.log(s_like1 / (mp.pi() * n * n)), 2)) / mp.power( n, s) else: A_sum += 1 / mp.power(n, s) A = A_pre * A_sum B_pre = initial_term * mp.power( mp.pi(), (s - 1) / 2) * mp.exp((s_like2 - 0.5) * mp.log(s_like2) - s_like2) B_sum = 0.0 ddxB_sum = 0.0 for m in range(1, M + 1): if t.real > 0: mth_term = mp.exp( (t / 16) * mp.power(mp.log(s_like2 / (mp.pi() * m * m)), 2)) / mp.power( m, 1 - s) else: mth_term = 1 / mp.power(m, 1 - s) B_sum += mth_term ddxB_sum += mth_term * mp.log(m) B = B_pre * B_sum B_common_term = mp.exp((t / 16) * mp.power(mp.log(s_like2 / mp.pi()), 2)) B0 = B_pre * B_common_term ddxBB0 = 0.5j * ddxB_sum / B_common_term AplusB = A + B ABB0 = AplusB / B0 return (AplusB, B0, ABB0, abs(ABB0), ddxBB0, abs(ddxBB0))
def phi_decay(u,n_max=100): running_sum=0 u=mp.mpc(u) for n in range(1,n_max+1): term1=2*PI_sq*mp.power(n,4)*mp.exp(9*u) - 3*PI*mp.power(n,2)*mp.exp(5*u) term2=mp.exp(-1*PI*mp.power(n,2)*mp.exp(4*u)) running_sum += term1*term2 #print n,term1, term2, running_sum return running_sum
def H0_AFE(z): z = mp.mpc(z) f_arg1 = (1 + 1j * z.real - z.imag) / 2.0 f_arg2 = (1 + 1j * z.real + z.imag) / 2.0 if z.imag == 0: result = 0.5 * (F0(f_arg1).real) else: result = 0.25 * (F0(f_arg1) + F0(f_arg2).conjugate()) return result
def polyMulFast(p1,p2,n): r=len(p1); m=2**(r.bit_length()); p1F=[0]*m; p2F=[0]*m; p1F[0:len(p1)]=[mp.mpc(x) for x in p1]; p2F[0:len(p1)]=[mp.mpc(x) for x in p2]; p1F=fft(p1F); p2F=fft(p2F); result=[0]*m; for i in range(m): result[i]=p1F[i]*p2F[i]; result=fft(result,True); res=[0]*r; for i in range(len(result)): res[i%r]+=int(round(result[i].real)); # res[i%r]%=n; #res[i%len(p1)]%=n; return res;
def Ht_AFE_ADJ_AB(z, t): """ This uses the adjusted A'+B' estimate from Terry's blog to compute H_t for moderate to large T, where the C term is small. Also, there are some rearrangements to the A' and B' formulas to make them faster to compute :param z: point at which H_t is computed :param t: the "time" parameter :return: Ht as A'+B' """ z, t = mp.mpc(z), mp.mpc(t) s = (1 + 1j * z.real - z.imag) / 2.0 tau = mp.sqrt(s.imag / (2 * mp.pi())) N = int(tau) M = int(tau) s_like1 = (s + 4) / 2.0 s_like2 = (5 - s) / 2.0 log_sp1 = mp.log(s_like1 / mp.pi()) log_sp2 = mp.log(s_like2 / mp.pi()) initial_term = 0.25 * mp.sqrt(2 * mp.pi()) A0 = initial_term * mp.power(mp.pi(), -1 * s / 2.0) * mp.exp( (s_like1 - 0.5) * mp.log(s_like1) - s_like1 + (t / 16.0) * mp.power(log_sp1, 2)) B0 = initial_term * mp.power( mp.pi(), (s - 1) / 2.0) * mp.exp((s_like2 - 0.5) * mp.log(s_like2) - s_like2 + (t / 16.0) * mp.power(log_sp2, 2)) A_sum_exponent = s + (t / 4.0) * log_sp1 B_sum_exponent = 1 - s + (t / 4.0) * log_sp2 A_sum = 0.0 for n in range(1, N + 1): A_sum += mp.power(n, (t / 4.0) * mp.log(n) - A_sum_exponent) A = A0 * A_sum B_sum = 0.0 for m in range(1, M + 1): B_sum += mp.power(m, (t / 4.0) * mp.log(m) - B_sum_exponent) B = B0 * B_sum H = A + B if z.imag == 0: return H.real else: return H
def preserves_hermitian_form(SL2C_matrices): """ >>> CC = ComplexField(100) >>> A = matrix(CC, [[1, 1], [1, 2]]); >>> B = matrix(CC, [[0, 1], [-1, 0]]) >>> C = matrix(CC, [[CC('I'),0], [0, -CC('I')]]) >>> ans, sig, form = preserves_hermitian_form([A, B]) >>> ans True >>> sig 'indefinite' >>> form.change_ring(ComplexField(10)) [ 0.00 -1.0*I] [ 1.0*I 0.00] >>> preserves_hermitian_form([A, B, C]) (False, None, None) >>> ans, sig, form = preserves_hermitian_form([B, C]) >>> sig 'definite' """ M = block_matrix(len(SL2C_matrices), 1, [ left_mult_by_adjoint(A) - right_mult_by_inverse(A) for A in SL2C_matrices ]) CC = M.base_ring() mp.prec = CC.prec() RR = RealField(CC.prec()) epsilon = RR(2)**(-int(0.8 * mp.prec)) U, S, V = mp.svd(sage_matrix_to_mpmath(M)) S = list(mp.chop(S, epsilon)) if mp.zero not in S: return False, None, None elif S.count(mp.zero) > 1: for i, A in enumerate(SL2C_matrices): for B in SL2C_matrices[i + 1:]: assert (A * B - B * A).norm() < epsilon sig = 'indefinite' if any(abs(A.trace()) > 2 for A in SL2C_matrices) else 'both' return True, sig, None else: in_kernel = list(mp.chop(V.H.column(S.index(mp.zero)))) J = mp.matrix([in_kernel[:2], in_kernel[2:]]) iJ = mp.mpc(imag=1) * J J1, J2 = J + J.H, iJ + iJ.H J = J1 if mp.norm(J1) >= mp.norm(J2) else J2 J = (1 / mp.sqrt(abs(mp.det(J)))) * J J = mpmath_matrix_to_sage(J) assert all((A.conjugate_transpose() * J * A - J).norm() < epsilon for A in SL2C_matrices) sig = 'definite' if J.det() > 0 else 'indefinite' return True, sig, J
def Ht_AFE_C(z, t): """ This is the much more accurate approx functional eqn posted by Terry at https://terrytao.wordpress.com/2018/02/02/polymath15-second-thread-generalising-the-riemann-siegel-approximate-functional-equation/#comment-492182 :param z: point at which H_t is computed :param t: the "time" parameter :return: the C part in Ht """ z, t = mp.mpc(z), mp.mpc(t) s = (1 + 1j * z.real - z.imag) / 2 tau = mp.sqrt(s.imag / (2 * mp.pi())) N = int(tau) M = int(tau) C_pre1 = -(1 / 16.0) * s * (s - 1) * mp.power(mp.pi(), -0.5 * s) * mp.gamma(0.5 * s) C_pre2 = mp.gamma(1 - s) * mp.exp(-1j * mp.pi() * s) / (2j * mp.pi()) C_pre3 = mp.power(2j * mp.pi() * M, s - 1) * mp.exp( -1 * t * mp.pi() * mp.pi() / 64.0) C_psi = psi((s / (2j * M * mp.pi())) - N) return C_pre1 * C_pre2 * C_pre3 * C_psi
def AB_analysis(z, t): z, t = mp.mpc(z), mp.mpc(t) s = (1 + 1j * z.real - z.imag) / 2 tau = mp.sqrt(s.imag / (2 * mp.pi())) N = int(tau) M = int(tau) A_pre = (1 / 16) * s * (s - 1) * mp.power(mp.pi(), -1 * s / 2) * mp.gamma( s / 2) A_sum = 0.0 for n in range(1, N + 1): if t.real > 0: A_sum += mp.exp( (t / 16) * mp.power(mp.log( (s + 4) / (2 * mp.pi() * n * n)), 2)) / mp.power(n, s) else: A_sum += 1 / mp.power(n, s) A = A_pre * A_sum B_pre = (1 / 16) * s * (s - 1) * mp.power(mp.pi(), (s - 1) / 2) * mp.gamma( (1 - s) / 2) B_sum = 0.0 for m in range(1, M + 1): if t.real > 0: B_sum += mp.exp( (t / 16) * mp.power(mp.log( (5 - s) / (2 * mp.pi() * m * m)), 2)) / mp.power(m, 1 - s) else: B_sum += 1 / mp.power(m, 1 - s) B = B_pre * B_sum B0 = B_pre * mp.exp((t / 16) * mp.power(mp.log( (5 - s) / (2 * mp.pi())), 2)) AplusB = A + B ABB0 = AplusB / B0 return (AplusB, B0, ABB0, abs(ABB0))
def pade_ls_coefficients(f, e, n): # Subroutine pade_ls_coeficients() finds coefficient of Pade approximant by Least Squares method # f - values of complex function for approximation # e - complex points in which function z is determined # n - number of coefficients, should be less than number of points in e (n<m) m = len(e) r = n / 2 # Preparation of arrays to calc Pade coefficiens s = mp.zeros(m, 1) x = mp.zeros(m, n) for i in range(0, m): s[i] = f[i] * e[i]**r for j in range(0, r): x[i, j] = e[i]**j for j in range(r, 2 * r): x[i, j] = -f[i] * e[i]**(j - r) # Solving the equation: aX=b, where # a=x, b=s, # |p| # X = | | # |q| # pq = linalg.lstsq(x, s)[0] success = True solver = 'LU solver' try: pq = mp.lu_solve(x, s) # success = True # except ZeroDivisionError as err: except ZeroDivisionError: # if 'matrix is numerically singular' in err.message: try: pq = mp.qr_solve(x, s) pq = pq[0] solver = 'QR solver' # success = True except ValueError: # if 'matrix is numerically singular' in err.message: success = False pq = 123456.7 # else: # raise if success is True: pq.rows += 1 pq[n, 0] = mp.mpc(1, 0) return pq, success, solver
def phi_decay(u, n_max=100): """ Computes Phi(u) in Terry' blog at https://terrytao.wordpress.com/2018/02/02/polymath15-second-thread-generalising-the-riemann-siegel-approximate-functional-equation/ :param u: input complex number :param n_max: upper limit for summation. It has to be a positive integer :return: Phi(u) """ running_sum = 0 u = mp.mpc(u) for n in range(1, n_max + 1): term1 = 2 * mp.pi() * mp.pi() * mp.power(n, 4) * mp.exp(9*u) \ - 3 * mp.pi() * mp.power(n, 2) * mp.exp(5*u) term2 = mp.exp(-1 * mp.pi() * mp.power(n, 2) * mp.exp(4 * u)) running_sum += term1 * term2 return running_sum
def set_arbitrary_precision(self, arbitrary_precision, force=False, update_render=True): """ arbitrary_precision: bool """ # Precision is not actually arbitrary during runtime but can be increased in # 'mandelbrot.py'. if (self.arbitrary_precision == arbitrary_precision and not force): return self.arbitrary_precision = arbitrary_precision if self.arbitrary_precision: self._complex = mp.mpc self.center = mp.mpc(self.center) else: self._complex = complex self.center = complex(self.center) self._rebuild_maps() if update_render: self.update_render_p()
def log_partition_function(E,J_matrix,L,T): q=2 beta = np.log((q**2+1)/q) basis = spin_basis(len(J_matrix)) PF = mp.mpc(0) Eb = [] for i in range(len(basis)): v = basis[i] Eb += [-0.5*np.dot(v,np.dot(J_matrix,v))/beta] PF += mp.exp(0.5*np.dot(v,np.dot(J_matrix,v))+0j) #np.set_printoptions(threshold=sys.maxsize) indx = np.argsort(Eb) basis = basis[indx] k=0 plot_configuration(basis[k],L,T,basis,Eb,E) print('energy shift:',-E/beta) print('energy of trajectory:',Eb[k]) return E+mp.log(PF)
def iterations_to_escape_ap(c, max_iterations=100): """ Calculate the number of iterations to escape the mandelbrot set. Uses arbitrary precision for calculations. Returns an (interpolated) mpmath floating point value. If no escape, returns a value greater than max_iterations. """ iterations = 0 z = mp.mpc(0) while mp.mag(z) < ESCAPE_MAGNITUDE: iterations += 1 if iterations > max_iterations: break z = z * z + c inner_log = mp.log(mp.fabs(z) / ESCAPE_MAGNITUDE) if inner_log.real > 0: adjustment = 1 - mp.log(inner_log, b=2) else: adjustment = 0 return float(iterations + adjustment)
def conjugator_into_SL2R(SL2C_matrices): """ Returns a matrix C in SL(2, C) so that C^-1 * M * C is (essentially) in SL(2, R) for all the input matrices M. """ ans, sig, form = preserves_hermitian_form(SL2C_matrices) if ans is None: raise ValueError('No invariant hermitian form found') if sig == 'definite': raise ValueError('Conjugate into SU(2), not SL(2, R)') if sig == 'both': raise ValueError('This degnerate case not implemented') assert sig == 'indefinite' J = sage_matrix_to_mpmath(form) eigs, U = mp.eighe(J) C = U * mp.diag([1 / mp.sqrt(abs(e)) for e in eigs]) sq_two = mp.sqrt(2) sq_two_i = mp.mpc(imag=sq_two) S = mp.matrix([[1 / sq_two_i, 1 / sq_two_i], [-1 / sq_two, 1 / sq_two]]) C = C * S.H C = (1 / mp.sqrt(mp.det(C))) * C return mpmath_matrix_to_sage(C)
def zetaEMS(s, N, v): sum1 = mp.mpc(0) s = mp.mpc(s) for n in range(1, N): sum1 = sum1 + (n**(-s)) sum1 = sum1 + ((N**(1 - s)) / mp.mpc(s - 1)) sum1 = sum1 + ((N**(-s)) / mp.mpc(2)) sum2 = 0 for k1 in range(1, v + 1): t1 = (bernoulli(2 * k1) / mp.mpc(fact(2 * k1))) prd = mp.mpc(1) for h in range(0, (2 * k1) - 1): prd = prd * (s + mp.mpc(h)) t2 = prd t3 = N**(1 - s - (2 * k1)) sum2 = sum2 + (t1 * t2 * t3) return sum1 + sum2
def mpmathify(expr, **kwargs): from mpmath import mp vc = lambda x: mp.mpc(x) if isinstance(x, (complex, mp.mpc)) else mp.mpf(x) compiler = LambdaCompiler(value_converter=vc, function_module=mp, **kwargs) f = compiler.visit(e.S(expr)) return lambda **args: f(args)
def mpmathify(expr,**kwargs): from mpmath import mp vc = lambda x:mp.mpc(x) if isinstance(x,(complex,mp.mpc)) else mp.mpf(x) compiler = LambdaCompiler(value_converter=vc,function_module=mp,**kwargs) f = compiler.visit(e.S(expr)) return lambda **args:f(args)
def Ht_complex_root_finder(complex_guess, t): result = mp.findroot(lambda z: Ht_complex(z, t), mp.mpc(complex_guess)) return result
def spherical_multiRegion_Green_Arnoldi_Mmn_Uconverge(n,k,RPlist, invchi, gridpts=10000, mpdps=60, klim=25, Taylor_tol=1e-12, Unormtol=1e-8, veclim=3, delveclim=2, maxveclim=40): """ generates a representation of the Green's function/Umatrix over spherical region of radius R with sub-bases with support in shell regions with boundaries delineated by RPlist this is done so that the projection operator for spatial projection based constraints is explicit the sub-regions are 0-RPlist[0], RPlist[0]-RPlist[1], ..., RPlist[-2]-RPlist[-1] RPlist[-1] is the radius of the entire bounding sphere the first region is an inner sphere, the other regions are cocentric shells note here we are still using the old convention for the U matrix to be consistent with older Arnoldi code in the new optimizations U = V^\dagger-1 - G^\dagger; here we calculate Uinv, and Uinv = V^-1-G """ mp.dps = mpdps #set mpmath precision #first step: generate the sub-bases and sub-Gmat/Uinvs for each block regionnum = len(RPlist) unitRgdotRglist = np.zeros(regionnum, dtype=type(1j*mp.one)) #values needed for computing coupling between different sub-bases in Gmat unitRgdotOutlist = np.zeros(regionnum, dtype=type(1j*mp.one)) #stored using mpmath to avoid underflow when calculating Gmat couplings unitImdotOutlist = np.zeros(regionnum, dtype=type(1j*mp.one)) subGmatlist = [] vecnum = 0 subbasis_head_indlist = [] All_unitMvecs = [] rgridlist = [] for i in range(regionnum): print('M wave Region #', i) if i==0: #inner spherical region is special because it contains origin, use old mpmath Taylor Arnoldi code subbasis_head_indlist.append(0) rmnRgM, rnImM, unitrmnMpols, Uinv = speedup_Green_Taylor_Arnoldi_RgMmn_Uconverge(n,k,RPlist[0], klim=klim, Taylor_tol=Taylor_tol, invchi=invchi, Unormtol=Unormtol) unitRgdotRglist[0] = mp.sqrt(rmnMnormsqr_Taylor(n,k,RPlist[0],rmnRgM)) #unitRg dot Rg is just norm of the regular wave #for the inner sphere, the outgoing wave quantities are not relevant since the inner sphere contains origin subGmat = mp.eye(Uinv.rows)*invchi-Uinv subGmatlist.append(np.array(mpmath.fp.matrix(subGmat.tolist()).tolist())) vecnum += Uinv.rows #generate ptval representation for the Arnoldi basis to be outputted rgrid = np.linspace(0,RPlist[0],gridpts) rgridlist.append(rgrid) for i in range(len(unitrmnMpols)-1): #don't include the last unorthogonalized, unnormalized Arnoldi vector All_unitMvecs.append((k*rgrid)**n * po.polyval(k*rgrid, unitrmnMpols[i].coef)) else: subbasis_head_indlist.append(vecnum) try: rgrid, rsqrgrid, rdiffgrid, RgMgrid, ImMgrid, unitMvecs, Uinv, Gmat = shell_Green_grid_Arnoldi_RgandImMmn_Uconverge(n,k,RPlist[i-1],RPlist[i], invchi, gridpts=gridpts, Unormtol=Unormtol, maxveclim=maxveclim) OutMgrid = RgMgrid + 1j*ImMgrid unitRgdotRglist[i] = mp.sqrt(rgrid_Mmn_normsqr(RgMgrid,rsqrgrid,rdiffgrid)) unitRgdotOutlist[i] = mp.mpc(rgrid_Mmn_dot(unitMvecs[0], OutMgrid, rsqrgrid,rdiffgrid)) unitImdotOutlist[i] = mp.mpc(rgrid_Mmn_dot(unitMvecs[1], OutMgrid, rsqrgrid,rdiffgrid)) except FloatingPointError: rgrid, rsqrgrid, rdiffgrid, RgMgrid, ImMgrid, unitMvecs, Uinv, Gmat = shell_Green_grid_Arnoldi_RgandImMmn_Uconverge_mp(n,k,RPlist[i-1],RPlist[i], invchi, gridpts=gridpts, Unormtol=Unormtol, maxveclim=maxveclim) OutMgrid = RgMgrid + 1j*ImMgrid unitRgdotRglist[i] = mp.sqrt(rgrid_Mmn_normsqr(RgMgrid,rsqrgrid,rdiffgrid)) unitRgdotOutlist[i] = rgrid_Mmn_dot(unitMvecs[0], OutMgrid, rsqrgrid,rdiffgrid) unitImdotOutlist[i] = rgrid_Mmn_dot(unitMvecs[1], OutMgrid, rsqrgrid,rdiffgrid) Gmat = np.array(mpmath.fp.matrix(Gmat.tolist()).tolist()) subGmatlist.append(Gmat) vecnum += Gmat.shape[0] All_unitMvecs.extend(unitMvecs[:-2]) #don't include the last two unorthogonalized, unnormalized Arnoldi vectors rgridlist.append(rgrid) subbasis_head_indlist.append(vecnum) #for bookkeeping convenience put the total number of basis vectors at end of the subbasis family head index list Gmat = np.zeros((vecnum,vecnum),dtype=np.complex) #the Green's function representation for the entire domain for i in range(regionnum): indstart = subbasis_head_indlist[i]; indend = subbasis_head_indlist[i+1] Gmat[indstart:indend,indstart:indend] = subGmatlist[i][:,:] #print('RgdotRgM', unitRgdotRglist) #print('RgdotOut', unitRgdotOutlist) #print('ImdotOut', unitImdotOutlist) #next generate the couplings between different subbases jkcubed = 1j * k**3 for i in range(regionnum): Rgiind = subbasis_head_indlist[i] Imiind = Rgiind+1 #first do regions lying within region #i for j in range(i): Rgjind = subbasis_head_indlist[j] Gmat[Rgjind,Rgiind] = np.complex(jkcubed * unitRgdotRglist[j] * unitRgdotOutlist[i]) Gmat[Rgjind,Imiind] = np.complex(jkcubed * unitRgdotRglist[j] * unitImdotOutlist[i]) #then do regions lying outside region #i for j in range(i+1,regionnum): Rgjind = subbasis_head_indlist[j] Imjind = Rgjind+1 Gmat[Rgjind,Rgiind] = np.complex(jkcubed * unitRgdotOutlist[j] * unitRgdotRglist[i]) Gmat[Imjind,Rgiind] = np.complex(jkcubed * unitImdotOutlist[j] * unitRgdotRglist[i]) #prepare for output #outputting Rgnormlist is for use later to construct source vectors #outputting subbasis_head_indlist is for use later to construct projection matrices Uinv = invchi*np.eye(vecnum) - Gmat #create an rgrid over the entire domain and extend the ptval representation of all the subbases onto the entire domain, for potential plotting purposes later fullrgrid = rgridlist[0].copy() rboundaries = [0,gridpts] for i in range(1,len(rgridlist)): fullrgrid = np.concatenate((fullrgrid,rgridlist[i][1:])) #1: so we don't have overlapping grid points rboundaries.append(len(fullrgrid)) All_fullr_unitMvecs = [] for i in range(len(rgridlist)): for j in range(subbasis_head_indlist[i],subbasis_head_indlist[i+1]): vecgrid = np.zeros_like(fullrgrid) if i==0: #print(All_unitMvecs[j]) vecgrid[rboundaries[i]:rboundaries[i+1]] = mparr_to_npreal(mp_re(All_unitMvecs[j][:])) else: vecgrid[rboundaries[i]:rboundaries[i+1]] = mparr_to_npreal(mp_re(All_unitMvecs[j][1:])) All_fullr_unitMvecs.append(vecgrid) return Gmat, Uinv, unitRgdotRglist, subbasis_head_indlist, fullrgrid, All_fullr_unitMvecs
def mpc(x, y): return mp.mpc(x, y)