예제 #1
0
파일: cgs.py 프로젝트: cfd-hust/PyNS
def cgs(a, phi, b, tol, verbose=False, max_iter=-1):
    # -----------------------------------------------------------------------------
    """
    Args:
      a: ...... Object of the type "Matrix", holding the system matrix.
      phi: .... Object of the type "Unknown" to be solved.
      b: ...... Three-dimensional array holding the source term.
      tol: .... Absolute solver tolerance
      verbose:  Logical variable setting if solver will be verbose (print
                info on Python console) or not.
      max_iter: Maxiumum number of iterations.
      
    Returns:
      x: Three-dimensional array with solution.
    """

    if verbose is True:
        write.at(__name__)

    # Helping variable
    x = phi.val

    # Intitilize arrays
    p = zeros(x.shape)
    p_hat = Unknown("vec_p_hat",
                    phi.pos,
                    x.shape,
                    -1,
                    per=phi.per,
                    verbose=False)
    q = zeros(x.shape)
    r = zeros(x.shape)
    r_tilda = zeros(x.shape)
    u = zeros(x.shape)
    u_hat = Unknown("vec_u_hat",
                    phi.pos,
                    x.shape,
                    -1,
                    per=phi.per,
                    verbose=False)
    v_hat = zeros(x.shape)

    # r = b - A * x
    r[:, :, :] = b[:, :, :] - mat_vec_bnd(a, phi)

    # Chose r~
    r_tilda[:, :, :] = r[:, :, :]

    # ---------------
    # Iteration loop
    # ---------------
    if max_iter == -1:
        max_iter = prod(phi.val.shape)

    for i in range(1, max_iter):

        if verbose is True:
            print("  iteration: %3d:" % (i), end="")

        # rho = r~ * r
        rho = vec_vec(r_tilda, r)

        # If rho == 0 method fails
        if abs(rho) < TINY * TINY:
            if verbose is True == True:
                write.at(__name__)
                print("  Fails becuase rho = %12.5e" % rho)
            return x

        if i == 1:
            # u = r
            u[:, :, :] = r[:, :, :]

            # p = u
            p[:, :, :] = u[:, :, :]

        else:
            # beta = rho / rho_old
            beta = rho / rho_old

            # u = r + beta q
            u[:, :, :] = r[:, :, :] + beta * q[:, :, :]

            # p = u + beta (q + beta p)
            p[:, :, :] = u[:, :, :] + beta * (q[:, :, :] + beta * p[:, :, :])

        # Solve M p_hat = p
        p_hat.val[:, :, :] = p[:, :, :] / a.C[:, :, :]

        # v^ = A * p^
        v_hat[:, :, :] = mat_vec_bnd(a, p_hat)

        # alfa = rho / (r~ * v^)
        alfa = rho / vec_vec(r_tilda, v_hat)

        # q = u - alfa v^
        q[:, :, :] = u[:, :, :] - alfa * v_hat[:, :, :]

        # Solve M u^ = u + q
        u_hat.val[:, :, :] = (u[:, :, :] + q[:, :, :]) / a.C[:, :, :]

        # x = x + alfa u^
        x[:, :, :] += alfa * u_hat.val[:, :, :]

        # q^ = A u^
        q_hat = mat_vec_bnd(a, u_hat)

        # r = r - alfa q^
        r[:, :, :] -= alfa * q_hat[:, :, :]

        # Compute residual
        res = norm(r)

        if verbose is True:
            print("%12.5e" % res)

        # If tolerance has been reached, get out of here
        if res < tol:
            return x

        # Prepare for next iteration
        rho_old = rho

    return x  # end of function
예제 #2
0
파일: jacobi.py 프로젝트: cfd-hust/PyNS
def jacobi(a, phi, b, tol, verbose=False, max_iter=-1):
    # -----------------------------------------------------------------------------
    """
    Args:
      a: ...... Object of the type "Matrix", holding the system matrix.
      phi: .... Object of the type "Unknown" to be solved.
      b: ...... Three-dimensional array holding the source term.
      tol: .... Absolute solver tolerance
      verbose:  Logical variable setting if solver will be verbose (print
                info on Python console) or not.
      max_iter: Maxiumum number of iterations.

    Returns:
      phi.val: Three-dimensional array with solution.
    """

    if verbose is True:
        write.at(__name__)

    sum = zeros(phi.val.shape)
    r = zeros(phi.val.shape)

    if max_iter == -1:
        max_iter = prod(phi.val.shape)

    # Under-relaxation factor
    alfa = 0.9

    # Main iteration loop
    for iter in range(0, max_iter):

        if verbose is True:
            print("  iteration: %3d:" % (iter), end="")

        # Add source term
        sum[:] = b[:]

        # Add contribution from west and east
        sum[:1, :, :] += a.W[:1, :, :] * phi.bnd[W].val[:1, :, :]
        sum[-1:, :, :] += a.E[-1:, :, :] * phi.bnd[E].val[:1, :, :]

        # Add up west and east neighbors from the inside
        sum[1:, :, :] += a.W[1:, :, :] * phi.val[:-1, :, :]
        sum[:-1, :, :] += a.E[:-1, :, :] * phi.val[1:, :, :]

        # Add contribution from south and north
        sum[:, :1, :] += a.S[:, :1, :] * phi.bnd[S].val[:, :1, :]
        sum[:, -1:, :] += a.N[:, -1:, :] * phi.bnd[N].val[:, :1, :]

        # Add up south and north neighbors from the inside
        sum[:, 1:, :] += a.S[:, 1:, :] * phi.val[:, :-1, :]
        sum[:, :-1, :] += a.N[:, :-1, :] * phi.val[:, 1:, :]

        # Add contribution from bottom and top
        sum[:, :, :1] += a.B[:, :, :1] * phi.bnd[B].val[:, :, :1]
        sum[:, :, -1:] += a.T[:, :, -1:] * phi.bnd[T].val[:, :, :1]

        # Add up south and north neighbors from the inside
        sum[:, :, 1:] += a.B[:, :, 1:] * phi.val[:, :, :-1]
        sum[:, :, :-1] += a.T[:, :, :-1] * phi.val[:, :, 1:]

        phi.val[:,:,:] = (1.0 - alfa) * phi.val[:,:,:]   \
                       +        alfa  * sum[:,:,:] / a.C[:,:,:]
        phi.exchange()

        # r = b - A * x
        r[:, :, :] = b[:, :, :] - mat_vec_bnd(a, phi)

        # Compute residual
        res = norm(r)

        if verbose is True:
            print("%12.5e" % res)

        # If tolerance has been reached, get out of here
        if res < tol:
            return phi.val

    return phi.val  # end of function
예제 #3
0
파일: bicgstab.py 프로젝트: pya/PyNS
def bicgstab(a, phi, b, tol, ver):
# -----------------------------------------------------------------------------
    """
    Args:
      a:   System matrix in PyNS format (which ssentially means storing a
           bundle of non-zero diagonals in compas directions)
      phi: Unknown to be solved (from "create_unknown" function)
      b:   Three-dimensional matrix holding the source term.
      tol: Absolute solver tolerance
      ver: Logical variable setting if solver will be verbatim (print
           info on Python console) or not.

    Returns:
      x: Three-dimensional matrix with solution.

    Note:
      One should also consider implementing periodic boundary conditions
      in this version of the solver.
    """

    if ver:
        print("Solver: BiCGStab")

    # Helping variables
    x = phi.val
    n = prod(x.shape)

    # Intitilize arrays
    p       = zeros(x.shape)
    p_hat   = zeros(x.shape)
    r       = zeros(x.shape)
    r_tilda = zeros(x.shape)
    s       = zeros(x.shape)
    s_hat   = zeros(x.shape)
    v       = zeros(x.shape)

    # r = b - A * x
    r[:,:,:] = b[:,:,:] - mat_vec_bnd(a, phi)

    # Chose r~
    r_tilda[:,:,:] = r[:,:,:]

    # ---------------
    # Iteration loop
    # ---------------
    for i in range(1,n):

        if ver:
            print("  iteration: %3d:" % (i), end = "" )

        # rho = r~ * r
        rho = vec_vec(r_tilda, r)

        # If rho == 0 method fails
        if abs(rho) < TINY * TINY:
            print("bicgstab fails becuase rho = %12.5e" % rho)
            return x

        if i == 1:
            # p = r
            p[:,:,:] = r[:,:,:]

        else:
            # beta = (rho / rho_old)(alfa/omega)
            beta = rho / rho_old * alfa / omega

            # p = r + beta (p - omega v)
            p[:,:,:] = r[:,:,:] + beta * (p[:,:,:] - omega * v[:,:,:])

        # Solve M p_hat = p
        p_hat[:,:,:] = p[:,:,:] / a.P[:,:,:]

        # v = A * p^
        v[:,:,:] = mat_vec(a, p_hat)

        # alfa = rho / (r~ * v)
        alfa = rho / vec_vec(r_tilda, v)

        # s = r - alfa v
        s[:,:,:] = r[:,:,:] - alfa * v[:,:,:]

        # Check norm of s, if small enough set x = x + alfa p_hat and stop
        res = norm(s)
        if res < tol:
            if ver:
                print("%12.5e" %res)
            x[:,:,:] += alfa * p_hat[:,:,:]
            return x

        # Solve M s^ = s
        s_hat[:,:,:] = s[:,:,:] / a.P[:,:,:]

        # t = A s^
        t = mat_vec(a, s_hat)

        # omega = (t * s) / (t * t)
        omega = vec_vec(t, s) / vec_vec(t, t)

        # x = x + alfa p^ + omega * s^
        x[:,:,:] += alfa * p_hat[:,:,:] + omega * s_hat[:,:,:]

        # r = s - omega q^
        r[:,:,:] = s[:,:,:] - omega * t[:,:,:]

        # Compute residual
        res = norm(r)

        if ver:
            print("%12.5e" %res)

        # If tolerance has been reached, get out of here
        if res < tol:
            return x

        # Prepare for next iteration
        rho_old = rho

    return x  # end of function
예제 #4
0
def cgs(a, phi, b, tol, ver):
    # -----------------------------------------------------------------------------
    """
    Args:
      a:   System matrix in PyNS format (which ssentially means storing a
           bundle of non-zero diagonals in compas directions)
      phi: Unknown to be solved (from "create_unknown" function)
      b:   Three-dimensional matrix holding the source term.
      tol: Absolute solver tolerance
      ver: Logical variable setting if solver will be verbatim (print
           info on Python console) or not.

    Returns:
      x: Three-dimensional matrix with solution.

    Note:
      One should also consider implementing periodic boundary conditions
      in this version of the solver.
    """

    if ver:
        print("Solver: CGS")

    # Helping variables
    x = phi.val
    n = prod(x.shape)

    # Intitilize arrays
    p = zeros(x.shape)
    p_hat = zeros(x.shape)
    q = zeros(x.shape)
    r = zeros(x.shape)
    r_tilda = zeros(x.shape)
    u = zeros(x.shape)
    u_hat = zeros(x.shape)
    v_hat = zeros(x.shape)

    # r = b - A * x
    r[:, :, :] = b[:, :, :] - mat_vec_bnd(a, phi)

    # Chose r~
    r_tilda[:, :, :] = r[:, :, :]

    # ---------------
    # Iteration loop
    # ---------------
    for i in range(1, n):

        if ver:
            print("  iteration: %3d:" % (i), end="")

        # rho = r~ * r
        rho = vec_vec(r_tilda, r)

        # If rho == 0 method fails
        if abs(rho) < TINY * TINY:
            print("cgs fails becuase rho = %12.5e" % rho)
            return x

        if i == 1:
            # u = r
            u[:, :, :] = r[:, :, :]

            # p = u
            p[:, :, :] = u[:, :, :]

        else:
            # beta = rho / rho_old
            beta = rho / rho_old

            # u = r + beta q
            u[:, :, :] = r[:, :, :] + beta * q[:, :, :]

            # p = u + beta (q + beta p)
            p[:, :, :] = u[:, :, :] + beta * (q[:, :, :] + beta * p[:, :, :])

        # Solve M p_hat = p
        p_hat[:, :, :] = p[:, :, :] / a.P[:, :, :]

        # v^ = A * p^
        v_hat[:, :, :] = mat_vec(a, p_hat)

        # alfa = rho / (r~ * v^)
        alfa = rho / vec_vec(r_tilda, v_hat)

        # q = u - alfa v^
        q[:, :, :] = u[:, :, :] - alfa * v_hat[:, :, :]

        # Solve M u^ = u + q
        u_hat[:, :, :] = (u[:, :, :] + q[:, :, :]) / a.P[:, :, :]

        # x = x + alfa u^
        x[:, :, :] += alfa * u_hat[:, :, :]

        # q^ = A u^
        q_hat = mat_vec(a, u_hat)

        # r = r - alfa q^
        r[:, :, :] -= alfa * q_hat[:, :, :]

        # Compute residual
        res = norm(r)

        if ver:
            print("%12.5e" % res)

        # If tolerance has been reached, get out of here
        if res < tol:
            return x

        # Prepare for next iteration
        rho_old = rho

    return x  # end of function
예제 #5
0
파일: bicgstab.py 프로젝트: cfd-hust/PyNS
def bicgstab(a, phi, b, tol, verbose=False, max_iter=-1):
    # -----------------------------------------------------------------------------
    """
    Args:
      a: ...... Object of the type "Matrix", holding the system matrix.
      phi: .... Object of the type "Unknown" to be solved.
      b: ...... Three-dimensional array holding the source term.
      tol: .... Absolute solver tolerance
      verbose:  Logical variable setting if solver will be verbose (print
                info on Python console) or not.
      max_iter: Maxiumum number of iterations.

    Returns:
      x: Three-dimensional array with solution.
    """

    if verbose is True:
        write.at(__name__)

    # Helping variable
    x = phi.val

    # Intitilize arrays
    p = zeros(x.shape)
    p_hat = Unknown("vec_p_hat",
                    phi.pos,
                    x.shape,
                    -1,
                    per=phi.per,
                    verbose=False)
    r = zeros(x.shape)
    r_tilda = zeros(x.shape)
    s = zeros(x.shape)
    s_hat = Unknown("vec_s_hat",
                    phi.pos,
                    x.shape,
                    -1,
                    per=phi.per,
                    verbose=False)
    v = zeros(x.shape)

    # r = b - A * x
    r[:, :, :] = b[:, :, :] - mat_vec_bnd(a, phi)

    # Chose r~
    r_tilda[:, :, :] = r[:, :, :]

    # ---------------
    # Iteration loop
    # ---------------
    if max_iter == -1:
        max_iter = prod(phi.val.shape)

    for i in range(1, max_iter):

        if verbose is True:
            print("  iteration: %3d:" % (i), end="")

        # rho = r~ * r
        rho = vec_vec(r_tilda, r)

        # If rho == 0 method fails
        if abs(rho) < TINY * TINY:
            write.at(__name__)
            print("  Fails becuase rho = %12.5e" % rho)
            return x

        if i == 1:
            # p = r
            p[:, :, :] = r[:, :, :]

        else:
            # beta = (rho / rho_old)(alfa/omega)
            beta = rho / rho_old * alfa / omega

            # p = r + beta (p - omega v)
            p[:, :, :] = r[:, :, :] + beta * (p[:, :, :] - omega * v[:, :, :])

        # Solve M p_hat = p
        p_hat.val[:, :, :] = p[:, :, :] / a.C[:, :, :]

        # v = A * p^
        v[:, :, :] = mat_vec_bnd(a, p_hat)

        # alfa = rho / (r~ * v)
        alfa = rho / vec_vec(r_tilda, v)

        # s = r - alfa v
        s[:, :, :] = r[:, :, :] - alfa * v[:, :, :]

        # Check norm of s, if small enough set x = x + alfa p_hat and stop
        res = norm(s)
        if res < tol:
            if verbose is True == True:
                write.at(__name__)
                print("  Fails becuase rho = %12.5e" % rho)
            x[:, :, :] += alfa * p_hat.val[:, :, :]
            return x

        # Solve M s^ = s
        s_hat.val[:, :, :] = s[:, :, :] / a.C[:, :, :]

        # t = A s^
        t = mat_vec_bnd(a, s_hat)

        # omega = (t * s) / (t * t)
        omega = vec_vec(t, s) / vec_vec(t, t)

        # x = x + alfa p^ + omega * s^
        x[:, :, :] += alfa * p_hat.val[:, :, :] + omega * s_hat.val[:, :, :]

        # r = s - omega q^
        r[:, :, :] = s[:, :, :] - omega * t[:, :, :]

        # Compute residual
        res = norm(r)

        if verbose is True:
            print("%12.5e" % res)

        # If tolerance has been reached, get out of here
        if res < tol:
            return x

        # Prepare for next iteration
        rho_old = rho

    return x  # end of function
예제 #6
0
def cg(a, phi, b, tol, ver):
    # -----------------------------------------------------------------------------
    """
    Args:
      a:   System matrix in PyNS format (which ssentially means storing a
           bundle of non-zero diagonals in compas directions)
      phi: Unknown to be solved (from "create_unknown" function)
      b:   Three-dimensional matrix holding the source term.
      tol: Absolute solver tolerance
      ver: Logical variable setting if solver will be verbatim (print
           info on Python console) or not.

    Returns:
      x: Three-dimensional matrix with solution.

    Note:
      One should also consider implementing periodic boundary conditions
      in this version of the solver.
    """

    if ver:
        print("Solver: CG")

    # Helping variables
    x = phi.val
    n = prod(x.shape)

    # Intitilize arrays
    p = zeros(x.shape)
    q = zeros(x.shape)
    r = zeros(x.shape)
    z = zeros(x.shape)

    # r = b - A * x
    r[:, :, :] = b[:, :, :] - mat_vec_bnd(a, phi)

    # ---------------
    # Iteration loop
    # ---------------
    for i in range(1, n):

        if ver:
            print("  iteration: %3d:" % (i), end="")

        # Solve M z = r
        z[:, :, :] = r[:, :, :] / a.P[:, :, :]

        # rho = r * z
        rho = vec_vec(r, z)

        if i == 1:
            # p = z
            p[:, :, :] = z[:, :, :]

        else:
            # beta = rho / rho_old
            beta = rho / rho_old

            # p = z + beta p
            p[:, :, :] = z[:, :, :] + beta * p[:, :, :]

        # q = A * p
        q[:, :, :] = mat_vec(a, p)

        # alfa = rho / (p * q)
        alfa = rho / vec_vec(p, q)

        # x = x + alfa p
        x[:, :, :] += alfa * p[:, :, :]

        # r = r - alfa q
        r[:, :, :] -= alfa * q[:, :, :]

        # Compute residual
        res = norm(r)

        if ver:
            print("%12.5e" % res)

        # If tolerance has been reached, get out of here
        if res < tol:
            return x

        # Prepare for next iteration
        rho_old = rho

    return x  # end of function
예제 #7
0
def gamg_v_cycle(a, phi, b, tol, verbose=False, max_cycles=8, max_smooth=4):
    # -----------------------------------------------------------------------------
    """
    Args:
      a: ..... Object of the type "Matrix", holding the system matrix.
      phi: ... Object of the type "Unknown" to be solved.
      b: ..... Three-dimensional array holding the source term.
      tol: ... Absolute solver tolerance
      verbose: Logical variable setting if solver will be verbose (print
               info on Python console) or not.

    Returns:
      x: Three-dimensional array with solution.
    """

    if verbose is True:
        write.at(__name__)

    # ------------------
    #
    # Get system levels
    #
    # ------------------
    n_, shape_, a_, i_, d_, phi_, b_, r_ = gamg_coarsen_system(a, phi, b)

    # Set a couple of parameters for the solver
    n_steps = n_ - 1  # number of steps down the "V" cycle

    # -----------------------------------------------------
    #
    # Solve a bit on the finest level and compute residual
    #
    # -----------------------------------------------------
    grid = 0  # finest level
    phi_[grid].val = jacobi(a_[grid],
                            phi_[grid],
                            b_[grid],
                            TOL,
                            verbose=True,
                            max_iter=4)
    # r = b - A * x
    r_[grid].val[:] = b_[grid][:] - mat_vec_bnd(a_[grid], phi_[grid])
    if verbose is True:
        print("  residual at level %d" % grid, norm(r_[grid].val))

    # =========================================================================
    #
    # Start the V-cycle
    #
    # =========================================================================
    for cycle in range(0, max_cycles):

        if verbose is True:
            write.cycle(cycle)

        # --------------------
        #
        # Go down a few steps
        #
        # --------------------
        for level in range(1, n_steps + 1):
            grid = grid + 1

            # Compute ratio between grid levels
            rx = shape_[grid - 1][X] // shape_[grid][X]
            ry = shape_[grid - 1][Y] // shape_[grid][Y]
            rz = shape_[grid - 1][Z] // shape_[grid][Z]

            # Lower bounds for browsing through grid levels
            wl = 0
            el = 1
            sl = 0
            nl = 1
            bl = 0
            tl = 1

            if rx < 2:
                el = 0
            if ry < 2:
                nl = 0
            if rz < 2:
                tl = 0

            # -------------------------------------
            # Restrict
            #
            # Computes r.h.s. on the coarser level
            # from residual on the finer level.
            # -------------------------------------
            b_[grid][:] = r_[grid - 1].val[wl::rx, sl::ry, bl::rz]
            b_[grid][:] += r_[grid - 1].val[wl::rx, nl::ry, bl::rz]
            b_[grid][:] += r_[grid - 1].val[wl::rx, sl::ry, tl::rz]
            b_[grid][:] += r_[grid - 1].val[wl::rx, nl::ry, tl::rz]
            b_[grid][:] += r_[grid - 1].val[el::rx, sl::ry, bl::rz]
            b_[grid][:] += r_[grid - 1].val[el::rx, nl::ry, bl::rz]
            b_[grid][:] += r_[grid - 1].val[el::rx, sl::ry, tl::rz]
            b_[grid][:] += r_[grid - 1].val[el::rx, nl::ry, tl::rz]
            b_[grid][:] = b_[grid][:] / ((3 - rx) * (3 - ry) * (3 - rz))

            # ------------------------------------------------
            # Solve on the coarser level and compute residual
            # ------------------------------------------------
            phi_[grid].val[:] = 0  # nulify to forget previous corrections
            phi_[grid].val = jacobi(a_[grid],
                                    phi_[grid],
                                    b_[grid],
                                    TOL,
                                    verbose=False,
                                    max_iter=max_smooth)
            # r = b - A * x
            r_[grid].val[:] = b_[grid][:] - mat_vec_bnd(a_[grid], phi_[grid])
            if verbose is True:
                print("  residual at level %d" % grid, norm(r_[grid].val))

        # ==================================
        #
        # This is the bottom of the V-cycle
        #
        # ==================================

        # ------------------
        #
        # Go up a few steps
        #
        # ------------------
        for level in range(1, n_steps + 1):
            grid = grid - 1

            # Compute ratio between grid levels
            rx = shape_[grid][X] // shape_[grid + 1][X]
            ry = shape_[grid][Y] // shape_[grid + 1][Y]
            rz = shape_[grid][Z] // shape_[grid + 1][Z]

            # Lower bounds for browsing through grid levels
            wl = 0
            el = 1
            sl = 0
            nl = 1
            bl = 0
            tl = 1

            if rx < 2:
                el = 0
            if ry < 2:
                nl = 0
            if rz < 2:
                tl = 0

            # -------------------------------------------
            # Prolongation
            #
            # Interpolates the solution from the coarser
            # level as the correction to the current.
            # It also smoooths it out a little bit.
            # -------------------------------------------
            r_[grid].val[:] = 0

            # First copy in each available cell on fine level
            r_[grid].val[wl::rx, sl::ry, bl::rz] = phi_[grid + 1].val[:]

            # Then spread arond
            r_[grid].val[el::rx, sl::ry, bl::rz] = r_[grid].val[wl::rx, sl::ry,
                                                                bl::rz]
            r_[grid].val[wl::rx, nl::ry, bl::rz] = r_[grid].val[wl::rx, sl::ry,
                                                                bl::rz]
            r_[grid].val[el::rx, nl::ry, bl::rz] = r_[grid].val[wl::rx, sl::ry,
                                                                bl::rz]

            r_[grid].val[wl::rx, sl::ry, tl::rz] = r_[grid].val[wl::rx, sl::ry,
                                                                bl::rz]
            r_[grid].val[el::rx, sl::ry, tl::rz] = r_[grid].val[wl::rx, sl::ry,
                                                                bl::rz]
            r_[grid].val[wl::rx, nl::ry, tl::rz] = r_[grid].val[wl::rx, sl::ry,
                                                                bl::rz]
            r_[grid].val[el::rx, nl::ry, tl::rz] = r_[grid].val[wl::rx, sl::ry,
                                                                bl::rz]

            # Then smooth them out a little bit
            for smooth in range(0, max_smooth):
                r_[grid].exchange()
                summ = zeros((shape_[grid]))
                summ[:] += cat_x((r_[grid].bnd[W].val,
                                  r_[grid].val[:-1, :, :])) * a_[grid].W
                summ[:] += cat_x(
                    (r_[grid].val[1:, :, :], r_[grid].bnd[E].val)) * a_[grid].E
                summ[:] += cat_y((r_[grid].bnd[S].val,
                                  r_[grid].val[:, :-1, :])) * a_[grid].S
                summ[:] += cat_y(
                    (r_[grid].val[:, 1:, :], r_[grid].bnd[N].val)) * a_[grid].N
                summ[:] += cat_z((r_[grid].bnd[B].val,
                                  r_[grid].val[:, :, :-1])) * a_[grid].B
                summ[:] += cat_z(
                    (r_[grid].val[:, :, 1:], r_[grid].bnd[T].val)) * a_[grid].T
                r_[grid].val[:] = summ[:] / d_[grid][:]

            # -----------------------------------------------
            # Correction on the finer level, followed by a
            # bit of smoothing and computation of residuals.
            # -----------------------------------------------
            phi_[grid].val[:] += r_[grid].val[:]
            phi_[grid].val = jacobi(a_[grid],
                                    phi_[grid],
                                    b_[grid],
                                    TOL,
                                    verbose=False,
                                    max_iter=max_smooth)
            # r = b - A * x
            r_[grid].val[:] = b_[grid][:]  \
                                - mat_vec_bnd(a_[grid], phi_[grid])
            print("  residual at level %d" % grid, norm(r_[grid].val))

    return phi_[0].val  # end of function
예제 #8
0
def cg(a, phi, b, tol, verbose=False, max_iter=-1):
    # -----------------------------------------------------------------------------
    """
    Args:
      a: ...... Object of the type "Matrix", holding the system matrix.
      phi: .... Object of the type "Unknown" to be solved.
      b: ...... Three-dimensional array holding the source term.
      tol: .... Absolute solver tolerance
      verbose:  Logical variable setting if solver will be verbose (print
                info on Python console) or not.
      max_iter: Maxiumum number of iterations.

    Returns:
      x: Three-dimensional array with solution.
    """

    if verbose is True:
        write.at(__name__)

    # Helping variable
    x = phi.val

    # Intitilize arrays
    p = Unknown("vec_p", phi.pos, x.shape, -1, per=phi.per, verbose=False)
    q = zeros(x.shape)
    r = zeros(x.shape)
    z = zeros(x.shape)

    # r = b - A * x
    r[:, :, :] = b[:, :, :] - mat_vec_bnd(a, phi)

    # ---------------
    # Iteration loop
    # ---------------
    if max_iter == -1:
        max_iter = prod(phi.val.shape)

    for i in range(1, max_iter):

        if verbose is True:
            print("  iteration: %3d:" % (i), end="")

        # Solve M z = r
        z[:, :, :] = r[:, :, :] / a.C[:, :, :]

        # rho = r * z
        rho = vec_vec(r, z)

        if i == 1:
            # p = z
            p.val[:, :, :] = z[:, :, :]

        else:
            # beta = rho / rho_old
            beta = rho / rho_old

            # p = z + beta p
            p.val[:, :, :] = z[:, :, :] + beta * p.val[:, :, :]

        # q = A * p
        q[:, :, :] = mat_vec_bnd(a, p)

        # alfa = rho / (p * q)
        alfa = rho / vec_vec(p.val, q)

        # x = x + alfa p
        x[:, :, :] += alfa * p.val[:, :, :]

        # r = r - alfa q
        r[:, :, :] -= alfa * q[:, :, :]

        # Compute residual
        res = norm(r)

        if verbose is True:
            print("%12.5e" % res)

        # If tolerance has been reached, get out of here
        if res < tol:
            return x

        # Prepare for next iteration
        rho_old = rho

    return x  # end of function