def run_eigsy(A, verbose = False): if verbose: print("original matrix:\n", str(A)) D, Q = mp.eigsy(A) B = Q * mp.diag(D) * Q.transpose() C = A - B E = Q * Q.transpose() - mp.eye(A.rows) if verbose: print("eigenvalues:\n", D) print("eigenvectors:\n", Q) NC = mp.mnorm(C) NE = mp.mnorm(E) if verbose: print("difference:", NC, "\n", C, "\n") print("difference:", NE, "\n", E, "\n") eps = mp.exp( 0.8 * mp.log(mp.eps)) assert NC < eps assert NE < eps return NC
def run_eigsy(A, verbose=False): if verbose: print("original matrix:\n", str(A)) D, Q = mp.eigsy(A) B = Q * mp.diag(D) * Q.transpose() C = A - B E = Q * Q.transpose() - mp.eye(A.rows) if verbose: print("eigenvalues:\n", D) print("eigenvectors:\n", Q) NC = mp.mnorm(C) NE = mp.mnorm(E) if verbose: print("difference:", NC, "\n", C, "\n") print("difference:", NE, "\n", E, "\n") eps = mp.exp(0.8 * mp.log(mp.eps)) assert NC < eps assert NE < eps return NC
def gauss_laguerre(n): d = mp.matrix(mp.arange(1, 2 * n, 2)) e = mp.matrix(mp.arange(-1, -n - 1, -1)) z = mp.eye(n)[0, :] tridiag_eigen(mp, d, e, z) z = z.apply(lambda x: x**2) return d, z.T
def MPDBiteration(M): Xk = M.copy() Yk = mp.eye(M.cols) for i in range(1,31): Xk1 = (Xk + Yk**-1)/2 Yk1 = (Yk + Xk**-1)/2 Xk = Xk1 Yk = Yk1 return Xk
def gauss_hermite(n): d = mp.matrix([mp.mpf('0.0') for _ in range(n)]) e = [mp.sqrt(k / 2) for k in mp.arange(1, n)] e.append(mp.mpf('0.0')) e = mp.matrix(e) z = mp.eye(n)[0, :] tridiag_eigen(mp, d, e, z) z = mp.sqrt(mp.pi) * z.apply(lambda x: x**2) return d, z.T
def gauss_legendre(n): d = mp.matrix([mp.mpf('0.0') for _ in range(n)]) e = [k / mp.sqrt(4 * k**2 - 1) for k in mp.arange(1, n)] e.append(mp.mpf('0.0')) e = mp.matrix(e) z = mp.eye(n)[0, :] tridiag_eigen(mp, d, e, z) z = 2 * z.apply(lambda x: x**2) return d, z.T
def gauss_genlaguerre(n, alpha): d = mp.matrix([i + alpha for i in mp.arange(1, 2 * n, 2)]) e = [-mp.sqrt(k * (k + alpha)) for k in mp.arange(1, n)] e.append(mp.mpf('0.0')) e = mp.matrix(e) z = mp.eye(n)[0, :] tridiag_eigen(mp, d, e, z) z = mp.gamma(alpha + 1) * z.apply(lambda x: x**2) return d, z.T
def MPDBsc(M): Xk = M.copy() Yk = mp.eye(M.cols) dA = mp.det(M)**(mp.mpf('1.0')/2) for i in range(1,30): uk = mp.fabs(mp.det(Xk)/dA)**(-1.0/i) Xk1 = (uk*Xk + (uk**(-1))*(Yk**(-1)))/2 Yk1 = (uk*Yk + (uk**(-1))*(Xk**(-1)))/2 Xk = Xk1 Yk = Yk1 return Xk
def run_svd_r(A, full_matrices=False, verbose=True): m, n = A.rows, A.cols eps = mp.exp(0.8 * mp.log(mp.eps)) if verbose: print("original matrix:\n", str(A)) print("full", full_matrices) U, S0, V = mp.svd_r(A, full_matrices=full_matrices) S = mp.zeros(U.cols, V.rows) for j in xrange(min(m, n)): S[j, j] = S0[j] if verbose: print("U:\n", str(U)) print("S:\n", str(S0)) print("V:\n", str(V)) C = U * S * V - A err = mp.mnorm(C) if verbose: print("C\n", str(C), "\n", err) assert err < eps D = V * V.transpose() - mp.eye(V.rows) err = mp.mnorm(D) if verbose: print("D:\n", str(D), "\n", err) assert err < eps E = U.transpose() * U - mp.eye(U.cols) err = mp.mnorm(E) if verbose: print("E:\n", str(E), "\n", err) assert err < eps
def run_svd_r(A, full_matrices = False, verbose = True): m, n = A.rows, A.cols eps = mp.exp(0.8 * mp.log(mp.eps)) if verbose: print("original matrix:\n", str(A)) print("full", full_matrices) U, S0, V = mp.svd_r(A, full_matrices = full_matrices) S = mp.zeros(U.cols, V.rows) for j in xrange(min(m, n)): S[j,j] = S0[j] if verbose: print("U:\n", str(U)) print("S:\n", str(S0)) print("V:\n", str(V)) C = U * S * V - A err = mp.mnorm(C) if verbose: print("C\n", str(C), "\n", err) assert err < eps D = V * V.transpose() - mp.eye(V.rows) err = mp.mnorm(D) if verbose: print("D:\n", str(D), "\n", err) assert err < eps E = U.transpose() * U - mp.eye(U.cols) err = mp.mnorm(E) if verbose: print("E:\n", str(E), "\n", err) assert err < eps
def gauss_gegenbauer(n, alpha): d = mp.matrix([mp.mpf('0.0') for _ in range(n)]) e = [ mp.sqrt(k * (k + 2 * alpha - 1) / ((2 * k + 2 * alpha - 1)**2 - 1)) for k in mp.arange(1, n) ] e.append(mp.mpf('0.0')) e = mp.matrix(e) z = mp.eye(n)[0, :] tridiag_eigen(mp, d, e, z) z = 2**(2 * alpha) * mp.beta(alpha + 1 / 2, alpha + 1 / 2) * z.apply(lambda x: x**2) return d, z.T
def gauss_jacobi(n, alpha, beta): d = mp.matrix([(beta**2 - alpha**2) / (2 * k + alpha + beta) / (2 * k + alpha + beta - 2) for k in mp.arange(1, n + 1)]) e = [ k * (k + alpha) * (k + beta) * (k + alpha + beta) / ((2 * k + alpha + beta)**2 - 1) for k in mp.arange(1, n) ] e = [ 2 / (2 * k + alpha + beta) * mp.sqrt(x) for k, x in zip(mp.arange(1, n), e) ] e.append(mp.mpf('0.0')) e = mp.matrix(e) z = mp.eye(n)[0, :] tridiag_eigen(mp, d, e, z) z = 2**(alpha + beta + 1) * mp.beta(alpha + 1, beta + 1) * z.apply(lambda x: x**2) return d, z.T
def get_G_from_U(U, chi): n = U.rows Vinvdagger = mp.eye(n) * mp.one / mp.conj(chi) Gdagger = Vinvdagger - U return Gdagger.H
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 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