コード例 #1
0
ファイル: pade-m-p.py プロジェクト: nskorikov/amulet_tools
def choose_random_points(e, f, nneg, npos):
    # Subroutine selects nneg+npos points randomly
    # temporary it does not select negative points
    # It is a very bad idea to pick all points randomly
    # Use for testing purpose

    if (nneg + npos) % 2 != 0:
        print('Number of chosen points should be even!', nneg, npos,
              nneg + npos)
        npos += 1
    q = nneg + npos
    r = len(e)

    points = random.sample(range(0, r - 1), q - 1)

    # points = np.random.randint(low=0, high=r - 1, size=q - 1)
    points.sort()
    for i in range(0, q - 2):
        if points[i] == points[i + 1]:
            points[i + 1] += 1

    ee = mp.zeros(q, 1)
    ff = mp.zeros(q, f.cols)
    for i in range(0, q - 1):
        ee[i] = e[points[i]]
        ff[i] = f[points[i]]
    return ee, ff
コード例 #2
0
ファイル: pade-m-p.py プロジェクト: nskorikov/amulet_tools
def pade_coeficients(f, e):
    # Subroutine pade_coeficients() finds coefficient of Pade approximant
    # f - values of complex function for approximation
    # e - complex points in which function f is determined

    r = len(e) / 2
    # Preparation of arrays to calc Pade coefficiens
    s = mp.zeros(2 * r, 1)
    x = mp.zeros(2 * r)
    for i in range(0, 2 * r):
        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: |p|
    #                       | |=X^{-1}*s
    #                       |q|
    # Here we should catch exception in linalg!!
    try:
        x = mp.inverse(x)
        pq = x * s
        # x **= -1
        # pq = np.dot(x, s)
        success = True
    except ZeroDivisionError as err:
        if 'matrix is numerically singular' in err.message:
            pq = 123456.7
            success = False
        else:
            raise
    return pq, success
コード例 #3
0
    def check_site_type(site_type, theta0):
        if site_type == 'single':
            func = NH3mkm.get_odes
            if not len(theta0) == 4:
                theta0 = mp.zeros(1, 4)

        elif site_type == 'two-site':
            func = NH3mkm.get_odes_two_site
            if not len(theta0) == 6:
                theta0 = mp.zeros(1, 6)
        return func, theta0
コード例 #4
0
ファイル: pade-m-p.py プロジェクト: nskorikov/amulet_tools
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
コード例 #5
0
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
コード例 #6
0
ファイル: main.py プロジェクト: donkeyofDeath/quadpy
def _scheme_from_rc_mpmath(alpha, beta):
    # Create vector cut of the first value of beta
    n = len(alpha)
    b = mp.zeros(n, 1)
    for i in range(n - 1):
        b[i] = mp.sqrt(beta[i + 1])

    z = mp.zeros(1, n)
    z[0, 0] = 1
    d = mp.matrix(alpha)
    tridiag_eigen(mp, d, b, z)

    # nx1 matrix -> list of mpf
    x = numpy.array([mp.mpf(sympy.N(xx, mp.dps)) for xx in d])
    w = numpy.array([mp.mpf(sympy.N(beta[0], mp.dps)) * mp.power(ww, 2) for ww in z])
    return x, w
コード例 #7
0
    def integrate_odes(
            self,
            site_type='single',
            theta0=mp.zeros(1, 4),
            timespan=[0, 1e8],
            h0=1e-20,
            mxstep=200000,  # maximum number of steps
            rtol=1E-12,  # relative tolerance
            atol=1E-15,  # Absolute tolerance
            full_output=1):

        func, theta0 = NH3mkm.check_site_type(site_type, theta0)
        self.theta0 = theta0
        args = self,

        # Integrate the ODEs for 1E10 sec (enough to reach steady-state)
        theta, out = odeint(
            func,  # system of ODEs
            theta0,  # initial guess
            timespan,  # time span
            args=args,
            h0=h0,  # initial time step
            mxstep=mxstep,  # maximum number of steps
            rtol=rtol,  # relative tolerance
            atol=atol,  # Absolute tolerance
            full_output=full_output)
        self.integrated_thetas = theta
        self.ode_output = out

        # Return the value of theta at the last timestep
        return theta[-1, :]
コード例 #8
0
ファイル: pade-m-p.py プロジェクト: nskorikov/amulet_tools
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
コード例 #9
0
ファイル: mpf_matrix_fadd.py プロジェクト: fixif/fixif
def mpf_matrix_fadd(A, B):
	"""
	Given a m x n matrix A and m x n matrix B either in numpy.matrix
	or mpmath.matrix format,
	this function computes the sum C = A + B exactly.
	The output matrix C is always given in the MPMATH format.


	Parameters
	----------
	A - m x n matrix
	B - m x n matrix

	Returns
	-------
	C - m x n matrix
	"""

	if isinstance(A, numpy.matrix):
		try:
			A = python2mpf_matrix(A)
		except ValueError as e:
			raise ValueError('Cannot compute exact sum of two matrices. %s' % e)
	else:
		if not isinstance(A, mpmath.matrix):
			raise ValueError('Cannot compute exact sum of two matrices: unexpected input type, excpected numpy.matrix or mpmath.matrix but got %s') %type(A)

	if isinstance(B, numpy.matrix):
		try:
			B = python2mpf_matrix(B)
		except ValueError as e:
			raise ValueError('Cannot compute exact sum of two matrices. %s' % e)
	else:
		if not isinstance(B, mpmath.matrix):
			raise ValueError('Cannot compute exact sum of two matrices: unexpected input type, excpected numpy.matrix or mpmath.matrix but got %s') % type(B)


	#here both A and B are mpmath matrices
	#we consider that A and B are MPF matrices if their first elements are of type mpf, let's test it

	if not isinstance(A[0,0], mpmath.mpf) or not isinstance(B[0,0], mpmath.mpf):
		raise ValueError('Cannot compute exact product of two matrices: cannot sum complex matrices.')

	#test sizes
	if A.rows != B.rows or A.cols != B.cols:
		raise ValueError('Cannot compute exact sum of two matrices: incorrect sizes.')

	m = A.rows
	n = A.cols
	C = mp.zeros(m, n)
	for i in range(0, m):
		for j in range(0, n):
			C[i,j] = mpmath.fadd(A[i,j], B[i,j], exact=True)
			if mpmath.isnan(C[i,j]) or mpmath.isinf(C[i,j]):
				print('WARNING: in matrix sum an abnormal number (NaN/Inf) occured: %f' % C[i,j])


	return C
コード例 #10
0
 def evaluate_all_at(self, x, n=0):
     num = self.num
     if n == 0:
         row = mp.zeros(1, num) if self._use_mp else np.zeros(num)
         row = cheby.evaluate_Tn(x, row, use_mp=self._use_mp)
         return row
     dnT = self.Tderiv(n)
     s = self._scl**n
     fl = mp.mpf if self._use_mp else float
     return [s * fl(dnT[i](x)) for i in range(num)]
コード例 #11
0
ファイル: mpf_matrix_lt_inverse.py プロジェクト: fixif/fixif
def mpf_matrix_lt_inverse(L):
	"""
	For a lower-triangular n x n real matrix L with 1s on the main diagonal
	this function computes its inverse X exactly such that
				    L * X = I
	Matrix L must be in the numpy.matrix of mpmath.matrix formats.
	The function returns X as n x n real a mpmath.matrix


	Parameters
	----------
	L - n x n lower-triangular matrix

	Returns
	-------
	X - n x n matrix

	"""

	if isinstance(L, numpy.matrix):
		try:
			L = python2mpf_matrix(L)
		except ValueError as e:
			raise ValueError('Cannot compute exact difference of two matrices. %s') % e
	else:
		if not isinstance(L, mpmath.matrix):
			raise ValueError('Cannot compute exact difference of two matrices: unexpected input type, excpected numpy.matrix or mpmath.matrix but got %s') % type(L)


	#checking the size
	if L.rows != L.cols:
		raise ValueError('Cannot compute inverse: matrix must be square but istead is %s x %s' % L.rows, L.cols)
	else:
		n = L.rows

	#checking if the matrix is indeed lower-triangular with 1s on the main diagonal
	for i in range(0,n):
		if L[i,i] != mpmath.mp.one:
			raise ValueError('Cannot compute inverse: matrix must have 1s on the main diagonal.')
		for j in range(i+1, n):
			if L[i,j] != mpmath.mp.zero:
				raise ValueError('Cannot compute inverse: matrix must be lower triangular.')


	X = mp.zeros(n, n)
	for i in range(0,n):
		X[:, i] = my_forward_subst(L, i)


	return X
コード例 #12
0
def _gauss_from_coefficients_mpmath(alpha, beta, decimal_places):
    mp.dps = decimal_places

    # Create vector cut of the first value of beta
    n = len(alpha)
    b = mp.zeros(n, 1)
    for i in range(n - 1):
        # work around <https://github.com/fredrik-johansson/mpmath/issues/382>
        x = beta[i + 1]
        if isinstance(x, numpy.int64):
            x = int(x)
        b[i] = mp.sqrt(x)

    z = mp.zeros(1, n)
    z[0, 0] = 1
    d = mp.matrix(alpha)
    tridiag_eigen(mp, d, b, z)

    # nx1 matrix -> list of mpf
    x = numpy.array([mp.mpf(sympy.N(xx, decimal_places)) for xx in d])
    w = numpy.array([
        mp.mpf(sympy.N(beta[0], decimal_places)) * mp.power(ww, 2) for ww in z
    ])
    return x, w
コード例 #13
0
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
コード例 #14
0
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
コード例 #15
0
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
コード例 #16
0
def main():
    print('Start at %s ' % time.ctime())
    start_time = time.time()

    handle_input()
    print_params(logfile)
    print_params()
    fp.dps = 12
    w, f = readsigma(infile)
    e = make_e_mesh(emin, de, npts)
    w1 = []
    w2 = []
    w3 = []
    solutions = []
    sets = []
    mmts = []

    if not use_moments:
        print('%4s %4s %4s %4s %20s %11s %12s %12s\b' %
              ('npo', 'nne', 'try', 'ils', 'delta', 'm0', 'm1', 'm2'))
    else:
        print('%4s %4s %4s %4s %10s' % ('npo', 'nne', 'try', 'ils', 'delta'))

    for ipo in range(npo[0], npo[1], 1):
        for ine in range(ne[0], ne[1]):
            if ls:
                qq2 = ipo // 4
            else:
                qq2 = 1
#             for q1 in range(0, ipo//4, 2):
            for q1 in range(0, qq2, 2):
                sys.stdout.flush()
                for qq in range(0, nrandomcycle):
                    if (ine + ipo) % 2 != 0:
                        continue

                    sys.stdout.write('%4i %4i %4i %4i %s\r' %
                                     (ipo, ine, qq, q1, " " * 16))

                    if randomp:
                        # tmp = choose_prandom_points(w, f, ine, ipo)      # the best shape, the worst moments
                        e1, f1 = choose_prandom_points(w, f, ine, ipo)
                    else:
                        # tmp = choose_seq_points_plus(w, f, ine, ipo)     # work only with pade_ls_coeff
                        # tmp = choose_seq_points(w, f, ine, ipo)          # work only with pade_ls_coeff
                        e1, f1 = choose_seq_points(w, f, ine, ipo)
                    # tmp = choose_points(w, f, nne, npo)                  # manual selection
                    # tmp = choose_random_points(w, f, nne, npo)           # bad idea

                    if use_moments:
                        f1[:, 0] = make_f_prime(f1[:, 0], e1, m)

                    if ls:
                        pq, success, used_solver = pade_ls_coefficients(
                            f1[:, 0], e1, ipo + ine - q1)
                    else:
                        pq, success = pade_coeficients(f1[:, 0], e1)
                        used_solver = ''

                    if not success:
                        continue

                    # use external information about momenta

                    if use_moments:
                        sigim = pade_m(pq, w, m)
                    else:
                        sigim = pade(pq, w)

                    if not is_imag_negative(w, sigim):
                        continue
                    delta = calc_residual(f, sigim)
                    # if delta > 1.00001:
                    #     continue
                    if use_moments:
                        sigre = pade_m(pq, e, m)
                    else:
                        sigre = pade(pq, e)

                    if not is_imag_negative(e, sigre):
                        continue

                    memusage = resource.getrusage(
                        resource.RUSAGE_SELF).ru_maxrss
                    if not use_moments:
                        moments = get_moments(pq)
                        mmts.append(moments)
                        # mmts = np.vstack([mmts, moments])
                        s = ''
                        for mm in moments:
                            s += '{:12.4f}'.format(mm)
                            # s += '{:18s}'.format(mp.nstr(mm, n=4))
                        s = '{:4d} {:4d} {:4d} {:4d}     {:18.12f} {:s}  {:24s}'. \
                            format(ipo, ine, qq, q1, float(delta), s, used_solver)
                        print('%s' % s)
                        s += '\n'
                    else:
                        s = '{:4d} {:4d} {:4d} {:4d}     {:18.12f}    {:24s} {:d}'. \
                            format(ipo, ine, qq, q1, float(delta), used_solver, memusage)
                        print('%s' % s)
                        s += '\n'

                    # Save "good" results for next consideration
                    # with workdps(12):
                    sets.append(s)
                    w1.append(delta)

                    tmp = []
                    for tt in sigre:
                        tmp.append(complex(tt))
                    solutions.append(tmp)

                    # Write continued function to the disk
                    if delta < 0.100000005:
                        outfile = 'imG_' + str(ipo) + '_' + str(ine) + '_' + \
                                  str(qq) + '_' + str(q1) + '.dat'
                        write_g_im(outfile, w, sigim)

                        outfile = 'reG_' + str(ipo) + '_' + str(ine) + '_' + \
                                  str(qq) + '_' + str(q1) + '.dat'
                        write_g_re(outfile, e, sigre)

    # mp.dps = 12
    if not use_moments:
        mmean = calc_mean(mmts)
        print('Mean moments: %12.3f %12.3f %12.3f' %
              (float(mmean[0]), float(mmean[1]), float(mmean[2])))

    qq = len(w1)
    with open(logfile, 'a') as f:
        if not use_moments:
            s = '{:4s} {:4s} {:4s} {:4s} {:9s} {:15s} {:16s} {:16s}\n'. \
                format('npo', 'nne', 'try', 'ils', 'delta', 'm0', 'm1', 'm2')
            f.write(s)
        else:
            s = '{:4s} {:4s} {:4s} {:4s} {:9s}\n'.format(
                'npo', 'nne', 'try', 'ils', 'delta')
            f.write(s)
        for i in range(0, qq):
            f.write(sets[i])
        f.write('\n')
        if not use_moments:
            s = '{0:38s}{1:12.3f}{2:12.3f}{3:12.3f}\n'. \
                format('Mean moments', float(mmean[0]), float(mmean[1]), float(mmean[2]))
            f.write(s)
        f.write('\n\n\n')

    if qq == 0:
        print('There are no solutions')
        print("Stop at %s" % time.ctime())
        end_time = time.time()
        run_time = end_time - start_time
        print(run_time)
        hour = int((run_time / 60) / 60)
        minute = int((run_time / 60) - (hour * 60))
        sec = run_time % 60
        print('Program runtime = %2i:%2i:%2i' % (hour, minute, sec))
        sys.exit()

    w = 0.0
    w2 = mp.zeros(len(w1), 1)
    w3 = mp.zeros(len(w1), 1)
    for i in range(0, qq):
        # w1[i] = 1 / w1[i]
        w1[i] = float(w1[i])
        w3[i] = 200000 * (min(w1) - w1[i])
        w2[i] = math.exp(w3[i])
    for i in range(0, qq):
        w3[i] = w1[i]

    for i in range(0, qq):
        w1[i] = 1 / w1[i]

    w1sum = sum(w1)
    w2sum = sum(w2)
    for i in range(0, qq):
        w1[i] /= w1sum
        w2[i] /= w2sum

    with open('weights.dat', 'w') as f:
        for i in range(0, qq):
            s = '{:16.12f} {:16.12f} {:16.12f}\n'.format(
                float(w3[i]), float(w1[i]), float(w2[i]))
            # s = '{:d} {:16.12f} {:16.12f}\n'.format(i, float(w1[i]), float(w2[i]))
            f.write(s)

    sigre = mp.zeros(len(e), 1)
    for i in range(0, qq):
        for j in range(0, len(e)):
            sigre[j] += solutions[i][j] * w1[i]
    outfile = 'solution_w1.dat'
    write_g_re(outfile, e, sigre)
    sigre[:] = 0.0
    for i in range(0, qq):
        for j in range(0, len(e)):
            sigre[j] += solutions[i][j] * w2[i]
    outfile = 'solution_w2.dat'
    write_g_re(outfile, e, sigre)

    print("Stop at %s" % time.ctime())
    end_time = time.time()
    run_time = end_time - start_time
    print(run_time)
    hour = int((run_time / 60) / 60)
    minute = int((run_time / 60) - (hour * 60))
    sec = run_time % 60

    print('Program runtime = %i:%i:%i' % (hour, minute, sec))
    with open(logfile, 'a') as f:

        f.write('       %f       ' % run_time)
        f.write('Program runtime = %i:%i:%i' % (hour, minute, sec))
コード例 #17
0
ファイル: pade-m-p.py プロジェクト: nskorikov/amulet_tools
        f.write('\n\n\n')

    if qq == 0:
        print('There are no solutions')
        print("Stop at %s" % time.ctime())
        end_time = time.time()
        run_time = end_time - start_time
        print(run_time)
        hour = int((run_time / 60) / 60)
        minute = int((run_time / 60) - (hour * 60))
        sec = run_time % 60
        print('Program runtime = %2i:%2i:%2i' % (hour, minute, sec))
        sys.exit()

    w = 0.0
    w2 = mp.zeros(len(w1), 1)
    w3 = mp.zeros(len(w1), 1)
    for i in range(0, qq):
        # w1[i] = 1 / w1[i]
        w1[i] = float(w1[i])
        w3[i] = 200000 * (min(w1) - w1[i])
        w2[i] = math.exp(w3[i])
    for i in range(0, qq):
        w3[i] = w1[i]

    for i in range(0, qq):
        w1[i] = 1 / w1[i]

    w1sum = sum(w1)
    w2sum = sum(w2)
    for i in range(0, qq):
コード例 #18
0
    def impose(self, basis, L, f, blocked_indices, L_done=False, f_done=False,
               use_mp=False):
        r"""Impose the condition by modifying the operator and inhomogeneity.

        This should be called only during the solving process when the
        operator matrix `L` and inhomogeneity vector `f` have been built. The
        caller should supply the indices of rows (via `blocked_indices`) on
        which previous conditions have been placed to avoid overwriting them
        with the new conditions. The indices used here will be added to this
        list (i.e. the caller only needs to repeatedly supply this list,
        starting with an empty one).

        @param basis
            Spectral basis used during solving.
        @param L
            Fully populated operator matrix.
        @param f
            Inhomogeneity vector.
        @param blocked_indices
            List which is updated by this method to store which equations have
            been replaced (in order not to replace a condition in later
            calls).
        @param L_done
            Whether the operator matrix `L` has already been processed and
            should be left untouched. May be useful if caching of matrices
            with conditions already imposed is done, which may speed up
            computation significantly.
        @param f_done
            Whether the inhomogeneity has already been processed and should be
            left untouched. Might be useful when re-using the same
            inhomogeneity (and same basis) to solve the same equation with
            different boundary conditions.
        @param use_mp
            Whether to use arbitrary precision math operations (`True`) or
            faster floating point precision operations (`False`, default).
        """
        if L_done and f_done:
            return L, f
        alpha = _make_callable(self._alpha, use_mp=use_mp)
        beta = _make_callable(self._beta, use_mp=use_mp)
        value = _make_callable(self._value, use_mp=use_mp)
        num = basis.num
        idx = range(num)
        zero_row = mp.zeros(1, num) if use_mp else np.zeros(num)
        diff = self._idx + 1
        rows_to_append = []
        vals_to_append = []
        for i, x in self._get_points(basis):
            i = self._find_free_index(i, num-1, blocked_indices)
            if i is not None:
                blocked_indices.append(i)
            x_phys = basis.transform(x, back=False)
            a = alpha(x_phys)
            b = beta(x_phys)
            v = value(x_phys)
            if a == b == 0:
                continue
            if not L_done:
                Cx = DCx = zero_row
                if a != 0:
                    Cx = basis.evaluate_all_at(x, 0)
                if b != 0:
                    if self._dim > 2:
                        raise NotImplementedError("Neumann or mixed conditions not "
                                                  "implemented for dim > 2.")
                    DCx = basis.evaluate_all_at(x, diff)
                # NOTE: Originally, we had sparse indices (e.g. for basis functions
                #       left out from the set). This led to high complexity in
                #       index-types, i.e. the consecutive running indices vs.
                #       the subscript of the actual basis function. This might
                #       be required if we add further functionality to the
                #       system. At this point, one remainder is that the
                #       indices in `idx` could be sparse, whereas `j` can't.
                row = [a*Cx[j] + b*DCx[j] for j in range(len(idx))]
                if not any(row):
                    raise NDSolveError("Boundary condition numerically ill-conditioned. "
                                       "The condition might already be satisfied by the "
                                       "chosen basis or alpha = beta = 0.")
                if i is None:
                    rows_to_append.append(row)
                else:
                    self._replace_row(basis.ctx, L, i, row)
            if not f_done:
                if i is None:
                    vals_to_append.append([v])
                else:
                    f[i] = v
        if rows_to_append:
            L = self._append_rows(L, rows_to_append)
        if vals_to_append:
            f = self._append_rows(f, vals_to_append)
        return L, f
コード例 #19
0
    def construct_operator_matrix(self, op, as_numpy=False):
        r"""Compute the operator matrix for the given differential operator.

        This matrix, `L`, is defined as the matrix that results from applying
        the differential operator of the given problem to the matrix `M`
        consisting of the basis functions evaluated at the collocation
        points, i.e. \f[
            M_{ij} = \phi_j(x_i),
        \f]
        where \f$\phi_j\f$ is the j'th basis function and \f$x_i\f$ the i'th
        collocation point.

        The differential operator is given by a list of coefficient functions
        `op`, where the elements correspond to the different values of `n`
        used for calling deriv_mat().

        For example (for a 1D basis):

        \code{.unparsed}
        op[0]: multiplies the function phi(x) itself
        op[1]: multiplies phi'(x)
        op[2]: multiplies phi''(x)
        ...
        \endcode

        Alternatively, `op` may be a callable. In this case, it will be called
        with the full list of collocation points to evaluate the operator at.
        It should return an array/list of operator components (as above), each
        with as many elements as the given points list has.

        Args:
            op: Operator coefficient functions or a callable to compute them
                all at once or a list of lists already containing the
                evaluated operator.
            as_numpy: Whether to construct a NumPy operator matrix (if `True`)
                or an mpmath matrix (default), the latter being much slower
                and requiring much memory.
        """
        if callable(op):
            sampled_op = op(np.array(self.pts) if as_numpy else self.pts)
        elif callable(op[0]):
            sampled_op = self.sample_operator_funcs(op)
        else:
            sampled_op = op
        real = self._is_op_real(sampled_op)
        L = self.zero_op(as_numpy, real=real)
        rows = cols = self._num
        if self._use_mp:
            fl = mp.mpf if real else mp.mpc
        else:
            fl = float if real else complex
        zeros = mp.zeros(1, cols) if self._use_mp else np.zeros(cols, dtype=fl)
        for row_idx in range(rows):
            row = zeros.copy()
            for n in range(len(sampled_op)):
                try:
                    op_coeff = sampled_op[n][row_idx]
                except TypeError:
                    op_coeff = sampled_op[n]
                if not self._use_mp:
                    op_coeff = fl(op_coeff)
                if op_coeff != 0:
                    op_row = self._compute_deriv_mat_row(n, row_idx)
                    if op_coeff is None:
                        # Coefficient failed to compute. Let's hope the basis
                        # is zero there...
                        if any(op_row):
                            raise RuntimeError("Operator (n=%d) evaluated to "
                                               "an invalid value at %s." %
                                               (n, self.pts[row_idx]))
                        continue
                    row += op_coeff * op_row
            if as_numpy:
                L[row_idx, :] = lmap(fl, row)
            else:
                L[row_idx, :] = row
        return L
コード例 #20
0
def modS_opt_mpmath(initdof,
                    S1list,
                    dgHfunc,
                    mineigfunc,
                    opttol=1e-2,
                    modSratio=1e-2,
                    check_iter_period=20):

    modenum = len(S1list)

    modSlist = []
    epsSlist = [0] * modenum
    test_modSlist = []
    test_S1list = []
    test_epsSlist = [
        0
    ] * modenum  #these test_ lists are for helping to evaluate how big to set future modS
    for mode in range(modenum):
        modSlist.append(mp.matrix(S1list[mode].rows, 1))
        test_modSlist.append(mp.matrix(S1list[mode].rows, 1))
        test_S1list.append(mp.matrix(S1list[mode].rows, 1))

    dofnum = initdof.rows
    dof = initdof.copy(
    )  #.copy() because we don't wont to modify the initialization array in place
    dofgrad = mp.matrix(dofnum, 1)
    dofHess = mp.matrix(dofnum, dofnum)

    tic = time.time()

    iternum = 0
    prevD = mp.inf
    alphaopt_grad = mp.one
    alphaopt_Hess = mp.one
    tol_orthoS = 1e-5
    dualfunc = lambda d: get_spatialProj_dualgradHess_modS(d, [], [],
                                                           dgHfunc,
                                                           S1list,
                                                           modSlist,
                                                           epsSlist,
                                                           get_grad=False,
                                                           get_Hess=False)

    while True:
        iternum += 1

        print('the iteration number is:', iternum, flush=True)

        doGD = (
            iternum % 2 == 0
        )  #flag for deciding whether to do a gradient step or a Newton step

        dualval = get_spatialProj_dualgradHess_modS(dof,
                                                    dofgrad,
                                                    dofHess,
                                                    dgHfunc,
                                                    S1list,
                                                    modSlist,
                                                    epsSlist,
                                                    get_grad=True,
                                                    get_Hess=(not doGD))
        objval = dualval - (dof.T * dofgrad)[0]
        abs_cstrt_sum = mp_dblabsdot(dof, dofgrad)
        print(
            'current dual, objective, absolute sum of constraint violation are',
            dualval, objval, abs_cstrt_sum)

        if np.abs(dualval - objval) < opttol * min(np.abs(
                objval), np.abs(dualval)) and abs_cstrt_sum < opttol * min(
                    np.abs(objval),
                    np.abs(dualval)):  #objective convergence termination
            break

        if iternum % check_iter_period == 0:
            print('previous dual is', prevD)
            if np.abs(prevD - dualval) < np.abs(
                    dualval
            ) * 1e-3:  #dual convergence / stuck optimization terminatino
                break
            prevD = dualval

        normgrad = np.linalg.norm(dofgrad)
        if not doGD:
            Ndir = mp.lu_solve(dofHess, -dofgrad)
            normNdir = np.linalg.norm(Ndir)
            pdir = Ndir / normNdir
            print('do regular Hessian step')
            print('normNdir is', normNdir)
            print('normgrad is', normgrad)
            print('Ndir dot grad is', np.dot(Ndir, dofgrad))
        if doGD:
            print('do regular gradient step')
            pdir = -dofgrad / normgrad
            print('normgrad is', normgrad)

        c1 = 0.5
        c2 = 0.7  #the parameters for doing line search
        if doGD:
            alpha_start = alphaopt_grad
        else:
            alpha_start = alphaopt_Hess
        alpha = alpha_start

        print('alpha before feasibility backtrack', alpha)
        while mineigfunc(dof + alpha * pdir)[1] <= 0:
            alpha *= c2

        alpha_feas = alpha
        print('alpha before backtracking is', alpha_feas)
        alphaopt = alpha
        Dopt = mp.inf
        while True:
            tmp = dualfunc(dof + alpha * pdir)
            if tmp < Dopt:  #the dual is still decreasing as we backtrack, continue
                Dopt = tmp
                alphaopt = alpha
            else:
                alphaopt = alpha
                break
            if tmp <= dualval + c1 * alpha * np.dot(
                    pdir, dofgrad):  #Armijo backtracking condition
                alphaopt = alpha
                break
            alpha *= c2

        if alphaopt / alpha_start > (
                c2 + 1) / 2:  #in this case can start with bigger step
            alpha_newstart = alphaopt * 2
        else:
            alpha_newstart = alphaopt
            if alpha_feas / alpha_start < (
                    c2 + 1
            ) / 2 and alphaopt / alpha_feas > (
                    c2 + 1
            ) / 2:  #this means we encountered feasibility wall and backtracking linesearch didn't reduce step size, we should add mod source
                singular_dof = dof + (
                    alpha_feas /
                    c2) * pdir  #dof that is roughly on duality boundary
                singular_mode, singular_eigw, singular_eigv = mineigfunc(
                    singular_dof, eigvals_only=False)
                if epsSlist[singular_mode] <= 0:
                    print('new modS aded at mode', singular_mode)
                    test_modSlist[singular_mode] = singular_eigv
                    test_epsSlist[singular_mode] = 1.0
                    modval = np.abs(
                        get_spatialProj_dualgradHess_modS(singular_dof, [], [],
                                                          dgHfunc,
                                                          test_S1list,
                                                          test_modSlist,
                                                          test_epsSlist,
                                                          get_grad=False,
                                                          get_Hess=False))
                    modSlist[singular_mode] = singular_eigv
                    epsSlist[singular_mode] = mp.sqrt(modSratio *
                                                      np.abs(dualval / modval))
                    test_modSlist[singular_mode] = mp.zeros(
                        S1list[singular_mode].rows, 1)
                    test_epsSlist[singular_mode] = 0
                elif np.abs(mp_conjdot(singular_eigv,
                                       modSlist[singular_mode])) < tol_orthoS:
                    print('changed modS at mode', singular_mode)
                    modSlist[singular_mode] = mp.sqrt(0.5) * (
                        modSlist[singular_mode] + singular_eigv)

        print('stepsize alphaopt is', alphaopt, '\n')
        dof += alpha * pdir
        if doGD:
            alphaopt_grad = alpha_newstart
        else:
            alphaopt_Hess = alpha_newstart

    ####NOW WE GRADUALLY BRING THE MAGNITUDES OF THE MODS DOWN TO ZERO####
    alphaopt_grad = max(alphaopt_grad, 5e-5 * mp.one)
    alphaopt_Hess = max(alphaopt_Hess, 5e-5 * mp.one)
    minalphatol = 1e-10
    olddualval = dualval
    reductFactor = 1e-1
    reductCount = 1
    lastReduct = False

    while True:  #gradual reduction of modified source amplitude, outer loop
        if not lastReduct:
            for i in range(len(epsSlist)):
                epsSlist[i] *= reductFactor
            modSratio *= reductFactor
        else:
            for i in range(len(epsSlist)):
                epsSlist[i] = 0

        iternum = 0
        while True:
            iternum += 1

            print('reducing modS now, at reduction #',
                  reductCount,
                  'the iteration number is:',
                  iternum,
                  flush=True)

            doGD = (
                iternum % 2 == 0
            )  #flag for deciding whether to do a gradient step or a Newton step

            dualval = get_spatialProj_dualgradHess_modS(dof,
                                                        dofgrad,
                                                        dofHess,
                                                        dgHfunc,
                                                        S1list,
                                                        modSlist,
                                                        epsSlist,
                                                        get_grad=True,
                                                        get_Hess=(not doGD))
            objval = dualval - (dof.T * dofgrad)[0]
            abs_cstrt_sum = mp_dblabsdot(dof, dofgrad)
            print(
                'current dual, objective, absolute sum of constraint violation are',
                dualval, objval, abs_cstrt_sum)

            if np.abs(dualval - objval) < opttol * min(np.abs(
                    objval), np.abs(dualval)) and abs_cstrt_sum < opttol * min(
                        np.abs(objval),
                        np.abs(dualval)):  #objective convergence termination
                break

            if iternum % check_iter_period == 0:
                print('previous dual is', prevD)
                if np.abs(prevD - dualval) < np.abs(
                        dualval
                ) * 1e-3:  #dual convergence / stuck optimization termination
                    break
                if alphaopt_grad < minalphatol and alphaopt_Hess < minalphatol:
                    alphaopt_grad = 5e-5
                    alphaopt_Hess = 5e-5  #periodically boost the max step size since we are gradually turning off the modified sources
                    ##SHOULD MAKE THIS MORE TRANSPARENT IN THE FUTURE##
                prevD = dualval

            normgrad = np.linalg.norm(dofgrad)
            if not doGD:
                Ndir = mp.lu_solve(dofHess, -dofgrad)
                normNdir = np.linalg.norm(Ndir)
                pdir = Ndir / normNdir
                print('do regular Hessian step')
                print('normNdir is', normNdir)
                print('normgrad is', normgrad)
                print('Ndir dot grad is', np.dot(Ndir, dofgrad))
            if doGD:
                print('do regular gradient step')
                pdir = -dofgrad / normgrad
                print('normgrad is', normgrad)

            c1 = 0.5
            c2 = 0.7  #the parameters for doing line search
            if doGD:
                alpha_start = alphaopt_grad
            else:
                alpha_start = alphaopt_Hess
            alpha = alpha_start

            print('alpha before feasibility backtrack', alpha)
            while mineigfunc(dof + alpha * pdir)[1] <= 0:
                alpha *= c2

            alpha_feas = alpha
            print('alpha before backtracking is', alpha_feas)
            alphaopt = alpha
            Dopt = mp.inf
            while True:
                tmp = dualfunc(dof + alpha * pdir)
                if tmp < Dopt:  #the dual is still decreasing as we backtrack, continue
                    Dopt = tmp
                    alphaopt = alpha
                else:
                    alphaopt = alpha
                    break
                if tmp <= dualval + c1 * alpha * np.dot(
                        pdir, dofgrad):  #Armijo backtracking condition
                    alphaopt = alpha
                    break
                alpha *= c2

            if alphaopt / alpha_start > (
                    c2 + 1) / 2:  #in this case can start with bigger step
                alpha_newstart = alphaopt * 2
            else:
                alpha_newstart = alphaopt
                if (not lastReduct) and alpha_feas / alpha_start < (
                        c2 + 1
                ) / 2 and alphaopt / alpha_feas > (
                        c2 + 1
                ) / 2:  #don't bother to modify sources if this is the final reduction iteration
                    singular_dof = dof + (
                        alpha_feas /
                        c2) * pdir  #dof that is roughly on duality boundary
                    singular_mode, singular_eigw, singular_eigv = mineigfunc(
                        singular_dof, eigvals_only=False)
                    if epsSlist[singular_mode] <= 0:
                        print('new modS aded at mode', singular_mode)
                        test_modSlist[singular_mode] = singular_eigv
                        test_epsSlist[singular_mode] = mp.one
                        modval = np.abs(
                            get_spatialProj_dualgradHess_modS(singular_dof, [],
                                                              [],
                                                              dgHfunc,
                                                              test_S1list,
                                                              test_modSlist,
                                                              test_epsSlist,
                                                              get_grad=False,
                                                              get_Hess=False))
                        modSlist[singular_mode] = singular_eigv
                        epsSlist[singular_mode] = mp.sqrt(
                            modSratio * np.abs(dualval / modval))
                        test_modSlist[singular_mode] = mp.zeros(
                            S1list[singular_mode].rows, 1)
                        test_epsSlist[singular_mode] = 0
                    elif np.abs(np.vdot(singular_eigv,
                                        modSlist[singular_mode])) < tol_orthoS:
                        print('changed modS at mode', singular_mode)
                        modSlist[singular_mode] = mp.sqrt(0.5) * (
                            modSlist[singular_mode] + singular_eigv)

            print('stepsize alphaopt is', alphaopt, '\n')
            dof += alpha * pdir
            if doGD:
                alphaopt_grad = alpha_newstart
            else:
                alphaopt_Hess = alpha_newstart

        if lastReduct:
            break
        if np.abs(olddualval - dualval) < opttol * np.abs(dualval):
            lastReduct = True
        olddualval = dualval
        reductCount += 1

    print('time elapsed:', time.time() - tic, flush=True)
    return dof, dofgrad, dualval, objval
コード例 #21
0
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