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 plot_C_pi(): C = [] for m in [0, 1]: Cm = [] for i in range(0, len(lmx)): Crow = [] for j in range(0, len(lmy)): if m == 0: Crow.append(1) if m == 1: Crow.append( float( mp.norm(-mp.exp(1j * (mp.atan( mp.im(eq5.fl(lmx[i][j], lmy[i][j], 0)) / mp.re(eq5.fl(lmx[i][j], lmx[i][j], 0)))))))) Cm.append(Crow) C.append(Cm) for m in range(0, len(C)): plt.figure() plt.title("C matrix for band pi, element number " + str(m)) plt.contourf(lmx, lmy, C[m], cmap=plt.get_cmap("coolwarm")) plt.colorbar() plt.xlabel(r'$l_x$ $[m^{-1}]$') plt.ylabel(r'$l_y$ $[m^{-1}]$')
def two_body_reference(self, t1, num_1 = 0, num_2 = 1): """ reference notations are same as Yoel's notes using a precision of 64 digits for max accuracy """ mp.dps = 64 self.load_data() t1 = mp.mpf(t1) m_1 = mp.mpf(self.planet_lst[num_1].mass) m_2 = mp.mpf(self.planet_lst[num_2].mass) x1_0 = mp.matrix(self.planet_lst[num_1].loc) x2_0 = mp.matrix(self.planet_lst[num_2].loc) v1_0 = mp.matrix(self.planet_lst[num_1].v) v2_0 = mp.matrix(self.planet_lst[num_2].v) M = m_1 + m_2 x_cm = (1/M)*((m_1*x1_0)+(m_2*x2_0)) v_cm = (1/M)*((m_1*v1_0)+(m_2*v2_0)) u1_0 = v1_0 - v_cm w = x1_0 - x_cm r_0 = mp.norm(w) alpha = mp.acos((np.inner(u1_0,w))/(mp.norm(u1_0)*mp.norm(w))) K = mp.mpf(self.G) * (m_2**3)/(M**2) u1_0 = mp.norm(u1_0) L = r_0 * u1_0 * mp.sin(alpha) cosgamma = ((L**2)/(K*r_0)) - 1 singamma = -((L*u1_0*mp.cos(alpha))/K) gamma = mp.atan2(singamma, cosgamma) e = mp.sqrt(((r_0*(u1_0**2)*(mp.sin(alpha)**2)/K)-1)**2 + \ (((r_0**2)*(u1_0**4)*(mp.sin(alpha)**2)*(mp.cos(alpha)**2))/(K**2)) ) r_theta = lambda theta: (L**2)/(K*(1+(e*mp.cos(theta - gamma)))) f = lambda x: r_theta(x)**2/L curr_theta = 0 max_it = 30 it = 1 converged = 0 while ((it < max_it) & (converged != 1)): t_val = mp.quad(f,[0,curr_theta]) - t1 dt_val = f(curr_theta) delta = t_val/dt_val if (abs(delta)<1.0e-6): converged = 1 curr_theta -= delta it += 1 x1_new = mp.matrix([r_theta(curr_theta)*mp.cos(curr_theta), r_theta(curr_theta)*mp.sin(curr_theta)]) # x2_new = -(m_1/m_2)*(x1_new) +(x_cm + v_cm*t1) x1_new = x1_new + (x_cm + v_cm*t1) return x1_new
def __init__(self, side, extended, distance): self.distance = mp.mpf(distance) rightPointX = mp.mpf('1.41949302') if extended else mp.sqrt(2) self.side = side # side length of square self.d = side / mp.cos(mp.pi / 12) # length of left edge sin60 = mp.sqrt(3) / 2 self.top = matrix([self.d / 2, sin60 * self.d]) self.right = matrix([side * rightPointX, 0]) self.nleft = matrix([[-sin60, 0.5]]) self.ndown = matrix([[0, -1]]) v = self.right - self.top norm = mp.norm(v) self.nright = matrix([[-v[1] / norm, v[0] / norm]]) self.offset = self.nright * self.right
def verify(self, x0, x1, y0, y1, s, t, x, y): "Verify the transformation given by (s, t, x, y) on pentagon." pentagon = [(x0, 0), (x1, 0), (0, y0), (0, y1), (self.side, self.side)] # reference point in interior of pentagon ref = matrix([x0 + x1 + self.side, y0 + y1 + self.side]) / 5 translation = matrix( [s * ref[0] + t * ref[1] + x, -t * ref[0] + s * ref[1] + y]) # reconstruct rotation angle norm = mp.sqrt(s * s + t * t) if t < 0: angle = -mp.acos(s / norm) else: angle = mp.acos(s / norm) rotation = matrix([[mp.cos(angle), mp.sin(angle)], [-mp.sin(angle), mp.cos(angle)]]) pentagon = list(map(lambda pt: matrix(pt), pentagon)) ipentagon = list( map(lambda pt: rotation * (pt - ref) + translation, pentagon)) # Verify that ipentagon is a congruent image of pentagon eps = mp.mpf(10)**-(mp.dps - 2) # accept error in last two digits for i in range(5): for j in range(i + 1, 5): d1 = mp.norm(pentagon[j] - pentagon[i]) d2 = mp.norm(ipentagon[j] - ipentagon[i]) dd = abs(d1 - d2) assert dd < eps, (pentagon, dd, eps) dists = [] for p in ipentagon: dists.append(self.nleft * p) dists.append(self.ndown * p) dists.append(self.nright * p - self.offset) dist = max(map(lambda m: m[0], dists)) if dist > -self.distance: sys.stderr.write("Pentagon failing slack test: %d %d %d %d\n" % (x0, x1, y0, y1)) return False return True
def solve_multiprecision(M, A, b, tolerance=1e-60): af = sparse_make_single_precision(M, A) so = sp.sparse.linalg.factorized(af) def solve(b): b = _TO_NUMPY(b).flatten() x = so(b) return FROM_NUMPY(x) """ def solve(b): b = _TO_NUMPY(b) x, e = sp.sparse.linalg.gmres(af, b) if e != 0: print("error", e) raise Exception("gmres error") return FROM_NUMPY(x) """ x = solve(b) current_prec = mp.prec try: guess = np.log2(M) - np.log2(tolerance) + 24 mp.prec = guess while True: residual = b - mmul(A, x) scale = mp.norm(residual, p='inf') print("residual: %e" % scale) if scale < tolerance: return x compare = solve(residual / scale) x += scale * compare amplification = float(mp.norm(compare, p='inf')) mp.prec = max(mp.prec, guess + np.log2(amplification)) print("precision:", mp.prec) finally: mp.prec = current_prec
def nearly_diagonal(A): assert A.rows == A.cols == 2 a = A[0, 0] return mp.norm(A - mp.diag([a, a])) < 1000 * mp.eps
def w2s(kx, ky, kz): return ct.nrm_s * ct.a0**(3 / 2) * ( ((ct.a0 * mp.norm([kx, ky, kz])) / ct.hbar)**2 - (ct.Zeff2s / 2)**2) / (((ct.a0 * mp.norm([kx, ky, kz])) / ct.hbar)**2 + (ct.Zeff2s / 2)**2)**3
def w2py(kx, ky, kz): return ct.nrm_py * ct.a0**(5 / 2) * (ky / ct.hbar) / ( (ct.a0 * mp.norm([kx, ky, kz]) / ct.hbar)**2 + (ct.Zeff2pxy / 2)**2)**3
def w2pz(kx, ky, kz): return ct.nrm_pz * ct.a0**(5 / 2) * (kz / ct.hbar) / ( (ct.a0 * mp.norm([kx, ky, kz]) / ct.hbar)**2 + (ct.Zeff2pz / 2)**2)**3
def speedup_Green_Taylor_Arnoldi_RgNmn_Uconverge(n, k, R, klim=10, Taylor_tol=1e-8, invchi=0.1, Unormtol=1e-4, veclim=3, delveclim=2, plotVectors=False): #sets up the Arnoldi matrix and associated unit vector lists for any given RgN #ti = time.time() kR = mp.mpf(k * R) pow_jndiv, coe_jndiv, pow_djn, coe_djn, pow_yndiv, coe_yndiv, pow_dyn, coe_dyn = get_Taylor_jndiv_djn_yndiv_dyn( n, kR, klim, tol=Taylor_tol) #print(time.time()-ti,'0') #print(len(pow_jndiv)) pow_jndiv = np.array(pow_jndiv) pow_djn = np.array(pow_djn) nfac = mp.sqrt(n * (n + 1)) rmRgN_Bpol = mp.one * np.zeros(pow_jndiv[-1] + 1 - (n - 1)) rmRgN_Ppol = mp.one * np.zeros(pow_jndiv[-1] + 1 - (n - 1)) rmRgN_Bpol[pow_jndiv - (n - 1)] += coe_jndiv rmRgN_Bpol[pow_djn - (n - 1)] += coe_djn rmRgN_Ppol[pow_jndiv - (n - 1)] += coe_jndiv rmRgN_Ppol *= nfac rmRgN_Bpol = po.Polynomial(rmRgN_Bpol) rmRgN_Ppol = po.Polynomial(rmRgN_Ppol) rnImN_Bpol = mp.one * np.zeros(pow_yndiv[-1] + 1 + (n + 2), dtype=np.complex) rnImN_Ppol = mp.one * np.zeros(pow_yndiv[-1] + 1 + (n + 2), dtype=np.complex) pow_yndiv = np.array(pow_yndiv) pow_dyn = np.array(pow_dyn) rnImN_Bpol[(n + 2) + pow_yndiv] += coe_yndiv rnImN_Bpol[(n + 2) + pow_dyn] += coe_dyn rnImN_Ppol[(n + 2) + pow_yndiv] += coe_yndiv rnImN_Ppol *= nfac rnImN_Bpol = po.Polynomial(rnImN_Bpol) rnImN_Ppol = po.Polynomial(rnImN_Ppol) if plotVectors: plot_rmnNpol(n, rmRgN_Bpol.coef, rmRgN_Ppol.coef, kR * 0.01, kR) unitrmnBpols = [] unitrmnPpols = [] #print(time.time()-ti,'1') RgNnorm = mp.sqrt(rmnNnormsqr_Taylor(n, k, R, rmRgN_Bpol, rmRgN_Ppol)) rmnBpol = rmRgN_Bpol / RgNnorm rmnPpol = rmRgN_Ppol / RgNnorm unitrmnBpols.append(rmnBpol) unitrmnPpols.append(rmnPpol) #print(time.time()-ti,'2') rmnGBpol, rmnGPpol = rmnGreen_Taylor_Nmn_vec(n, k, R, rmRgN_Bpol, rmRgN_Ppol, rnImN_Bpol, rnImN_Ppol, rmnBpol, rmnPpol) rmnGBpol = rmnGBpol.cutdeg(rmRgN_Bpol.degree()) rmnGPpol = rmnGPpol.cutdeg(rmRgN_Bpol.degree()) #print(time.time()-ti,'3') prefactpow, Upol = rmnNpol_dot(2 * n - 2, rmnBpol, rmnPpol, rmnGBpol, rmnGPpol) Uinv = mp.matrix([[invchi - kR**prefactpow * po.polyval(kR, Upol) / k**3]]) unitrmnBpols.append(rmnGBpol) unitrmnPpols.append(rmnGPpol) #set up beginning of Arnoldi iteration #print(time.time()-ti,'4') b = mp.matrix([mp.one]) prevUnorm = 1 / Uinv[0, 0] i = 1 while i < veclim: speedup_Green_Taylor_Arnoldi_step_RgNmn(n, k, R, invchi, rmRgN_Bpol, rmRgN_Ppol, rnImN_Bpol, rnImN_Ppol, unitrmnBpols, unitrmnPpols, Uinv, plotVectors=plotVectors) i += 1 if i == veclim: #solve for first column of U and see if its norm has converged b.rows = i x = mp.lu_solve(Uinv, b) Unorm = mp.norm(x) if np.abs(prevUnorm - Unorm) > np.abs(Unorm) * Unormtol: veclim += delveclim prevUnorm = Unorm #else: print(x) if veclim == 1: x = mp.one / Uinv[0, 0] """ #print(x) print(mp.norm(x)) plt.figure() plt.matshow(np.abs(np.array((Uinv**-1).tolist(),dtype=np.complex))) plt.show() #EUdUinv = mpmath.eigh(Uinv.transpose_conj()*Uinv, eigvals_only=True) #print(EUdUinv) #print(type(EUdUinv)) """ #print(time.time()-ti,'5') #returns everything necessary to potentially extend size of Uinv matrix later return rmRgN_Bpol, rmRgN_Ppol, rnImN_Bpol, rnImN_Ppol, unitrmnBpols, unitrmnPpols, Uinv
def speedup_Green_Taylor_Arnoldi_RgMmn_Uconverge(n, k, R, klim=10, Taylor_tol=1e-8, invchi=0.1, Unormtol=1e-4, veclim=3, delveclim=2, plotVectors=False): #sets up the Arnoldi matrix and associated unit vector lists for any given RgM kR = mp.mpf(k * R) pow_jn, coe_jn, pow_yn, coe_yn = get_Taylor_jn_yn(n, kR, klim, Taylor_tol) #print(len(pow_jn)) pow_jn = np.array(pow_jn) coe_jn = np.array(coe_jn) rmnRgM = mp.one * np.zeros(pow_jn[-1] + 1 - n) rmnRgM[pow_jn - n] += coe_jn rmnRgM = po.Polynomial(rmnRgM) pow_yn = np.array(pow_yn) coe_yn = np.array(coe_yn) rnImM = mp.one * np.zeros(pow_yn[-1] + 1 + n + 1) rnImM[pow_yn + n + 1] += coe_yn rnImM = po.Polynomial(rnImM) if plotVectors: plot_rmnMpol(n, rmnRgM.coef, 0.01 * kR, kR) unitrmnMpols = [] RgMnorm = mp.sqrt(rmnMnormsqr_Taylor(n, k, R, rmnRgM)) rmnMpol = rmnRgM / RgMnorm unitrmnMpols.append(rmnMpol) rmnGMpol = rmnGreen_Taylor_Mmn_vec(n, k, R, rmnRgM, rnImM, rmnMpol) rmnGMpol = rmnGMpol.cutdeg(rmnRgM.degree()) prefactpow, Upol = rmnMpol_dot(2 * n, rmnMpol, rmnGMpol) Uinv = mp.matrix([[invchi - kR**prefactpow * po.polyval(kR, Upol) / k**3]]) unitrmnMpols.append(rmnGMpol) #set up beginning of Arnoldi iteration b = mp.matrix([mp.one]) prevUnorm = 1 / Uinv[0, 0] i = 1 while i < veclim: speedup_Green_Taylor_Arnoldi_step_RgMmn(n, k, R, invchi, rmnRgM, rnImM, unitrmnMpols, Uinv, plotVectors=plotVectors) i += 1 if i == veclim: #solve for first column of U and see if its norm has converged b.rows = i x = mp.lu_solve(Uinv, b) Unorm = mp.norm(x) if np.abs(prevUnorm - Unorm) > np.abs(Unorm) * Unormtol: veclim += delveclim prevUnorm = Unorm #else: print(x) if veclim == 1: x = mp.one / Uinv[0, 0] """ print(x) print(mp.norm(x)) plt.figure() plt.matshow(np.abs(np.array((Uinv**-1).tolist(),dtype=np.complex))) plt.show() #EUdUinv = mpmath.eigh(Uinv.transpose_conj()*Uinv, eigvals_only=True) #print(EUdUinv) """ #returns everything necessary to potentially extend size of Uinv matrix later return rmnRgM, rnImM, unitrmnMpols, Uinv
def zdipole_field_xy2D_periodic_array(k0, L, xd, yd, zd, xp, yp, zp, sumtol=1e-12): #field at coord (xp,yp,zp) of z-polarized dipoles in a square array in the z=czd plane #generated by summing over discrete k-vectors; in evanescent region the summand decreases exponentially with increasing kp and abskz #it seems that directly summing over individual dipole fields leads to convergence issues due to relatively slow (polynomial) decay of dipole fields #order of summation in k-space: concentric squares, 0th square the origin, 1st square infinity-norm radius 1, 2nd square infinity-norm radius 2... #since we are using the angular representation for consistency we insist that zp>zd """ if not (xp<L/2 and xp>-L/2 and yp<L/2 and yp>-L/2): return 'target point out of Brillouin zone' """ if zp <= zd: return 'need zp>zd' field = mp.zeros(3, 1) oldfield = mp.zeros(3, 1) deltak = 2 * mp.pi / L deltax = xp - xd deltay = yp - yd deltaz = zp - zd i = 1 #label of which square we are on prefac = -1j / (2 * L**2 * k0**2) while True: #termination condition in loop #sum over the i-th square lkx = -i * deltak rkx = i * deltak for iy in range(-i, i + 1): ky = iy * deltak kpsqr = lkx**2 + ky**2 kz = mp.sqrt(k0**2 - kpsqr) lphasefac = mp.expj(lkx * deltax + ky * deltay + kz * deltaz) rphasefac = mp.expj(rkx * deltax + ky * deltay + kz * deltaz) field[0] += prefac * (lkx * lphasefac + rkx * rphasefac) field[1] += prefac * (lphasefac + rphasefac) * ky field[2] += prefac * (lphasefac + rphasefac) * (-kpsqr / kz) bky = -i * deltak uky = i * deltak for ix in range(-i + 1, i): kx = ix * deltak kpsqr = kx**2 + bky**2 kz = mp.sqrt(k0**2 - kpsqr) bphasefac = mp.expj(kx * deltax + bky * deltay + kz * deltaz) uphasefac = mp.expj(kx * deltax + uky * deltay + kz * deltaz) field[0] += prefac * (bphasefac + uphasefac) * kx field[1] += prefac * (bphasefac * bky + uphasefac * uky) field[2] += prefac * (bphasefac + uphasefac) * (-kpsqr / kz) if mp.norm(field - oldfield) < mp.norm(field) * sumtol: break print('i', i) #mp.nprint(field) oldfield = field.copy() i += 1 return field
def shell_Green_grid_Arnoldi_RgandImMmn_Uconverge_mp(n,k,R1,R2, invchi, gridpts=1000, Unormtol=1e-10, veclim=3, delveclim=2, maxveclim=40, plotVectors=False): np.seterr(over='raise',under='raise',invalid='raise') #for high angular momentum number could have floating point issues; in this case, raise error. Outer method will catch the error and use the mpmath version instead rgrid = np.linspace(R1,R2,gridpts) rsqrgrid = rgrid**2 rdiffgrid = np.diff(rgrid) """ RgMgrid = sp.spherical_jn(n, k*rgrid) #the argument for radial part of spherical waves is kr ImMgrid = sp.spherical_yn(n, k*rgrid) RgMgrid = RgMgrid.astype(np.complex) ImMgrid = ImMgrid.astype(np.complex) RgMgrid = complex_to_mp(RgMgrid) ImMgrid = complex_to_mp(ImMgrid) """ RgMgrid = mp_vec_spherical_jn(n, k*rgrid) ImMgrid = mp_vec_spherical_yn(n, k*rgrid) vecRgMgrid = RgMgrid / mp.sqrt(rgrid_Mmn_normsqr(RgMgrid, rsqrgrid,rdiffgrid)) vecImMgrid = ImMgrid - rgrid_Mmn_vdot(vecRgMgrid, ImMgrid, rsqrgrid,rdiffgrid)*vecRgMgrid vecImMgrid /= mp.sqrt(rgrid_Mmn_normsqr(vecImMgrid,rsqrgrid,rdiffgrid)) if plotVectors: rgrid_Mmn_plot(vecRgMgrid,rgrid) rgrid_Mmn_plot(vecImMgrid,rgrid) unitMvecs = [vecRgMgrid,vecImMgrid] GvecRgMgrid = shell_Green_grid_Mmn_vec_mp(n,k, rsqrgrid,rdiffgrid, RgMgrid,ImMgrid, vecRgMgrid) GvecImMgrid = shell_Green_grid_Mmn_vec_mp(n,k, rsqrgrid,rdiffgrid, RgMgrid,ImMgrid, vecImMgrid) Gmat = mp.zeros(2,2) Gmat[0,0] = rgrid_Mmn_vdot(vecRgMgrid, GvecRgMgrid, rsqrgrid,rdiffgrid) Gmat[0,1] = rgrid_Mmn_vdot(vecRgMgrid, GvecImMgrid, rsqrgrid,rdiffgrid) Gmat[1,0] = Gmat[0,1] Gmat[1,1] = rgrid_Mmn_vdot(vecImMgrid,GvecImMgrid, rsqrgrid,rdiffgrid) Uinv = mp.eye(2)*invchi-Gmat unitMvecs.append(GvecRgMgrid) unitMvecs.append(GvecImMgrid) #append unorthogonalized, unnormalized Arnoldi vector for further iterations b = mp.matrix([mp.one]) prevUnorm = 1 / Uinv[0,0] i=2 while i<veclim: Gmat = shell_Green_grid_Arnoldi_RgandImMmn_step_mp(n,k,invchi, rgrid,rsqrgrid,rdiffgrid, RgMgrid, ImMgrid, unitMvecs, Gmat, plotVectors=plotVectors) i += 1 print(i) if i==maxveclim: break if i==veclim: #solve for first column of U and see if its norm has converged Uinv = mp.eye(Gmat.rows)*invchi-Gmat b.rows = i x = mp.lu_solve(Uinv, b) Unorm = mp.norm(x) print('Unorm', Unorm, flush=True) if np.abs(prevUnorm-Unorm) > np.abs(Unorm)*Unormtol: veclim += delveclim prevUnorm = Unorm return rgrid,rsqrgrid,rdiffgrid, RgMgrid, ImMgrid, unitMvecs, Uinv, Gmat