def solve(t_y, t_x, mask, t_y_weights=None, t_x_weights=None):
    """Solve for the image which best matches the target vertical gradients
    t_y and horizontal gradients t_x, e.g. the one which minimizes sum of squares
    of the residual

       sum of (I[i,j] - I[i-1,j] - t_y[i,j])**2 + (I[i,j] - I[i,j-1] - t_x[i,j])**2

    Only considers the target gradients lying entirely within the mask.
    The first row of t_y and the first column of t_x are ignored. Optionally,
    you may pass in an array with the weights corresponding to each target
    gradient. The solution is unique up to a constant added to each of
    the pixels. """
    if t_y_weights is None:
        t_y_weights = np.ones(t_y.shape)
    if t_x_weights is None:
        t_x_weights = np.ones(t_x.shape)
    M, N = mask.shape
    numbers = get_numbers(mask)
    A = get_A(mask, t_y_weights, t_x_weights)
    b = get_b(t_y, t_x, mask, t_y_weights, t_x_weights)

    solver = pyamg.ruge_stuben_solver(A)
    x = solver.solve(b)
    
    I = np.zeros(mask.shape)
    for i in range(M):
        for j in range(N):
            I[i,j] = x[numbers[i,j]]
    return I
Beispiel #2
0
def test():
    class Gamma0(Subdomain):
        def is_inside(self, x):
            return x[1] < 0.5

        is_boundary_only = True

    class Gamma1(Subdomain):
        def is_inside(self, x):
            return x[1] >= 0.5

        is_boundary_only = True

    class Poisson(object):
        def apply(self, u):
            return integrate(lambda x: -n_dot_grad(u(x)), dS) - integrate(
                lambda x: 50 * sin(2 * pi * x[0]), dV
            )

        def dirichlet(self, u):
            return [(lambda x: u(x) - 0.0, Gamma0()), (lambda x: u(x) - 1.0, Gamma1())]

    # # Read the mesh from file
    # mesh, _, _ = pyfvm.reader.read('circle.vtu')

    # Create mesh using meshzoo
    import meshzoo

    vertices, cells = meshzoo.cube(0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 30, 30, 30)
    mesh = meshplex.MeshTetra(vertices, cells)
    # vertices, cells = meshzoo.rectangle(0.0, 2.0, 0.0, 1.0, 401, 201)
    # mesh = meshplex.MeshTri(vertices, cells)
    print(len(vertices))

    # import mshr
    # import dolfin
    # # h = 2.5e-3
    # h = 1.e-1
    # # cell_size = 2 * pi / num_boundary_points
    # c = mshr.Circle(dolfin.Point(0., 0., 0.), 1, int(2*pi / h))
    # # cell_size = 2 * bounding_box_radius / res
    # m = mshr.generate_mesh(c, 2.0 / h)
    # coords = m.coordinates()
    # coords = numpy.c_[coords, numpy.zeros(len(coords))]
    # cells = m.cells().copy()
    # mesh = meshplex.MeshTri(coords, cells)
    # # mesh = meshplex.lloyd_smoothing(mesh, 1.0e-4)

    matrix, rhs = pyfvm.discretize_linear(Poisson(), mesh)

    # ml = pyamg.smoothed_aggregation_solver(matrix)
    ml = pyamg.ruge_stuben_solver(matrix)
    u = ml.solve(rhs, tol=1e-10)
    # from scipy.sparse import linalg
    # u = linalg.spsolve(matrix, rhs)

    mesh.write("out.vtk", point_data={"u": u})
    return
Beispiel #3
0
def test_laplacian():

    import pylab as pl
    # Setup grid
    nx, ny = 500, 500
    d = 2*pi/nx
    Lx, Ly = nx * d, ny * d


    g = 0
    # make grid
    x = np.arange(-g, nx+g)*d
    y = np.arange(-g, ny+g)*d

    dx = x[1]-x[0]
    dy = y[1]-y[0]

    x, y =  np.meshgrid(x, y, indexing='ij')

    # build laplacian
    A = build_laplacian_matrix(nx,ny,d=d)
    # A = poisson((nx, ny), spacing=(dx, dy), format='csr')/d/d

    # right hand side
    f = np.sin(x)*np.cos(2*y)
    f = np.random.rand(A.shape[0])

    p_ex = np.sin(x)*np.cos(2*y)/(-1 - 4)

    print("Timing information")
    print("==================")
    print("")


    # with elapsed_timer() as elapsed:
    #     p_ap = la.spsolve(A, f.ravel())
    #     print("spsolve {0}".format(elapsed()))

    with elapsed_timer() as elapsed:
        p_cg = la.cg(A, f.ravel())[0]
        print("cg {0}".format(elapsed()))

    # with elapsed_timer() as elapsed:
    #     p_ap = la.gmres(A, f.ravel())
    #     print("gmres {0}".format(elapsed()))


    ml = ruge_stuben_solver(A)
    M = ml.aspreconditioner()
    with elapsed_timer() as elapsed:
        p_amg = la.cg(A, f.ravel(),M=M)
        print("pyamg cg {0}".format(elapsed()))

    pl.show()
def _solve_cg_mg(lap_sparse, B, tol):
    if not amg_loaded:
        print """the pyamg module (http://code.google.com/p/pyamg/)
        must be installed to use the amg mode"""
        raise ImportError
    X = []
    #lap_sparse = lap_sparse.tocsr()
    ml = ruge_stuben_solver(lap_sparse)
    M = ml.aspreconditioner(cycle='V')
    for i in range(len(B)):
        x0 = cg(lap_sparse, -B[i].todense(), tol=tol, M=M, maxiter=30)[0]
        X.append(x0)
    X = np.array(X)
    X = np.argmax(X, axis=0)
    return X
def _solve_cg_mg(lap_sparse, B, tol):
    """
    solves lap_sparse X_i = B_i for each phase i, using the conjugate
    gradient method with a multigrid preconditioner (ruge-stuben from
    pyamg). For each pixel, the label i corresponding to the maximal
    X_i is returned.
    """
    X = []
    ml = ruge_stuben_solver(lap_sparse)
    M = ml.aspreconditioner(cycle='V')
    for i in range(len(B)):
        x0 = cg(lap_sparse, -B[i].todense(), tol=tol, M=M, maxiter=30)[0]
        X.append(x0)
    X = np.array(X)
    X = np.argmax(X, axis=0)
    return X
def _solve_cg_mg(lap_sparse, B, tol, return_full_prob=False):
    """
    solves lap_sparse X_i = B_i for each phase i, using the conjugate
    gradient method with a multigrid preconditioner (ruge-stuben from
    pyamg). For each pixel, the label i corresponding to the maximal
    X_i is returned.
    """
    X = []
    ml = ruge_stuben_solver(lap_sparse)
    M = ml.aspreconditioner(cycle='V')
    for i in range(len(B)):
        x0 = cg(lap_sparse, -B[i].todense(), tol=tol, M=M, maxiter=30)[0]
        X.append(x0)
    if not return_full_prob:
        X = np.array(X)
        X = np.argmax(X, axis=0)
    return X
Beispiel #7
0
    def solver(A, b, **solve_time_kwargs):
        kwargs.update(solve_time_kwargs)

        import pyamg
        ml = pyamg.ruge_stuben_solver(A)
        kwargs['M'] = ml.aspreconditioner()  # params to be developed

        try:
            sol, info, _ = krylov(A, b, **{'callback': callback, **kwargs})
        except:
            sol, info = krylov(A, b, **{'callback': callback, **kwargs})
        if info > 0:
            warnings.warn("Convergence not achieved!")
        elif info == 0 and verbose:
            print(f"{krylov.__name__} converged to "
                  + f"tol={kwargs.get('tol', 'default')} and "
                  + f"atol={kwargs.get('atol', 'default')}")
        return sol
Beispiel #8
0
        def solver(A, b):
            num_iters = 0

            def callback(xk):
                nonlocal num_iters
                num_iters += 1

            ml = pyamg.ruge_stuben_solver(A)
            ptmp = ml.solve(b, tol=1e-16, callback=callback)
            # ptmp = scipy.sparse.linalg.spsolve(A,b,callback=callback)
            atol = 1e-5
            tol = 1e-12
            # ptmp,_ = scipy.sparse.linalg.cg(A, b,p0[1:-1, 1:-1].ravel(),callback=callback,tol=tol)
            # if max(tol*np.linalg.norm(b,2),atol) == atol:
            #     print('atol')
            # else:
            #     print('tol')
            return ptmp, num_iters
Beispiel #9
0
    def precondieitoner(self):

        tspace = self.tensorspace
        vspace = self.vectorspace
        tgdof = tspace.number_of_global_dofs()

        gdim = tspace.geo_dimension()

        bcs, ws = self.integrator.quadpts, self.integrator.weights
        phi = tspace.basis(bcs)

        # construct diag matrix D
        if gdim == 2:
            d = np.array([1, 1, 2])
        elif gdim == 3:
            d = np.array([1, 1, 1, 2, 2, 2])
        D = np.einsum('i, ijkm, m, ijkm, j->jk', ws, phi, d, phi, self.measure) 

        tcell2dof = tspace.cell_to_dof()
        self.D = np.bincount(tcell2dof.flat, weights=D.flat, minlength=tgdof)

        # construct amg solver 
        A = stiff_matrix(self.cspace, self.integrator, self.measure)
        isBdDof = self.cspace.boundary_dof()
        bdIdx = np.zeros((A.shape[0], ), np.int)
        bdIdx[isBdDof] = 1
        Tbd = spdiags(bdIdx, 0, A.shape[0], A.shape[0])
        T = spdiags(1-bdIdx, 0, A.shape[0], A.shape[0])
        A = T@A@T + Tbd
        self.ml = pyamg.ruge_stuben_solver(A) # 这里要求必须有网格内部节点 

        # Get interpolation matrix 
        NC = self.mesh.number_of_cells()
        bc = self.vectorspace.dof.multiIndex/self.vectorspace.p
        val = np.tile(bc, (NC, 1))
        c2d0 = self.vectorspace.dof.cell2dof
        c2d1 = self.cspace.cell_to_dof()

        gdim = self.tensorspace.geo_dimension()
        I = np.einsum('ij, k->ijk', c2d0, np.ones(gdim+1))
        J = np.einsum('ik, j->ijk', c2d1, np.ones(len(bc)))
        cgdof = self.cspace.number_of_global_dofs()
        fgdof = self.vectorspace.number_of_global_dofs()/self.mesh.geo_dimension()
        self.PI = csr_matrix((val.flat, (I.flat, J.flat)), shape=(fgdof, cgdof))
Beispiel #10
0
    def get_new_points(mesh, tol=1.0e-10):
        cells = mesh.cells["nodes"].T

        row_idx = []
        col_idx = []
        val = []
        a = numpy.ones(cells.shape[1], dtype=float)
        for i in [[0, 1], [1, 2], [2, 0]]:
            edges = cells[i]
            row_idx += [edges[0], edges[1], edges[0], edges[1]]
            col_idx += [edges[0], edges[1], edges[1], edges[0]]
            val += [+a, +a, -a, -a]

        row_idx = numpy.concatenate(row_idx)
        col_idx = numpy.concatenate(col_idx)
        val = numpy.concatenate(val)

        n = mesh.node_coords.shape[0]

        # Create CSR matrix for efficiency
        matrix = scipy.sparse.coo_matrix((val, (row_idx, col_idx)), shape=(n, n))
        matrix = matrix.tocsr()

        # Apply Dirichlet conditions.
        verts = numpy.where(mesh.is_boundary_node)[0]
        # Set all Dirichlet rows to 0.
        for i in verts:
            matrix.data[matrix.indptr[i] : matrix.indptr[i + 1]] = 0.0
        # Set the diagonal and RHS.
        d = matrix.diagonal()
        d[mesh.is_boundary_node] = 1.0
        matrix.setdiag(d)

        rhs = numpy.zeros((n, 2))
        rhs[mesh.is_boundary_node] = mesh.node_coords[mesh.is_boundary_node]

        # out = scipy.sparse.linalg.spsolve(matrix, rhs)
        ml = pyamg.ruge_stuben_solver(matrix)
        # Keep an eye on multiple rhs-solves in pyamg,
        # <https://github.com/pyamg/pyamg/issues/215>.
        out = numpy.column_stack(
            [ml.solve(rhs[:, 0], tol=tol), ml.solve(rhs[:, 1], tol=tol)]
        )
        return out[mesh.is_interior_node]
def _solve_linear_system(lap_sparse, B, tol, mode):

    if mode is None:
        mode = 'cg_j'

    if mode == 'cg_mg' and not amg_loaded:
        warn(
            '"cg_mg" not available, it requires pyamg to be installed. '
            'The "cg_j" mode will be used instead.',
            stacklevel=2)
        mode = 'cg_j'

    if mode == 'bf':
        X = spsolve(lap_sparse, B.toarray()).T
    else:
        maxiter = None
        if mode == 'cg':
            if UmfpackContext is None:
                warn(
                    '"cg" mode may be slow because UMFPACK is not available. '
                    'Consider building Scipy with UMFPACK or use a '
                    'preconditioned version of CG ("cg_j" or "cg_mg" modes).',
                    stacklevel=2)
            M = None
        elif mode == 'cg_j':
            M = sparse.diags(1.0 / lap_sparse.diagonal())
        else:
            # mode == 'cg_mg'
            lap_sparse = lap_sparse.tocsr()
            ml = ruge_stuben_solver(lap_sparse)
            M = ml.aspreconditioner(cycle='V')
            maxiter = 30
        cg_out = [
            cg(lap_sparse, B[:, i].toarray(), tol=tol, M=M, maxiter=maxiter)
            for i in range(B.shape[1])
        ]
        if np.any([info > 0 for _, info in cg_out]):
            warn(
                "Conjugate gradient convergence to tolerance not achieved. "
                "Consider decreasing beta to improve system conditionning.",
                stacklevel=2)
        X = np.asarray([x for x, _ in cg_out])

    return X
Beispiel #12
0
def picard(A, M, u0, tol=1e-12, atol=1e-12, ml=None):
    if ml is None:
        ml = pyamg.ruge_stuben_solver(A)
    d0 = (u0 @ A @ u0) / (u0 @ M @ u0)
    while True:
        u1 = ml.solve(d0 * M @ u0, x0=u0, tol=1e-12, accel='cg').reshape(-1)
        L0 = u1 @ M @ u1
        L1 = u1 @ A @ u1
        d1 = L1 / L0
        if norm(u1 - u0, ord=1) / norm(u1, ord=1) < tol or np.abs(d1 -
                                                                  d0) < atol:
            u0 = u1 / np.max(np.abs(u1))
            d0 = d1
            break
        else:
            u0 = u1 / np.max(np.abs(u1))
            d0 = d1

    return u0, d0
Beispiel #13
0
    def test(n=100):
        omega = 1.0
        iterations = 1
        print("Creating A")
        A = pyamg.gallery.poisson(
            (n, n), format='csr')  # 2D Poisson problem on nxn grid
        print("Creating ref")
        ml = pyamg.ruge_stuben_solver(A,
                                      max_coarse=1,
                                      max_levels=100,
                                      presmoother=('jacobi', {
                                          "withrho": True,
                                          "omega": omega
                                      }),
                                      postsmoother=('jacobi', {
                                          "withrho": True,
                                          "omega": omega
                                      }))  # construct the multigrid hierarchy

        mg = MultiGrid(A, omega=omega, iterations=iterations)

        b = np.random.rand(A.shape[0])  # pick a random right hand side
        x0 = np.random.rand(A.shape[0])
        xP = x0.copy()
        xV = x0.copy()
        xVa = x0.copy()
        xVa2 = x0.copy()
        xW = x0.copy()
        i = 0
        print("residuals : ", n, i, np.linalg.norm(b - A * xP),
              np.linalg.norm(b - A * xV), np.linalg.norm(b - A * xW))
        while True:
            i = i + 1
            xP = ml.solve(b, tol=1e-9, maxiter=iterations, x0=xP)
            mg.vcycle(xV, b)
            mg.vcycle_alt(xVa, b)
            mg.vcycle_alt2(xVa2, b)
            mg.wcycle(xW, b)
            print("residuals: ", n, i, np.linalg.norm(b - A * xP),
                  np.linalg.norm(b - A * xV), np.linalg.norm(b - A * xVa),
                  np.linalg.norm(b - A * xVa2), np.linalg.norm(b - A * xW))
            if np.linalg.norm(b - A * xV) < 1e-3:
                break
Beispiel #14
0
def solve1(a, L, uh, dirichlet=None, neuman=None, solver='cg'):
    space = a.space

    start = timer()
    A = a.get_matrix()
    b = L.get_vector()
    end = timer()

    print("Construct linear system time:", end - start)

    if neuman is not None:
        b += neuman.get_vector()

    if dirichlet is not None:
        AD, b = dirichlet.apply(A, b)
    else:
        AD = A


#    print("The condtion number is: ", np.linalg.cond(AD.todense()))
    if solver is 'cg':
        start = timer()
        D = AD.diagonal()
        M = spdiags(1 / D, 0, AD.shape[0], AD.shape[1])
        uh[:], info = cg(AD, b, tol=1e-14, M=M)
        end = timer()
        print(info)
    elif solver is 'amg':
        start = timer()
        ml = pyamg.ruge_stuben_solver(AD)
        uh[:] = ml.solve(b, tol=1e-12, accel='cg').reshape((-1, ))
        end = timer()
        print(ml)
    elif solver is 'direct':
        start = timer()
        uh[:] = spsolve(AD, b)
        end = timer()
    else:
        print("We don't support solver: " + solver)

    print("Solve time:", end - start)

    return A
Beispiel #15
0
    def __init__(self, A, P, isBdDof):
        """
        Notes
        -----

        这里的边界条件处理放到矩阵和向量的乘积运算当中, 所心不需要修改矩阵本身
        """
        self.gdof = P.shape[0]
        self.GD = A.shape[0] // self.gdof

        self.A = A
        self.isBdDof = isBdDof

        # 处理预条件子的边界条件
        bdIdx = np.zeros(P.shape[0], dtype=np.int_)
        bdIdx[isBdDof] = 1
        Tbd = spdiags(bdIdx, 0, P.shape[0], P.shape[0])
        T = spdiags(1 - bdIdx, 0, P.shape[0], P.shape[0])
        P = T @ P @ T + Tbd
        self.ml = pyamg.ruge_stuben_solver(P)
Beispiel #16
0
    def __init__(self, pde, n, tau, q):
        self.pde = pde 
        self.mesh = pde.space_mesh(n) 
        self.timemesh, self.tau = self.pde.time_mesh(tau)
        self.femspace = LagrangeFiniteElementSpace(self.mesh, 1) 

        self.uh0 = self.femspace.interpolation(pde.initdata)
        self.uh1 = self.femspace.function()

        self.area = self.mesh.entity_measure('cell')

        self.integrator = self.mesh.integrator(q)
        self.integralalg = IntegralAlg(self.integrator, self.mesh, self.area)

        self.A, self.B, self.gradphi = grad_recovery_matrix(self.femspace)
        self.M = doperator.mass_matrix(self.femspace, self.integrator, self.area)
        self.K = self.get_stiff_matrix()  
        self.D = self.M + self.tau * self.K
        self.ml = pyamg.ruge_stuben_solver(self.D)  
        print(self.ml)
        self.current = 0
def mode_solver_initialisation(mode, solver_data, a, solver_tol):
    solver_data['solver_timing'], solver_data['solver_tol'] = [], solver_tol
    solver_data['is_solver_direct'] = []
    
    id_n = sp.eye(a.shape[0], format='csr')
    solver_data['a'] = a
    solver_data['id_n'] = id_n

    if mode == 'pyamg':
        amg_hierarchy = pyamg.ruge_stuben_solver(a)
        orig_hierarchy = copy_hierarchy(amg_hierarchy)
        solver_data['amg_hierarchy'], solver_data['orig_hierarchy'] = amg_hierarchy, orig_hierarchy
    elif mode == 'pyamgE':
        B = np.ones((a.shape[0],1), dtype=a.dtype);
        amg_hierarchy = pyamg.rootnode_solver(a, max_levels = 15, max_coarse = 300, coarse_solver = 'pinv', presmoother = ('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 1}), postsmoother = ('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 1}), BH = B.copy(), 
                                              strength = ('evolution', {'epsilon': 4.0, 'k': 2, 'proj_type': 'l2'}), aggregate ='standard', smooth = ('energy', {'weighting': 'local', 'krylov': 'gmres', 'degree': 1, 'maxiter': 2}), improve_candidates = [('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 4}), None, None, None, None, None, None, None, None, None, None, None, None, None, None]) 
        orig_hierarchy = copy_hierarchy(amg_hierarchy)
        solver_data['amg_hierarchy'], solver_data['orig_hierarchy'] = amg_hierarchy, orig_hierarchy
    elif mode == 'splu':
        solver_data['lu'] = sla.splu(a.tocsc())
    return
Beispiel #18
0
    def __init__(self, A, F, P, I, isBdDof):
        """


        Notes
        -----
            求解高次拉格朗日有限元的快速算法

            
        """
        self.gdof = len(isBdDof)
        self.A = A # 矩阵 (gdof, gdof), 注意这里是没有处理 D 氏边界的矩阵
        self.F = F # 右端 (gdof, ), 注意这里也没有处理 D 氏边界
        self.I = I # 插值矩阵 (gdof, NN), 把线性元的解插值到 p 次解
        self.isBdDof = isBdDof

        # 获得磨光子
        gdof = self.gdof
        bdIdx = np.zeros(gdof, dtype=np.int_)
        bdIdx[isBdDof] = 1 # 这里假定 A 的前 NN 个自由度是网格节点
        Tbd = spdiags(bdIdx, 0, gdof, gdof)
        T = spdiags(1-bdIdx, 0, gdof, gdof)
        A = T@A@T + Tbd

        self.L0 = tril(A).tocsr()
        self.U0 = triu(A, k=1).tocsr()

        self.U1 = self.L0.T.tocsr()
        self.L1 = self.U0.T.tocsr()


        # 处理预条件子的边界条件
        NN = P.shape[0]
        bdIdx = np.zeros(NN, dtype=np.int_)
        bdIdx[isBdDof[:NN]] = 1 # 这里假定 A 的前 NN 个自由度是网格节点
        Tbd = spdiags(bdIdx, 0, NN, NN)
        T = spdiags(1-bdIdx, 0, NN, NN)
        P = T@P@T + Tbd
        self.ml = pyamg.ruge_stuben_solver(P)  # P 的 D 氏边界条件用户先处理一下
Beispiel #19
0
    def __init__(self, A, P, isBdDof):
        """
        Notes
        -----
        A: [[A00, A01], [A10, A11]] (2*gdof, 2*gdof)
           [[A00, A01, A02], [A10, A11, A12], [A20, A21, A22]] (3*gdof, 3*gdof)
        P: 预条件子 (gdof, gdof)

        这里的边界条件处理放到矩阵和向量的乘积运算当中, 所心不需要修改矩阵本身
        """
        self.GD = len(A)
        self.gdof = P.shape[0]

        self.A = A
        self.isBdDof = isBdDof

        # 处理预条件子的边界条件
        bdIdx = np.zeros(P.shape[0], dtype=np.int_)
        bdIdx[isBdDof] = 1
        Tbd = spdiags(bdIdx, 0, P.shape[0], P.shape[0])
        T = spdiags(1 - bdIdx, 0, P.shape[0], P.shape[0])
        P = T @ P @ T + Tbd
        self.ml = pyamg.ruge_stuben_solver(P)
Beispiel #20
0
def solve(dmodel, uh, dirichlet=None, solver='cg'):
    space = uh.space
    start = timer()
    A = dmodel.get_left_matrix()
    b = dmodel.get_right_vector()
    end = timer()

    print("Construct linear system time:", end - start)

    if dirichlet is not None:
        AD, b = dirichlet.apply(A, b)
    else:
        AD = A

    if solver is 'cg':
        start = timer()
        D = AD.diagonal()
        M = spdiags(1/D, 0, AD.shape[0], AD.shape[1])
        uh[:], info = cg(AD, b, tol=1e-14, M=M)
        end = timer()
        print(info)
    elif solver is 'amg':
        start = timer()
        ml = pyamg.ruge_stuben_solver(AD)  
        uh[:] = ml.solve(b, tol=1e-12, accel='cg').reshape(-1)
        end = timer()
        print(ml)
    elif solver is 'direct':
        start = timer()
        uh[:] = spsolve(AD, b)
        end = timer()
    else:
        raise ValueError("We don't support solver `{}`! ".format(solver))

    print("Solve time:", end-start)

    return AD, b 
Beispiel #21
0
    def solve(self, uh, timeline):
        '''  piccard 迭代  C-N 方法 '''
        from nonlinear_robin import nonlinear_robin

        i = timeline.current
        t1 = timeline.next_time_level()
        dt = timeline.current_time_step_length()
        F = self.pde.right_vector(uh, timeline)

        # 网格数据
        rho = self.mesh.meshdata['rho']
        c = self.mesh.meshdata['c']
        kappa = self.mesh.meshdata['kappa']
        epsilon = self.mesh.meshdata['epsilon']
        sigma = self.mesh.meshdata['sigma']

        A = kappa * self.A
        M = rho * c * self.M
        b = self.apply_boundary_condition(A, F, uh, timeline)

        e = 0.0000000001
        error = 1
        xi_new = self.space.function()
        xi_new[:] = copy.deepcopy(uh[:, i])
        while error > e:
            xi_tmp = copy.deepcopy(xi_new[:])
            R = self.nr.robin_bc(A,
                                 xi_new,
                                 lambda x, n: self.pde.robin(x, n, t1),
                                 threshold=self.pde.is_robin_boundary)
            r = M @ uh[:, i] + dt * b
            R = M + dt * R
            ml = pyamg.ruge_stuben_solver(R)
            xi_new[:] = ml.solve(r, tol=1e-12, accel='cg').reshape(-1)
            #            xi_new[:] = spsolve(R, b).reshape(-1)
            error = np.max(np.abs(xi_tmp - xi_new[:]))
        uh[:, i + 1] = xi_new
Beispiel #22
0
    def Asq_solve_sandwich(self, b, S, use_pyamg=False):
        """
        Solves A @ S @ A.T @ x = b (where A is self.get_cycle_matrix()).

        Parameters
        ----------
        b : (Nf,) or (Nf, W) array
            Right-hand side of system.
        S : (Nj, Nj) sparse array
            Sandwich matrix.

        Returns
        -------
        x : shape of b
            Solution of system.
        """
        Sd = S.diagonal()
        if S.nnz == np.count_nonzero(Sd):
            if np.allclose(Sd[0], Sd):
                return self.Asq_solve(b) / Sd[0]
        if use_pyamg:
            import pyamg
            import pyamg.util.linalg
            A = self.cycle_matrix @ S @ self.cycle_matrix.T
            pyamg_cb = PyamgCallback(A, b)
            ml = pyamg.ruge_stuben_solver(A, strength=('classical', {'theta': 0.2}))
            try:
                mg_out = ml.solve(b, tol=1e-8, maxiter=3, callback=pyamg_cb.cb)
            except DivergenceError:
                mg_out = pyamg_cb.x
            if not pyamg_cb.has_diverged:
                return mg_out
            else:
                return self.Asq_solve_sandwich(b, S, use_pyamg=False)
        else:
            AsqF = scipy.sparse.linalg.factorized(self.cycle_matrix @ S @ self.cycle_matrix.T)
            return AsqF(b)
Beispiel #23
0
 def generateQTBNQ(self):
     self.QTBNQ = self.QT * self.BNQ
     idx = list(self.QTBNQ.indices).index(0)
     self.QTBNQ.data[idx] *= 2.0
     self.ml = pyamg.ruge_stuben_solver(self.QTBNQ)
Beispiel #24
0
def apply_inverse(matrix, U, options=None):
    """Solve linear equation system.

    Applies the inverse of `matrix` to the row vectors in `U`.

    See :func:`sparse_options` for documentation of all possible options for
    sparse matrices.

    Parameters
    ----------
    matrix
        The |NumPy| matrix to invert.
    U
        2-dimensional |NumPy array| containing as row vectors
        the right-hand sides of the linear equation systems to
        solve.
    options
        |invert_options| to use. (See :func:`invert_options`.)

    Returns
    -------
    |NumPy array| of the solution vectors.
    """

    default_options = invert_options(matrix)

    if options is None:
        options = default_options.values()[0]
    elif isinstance(options, str):
        if options == 'least_squares':
            for k, v in default_options.iteritems():
                if k.startswith('least_squares'):
                    options = v
                    break
            assert not isinstance(options, str)
        else:
            options = default_options[options]
    else:
        assert 'type' in options and options['type'] in default_options \
            and options.viewkeys() <= default_options[options['type']].viewkeys()
        user_options = options
        options = default_options[user_options['type']]
        options.update(user_options)

    R = np.empty((len(U), matrix.shape[1]))

    if options['type'] == 'solve':
        for i, UU in enumerate(U):
            try:
                R[i] = np.linalg.solve(matrix, UU)
            except np.linalg.LinAlgError as e:
                raise InversionError('{}: {}'.format(str(type(e)), str(e)))
    elif options['type'] == 'least_squares_lstsq':
        for i, UU in enumerate(U):
            try:
                R[i], _, _, _ = np.linalg.lstsq(matrix, UU, rcond=options['rcond'])
            except np.linalg.LinAlgError as e:
                raise InversionError('{}: {}'.format(str(type(e)), str(e)))
    elif options['type'] == 'bicgstab':
        for i, UU in enumerate(U):
            R[i], info = bicgstab(matrix, UU, tol=options['tol'], maxiter=options['maxiter'])
            if info != 0:
                if info > 0:
                    raise InversionError('bicgstab failed to converge after {} iterations'.format(info))
                else:
                    raise InversionError('bicgstab failed with error code {} (illegal input or breakdown)'.
                                         format(info))
    elif options['type'] == 'bicgstab_spilu':
        ilu = spilu(matrix, drop_tol=options['spilu_drop_tol'], fill_factor=options['spilu_fill_factor'],
                    drop_rule=options['spilu_drop_rule'], permc_spec=options['spilu_permc_spec'])
        precond = LinearOperator(matrix.shape, ilu.solve)
        for i, UU in enumerate(U):
            R[i], info = bicgstab(matrix, UU, tol=options['tol'], maxiter=options['maxiter'], M=precond)
            if info != 0:
                if info > 0:
                    raise InversionError('bicgstab failed to converge after {} iterations'.format(info))
                else:
                    raise InversionError('bicgstab failed with error code {} (illegal input or breakdown)'.
                                         format(info))
    elif options['type'] == 'spsolve':
        for i, UU in enumerate(U):
            R[i] = spsolve(matrix, UU, permc_spec=options['permc_spec'])
    elif options['type'] == 'lgmres':
        for i, UU in enumerate(U):
            R[i], info = lgmres(matrix, UU.copy(i),
                                tol=options['tol'],
                                maxiter=options['maxiter'],
                                inner_m=options['inner_m'],
                                outer_k=options['outer_k'])
            if info > 0:
                raise InversionError('lgmres failed to converge after {} iterations'.format(info))
            assert info == 0
    elif options['type'] == 'least_squares_lsmr':
        for i, UU in enumerate(U):
            R[i], info, itn, _, _, _, _, _ = lsmr(matrix, UU.copy(i),
                                                  damp=options['damp'],
                                                  atol=options['atol'],
                                                  btol=options['btol'],
                                                  conlim=options['conlim'],
                                                  maxiter=options['maxiter'],
                                                  show=options['show'])
            assert 0 <= info <= 7
            if info == 7:
                raise InversionError('lsmr failed to converge after {} iterations'.format(itn))
    elif options['type'] == 'least_squares_lsqr':
        for i, UU in enumerate(U):
            R[i], info, itn, _, _, _, _, _, _, _ = lsqr(matrix, UU.copy(i),
                                                        damp=options['damp'],
                                                        atol=options['atol'],
                                                        btol=options['btol'],
                                                        conlim=options['conlim'],
                                                        iter_lim=options['iter_lim'],
                                                        show=options['show'])
            assert 0 <= info <= 7
            if info == 7:
                raise InversionError('lsmr failed to converge after {} iterations'.format(itn))
    elif options['type'] == 'pyamg':
        if len(U) > 0:
            U_iter = iter(enumerate(U))
            R[0], ml = pyamg.solve(matrix, next(U_iter)[1],
                                   tol=options['tol'],
                                   maxiter=options['maxiter'],
                                   return_solver=True)
            for i, UU in U_iter:
                R[i] = pyamg.solve(matrix, UU,
                                   tol=options['tol'],
                                   maxiter=options['maxiter'],
                                   existing_solver=ml)
    elif options['type'] == 'pyamg-rs':
        ml = pyamg.ruge_stuben_solver(matrix,
                                      strength=options['strength'],
                                      CF=options['CF'],
                                      presmoother=options['presmoother'],
                                      postsmoother=options['postsmoother'],
                                      max_levels=options['max_levels'],
                                      max_coarse=options['max_coarse'],
                                      coarse_solver=options['coarse_solver'])
        for i, UU in enumerate(U):
            R[i] = ml.solve(UU,
                            tol=options['tol'],
                            maxiter=options['maxiter'],
                            cycle=options['cycle'],
                            accel=options['accel'])
    elif options['type'] == 'pyamg-sa':
        ml = pyamg.smoothed_aggregation_solver(matrix,
                                               symmetry=options['symmetry'],
                                               strength=options['strength'],
                                               aggregate=options['aggregate'],
                                               smooth=options['smooth'],
                                               presmoother=options['presmoother'],
                                               postsmoother=options['postsmoother'],
                                               improve_candidates=options['improve_candidates'],
                                               max_levels=options['max_levels'],
                                               max_coarse=options['max_coarse'],
                                               diagonal_dominance=options['diagonal_dominance'])
        for i, UU in enumerate(U):
            R[i] = ml.solve(UU,
                            tol=options['tol'],
                            maxiter=options['maxiter'],
                            cycle=options['cycle'],
                            accel=options['accel'])
    elif options['type'].startswith('generic') or options['type'].startswith('least_squares_generic'):
        logger = getLogger('pymor.la.numpysolvers.apply_inverse')
        logger.warn('You have selected a (potentially slow) generic solver for a NumPy matrix operator!')
        from pymor.operators.basic import NumpyMatrixOperator
        from pymor.la import NumpyVectorArray
        return genericsolvers.apply_inverse(NumpyMatrixOperator(matrix),
                                            NumpyVectorArray(U, copy=False),
                                            options=options).data
    else:
        raise ValueError('Unknown solver type')
    return R
Beispiel #25
0
import pyamg
import numpy as np
import scipy.sparse

n = 100
omega = 1.2

A = pyamg.gallery.poisson((n, n),
                          format='csr')  # 2D Poisson problem on 500x500 grid
ml = pyamg.ruge_stuben_solver(A,
                              max_coarse=1,
                              max_levels=100,
                              presmoother=('jacobi', {
                                  "withrho": True,
                                  "omega": omega
                              }),
                              postsmoother=('jacobi', {
                                  "withrho": True,
                                  "omega": omega
                              }))  # construct the multigrid hierarchy
print(ml)  # print hierarchy information
b = np.random.rand(A.shape[0])  # pick a random right hand side
x = ml.solve(b, maxiter=2)  # solve Ax=b to a tolerance of 1e-8
print("residual: ",
      np.linalg.norm(b - A * x))  # compute norm of residual vector


def jacobi(A, x, b, omega):
    Ad = A.diagonal()
    Atmp = scipy.sparse.lil_matrix(A.shape)
    def search(self, itr=False):
        import numpy as np
    

        
        if self.amg:
            
            if self.itr<0:
                
                self.itr+=1
            
                from pyamg import ruge_stuben_solver
                from scipy.sparse import diags

                tempB = diags([self.B.tolist()] , [0])
                tempy = self.y

                #self.C =  (self.D *  (self.I + self.B) ) -self.A

                self.C =  (self.D *  (self.I + tempB) ) -self.A


                #self.H = self.D *  (tempB * self.y.T)

                self.H = self.D * (tempB * tempy)

                #self.H = self.H.todense()

                self.H = np.asarray(self.H)


                ml = ruge_stuben_solver(self.C)

                self.ml = ml

                if  itr:
                    solution = ml.solve(self.H, tol=0.5e-4, return_residuals=True)
                    f = np.squeeze(solution[0])
                    x = solution[1]

                    return (f, x)

                else:
                    f = np.squeeze(ml.solve(self.H, tol=0.5e-4))
                    self.out = f
                    return f


            
            else:
                
                self.ml = self.create_solver()
                
                self.out = self.ml.solve(self.H, tol=0.5e-4,x0=self.out,return_residuals=False)
                
                return self.out

        else:

            from scipy.sparse.linalg import spsolve

            self.C =  (self.D *  (self.I + self.B) ) -self.A

            self.H = self.D *  np.dot(np.diag(self.B) , self.y.T)


            f = np.squeeze(spsolve(self.C, self.H))

            return f             
Beispiel #27
0
    def apply_inverse(self, U, ind=None, mu=None, options=None):

        default_options = self.invert_options

        if options is None:
            options = default_options.values()[0]
        elif isinstance(options, str):
            options = default_options[options]
        else:
            assert 'type' in options and options['type'] in default_options \
                and options.viewkeys() <= default_options[options['type']].viewkeys()
            user_options = options
            options = default_options[user_options['type']]
            options.update(user_options)

        assert isinstance(U, NumpyVectorArray)
        assert self.dim_range == U.dim

        U = U._array[:U._len] if ind is None else U._array[ind]
        if U.shape[1] == 0:
            return NumpyVectorArray(U)
        R = np.empty((len(U), self.dim_source))

        if self.sparse:
            if options['type'] == 'bicgstab':
                for i, UU in enumerate(U):
                    R[i], info = bicgstab(self._matrix, UU, tol=options['tol'], maxiter=options['maxiter'])
                    if info != 0:
                        if info > 0:
                            raise InversionError('bicgstab failed to converge after {} iterations'.format(info))
                        else:
                            raise InversionError('bicgstab failed with error code {} (illegal input or breakdown)'.
                                                 format(info))
            elif options['type'] == 'bicgstab-spilu':
                ilu = spilu(self._matrix, drop_tol=options['spilu_drop_tol'], fill_factor=options['spilu_fill_factor'],
                            drop_rule=options['spilu_drop_rule'], permc_spec=options['spilu_permc_spec'])
                precond = LinearOperator(self._matrix.shape, ilu.solve)
                for i, UU in enumerate(U):
                    R[i], info = bicgstab(self._matrix, UU, tol=options['tol'], maxiter=options['maxiter'], M=precond)
                    if info != 0:
                        if info > 0:
                            raise InversionError('bicgstab failed to converge after {} iterations'.format(info))
                        else:
                            raise InversionError('bicgstab failed with error code {} (illegal input or breakdown)'.
                                                 format(info))
            elif options['type'] == 'spsolve':
                for i, UU in enumerate(U):
                    R[i] = spsolve(self._matrix, UU, permc_spec=options['permc_spec'])
            elif options['type'] == 'pyamg':
                if len(U) > 0:
                    U_iter = iter(enumerate(U))
                    R[0], ml = pyamg.solve(self._matrix, next(U_iter)[1],
                                           tol=options['tol'],
                                           maxiter=options['maxiter'],
                                           return_solver=True)
                    for i, UU in U_iter:
                        R[i] = pyamg.solve(self._matrix, UU,
                                           tol=options['tol'],
                                           maxiter=options['maxiter'],
                                           existing_solver=ml)
            elif options['type'] == 'pyamg-rs':
                ml = pyamg.ruge_stuben_solver(self._matrix,
                                              strength=options['strength'],
                                              CF=options['CF'],
                                              presmoother=options['presmoother'],
                                              postsmoother=options['postsmoother'],
                                              max_levels=options['max_levels'],
                                              max_coarse=options['max_coarse'],
                                              coarse_solver=options['coarse_solver'])
                for i, UU in enumerate(U):
                    R[i] = ml.solve(UU,
                                    tol=options['tol'],
                                    maxiter=options['maxiter'],
                                    cycle=options['cycle'],
                                    accel=options['accel'])
            elif options['type'] == 'pyamg-sa':
                ml = pyamg.smoothed_aggregation_solver(self._matrix,
                                                       symmetry=options['symmetry'],
                                                       strength=options['strength'],
                                                       aggregate=options['aggregate'],
                                                       smooth=options['smooth'],
                                                       presmoother=options['presmoother'],
                                                       postsmoother=options['postsmoother'],
                                                       improve_candidates=options['improve_candidates'],
                                                       max_levels=options['max_levels'],
                                                       max_coarse=options['max_coarse'],
                                                       diagonal_dominance=options['diagonal_dominance'])
                for i, UU in enumerate(U):
                    R[i] = ml.solve(UU,
                                    tol=options['tol'],
                                    maxiter=options['maxiter'],
                                    cycle=options['cycle'],
                                    accel=options['accel'])
            else:
                raise ValueError('Unknown solver type')
        else:
            for i, UU in enumerate(U):
                try:
                    R[i] = np.linalg.solve(self._matrix, UU)
                except np.linalg.LinAlgError as e:
                    raise InversionError('{}: {}'.format(str(type(e)), str(e)))

        return NumpyVectorArray(R)
Beispiel #28
0
 def __init__(self, A):
     super().__init__(A)
     ml = pyamg.ruge_stuben_solver(A.tocsr(), strength=('classical'))
     self.gamg = ml.aspreconditioner()
Beispiel #29
0
    def alg_3_2(self, maxit=None):
        """
        1. 自适应求解 -\Delta u = 1。
        1. 在最细网格上求最小特征值和特征向量。

        refine maxit, picard: 1
        """
        print("算法 3.2")
        if maxit is None:
            maxit = self.maxit

        start = timer()
        if self.step == 0:
            idx = []
        else:
            idx = list(range(0, self.maxit, self.step)) + [self.maxit - 1]

        mesh = self.pde.init_mesh(n=self.numrefine)
        GD = mesh.geo_dimension()
        if (self.step > 0) and (0 in idx):
            NN = mesh.number_of_nodes()
            fig = plt.figure()
            fig.set_facecolor('white')
            if GD == 2:
                axes = fig.gca()
            else:
                axes = Axes3D(fig)
            mesh.add_plot(axes, cellcolor='w')
            fig.savefig(self.resultdir + 'mesh_3_2_0_' + str(NN) + '.pdf')
            plt.close()
            self.savemesh(mesh,
                          self.resultdir + 'mesh_3_2_0_' + str(NN) + '.mat')

        final = 0
        integrator = mesh.integrator(self.q)
        for i in range(maxit):
            space = LagrangeFiniteElementSpace(mesh, 1)
            gdof = space.number_of_global_dofs()

            A = self.get_stiff_matrix(space)
            M = self.get_mass_matrix(space)
            b = M @ np.ones(gdof)

            isFreeDof = ~(space.boundary_dof())
            A = A[isFreeDof, :][:, isFreeDof].tocsr()
            M = M[isFreeDof, :][:, isFreeDof].tocsr()

            uh = space.function()
            if self.matlab is False:
                uh[isFreeDof] = self.psolve(A, b[isFreeDof], M)
            else:
                uh[isFreeDof] = self.msolve(A, b[isFreeDof])

            eta = self.residual_estimate(uh)
            markedCell = mark(eta, self.theta)
            IM = mesh.bisect(markedCell, returnim=True)
            NN = mesh.number_of_nodes()
            print(i + 1, "refine :", NN)
            if (self.step > 0) and (i in idx):
                fig = plt.figure()
                fig.set_facecolor('white')
                if GD == 2:
                    axes = fig.gca()
                else:
                    axes = Axes3D(fig)
                mesh.add_plot(axes, cellcolor='w')
                fig.savefig(self.resultdir + 'mesh_3_2_' + str(i + 1) + '_' +
                            str(NN) + '.pdf')
                plt.close()
                self.savemesh(
                    mesh, self.resultdir + 'mesh_3_2_' + str(i + 1) + '_' +
                    str(NN) + '.mat')
            final = i + 1
            if NN > self.maxdof:
                break

        if self.step > 0:
            NN = mesh.number_of_nodes()
            fig = plt.figure()
            fig.set_facecolor('white')
            if GD == 2:
                axes = fig.gca()
            else:
                axes = Axes3D(fig)
            mesh.add_plot(axes, cellcolor='w')
            fig.savefig(self.resultdir + 'mesh_3_2_' + str(final) + '_' +
                        str(NN) + '.pdf')
            plt.close()
            self.savemesh(
                mesh, self.resultdir + 'mesh_3_2_' + str(final) + '_' +
                str(NN) + '.mat')

        space = LagrangeFiniteElementSpace(mesh, 1)
        gdof = space.number_of_global_dofs()

        A = self.get_stiff_matrix(space)
        M = self.get_mass_matrix(space)
        isFreeDof = ~(space.boundary_dof())
        A = A[isFreeDof, :][:, isFreeDof].tocsr()
        M = M[isFreeDof, :][:, isFreeDof].tocsr()

        if self.multieigs is True:
            self.A = A
            self.M = M
            self.ml = pyamg.ruge_stuben_solver(self.A)
            self.eigs()
        else:
            uh = IM @ uh
            if self.matlab is False:
                uh[isFreeDof], d = self.eig(A, M)
            else:
                uh[isFreeDof], d = self.meigs(A, M)
            print("smallest eigns:", d)
            return space.function(array=uh)
        end = timer()
        print("with time: ", end - start)
Beispiel #30
0
def perform_convergence_tests(
        problem, exact_sol, get_mesh, rng, verbose=False
        ):
    n = len(rng)
    H = numpy.empty(n)
    error_norm_1 = numpy.empty(n)
    order_1 = numpy.empty(n-1)
    error_norm_inf = numpy.empty(n)
    order_inf = numpy.empty(n-1)

    if verbose:
        print(79 * '-')
        print('k' + 5*' ' + 'num verts' + 4*' ' + 'max edge length' + 4*' ' +
              '||error||_1' + 8*' ' + '||error||_inf'
              )
        print(38*' ' + '(order)' + 12*' ' + '(order)')
        print(79 * '-')

    # Add "zero" to all entities. This later gets translated into
    # np.zeros with the appropriate length, making sure that scalar
    # terms in the lambda expression correctly return np.arrays.
    zero = sympy.Symbol('zero')
    x = sympy.DeferredVector('x')
    # See <http://docs.sympy.org/dev/modules/utilities/lambdify.html>.
    array2array = [{'ImmutableMatrix': numpy.array}, 'numpy']
    exact_eval = sympy.lambdify((x, zero), exact_sol(x), modules=array2array)

    for k in rng:
        mesh = get_mesh(k)
        H[k] = max(mesh.edge_lengths)

        linear_system = pyfvm.discretize(problem, mesh)

        # x = linalg.spsolve(linear_system.matrix, linear_system.rhs)
        ml = pyamg.ruge_stuben_solver(linear_system.matrix)
        x = ml.solve(linear_system.rhs, tol=1e-10)

        zero = numpy.zeros(len(mesh.node_coords))
        error = x - exact_eval(mesh.node_coords.T, zero)

        # import meshio
        # meshio.write(
        #     'sol%d.vtu' % k,
        #     mesh.node_coords, {'triangle': mesh.cells['nodes']},
        #     point_data={'x': x, 'error': error},
        #     )

        error_norm_1[k] = numpy.sum(abs(mesh.control_volumes * error))
        error_norm_inf[k] = max(abs(error))

        # numerical orders of convergence
        if k > 0:
            order_1[k-1] = \
                numpy.log(error_norm_1[k-1] / error_norm_1[k]) / \
                numpy.log(H[k-1] / H[k])
            order_inf[k-1] = \
                numpy.log(error_norm_inf[k-1] / error_norm_inf[k]) / \
                numpy.log(H[k-1] / H[k])
            if verbose:
                print
                print((38*' ' + '%0.5f' + 12*' ' + '%0.5f') %
                      (order_1[k-1], order_inf[k-1])
                      )
                print

        if verbose:
            num_nodes = len(mesh.control_volumes)
            print('%2d    %5.3e    %0.10e   %0.10e   %0.10e' %
                  (k, num_nodes, H[k], error_norm_1[k], error_norm_inf[k])
                  )

    return H, error_norm_1, error_norm_inf, order_1, order_inf
Beispiel #31
0
t = time.time()
res = []
x = ml.solve(b, residuals=res, tol=1e-12, accel='cg')

print(res)
print("residual: ", numpy.linalg.norm(b - A * x))

elapsed = time.time() - t
timescale = numpy.linspace(0, elapsed, num=len(res))
plt.semilogy(timescale, res, marker='o', label='SA')
print('solve time = ', elapsed)

# Classical -------------------
print("****** Ruge Stuben solver ******")
ml = pyamg.ruge_stuben_solver(A, max_coarse=100)
print(ml)

n = 0


def residual(w):
    global n
    res = A * w - b
    write_meshio('file%d.xdmf' % n, mesh, res)
    n += 1
    print(numpy.linalg.norm(res))


t = time.time()
res = []
Beispiel #32
0
# Illustrates the selection of Coarse-Fine (CF)
# splittings in Classical AMG.

import numpy
from scipy.io import loadmat
from pyamg import ruge_stuben_solver
from pyamg.gallery import load_example

data = loadmat('square.mat')  #load_example('airfoil')

A = data['A']  # matrix
V = data['vertices'][:A.shape[0]]  # vertices of each variable
E = numpy.vstack((A.tocoo().row, A.tocoo().col)).T  # edges of the matrix graph

# Use Ruge-Stuben Splitting Algorithm (use 'keep' in order to retain the splitting)
mls = ruge_stuben_solver(A, max_levels=2, max_coarse=1, CF='RS', keep=True)
print mls

# The CF splitting, 1 == C-node and 0 == F-node
splitting = mls.levels[0].splitting
C_nodes = splitting == 1
F_nodes = splitting == 0

from draw import lineplot
from pylab import figure, axis, scatter, show

figure(figsize=(6, 6))
axis('equal')
lineplot(V, E)
scatter(V[:, 0][C_nodes], V[:, 1][C_nodes], c='r',
        s=100.0)  #plot C-nodes in red
for i in range(maxit):
    space = LagrangeFiniteElementSpace(mesh, p=p)

    NDof[i] = space.number_of_global_dofs()

    uh = space.function()
    A = space.stiff_matrix()
    F = space.source_vector(pde.source)

    bc = RobinBC(space, pde.robin)
    A, F = bc.apply(A, F)

    #uh[:] = spsolve(A, F).reshape(-1)

    ml = pyamg.ruge_stuben_solver(A)
    uh[:] = ml.solve(F, tol=1e-12, accel='cg').reshape(-1)

    errorMatrix[0, i] = space.integralalg.L2_error(pde.solution, uh)
    errorMatrix[1, i] = space.integralalg.L2_error(pde.gradient, uh.grad_value)

    if i < maxit - 1:
        mesh.uniform_refine()

if d == 2:
    fig = plt.figure()
    axes = fig.gca(projection='3d')
    uh.add_plot(axes, cmap='rainbow')
elif d == 3:
    print('The 3d function plot is not been implemented!')
Beispiel #34
0
    def apply_inverse(op,
                      V,
                      options=None,
                      least_squares=False,
                      check_finite=True,
                      default_solver='pyamg_solve'):
        """Solve linear equation system.

        Applies the inverse of `op` to the vectors in `rhs` using PyAMG.

        Parameters
        ----------
        op
            The linear, non-parametric |Operator| to invert.
        rhs
            |VectorArray| of right-hand sides for the equation system.
        options
            The |solver_options| to use (see :func:`solver_options`).
        least_squares
            Must be `False`.
        check_finite
            Test if solution only contains finite values.
        default_solver
            Default solver to use (pyamg_solve, pyamg_rs, pyamg_sa).

        Returns
        -------
        |VectorArray| of the solution vectors.
        """

        assert V in op.range

        if least_squares:
            raise NotImplementedError

        if isinstance(op, NumpyMatrixOperator):
            matrix = op.matrix
        else:
            from pymor.algorithms.to_matrix import to_matrix
            matrix = to_matrix(op)

        options = _parse_options(options, solver_options(), default_solver,
                                 None, least_squares)

        V = V.to_numpy()
        promoted_type = np.promote_types(matrix.dtype, V.dtype)
        R = np.empty((len(V), matrix.shape[1]), dtype=promoted_type)

        if options['type'] == 'pyamg_solve':
            if len(V) > 0:
                V_iter = iter(enumerate(V))
                R[0], ml = pyamg.solve(matrix,
                                       next(V_iter)[1],
                                       tol=options['tol'],
                                       maxiter=options['maxiter'],
                                       return_solver=True)
                for i, VV in V_iter:
                    R[i] = pyamg.solve(matrix,
                                       VV,
                                       tol=options['tol'],
                                       maxiter=options['maxiter'],
                                       existing_solver=ml)
        elif options['type'] == 'pyamg_rs':
            ml = pyamg.ruge_stuben_solver(
                matrix,
                strength=options['strength'],
                CF=options['CF'],
                presmoother=options['presmoother'],
                postsmoother=options['postsmoother'],
                max_levels=options['max_levels'],
                max_coarse=options['max_coarse'],
                coarse_solver=options['coarse_solver'])
            for i, VV in enumerate(V):
                R[i] = ml.solve(VV,
                                tol=options['tol'],
                                maxiter=options['maxiter'],
                                cycle=options['cycle'],
                                accel=options['accel'])
        elif options['type'] == 'pyamg_sa':
            ml = pyamg.smoothed_aggregation_solver(
                matrix,
                symmetry=options['symmetry'],
                strength=options['strength'],
                aggregate=options['aggregate'],
                smooth=options['smooth'],
                presmoother=options['presmoother'],
                postsmoother=options['postsmoother'],
                improve_candidates=options['improve_candidates'],
                max_levels=options['max_levels'],
                max_coarse=options['max_coarse'],
                diagonal_dominance=options['diagonal_dominance'])
            for i, VV in enumerate(V):
                R[i] = ml.solve(VV,
                                tol=options['tol'],
                                maxiter=options['maxiter'],
                                cycle=options['cycle'],
                                accel=options['accel'])
        else:
            raise ValueError('Unknown solver type')

        if check_finite:
            if not np.isfinite(np.sum(R)):
                raise InversionError('Result contains non-finite values')

        return op.source.from_numpy(R)
Beispiel #35
0
    def alg_3_4(self, maxit=None):
        """
        1. 最粗网格上求解最小特征特征值问题,得到最小特征值 d_H 和特征向量 u_H
        2. 自适应求解  - \Delta u_h = u_H
            *  u_H 插值到下一层网格上做为新 u_H
        3. 最新网格层上求出的 uh 做为一个基函数,加入到最粗网格的有限元空间中,
           求解最小特征值问题。

        自适应 maxit, picard:2
        """
        print("算法 3.4")
        if maxit is None:
            maxit = self.maxit

        start = timer()
        if self.step == 0:
            idx = []
        else:
            idx = list(range(0, self.maxit, self.step)) + [self.maxit - 1]

        mesh = self.pde.init_mesh(n=self.numrefine)
        integrator = mesh.integrator(self.q)

        # 1. 粗网格上求解最小特征值问题
        space = LagrangeFiniteElementSpace(mesh, 1)
        AH = self.get_stiff_matrix(space)
        MH = self.get_mass_matrix(space)
        isFreeHDof = ~(space.boundary_dof())

        gdof = space.number_of_global_dofs()
        print("initial mesh :", gdof)

        uH = np.zeros(gdof, dtype=np.float)

        A = AH[isFreeHDof, :][:, isFreeHDof].tocsr()
        M = MH[isFreeHDof, :][:, isFreeHDof].tocsr()

        if self.matlab is False:
            uH[isFreeHDof], d = self.eig(A, M)
        else:
            uH[isFreeHDof], d = self.meigs(A, M)

        uh = space.function()
        uh[:] = uH

        GD = mesh.geo_dimension()
        if (self.step > 0) and (0 in idx):
            NN = mesh.number_of_nodes()
            fig = plt.figure()
            fig.set_facecolor('white')
            if GD == 2:
                axes = fig.gca()
            else:
                axes = Axes3D(fig)
            mesh.add_plot(axes, cellcolor='w')
            fig.savefig(self.resultdir + 'mesh_3_4_0_' + str(NN) + '.pdf')
            plt.close()
            self.savemesh(mesh,
                          self.resultdir + 'mesh_3_4_0_' + str(NN) + '.mat')

        # 2. 以 u_H 为右端项自适应求解 -\Deta u = u_H
        I = eye(gdof)
        final = 0
        for i in range(maxit):
            eta = self.residual_estimate(uh)
            markedCell = mark(eta, self.theta)
            IM = mesh.bisect(markedCell, returnim=True)
            print(i + 1, "refine :", mesh.number_of_nodes())
            if (self.step > 0) and (i in idx):
                NN = mesh.number_of_nodes()
                fig = plt.figure()
                fig.set_facecolor('white')
                if GD == 2:
                    axes = fig.gca()
                else:
                    axes = Axes3D(fig)
                mesh.add_plot(axes, cellcolor='w')
                fig.savefig(self.resultdir + 'mesh_3_4_' + str(i + 1) + '_' +
                            str(NN) + '.pdf')
                plt.close()
                self.savemesh(
                    mesh, self.resultdir + 'mesh_3_4_' + str(i + 1) + '_' +
                    str(NN) + '.mat')

            I = IM @ I
            uH = IM @ uH

            space = LagrangeFiniteElementSpace(mesh, 1)
            gdof = space.number_of_global_dofs()

            A = self.get_stiff_matrix(space)
            M = self.get_mass_matrix(space)
            isFreeDof = ~(space.boundary_dof())
            b = M @ uH

            uh = space.function()
            if self.matlab is False:
                uh[isFreeDof] = self.psolve(
                    A[isFreeDof, :][:, isFreeDof].tocsr(), b[isFreeDof],
                    M[isFreeDof, :][:, isFreeDof].tocsr())
            else:
                uh[isFreeDof] = self.msolve(
                    A[isFreeDof, :][:, isFreeDof].tocsr(), b[isFreeDof])
            final = i + 1
            if gdof > self.maxdof:
                break

        if self.step > 0:
            NN = mesh.number_of_nodes()
            fig = plt.figure()
            fig.set_facecolor('white')
            if GD == 2:
                axes = fig.gca()
            else:
                axes = Axes3D(fig)
            mesh.add_plot(axes, cellcolor='w')
            fig.savefig(self.resultdir + 'mesh_3_4_' + str(final) + '_' +
                        str(NN) + '.pdf')
            plt.close()
            self.savemesh(
                mesh, self.resultdir + 'mesh_3_4_' + str(final) + '_' +
                str(NN) + '.mat')

        # 3. 把 uh 加入粗网格空间, 组装刚度和质量矩阵
        w0 = uh @ A
        w1 = w0 @ uh
        w2 = w0 @ I
        AA = bmat([[AH, w2.reshape(-1, 1)], [w2, w1]], format='csr')

        w0 = uh @ M
        w1 = w0 @ uh
        w2 = w0 @ I
        MM = bmat([[MH, w2.reshape(-1, 1)], [w2, w1]], format='csr')

        isFreeDof = np.r_[isFreeHDof, True]

        u = np.zeros(len(isFreeDof))

        ## 求解特征值
        A = AA[isFreeDof, :][:, isFreeDof].tocsr()
        M = MM[isFreeDof, :][:, isFreeDof].tocsr()

        if self.multieigs is True:
            self.A = A
            self.M = M
            self.ml = pyamg.ruge_stuben_solver(self.A)
            self.eigs()
        else:
            if self.matlab is False:
                u[isFreeDof], d = self.eig(A, M)
            else:
                u[isFreeDof], d = self.meigs(A, M)
            print("smallest eigns:", d)
            uh *= u[-1]
            uh += I @ u[:-1]

            uh /= np.max(np.abs(uh))
            uh = space.function(array=uh)
            return uh

        end = timer()
        print("with time: ", end - start)
Beispiel #36
0
    def alg_3_3(self, maxit=None):
        """
        1. 最粗网格上求解最小特征特征值问题,得到最小特征值 d_H 和特征向量 u_H
        2. 自适应求解  - \Delta u_h = u_H
            *  u_H 插值到下一层网格上做为新 u_H
        3. 在最细网格上求解一次最小特征值问题

        自适应 maxit, picard:2
        """
        print("算法 3.3")

        if maxit is None:
            maxit = self.maxit

        start = timer()

        if self.step == 0:
            idx = []
        else:
            idx = list(range(0, self.maxit, self.step))

        mesh = self.pde.init_mesh(n=self.numrefine)
        # 1. 粗网格上求解最小特征值问题
        space = LagrangeFiniteElementSpace(mesh, 1)
        AH = self.get_stiff_matrix(space)
        MH = self.get_mass_matrix(space)
        isFreeHDof = ~(space.boundary_dof())

        gdof = space.number_of_global_dofs()
        uH = np.zeros(gdof, dtype=mesh.ftype)
        print("initial mesh :", gdof)

        A = AH[isFreeHDof, :][:, isFreeHDof].tocsr()
        M = MH[isFreeHDof, :][:, isFreeHDof].tocsr()
        if self.matlab is False:
            uH[isFreeHDof], d = self.eig(A, M)
        else:
            uH[isFreeHDof], d = self.meigs(A, M)

        uh = space.function()
        uh[:] = uH

        GD = mesh.geo_dimension()
        if (self.step > 0) and (0 in idx):
            NN = mesh.number_of_nodes()
            fig = plt.figure()
            fig.set_facecolor('white')
            if GD == 2:
                axes = fig.gca()
            else:
                axes = Axes3D(fig)
            mesh.add_plot(axes, cellcolor='w')
            fig.savefig(self.resultdir + 'mesh_3_3_0_' + str(NN) + '.pdf')
            plt.close()
            self.savemesh(mesh,
                          self.resultdir + 'mesh_3_3_0_' + str(NN) + '.mat')

        # 2. 以 u_H 为右端项自适应求解 -\Deta u = u_H
        I = eye(gdof)
        final = 0
        for i in range(maxit - 1):
            eta = self.residual_estimate(uh)
            markedCell = mark(eta, self.theta)
            IM = mesh.bisect(markedCell, returnim=True)
            NN = mesh.number_of_nodes()
            print(i + 1, "refine : ", NN)
            if (self.step > 0) and (i in idx):
                NN = mesh.number_of_nodes()
                fig = plt.figure()
                fig.set_facecolor('white')
                if GD == 2:
                    axes = fig.gca()
                else:
                    axes = Axes3D(fig)
                mesh.add_plot(axes, cellcolor='w')
                fig.savefig(self.resultdir + 'mesh_3_3_' + str(i + 1) + '_' +
                            str(NN) + '.pdf')
                plt.close()
                self.savemesh(
                    mesh, self.resultdir + 'mesh_3_3_' + str(i + 1) + '_' +
                    str(NN) + '.mat')
            final = i + 1
            if NN > self.maxdof:
                break

            I = IM @ I
            uH = IM @ uH

            space = LagrangeFiniteElementSpace(mesh, 1)
            gdof = space.number_of_global_dofs()

            A = self.get_stiff_matrix(space)
            M = self.get_mass_matrix(space)
            isFreeDof = ~(space.boundary_dof())
            b = M @ uH

            uh = space.function()
            if self.matlab is False:
                uh[isFreeDof] = self.psolve(
                    A[isFreeDof, :][:, isFreeDof].tocsr(), b[isFreeDof],
                    M[isFreeDof, :][:, isFreeDof].tocsr())
            else:
                uh[isFreeDof] = self.msolve(
                    A[isFreeDof, :][:, isFreeDof].tocsr(), b[isFreeDof])

        # 3. 在最细网格上求解一次最小特征值问题

        if self.step > 0:
            NN = mesh.number_of_nodes()
            fig = plt.figure()
            fig.set_facecolor('white')
            if GD == 2:
                axes = fig.gca()
            else:
                axes = Axes3D(fig)
            mesh.add_plot(axes, cellcolor='w')
            fig.savefig(self.resultdir + 'mesh_3_3_' + str(final) + '_' +
                        str(NN) + '.pdf')
            plt.close()
            self.savemesh(
                mesh, self.resultdir + 'mesh_3_3_' + str(final) + '_' +
                str(NN) + '.mat')

        space = LagrangeFiniteElementSpace(mesh, 1)
        gdof = space.number_of_global_dofs()
        A = self.get_stiff_matrix(space)
        M = self.get_mass_matrix(space)
        isFreeDof = ~(space.boundary_dof())
        uh = space.function(array=uh)
        A = A[isFreeDof, :][:, isFreeDof].tocsr()
        M = M[isFreeDof, :][:, isFreeDof].tocsr()
        uh = space.function()

        if self.multieigs is True:
            self.A = A
            self.M = M
            self.ml = pyamg.ruge_stuben_solver(self.A)
            self.eigs()
        else:
            if self.matlab is False:
                uh[isFreeDof], d = self.eig(A, M)
            else:
                uh[isFreeDof], d = self.meigs(A, M)
            print("smallest eigns:", d)
            return uh
        end = timer()
        print("with time: ", end - start)
Beispiel #37
0
    def apply_inverse(op, V, options=None, least_squares=False, check_finite=True, default_solver='pyamg_solve'):
        """Solve linear equation system.

        Applies the inverse of `op` to the vectors in `rhs` using PyAMG.

        Parameters
        ----------
        op
            The linear, non-parametric |Operator| to invert.
        rhs
            |VectorArray| of right-hand sides for the equation system.
        options
            The |solver_options| to use (see :func:`solver_options`).
        check_finite
            Test if solution only containes finite values.
        default_solver
            Default solver to use (pyamg_solve, pyamg_rs, pyamg_sa).

        Returns
        -------
        |VectorArray| of the solution vectors.
        """

        assert V in op.range

        if isinstance(op, NumpyMatrixOperator):
            matrix = op._matrix
        else:
            from pymor.algorithms.to_matrix import to_matrix
            matrix = to_matrix(op)

        options = _parse_options(options, solver_options(), default_solver, None, least_squares)

        V = V.data
        promoted_type = np.promote_types(matrix.dtype, V.dtype)
        R = np.empty((len(V), matrix.shape[1]), dtype=promoted_type)

        if options['type'] == 'pyamg_solve':
            if len(V) > 0:
                V_iter = iter(enumerate(V))
                R[0], ml = pyamg.solve(matrix, next(V_iter)[1],
                                       tol=options['tol'],
                                       maxiter=options['maxiter'],
                                       return_solver=True)
                for i, VV in V_iter:
                    R[i] = pyamg.solve(matrix, VV,
                                       tol=options['tol'],
                                       maxiter=options['maxiter'],
                                       existing_solver=ml)
        elif options['type'] == 'pyamg_rs':
            ml = pyamg.ruge_stuben_solver(matrix,
                                          strength=options['strength'],
                                          CF=options['CF'],
                                          presmoother=options['presmoother'],
                                          postsmoother=options['postsmoother'],
                                          max_levels=options['max_levels'],
                                          max_coarse=options['max_coarse'],
                                          coarse_solver=options['coarse_solver'])
            for i, VV in enumerate(V):
                R[i] = ml.solve(VV,
                                tol=options['tol'],
                                maxiter=options['maxiter'],
                                cycle=options['cycle'],
                                accel=options['accel'])
        elif options['type'] == 'pyamg_sa':
            ml = pyamg.smoothed_aggregation_solver(matrix,
                                                   symmetry=options['symmetry'],
                                                   strength=options['strength'],
                                                   aggregate=options['aggregate'],
                                                   smooth=options['smooth'],
                                                   presmoother=options['presmoother'],
                                                   postsmoother=options['postsmoother'],
                                                   improve_candidates=options['improve_candidates'],
                                                   max_levels=options['max_levels'],
                                                   max_coarse=options['max_coarse'],
                                                   diagonal_dominance=options['diagonal_dominance'])
            for i, VV in enumerate(V):
                R[i] = ml.solve(VV,
                                tol=options['tol'],
                                maxiter=options['maxiter'],
                                cycle=options['cycle'],
                                accel=options['accel'])
        else:
            raise ValueError('Unknown solver type')

        if check_finite:
            if not np.isfinite(np.sum(R)):
                raise InversionError('Result contains non-finite values')

        return op.source.from_data(R)
# Illustrates the selection of Coarse-Fine (CF)
# splittings in Classical AMG.
import numpy
from pyamg import ruge_stuben_solver
from scipy.io import loadmat
from scipy.io import savemat

data = loadmat('Mat/NcutData.mat')
Acsc = data['NcutMatrix']  # matrix
Acsr = Acsc.tocsr()
mls = ruge_stuben_solver(Acsr,
                         max_levels=6,
                         max_coarse=150,
                         CF='RS',
                         keep=True)
#mls = ruge_stuben_solver(Acsr, keep=True)
'''
Parameters
    #----------
    A : csr_matrix
        Square matrix in CSR format
    strength : ['symmetric', 'classical', 'evolution', None]
        Method used to determine the strength of connection between unknowns
        of the linear system.  Method-specific parameters may be passed in
        using a tuple, e.g. strength=('symmetric',{'theta' : 0.25 }). If
        strength=None, all nonzero entries of the matrix are considered strong.
    CF : {string} : default 'RS'
        Method used for coarse grid selection (C/F splitting)
        Supported methods are RS, PMIS, PMISc, CLJP, and CLJPc
    presmoother : {string or dict}
        Method used for presmoothing at each level.  Method-specific parameters
Beispiel #39
0
def apply_inverse(matrix, U, options=None):
    """Solve linear equation system.

    Applies the inverse of `matrix` to the row vectors in `U`.

    See :func:`sparse_options` for documentation of all possible options for
    sparse matrices.

    This method is called by :meth:`pymor.core.NumpyMatrixOperator.apply_inverse`
    and usually should not be used directly.

    Parameters
    ----------
    matrix
        The |NumPy| matrix to invert.
    U
        2-dimensional |NumPy array| containing as row vectors
        the right-hand sides of the linear equation systems to
        solve.
    options
        |invert_options| to use. (See :func:`invert_options`.)

    Returns
    -------
    |NumPy array| of the solution vectors.
    """

    default_options = invert_options(matrix)

    if options is None:
        options = default_options.values()[0]
    elif isinstance(options, str):
        if options == 'least_squares':
            for k, v in default_options.iteritems():
                if k.startswith('least_squares'):
                    options = v
                    break
            assert not isinstance(options, str)
        else:
            options = default_options[options]
    else:
        assert 'type' in options and options['type'] in default_options \
            and options.viewkeys() <= default_options[options['type']].viewkeys()
        user_options = options
        options = default_options[user_options['type']]
        options.update(user_options)

    R = np.empty((len(U), matrix.shape[1]))

    if options['type'] == 'solve':
        for i, UU in enumerate(U):
            try:
                R[i] = np.linalg.solve(matrix, UU)
            except np.linalg.LinAlgError as e:
                raise InversionError('{}: {}'.format(str(type(e)), str(e)))
    elif options['type'] == 'least_squares_lstsq':
        for i, UU in enumerate(U):
            try:
                R[i], _, _, _ = np.linalg.lstsq(matrix,
                                                UU,
                                                rcond=options['rcond'])
            except np.linalg.LinAlgError as e:
                raise InversionError('{}: {}'.format(str(type(e)), str(e)))
    elif options['type'] == 'bicgstab':
        for i, UU in enumerate(U):
            R[i], info = bicgstab(matrix,
                                  UU,
                                  tol=options['tol'],
                                  maxiter=options['maxiter'])
            if info != 0:
                if info > 0:
                    raise InversionError(
                        'bicgstab failed to converge after {} iterations'.
                        format(info))
                else:
                    raise InversionError(
                        'bicgstab failed with error code {} (illegal input or breakdown)'
                        .format(info))
    elif options['type'] == 'bicgstab_spilu':
        ilu = spilu(matrix,
                    drop_tol=options['spilu_drop_tol'],
                    fill_factor=options['spilu_fill_factor'],
                    drop_rule=options['spilu_drop_rule'],
                    permc_spec=options['spilu_permc_spec'])
        precond = LinearOperator(matrix.shape, ilu.solve)
        for i, UU in enumerate(U):
            R[i], info = bicgstab(matrix,
                                  UU,
                                  tol=options['tol'],
                                  maxiter=options['maxiter'],
                                  M=precond)
            if info != 0:
                if info > 0:
                    raise InversionError(
                        'bicgstab failed to converge after {} iterations'.
                        format(info))
                else:
                    raise InversionError(
                        'bicgstab failed with error code {} (illegal input or breakdown)'
                        .format(info))
    elif options['type'] == 'spsolve':
        if scipy.version.version >= '0.14':
            if hasattr(matrix, 'factorization'):
                R = matrix.factorization.solve(U.T).T
            elif options['keep_factorization']:
                matrix.factorization = splu(matrix,
                                            permc_spec=options['permc_spec'])
                R = matrix.factorization.solve(U.T).T
            else:
                R = spsolve(matrix, U.T, permc_spec=options['permc_spec']).T
        else:
            if hasattr(matrix, 'factorization'):
                for i, UU in enumerate(U):
                    R[i] = matrix.factorization.solve(UU)
            elif options['keep_factorization']:
                matrix.factorization = splu(matrix,
                                            permc_spec=options['permc_spec'])
                for i, UU in enumerate(U):
                    R[i] = matrix.factorization.solve(UU)
            elif len(U) > 1:
                factorization = splu(matrix, permc_spec=options['permc_spec'])
                for i, UU in enumerate(U):
                    R[i] = factorization.solve(UU)
            else:
                R = spsolve(matrix, U.T,
                            permc_spec=options['permc_spec']).reshape((1, -1))
    elif options['type'] == 'lgmres':
        for i, UU in enumerate(U):
            R[i], info = lgmres(matrix,
                                UU.copy(i),
                                tol=options['tol'],
                                maxiter=options['maxiter'],
                                inner_m=options['inner_m'],
                                outer_k=options['outer_k'])
            if info > 0:
                raise InversionError(
                    'lgmres failed to converge after {} iterations'.format(
                        info))
            assert info == 0
    elif options['type'] == 'least_squares_lsmr':
        for i, UU in enumerate(U):
            R[i], info, itn, _, _, _, _, _ = lsmr(matrix,
                                                  UU.copy(i),
                                                  damp=options['damp'],
                                                  atol=options['atol'],
                                                  btol=options['btol'],
                                                  conlim=options['conlim'],
                                                  maxiter=options['maxiter'],
                                                  show=options['show'])
            assert 0 <= info <= 7
            if info == 7:
                raise InversionError(
                    'lsmr failed to converge after {} iterations'.format(itn))
    elif options['type'] == 'least_squares_lsqr':
        for i, UU in enumerate(U):
            R[i], info, itn, _, _, _, _, _, _, _ = lsqr(
                matrix,
                UU.copy(i),
                damp=options['damp'],
                atol=options['atol'],
                btol=options['btol'],
                conlim=options['conlim'],
                iter_lim=options['iter_lim'],
                show=options['show'])
            assert 0 <= info <= 7
            if info == 7:
                raise InversionError(
                    'lsmr failed to converge after {} iterations'.format(itn))
    elif options['type'] == 'pyamg':
        if len(U) > 0:
            U_iter = iter(enumerate(U))
            R[0], ml = pyamg.solve(matrix,
                                   next(U_iter)[1],
                                   tol=options['tol'],
                                   maxiter=options['maxiter'],
                                   return_solver=True)
            for i, UU in U_iter:
                R[i] = pyamg.solve(matrix,
                                   UU,
                                   tol=options['tol'],
                                   maxiter=options['maxiter'],
                                   existing_solver=ml)
    elif options['type'] == 'pyamg-rs':
        ml = pyamg.ruge_stuben_solver(matrix,
                                      strength=options['strength'],
                                      CF=options['CF'],
                                      presmoother=options['presmoother'],
                                      postsmoother=options['postsmoother'],
                                      max_levels=options['max_levels'],
                                      max_coarse=options['max_coarse'],
                                      coarse_solver=options['coarse_solver'])
        for i, UU in enumerate(U):
            R[i] = ml.solve(UU,
                            tol=options['tol'],
                            maxiter=options['maxiter'],
                            cycle=options['cycle'],
                            accel=options['accel'])
    elif options['type'] == 'pyamg-sa':
        ml = pyamg.smoothed_aggregation_solver(
            matrix,
            symmetry=options['symmetry'],
            strength=options['strength'],
            aggregate=options['aggregate'],
            smooth=options['smooth'],
            presmoother=options['presmoother'],
            postsmoother=options['postsmoother'],
            improve_candidates=options['improve_candidates'],
            max_levels=options['max_levels'],
            max_coarse=options['max_coarse'],
            diagonal_dominance=options['diagonal_dominance'])
        for i, UU in enumerate(U):
            R[i] = ml.solve(UU,
                            tol=options['tol'],
                            maxiter=options['maxiter'],
                            cycle=options['cycle'],
                            accel=options['accel'])
    elif options['type'].startswith('generic') or options['type'].startswith(
            'least_squares_generic'):
        logger = getLogger('pymor.la.numpysolvers.apply_inverse')
        logger.warn(
            'You have selected a (potentially slow) generic solver for a NumPy matrix operator!'
        )
        from pymor.operators.numpy import NumpyMatrixOperator
        from pymor.la.numpyvectorarray import NumpyVectorArray
        return genericsolvers.apply_inverse(NumpyMatrixOperator(matrix),
                                            NumpyVectorArray(U, copy=False),
                                            options=options).data
    else:
        raise ValueError('Unknown solver type')
    return R
Beispiel #40
0
    def _solve(self, A=None, b=None, x0=None):
        r"""
        Sends the A and b matrices to the specified solver, and solves for *x*
        given the boundary conditions, and source terms based on the present
        value of *x*.  This method does NOT iterate to solve for non-linear
        source terms or march time steps.

        Parameters
        ----------
        A : sparse matrix
            The coefficient matrix in sparse format. If not specified, then
            it uses  the ``A`` matrix attached to the object.

        b : ND-array
            The RHS matrix in any format.  If not specified, then it uses
            the ``b`` matrix attached to the object.

        x0 : ND-array
            The initial guess for the solution of Ax = b

        Notes
        -----
        The solver used here is specified in the ``settings`` attribute of the
        algorithm.

        """
        # Fetch A and b from self if not given, and throw error if not found
        A = self.A if A is None else A
        b = self.b if b is None else b
        if A is None or b is None:
            raise Exception('The A matrix or the b vector not yet built.')
        A = A.tocsr()
        x0 = np.zeros_like(b) if x0 is None else x0

        # Check if A and b are well-defined
        self._check_for_nans()

        # Raise error if solver_family not available
        if self.settings["solver_family"] not in ["scipy", "petsc", "pyamg"]:
            raise Exception(f"{self.settings['solver_family']} not available.")

        # Set tolerance for iterative solvers
        tol = self.settings["solver_tol"]
        max_it = self.settings["solver_maxiter"]
        atol = self._get_atol()
        rtol = self._get_rtol(x0=x0)
        # Check if A is symmetric
        is_sym = op.utils.is_symmetric(self.A)
        if self.settings['solver_type'] == 'cg' and not is_sym:
            raise Exception('CG solver only works on symmetric matrices.')

        # SciPy
        if self.settings['solver_family'] == 'scipy':
            # Umfpack by default uses its 32-bit build -> memory overflow
            try:
                import scikits.umfpack
                A.indices = A.indices.astype(np.int64)
                A.indptr = A.indptr.astype(np.int64)
            except ModuleNotFoundError:
                pass
            solver = getattr(scipy.sparse.linalg, self.settings['solver_type'])
            iterative = [
                'bicg', 'bicgstab', 'cg', 'cgs', 'gmres', 'lgmres', 'minres',
                'gcrotmk', 'qmr'
            ]
            if solver.__name__ in iterative:
                x, exit_code = solver(A=A,
                                      b=b,
                                      atol=atol,
                                      tol=tol,
                                      maxiter=max_it,
                                      x0=x0)
                if exit_code > 0:
                    raise Exception(
                        f'Solver did not converge, exit code: {exit_code}')
            else:
                x = solver(A=A, b=b)

        # PETSc
        if self.settings['solver_family'] == 'petsc':
            # Check if petsc is available
            try:
                import petsc4py
                from openpnm.utils.petsc import PETScSparseLinearSolver as SLS
            except Exception:
                raise ModuleNotFoundError('PETSc is not installed.')
            temp = {
                "type": self.settings["solver_type"],
                "preconditioner": self.settings["solver_preconditioner"]
            }
            ls = SLS(A=A, b=b, settings=temp)
            x = ls.solve(x0=x0, atol=atol, rtol=rtol, max_it=max_it)

        # PyAMG
        if self.settings['solver_family'] == 'pyamg':
            # Check if PyAMG is available
            try:
                import pyamg
            except Exception:
                raise ModuleNotFoundError('PyAMG is not installed.')
            ml = pyamg.ruge_stuben_solver(A)
            x = ml.solve(b=b, tol=rtol, maxiter=max_it)

        return x
"""
Test the convergence of a 100x100 anisotropic diffusion equation
"""
import numpy as np
import pyamg

n = 100
nx = n
ny = n

# Rotated Anisotropic Diffusion
stencil = pyamg.gallery.diffusion_stencil_2d(
    type='FE', epsilon=0.001, theta=np.pi / 3)

A = pyamg.gallery.stencil_grid(stencil, (nx, ny), format='csr')
S = pyamg.strength.classical_strength_of_connection(A, 0.0)

np.random.seed(625)
x = np.random.rand(A.shape[0])
b = A * np.random.rand(A.shape[0])

ml = pyamg.ruge_stuben_solver(A, max_coarse=10)

resvec = []
x = ml.solve(b, x0=x, maxiter=20, tol=1e-14, residuals=resvec)

for i, r in enumerate(resvec):
    print("residual at iteration {0:2}: {1:^6.2e}".format(i, r))
Beispiel #42
0
    def _solve(self, A=None, b=None):
        r"""
        Sends the A and b matrices to the specified solver, and solves for *x*
        given the boundary conditions, and source terms based on the present
        value of *x*.  This method does NOT iterate to solve for non-linear
        source terms or march time steps.

        Parameters
        ----------
        A : sparse matrix
            The coefficient matrix in sparse format. If not specified, then
            it uses  the ``A`` matrix attached to the object.

        b : ND-array
            The RHS matrix in any format.  If not specified, then it uses
            the ``b`` matrix attached to the object.

        Notes
        -----
        The solver used here is specified in the ``settings`` attribute of the
        algorithm.

        """
        # Fetch A and b from self if not given, and throw error if they've not
        # been calculated
        if A is None:
            A = self.A
            if A is None:
                raise Exception('The A matrix has not been built yet')
        if b is None:
            b = self.b
            if b is None:
                raise Exception('The b matrix has not been built yet')
        A = A.tocsr()

        # Default behavior -> use Scipy's default solver (spsolve)
        if self.settings['solver'] == 'pyamg':
            self.settings['solver_family'] = 'pyamg'
        if self.settings['solver'] == 'petsc':
            self.settings['solver_family'] = 'petsc'

        # Set tolerance for iterative solvers
        rtol = self.settings['solver_rtol']
        # Reference for residual's normalization
        ref = np.sum(np.absolute(self.A.diagonal())) or 1
        atol = ref * rtol

        # SciPy
        if self.settings['solver_family'] == 'scipy':
            if importlib.util.find_spec('scikit-umfpack'):
                A.indices = A.indices.astype(np.int64)
                A.indptr = A.indptr.astype(np.int64)
            iterative = ['bicg', 'bicgstab', 'cg', 'cgs', 'gmres', 'lgmres',
                         'minres', 'gcrotmk', 'qmr']
            solver = getattr(sprs.linalg, self.settings['solver_type'])
            if self.settings['solver_type'] in iterative:
                x, exit_code = solver(A=A, b=b, atol=atol, tol=rtol,
                                      maxiter=self.settings['solver_maxiter'])
                if exit_code > 0:
                    raise Exception('SciPy solver did not converge! '
                                    + 'Exit code: ' + str(exit_code))
            else:
                x = solver(A=A, b=b)
            return x

        # PETSc
        if self.settings['solver_family'] == 'petsc':
            # Check if petsc is available
            if importlib.util.find_spec('petsc4py'):
                from openpnm.utils.petsc import PETScSparseLinearSolver as SLS
            else:
                raise Exception('PETSc is not installed.')
            # Define the petsc linear system converting the scipy objects
            ls = SLS(A=A, b=b)
            sets = self.settings
            sets = {k: v for k, v in sets.items() if k.startswith('solver_')}
            sets = {k.split('solver_')[1]: v for k, v in sets.items()}
            ls.settings.update(sets)
            x = SLS.solve(ls)
            del(ls)
            return x

        # PyAMG
        if self.settings['solver_family'] == 'pyamg':
            if importlib.util.find_spec('pyamg'):
                import pyamg
            else:
                raise Exception('pyamg is not installed.')
            ml = pyamg.ruge_stuben_solver(A)
            x = ml.solve(b=b, tol=1e-10)
            return x
Beispiel #43
0
def _apply_inverse(matrix, V, options=None):
    """Solve linear equation system.

    Applies the inverse of `matrix` to the row vectors in `V`.

    See :func:`dense_options` for documentation of all possible options for
    sparse matrices.

    See :func:`sparse_options` for documentation of all possible options for
    sparse matrices.

    This method is called by :meth:`pymor.core.NumpyMatrixOperator.apply_inverse`
    and usually should not be used directly.

    Parameters
    ----------
    matrix
        The |NumPy| matrix to invert.
    V
        2-dimensional |NumPy array| containing as row vectors
        the right-hand sides of the linear equation systems to
        solve.
    options
        The solver options to use. (See :func:`_options`.)

    Returns
    -------
    |NumPy array| of the solution vectors.
    """

    default_options = _options(matrix)

    if options is None:
        options = default_options.values()[0]
    elif isinstance(options, str):
        if options == 'least_squares':
            for k, v in default_options.iteritems():
                if k.startswith('least_squares'):
                    options = v
                    break
            assert not isinstance(options, str)
        else:
            options = default_options[options]
    else:
        assert 'type' in options and options['type'] in default_options \
            and options.viewkeys() <= default_options[options['type']].viewkeys()
        user_options = options
        options = default_options[user_options['type']]
        options.update(user_options)

    promoted_type = np.promote_types(matrix.dtype, V.dtype)
    R = np.empty((len(V), matrix.shape[1]), dtype=promoted_type)

    if options['type'] == 'solve':
        for i, VV in enumerate(V):
            try:
                R[i] = np.linalg.solve(matrix, VV)
            except np.linalg.LinAlgError as e:
                raise InversionError('{}: {}'.format(str(type(e)), str(e)))
    elif options['type'] == 'least_squares_lstsq':
        for i, VV in enumerate(V):
            try:
                R[i], _, _, _ = np.linalg.lstsq(matrix, VV, rcond=options['rcond'])
            except np.linalg.LinAlgError as e:
                raise InversionError('{}: {}'.format(str(type(e)), str(e)))
    elif options['type'] == 'bicgstab':
        for i, VV in enumerate(V):
            R[i], info = bicgstab(matrix, VV, tol=options['tol'], maxiter=options['maxiter'])
            if info != 0:
                if info > 0:
                    raise InversionError('bicgstab failed to converge after {} iterations'.format(info))
                else:
                    raise InversionError('bicgstab failed with error code {} (illegal input or breakdown)'.
                                         format(info))
    elif options['type'] == 'bicgstab_spilu':
        ilu = spilu(matrix, drop_tol=options['spilu_drop_tol'], fill_factor=options['spilu_fill_factor'],
                    drop_rule=options['spilu_drop_rule'], permc_spec=options['spilu_permc_spec'])
        precond = LinearOperator(matrix.shape, ilu.solve)
        for i, VV in enumerate(V):
            R[i], info = bicgstab(matrix, VV, tol=options['tol'], maxiter=options['maxiter'], M=precond)
            if info != 0:
                if info > 0:
                    raise InversionError('bicgstab failed to converge after {} iterations'.format(info))
                else:
                    raise InversionError('bicgstab failed with error code {} (illegal input or breakdown)'.
                                         format(info))
    elif options['type'] == 'spsolve':
        try:
            # maybe remove unusable factorization:
            if hasattr(matrix, 'factorization'):
                fdtype = matrix.factorizationdtype
                if not np.can_cast(V.dtype, fdtype, casting='safe'):
                    del matrix.factorization

            if map(int, scipy.version.version.split('.')) >= [0, 14, 0]:
                if hasattr(matrix, 'factorization'):
                    # we may use a complex factorization of a real matrix to
                    # apply it to a real vector. In that case, we downcast
                    # the result here, removing the imaginary part,
                    # which should be zero.
                    R = matrix.factorization.solve(V.T).T.astype(promoted_type, copy=False)
                elif options['keep_factorization']:
                    # the matrix is always converted to the promoted type.
                    # if matrix.dtype == promoted_type, this is a no_op
                    matrix.factorization = splu(matrix_astype_nocopy(matrix, promoted_type), permc_spec=options['permc_spec'])
                    matrix.factorizationdtype = promoted_type
                    R = matrix.factorization.solve(V.T).T
                else:
                    # the matrix is always converted to the promoted type.
                    # if matrix.dtype == promoted_type, this is a no_op
                    R = spsolve(matrix_astype_nocopy(matrix, promoted_type), V.T, permc_spec=options['permc_spec']).T
            else:
                # see if-part for documentation
                if hasattr(matrix, 'factorization'):
                    for i, VV in enumerate(V):
                        R[i] = matrix.factorization.solve(VV).astype(promoted_type, copy=False)
                elif options['keep_factorization']:
                    matrix.factorization = splu(matrix_astype_nocopy(matrix, promoted_type), permc_spec=options['permc_spec'])
                    matrix.factorizationdtype = promoted_type
                    for i, VV in enumerate(V):
                        R[i] = matrix.factorization.solve(VV)
                elif len(V) > 1:
                    factorization = splu(matrix_astype_nocopy(matrix, promoted_type), permc_spec=options['permc_spec'])
                    for i, VV in enumerate(V):
                        R[i] = factorization.solve(VV)
                else:
                    R = spsolve(matrix_astype_nocopy(matrix, promoted_type), V.T, permc_spec=options['permc_spec']).reshape((1, -1))
        except RuntimeError as e:
            raise InversionError(e)
    elif options['type'] == 'lgmres':
        for i, VV in enumerate(V):
            R[i], info = lgmres(matrix, VV.copy(i),
                                tol=options['tol'],
                                maxiter=options['maxiter'],
                                inner_m=options['inner_m'],
                                outer_k=options['outer_k'])
            if info > 0:
                raise InversionError('lgmres failed to converge after {} iterations'.format(info))
            assert info == 0
    elif options['type'] == 'least_squares_lsmr':
        for i, VV in enumerate(V):
            R[i], info, itn, _, _, _, _, _ = lsmr(matrix, VV.copy(i),
                                                  damp=options['damp'],
                                                  atol=options['atol'],
                                                  btol=options['btol'],
                                                  conlim=options['conlim'],
                                                  maxiter=options['maxiter'],
                                                  show=options['show'])
            assert 0 <= info <= 7
            if info == 7:
                raise InversionError('lsmr failed to converge after {} iterations'.format(itn))
    elif options['type'] == 'least_squares_lsqr':
        for i, VV in enumerate(V):
            R[i], info, itn, _, _, _, _, _, _, _ = lsqr(matrix, VV.copy(i),
                                                        damp=options['damp'],
                                                        atol=options['atol'],
                                                        btol=options['btol'],
                                                        conlim=options['conlim'],
                                                        iter_lim=options['iter_lim'],
                                                        show=options['show'])
            assert 0 <= info <= 7
            if info == 7:
                raise InversionError('lsmr failed to converge after {} iterations'.format(itn))
    elif options['type'] == 'pyamg':
        if len(V) > 0:
            V_iter = iter(enumerate(V))
            R[0], ml = pyamg.solve(matrix, next(V_iter)[1],
                                   tol=options['tol'],
                                   maxiter=options['maxiter'],
                                   return_solver=True)
            for i, VV in V_iter:
                R[i] = pyamg.solve(matrix, VV,
                                   tol=options['tol'],
                                   maxiter=options['maxiter'],
                                   existing_solver=ml)
    elif options['type'] == 'pyamg-rs':
        ml = pyamg.ruge_stuben_solver(matrix,
                                      strength=options['strength'],
                                      CF=options['CF'],
                                      presmoother=options['presmoother'],
                                      postsmoother=options['postsmoother'],
                                      max_levels=options['max_levels'],
                                      max_coarse=options['max_coarse'],
                                      coarse_solver=options['coarse_solver'])
        for i, VV in enumerate(V):
            R[i] = ml.solve(VV,
                            tol=options['tol'],
                            maxiter=options['maxiter'],
                            cycle=options['cycle'],
                            accel=options['accel'])
    elif options['type'] == 'pyamg-sa':
        ml = pyamg.smoothed_aggregation_solver(matrix,
                                               symmetry=options['symmetry'],
                                               strength=options['strength'],
                                               aggregate=options['aggregate'],
                                               smooth=options['smooth'],
                                               presmoother=options['presmoother'],
                                               postsmoother=options['postsmoother'],
                                               improve_candidates=options['improve_candidates'],
                                               max_levels=options['max_levels'],
                                               max_coarse=options['max_coarse'],
                                               diagonal_dominance=options['diagonal_dominance'])
        for i, VV in enumerate(V):
            R[i] = ml.solve(VV,
                            tol=options['tol'],
                            maxiter=options['maxiter'],
                            cycle=options['cycle'],
                            accel=options['accel'])
    elif options['type'].startswith('generic') or options['type'].startswith('least_squares_generic'):
        logger = getLogger('pymor.operators.numpy._apply_inverse')
        logger.warn('You have selected a (potentially slow) generic solver for a NumPy matrix operator!')
        from pymor.operators.numpy import NumpyMatrixOperator
        from pymor.vectorarrays.numpy import NumpyVectorArray
        return genericsolvers.apply_inverse(NumpyMatrixOperator(matrix),
                                            NumpyVectorArray(V, copy=False),
                                            options=options).data
    else:
        raise ValueError('Unknown solver type')
    return R
def testgrid(parameters):
    exec ','.join(parameters) + ', = parameters.values()' # unpack the parameters into the local namespace
    description = '-' + description
    dt = 24.0*7 #hours per time step
    Nsteps = 1 #number of steps
    Nx = problemscale #number of cells, x-dimension
    Ny = problemscale
    Nz = problemscale
    ndims = 3
    N = Nx*Ny*Nz #number of cells, total
    size=N

    if verbose:
        print "N is %i." % N
    #h in feet
    hx=16.0 #length, x-dimension
    hy=16.0
    hz=10.0
    #perm in md, conversion factor for hours
    Perm =ones([3,Nz,Ny,Nx]).astype(np.float64)*100.0*.0002637 #mD is millidarcy=m^2/1000 #permeability
    Kinv = 1.0/Perm
    phi = .20 #unitless #porosity
    ct = 10.0E-06 #1/psi #conductivity?
    #B=1.0
    alpha = hx*hy*hz*phi*ct/dt #ft^3/hours/psi #???
    gamma = .433 #psi/ft #specific weight
    Phi =ones([Nz,Ny,Nx]).astype(np.float64)*2500.0 #Flow Potential
    Z=zeros([Nz,Ny,Nx]).astype(np.float64)
    for k in range(Nz):
        Z[k,:,:]+=k*hz # 3D field of all 0's in the bottom slice (z=0), adding 10 for each slice up (all 10s in slice where z=1, all 20s in slice where z=2, etc.)
    p = Phi-gamma*Z #potential
    Phi = Phi.flatten() #Phi is now just a row vector of 2500.0's, either Nx or Ny long. Really? Not Nx*Ny*Nz?
                        # We're switching from using a 3-tuple as an index to each cell to having a scalar between 0 and (N-1) as an index to each cell.

    TX = zeros([Nz,Ny,Nx+1]).astype(np.float64)#zeros([Nx+1,Ny,Nz])  #a 3D scalar field: x-components of transmissibility vectors
    TY = zeros([Nz,Ny+1,Nx]).astype(np.float64)#zeros([Nx,Ny+1,Nz])
    TZ = zeros([Nz+1,Ny,Nx]).astype(np.float64)#zeros([Nx,Ny,Nz+1])
                                                                    # (for Nx=3,Ny=4,Nz=5):
    TX[:,:,1:-1] = (2*hy*hz/hx)/(Kinv[0,:,:,0:-1]+Kinv[0,:,:,1: ])  # 2x4x5
    TY[:,1:-1,:] = (2*hx*hz/hy)/(Kinv [1,:,0:-1,:]+Kinv[1,:,1:,:])  # 3x3x5 Why are these not all 3x4x5?
    TZ[1:-1,:,:] = (2*hx*hy/hz)/(Kinv[2,0:-1,:,:]+Kinv[2,1:,:,:])   # 3x4x4

    x1 = TX[:,:,0:Nx].flatten()
    x2 = TX[:,:,1:].flatten()
    y1 = TY[:,0:Ny,:].flatten()
    y2 = TY[:,1:,:].flatten()
    z1 = TZ[0:Nz,:,:].flatten()
    z2 = TZ[1:,:,:].flatten()

    q = zeros([Nz,Ny,Nx]).astype(np.float64)
    q[:,4,4]=10.0*5.61/24.0
    Iw = (Nx*Ny-1)/2
    q = q.flatten()

    main_diag=x1+x2+y1+y2+z1+z2#+q2 #(when q2==1, sum is zero and vice versa)
    #DiagVecs = vstack((-z2,-y2,-x2,main_diag,-x1,-y1,-z1))
    DiagVecs  = vstack((-z2,-y2,-x2,          -x1,-y1,-z1))
    #DiagIndx = array([-Nx*Ny,-Nx,-1,0,1,Nx,Nx*Ny])
    DiagIndx  = array([-Nx*Ny,-Nx,-1,1,  Nx,Nx*Ny])
    Phi_w = zeros(Nsteps+1).astype(np.float64)
    Phi_w[0] = Phi[Iw]
    Phi_c = zeros(Nsteps+1).astype(np.float64)
    Phi_c[0] = Phi[-1]

    Phi_cl = zeros(Nsteps+1).astype(np.float64)
    Phi_cl[0] = Phi[0]

    level=0
    #whoami()
    #global N
    #global ndims
    A = sparse.spdiags(DiagVecs,DiagIndx,N/(2**ndims)**level,N/(2**ndims)**level,format='csr')

    DM =  sparse.spdiags(main_diag,array([0]),N/(2**ndims)**level,N/(2**ndims)**level,format='csr')

    D0 =  sparse.spdiags(ones(N/(2**ndims)**level)*alpha,array([0]),N/(2**ndims)**level,N/(2**ndims)**level,format='csr')

    A = sparse.spdiags(DiagVecs,DiagIndx,N/(2**ndims)**level,N/(2**ndims)**level,format='csr')
    DM =  sparse.spdiags(main_diag,array([0]),N/(2**ndims)**level,N/(2**ndims)**level,format='csr')
    D0 =  sparse.spdiags(ones(N/(2**ndims)**level)*alpha,array([0]),N/(2**ndims)**level,N/(2**ndims)**level,format='csr')
    LHS = (A+D0+DM).toarray().astype(np.float64)
    if verbose:
        print 'LHS shape is:'
        print LHS.shape


    # Main Timestep Loop
    info_dict = {'test_grid':True}
    for k in range(Nsteps):
        Qa = (-A.astype(np.float64)*Phi.astype(np.float64)).astype(np.float64)
        Qa-= DM*Phi

        if verbose: print 'solving with %s...' % solver
        ##CHOOSE THY SOLVER:
        if solver == 'pyamg':                                           ##PyAMG: Ruge-Steuben
            #make_sparsity_graph('graphs/pyamg_LHS.png','pyamg LHS',A+D0+DM)
            ml = pyamg.ruge_stuben_solver(A+D0+DM,max_levels=gridlevels,presmoother=('gauss_seidel',{'iterations':iterations}))
            u = ml.solve(q+Qa,cycle='F',tol=1e-06, accel='cg')
            info_dict['solverstring']='PyAMG-%icells' % N
            info_dict['cycle']=0
            info_dict['norm']=np.linalg.norm(q+Qa-np.dot(LHS,u))
        if solver == 'pyamg-linagg':                                           ##PyAMG; linear aggregation:
            #make_sparsity_graph('graphs/pyamg_LHS.png','pyamg LHS',A+D0+DM)
            ml=pyamg.smoothed_aggregation_solver(A+D0+DM)#,mat_flag= 'symmetric',strength= 'symmetric')
            u = ml.solve(q+Qa,cycle='F',tol=1e-06, accel='cg')
            info_dict['solverstring']='PyAMG-%icells' % N
            info_dict['cycle']=0
            info_dict['norm']=np.linalg.norm(q+Qa-np.dot(LHS,u))
        elif solver == 'mmg':                                           ##Our Multi-Multi-Grid
            #parameters['verbose']=False #uncomment to disable verbosity within the OpenMG code.
            if graph_pressure: parameters['cycles']=1
            (u,info_dict) = mg_solve(LHS,q+Qa,parameters) # info_dict here contains both cycle and norm

            if graph_pressure: parameters['cycles']=2
            if graph_pressure: (utwo,info_dict) = mg_solve(LHS,q+Qa,parameters) # info_dict here contains both cycle and norm
            if graph_pressure: parameters['cycles']=3
            if graph_pressure: (uthree,info_dict) = mg_solve(LHS,q+Qa,parameters) # info_dict here contains both cycle and norm

            info_dict['solverstring'] = '%igrid-%iiter-%icells%sthreshold-%icycles' % (gridlevels,iterations,N,threshold,cycles)
        elif solver == 'gs':                                            ##Our Gauss-Seidel iterative solver
            (u,gs_iterations) =   iterative_solve_to_threshold(LHS, q+Qa, np.zeros((q.size,)), threshold,verbose=verbose)
            info_dict['solverstring']='GaussSeidel-%iiter-%icells' % (gs_iterations,N)
            info_dict['cycle']=0
            info_dict['norm']=np.linalg.norm(q+Qa-np.dot(LHS,u))
        elif solver == 'gs_xiter':                                            ##Our Gauss-Seidel iterative solver, with a specified number of iterations
            #def iterative_solve(A,b,x,iterations,verbose=False):
            u =   iterative_solve(LHS, q+Qa, np.zeros((q.size,)), iterations,verbose)
            info_dict={}
            gs_iterations = iterations
            info_dict['solverstring']='GaussSeidel-%iiter-%icells' % (gs_iterations,N)
            info_dict['cycle']=0
            info_dict['norm']=np.linalg.norm(q+Qa-np.dot(LHS,u))
        else:                                                           ##Numpy's (pretty good) direct solver.
            solver = 'direct'
            u = np.linalg.solve(LHS,q+Qa)
            info_dict['solverstring']= 'direct-%icells' % N
            info_dict['cycle']=0
            info_dict['norm']=np.linalg.norm(q+Qa-np.dot(LHS,u))
        if graph_pressure: oldPhi = Phi.copy()
        Phi += u
        Phi_w[k+1]=Phi[Iw]
        Phi_cl[k+1]=Phi[0]
        Phi_c[k+1]=Phi[-1]
        info_dict['solverstring'] += description
        if graph_pressure:
            u_correct = np.linalg.solve(LHS,q+Qa)
            Phi_correct = oldPhi + u_correct
            Phi_graph_correct = reshape(Phi_correct,[Nz,Ny,Nx])

            Phi_two = oldPhi + utwo
            Phi_two_graph=reshape(Phi_two,[Nz,Ny,Nx])
            Phi_three = oldPhi + uthree
            Phi_three_graph=reshape(Phi_three,[Nz,Ny,Nx])

            Phi_graph=reshape(Phi,[Nz,Ny,Nx])
            filename='graphs/USS_output-%s.png' % (info_dict['solverstring'],)
            import visualization as viz
            viz.make_multiple_3d_graphs([Phi_graph_correct.T,Phi_graph.T,Phi_two_graph.T,Phi_three_graph.T],filename)
            del [Phi,Phi_c,Phi_cl,Phi_graph,Phi_w,u,Qa,DM,D0,LHS,A]
        else:
            del [Phi,Phi_c,Phi_cl,Phi_w,u,Qa,DM,D0,LHS,A]
        if verbose: print "completed solverstring is", info_dict['solverstring']
    return info_dict
def test_block_diagonalize_P():
    """Check if eigenvalues of block matrices are the same as eigenvalues of original block-circulant matrix"""
    init_octave(1)

    num_unknowns_per_block = 64
    root_num_blocks = 3
    A, _ = generate_A_delaunay_block_periodic_lognormal(
        num_unknowns_per_block, root_num_blocks)
    # A = A + 0.1 * scipy.sparse.diags(np.ones(num_unknowns_per_block * root_num_blocks**2))

    orig_solver = pyamg.ruge_stuben_solver(A,
                                           max_levels=2,
                                           max_coarse=1,
                                           CF='CLJP',
                                           keep=True)
    orig_splitting = orig_solver.levels[0].splitting
    block_splitting = list(chunks(orig_splitting, num_unknowns_per_block))
    common_block_splitting = most_frequent_splitting(block_splitting)
    repeated_splitting = np.tile(common_block_splitting, root_num_blocks**2)

    # we recompute the Ruge-Stuben prolongation matrix with the modified splitting, and the original strength
    # matrix. We assume the strength matrix is block-circulant (because A is block-circulant)
    C = orig_solver.levels[0].C
    P = direct_interpolation(A, C, repeated_splitting)
    P = tf.convert_to_tensor(P.toarray(), dtype=tf.float64)

    P_blocks = block_diagonalize_P(P, root_num_blocks,
                                   repeated_splitting.nonzero())
    P_blocks = P_blocks.numpy()

    A_c = P.numpy().T @ A.toarray() @ P.numpy()
    # double_W, double_W_conj_t = create_double_W(num_unknowns_per_block * root_num_blocks, root_num_blocks)
    # A_c_full_block_diag = double_W_conj_t @ A_c_full @ double_W

    # P_full_block_diag = double_W_conj_t @ full_P @ double_W
    # A_block_diag = double_W_conj_t @ A.toarray() @ double_W
    # A_c_full_block_diag_2 = P_full_block_diag.conj().T @ A_block_diag @ P_full_block_diag

    tf_A = tf.cast(tf.stack([A.toarray()]), tf.complex128)
    A_blocks = block_diagonalize_A_fast(
        tf_A, root_num_blocks,
        True).numpy()[0][1:]  # ignore the first zero mode block

    def relaxation_matrices(As, w=0.8):
        I = np.eye(As[0].shape[0])
        res = [I - w * np.diag(1 / (np.diag(A))) @ A for A in As]

        # computes the iteration matrix of the relaxation, here Gauss-Seidel is used.
        # This function is called on each block seperately.
        # num_As = len(As)
        # grid_sizes = [A.shape[0] for A in As]
        # Bs = [A.copy() for A in As]
        # for B, grid_size in zip(Bs, grid_sizes):
        #     B[np.tril_indices(grid_size, 0)[0], np.tril_indices(grid_size, 0)[1]] = 0.  # B is the upper part of A
        # res = []
        # for i in tqdm(range(num_As)):  # range(A.shape[0] // batch_size):
        #     res.append(scipy.linalg.solve_triangular(a=As[i],
        #                                              b=-Bs[i],
        #                                              lower=True, unit_diagonal=False,
        #                                              overwrite_b=False, debug=None, check_finite=True).astype(
        #         np.float64))
        return res

    S = relaxation_matrices([A.toarray()])[0]
    S_blocks = relaxation_matrices(A_blocks)

    # A_c = P.numpy().T @ A.toarray() @ P.numpy()
    A_c_blocks = P_blocks.transpose([0, 2, 1]).conj() @ A_blocks @ P_blocks

    A = A.toarray()
    C = np.eye(A.shape[0]) - P.numpy() @ np.linalg.inv(A_c) @ P.numpy().T @ A
    M = S @ C @ S

    I = np.eye(A_blocks[0].shape[0])
    C_blocks = [
        I - P_block @ np.linalg.inv(A_c_block) @ P_block.conj().T @ A_block
        for (P_block, A_c_block,
             A_block) in zip(P_blocks, A_c_blocks, A_blocks)
    ]
    M_blocks = [
        S_block @ C_block @ S_block
        for (S_block, C_block) in zip(S_blocks, C_blocks)
    ]

    # # extract only elements that correspond to coarse nodes
    # A_c_blocks = A_c_blocks[:, common_block_splitting.nonzero()[0][:, None], common_block_splitting.nonzero()[0]]

    A_c_block_eigs = np.sort(np.linalg.eigvals(A_c_blocks).flatten())
    A_c_eigs = np.sort(np.linalg.eigvals(A_c))

    C_block_eigs = np.sort(np.linalg.eigvals(C_blocks).flatten())
    C_eigs = np.sort(np.linalg.eigvals(C))

    M_block_eigs = np.sort(np.linalg.eigvals(M_blocks).flatten())
    M_eigs = np.sort(np.linalg.eigvals(M))

    pass
Beispiel #46
0
# Illustrates the selection of Coarse-Fine (CF) 
# splittings in Classical AMG.

import numpy
from scipy.io import loadmat
from pyamg import ruge_stuben_solver
from pyamg.gallery import load_example

data = loadmat('square.mat') #load_example('airfoil')

A = data['A']                                # matrix
V = data['vertices'][:A.shape[0]]            # vertices of each variable
E = numpy.vstack((A.tocoo().row,A.tocoo().col)).T  # edges of the matrix graph

# Use Ruge-Stuben Splitting Algorithm (use 'keep' in order to retain the splitting)
mls = ruge_stuben_solver(A, max_levels=2, max_coarse=1, CF='RS',keep=True)
print mls

# The CF splitting, 1 == C-node and 0 == F-node
splitting = mls.levels[0].splitting
C_nodes = splitting == 1
F_nodes = splitting == 0

from draw import lineplot
from pylab import figure, axis, scatter, show

figure(figsize=(6,6))
axis('equal')
lineplot(V, E)
scatter(V[:,0][C_nodes], V[:,1][C_nodes], c='r', s=100.0)  #plot C-nodes in red
scatter(V[:,0][F_nodes], V[:,1][F_nodes], c='b', s=100.0)  #plot F-nodes in blue
Beispiel #47
0
def _apply_inverse(matrix, V, options=None):
    """Solve linear equation system.

    Applies the inverse of `matrix` to the row vectors in `V`.

    See :func:`dense_options` for documentation of all possible options for
    sparse matrices.

    See :func:`sparse_options` for documentation of all possible options for
    sparse matrices.

    This method is called by :meth:`pymor.core.NumpyMatrixOperator.apply_inverse`
    and usually should not be used directly.

    Parameters
    ----------
    matrix
        The |NumPy| matrix to invert.
    V
        2-dimensional |NumPy array| containing as row vectors
        the right-hand sides of the linear equation systems to
        solve.
    options
        The solver options to use. (See :func:`_options`.)

    Returns
    -------
    |NumPy array| of the solution vectors.
    """

    default_options = _options(matrix)

    if options is None:
        options = default_options.values()[0]
    elif isinstance(options, str):
        if options == "least_squares":
            for k, v in default_options.iteritems():
                if k.startswith("least_squares"):
                    options = v
                    break
            assert not isinstance(options, str)
        else:
            options = default_options[options]
    else:
        assert (
            "type" in options
            and options["type"] in default_options
            and options.viewkeys() <= default_options[options["type"]].viewkeys()
        )
        user_options = options
        options = default_options[user_options["type"]]
        options.update(user_options)

    R = np.empty((len(V), matrix.shape[1]), dtype=np.promote_types(matrix.dtype, V.dtype))

    if options["type"] == "solve":
        for i, VV in enumerate(V):
            try:
                R[i] = np.linalg.solve(matrix, VV)
            except np.linalg.LinAlgError as e:
                raise InversionError("{}: {}".format(str(type(e)), str(e)))
    elif options["type"] == "least_squares_lstsq":
        for i, VV in enumerate(V):
            try:
                R[i], _, _, _ = np.linalg.lstsq(matrix, VV, rcond=options["rcond"])
            except np.linalg.LinAlgError as e:
                raise InversionError("{}: {}".format(str(type(e)), str(e)))
    elif options["type"] == "bicgstab":
        for i, VV in enumerate(V):
            R[i], info = bicgstab(matrix, VV, tol=options["tol"], maxiter=options["maxiter"])
            if info != 0:
                if info > 0:
                    raise InversionError("bicgstab failed to converge after {} iterations".format(info))
                else:
                    raise InversionError("bicgstab failed with error code {} (illegal input or breakdown)".format(info))
    elif options["type"] == "bicgstab_spilu":
        ilu = spilu(
            matrix,
            drop_tol=options["spilu_drop_tol"],
            fill_factor=options["spilu_fill_factor"],
            drop_rule=options["spilu_drop_rule"],
            permc_spec=options["spilu_permc_spec"],
        )
        precond = LinearOperator(matrix.shape, ilu.solve)
        for i, VV in enumerate(V):
            R[i], info = bicgstab(matrix, VV, tol=options["tol"], maxiter=options["maxiter"], M=precond)
            if info != 0:
                if info > 0:
                    raise InversionError("bicgstab failed to converge after {} iterations".format(info))
                else:
                    raise InversionError("bicgstab failed with error code {} (illegal input or breakdown)".format(info))
    elif options["type"] == "spsolve":
        try:
            if scipy.version.version >= "0.14":
                if hasattr(matrix, "factorization"):
                    R = matrix.factorization.solve(V.T).T
                elif options["keep_factorization"]:
                    matrix.factorization = splu(matrix, permc_spec=options["permc_spec"])
                    R = matrix.factorization.solve(V.T).T
                else:
                    R = spsolve(matrix, V.T, permc_spec=options["permc_spec"]).T
            else:
                if hasattr(matrix, "factorization"):
                    for i, VV in enumerate(V):
                        R[i] = matrix.factorization.solve(VV)
                elif options["keep_factorization"]:
                    matrix.factorization = splu(matrix, permc_spec=options["permc_spec"])
                    for i, VV in enumerate(V):
                        R[i] = matrix.factorization.solve(VV)
                elif len(V) > 1:
                    factorization = splu(matrix, permc_spec=options["permc_spec"])
                    for i, VV in enumerate(V):
                        R[i] = factorization.solve(VV)
                else:
                    R = spsolve(matrix, V.T, permc_spec=options["permc_spec"]).reshape((1, -1))
        except RuntimeError as e:
            raise InversionError(e)
    elif options["type"] == "lgmres":
        for i, VV in enumerate(V):
            R[i], info = lgmres(
                matrix,
                VV.copy(i),
                tol=options["tol"],
                maxiter=options["maxiter"],
                inner_m=options["inner_m"],
                outer_k=options["outer_k"],
            )
            if info > 0:
                raise InversionError("lgmres failed to converge after {} iterations".format(info))
            assert info == 0
    elif options["type"] == "least_squares_lsmr":
        for i, VV in enumerate(V):
            R[i], info, itn, _, _, _, _, _ = lsmr(
                matrix,
                VV.copy(i),
                damp=options["damp"],
                atol=options["atol"],
                btol=options["btol"],
                conlim=options["conlim"],
                maxiter=options["maxiter"],
                show=options["show"],
            )
            assert 0 <= info <= 7
            if info == 7:
                raise InversionError("lsmr failed to converge after {} iterations".format(itn))
    elif options["type"] == "least_squares_lsqr":
        for i, VV in enumerate(V):
            R[i], info, itn, _, _, _, _, _, _, _ = lsqr(
                matrix,
                VV.copy(i),
                damp=options["damp"],
                atol=options["atol"],
                btol=options["btol"],
                conlim=options["conlim"],
                iter_lim=options["iter_lim"],
                show=options["show"],
            )
            assert 0 <= info <= 7
            if info == 7:
                raise InversionError("lsmr failed to converge after {} iterations".format(itn))
    elif options["type"] == "pyamg":
        if len(V) > 0:
            V_iter = iter(enumerate(V))
            R[0], ml = pyamg.solve(
                matrix, next(V_iter)[1], tol=options["tol"], maxiter=options["maxiter"], return_solver=True
            )
            for i, VV in V_iter:
                R[i] = pyamg.solve(matrix, VV, tol=options["tol"], maxiter=options["maxiter"], existing_solver=ml)
    elif options["type"] == "pyamg-rs":
        ml = pyamg.ruge_stuben_solver(
            matrix,
            strength=options["strength"],
            CF=options["CF"],
            presmoother=options["presmoother"],
            postsmoother=options["postsmoother"],
            max_levels=options["max_levels"],
            max_coarse=options["max_coarse"],
            coarse_solver=options["coarse_solver"],
        )
        for i, VV in enumerate(V):
            R[i] = ml.solve(
                VV, tol=options["tol"], maxiter=options["maxiter"], cycle=options["cycle"], accel=options["accel"]
            )
    elif options["type"] == "pyamg-sa":
        ml = pyamg.smoothed_aggregation_solver(
            matrix,
            symmetry=options["symmetry"],
            strength=options["strength"],
            aggregate=options["aggregate"],
            smooth=options["smooth"],
            presmoother=options["presmoother"],
            postsmoother=options["postsmoother"],
            improve_candidates=options["improve_candidates"],
            max_levels=options["max_levels"],
            max_coarse=options["max_coarse"],
            diagonal_dominance=options["diagonal_dominance"],
        )
        for i, VV in enumerate(V):
            R[i] = ml.solve(
                VV, tol=options["tol"], maxiter=options["maxiter"], cycle=options["cycle"], accel=options["accel"]
            )
    elif options["type"].startswith("generic") or options["type"].startswith("least_squares_generic"):
        logger = getLogger("pymor.operators.numpy._apply_inverse")
        logger.warn("You have selected a (potentially slow) generic solver for a NumPy matrix operator!")
        from pymor.operators.numpy import NumpyMatrixOperator
        from pymor.vectorarrays.numpy import NumpyVectorArray

        return genericsolvers.apply_inverse(
            NumpyMatrixOperator(matrix), NumpyVectorArray(V, copy=False), options=options
        ).data
    else:
        raise ValueError("Unknown solver type")
    return R
Beispiel #48
0
#         25, 25, 25
#         )
# mesh = pyfvm.meshTetra.meshTetra(vertices, cells)
# vertices, cells = meshzoo.rectangle.create_mesh(
#         0.0, 2.0,
#         0.0, 1.0,
#         401, 201,
#         zigzag=True
#         )
# mesh = pyfvm.meshTri.meshTri(vertices, cells)

import mshr
import dolfin
h = 2.5e-2
# cell_size = 2 * pi / num_boundary_points
c = mshr.Circle(dolfin.Point(0., 0., 0.), 1, int(2*pi / h))
# cell_size = 2 * bounding_box_radius / res
m = mshr.generate_mesh(c, 2.0 / h)
coords = m.coordinates()
coords = numpy.c_[coords, numpy.zeros(len(coords))]
mesh = pyfvm.meshTri.meshTri(coords, m.cells())

linear_system = pyfvm.discretize(Poisson(), mesh)

ml = pyamg.ruge_stuben_solver(linear_system.matrix)
x = ml.solve(linear_system.rhs, tol=1e-10)
# from scipy.sparse import linalg
# x = linalg.spsolve(linear_system.matrix, linear_system.rhs)

mesh.write('out.vtu', point_data={'x': x})
	def generateQTBNQ(self):
		self.QTBNQ = self.QT*self.BNQ
		idx = list(self.QTBNQ.indices).index(0)
		self.QTBNQ.data[idx] *=2.0
		self.ml = pyamg.ruge_stuben_solver(self.QTBNQ)