Exemplo n.º 1
0
 def calcSolution(k):
     mat = Matrix(k + 1, k + 1, is_complex)
     for i in range(k + 1):
         mat[:, i] = H[i][:k + 1]
     rs = Vector(k + 1, is_complex)
     rs[:] = beta[:k + 1]
     y = mat.I * rs
     if xstart:
         x.data = xstart
     for i in range(k + 1):
         x.data += y[i] * Q[i]
Exemplo n.º 2
0
def PINVIT(mata,
           matm,
           pre,
           num=1,
           maxit=20,
           printrates=True,
           GramSchmidt=False):
    """preconditioned inverse iteration"""

    r = mata.CreateRowVector()

    uvecs = MultiVector(r, num)
    vecs = MultiVector(r, 2 * num)
    # hv = MultiVector(r, 2*num)

    for v in vecs[0:num]:
        v.SetRandom()
    uvecs[:] = pre * vecs[0:num]
    lams = Vector(num * [1])

    for i in range(maxit):
        vecs[0:num] = mata * uvecs - (matm * uvecs).Scale(lams)
        vecs[num:2 * num] = pre * vecs[0:num]
        vecs[0:num] = uvecs

        vecs.Orthogonalize()  # matm)

        # hv[:] = mata * vecs
        # asmall = InnerProduct (vecs, hv)
        # hv[:] = matm * vecs
        # msmall = InnerProduct (vecs, hv)
        asmall = InnerProduct(vecs, mata * vecs)
        msmall = InnerProduct(vecs, matm * vecs)

        ev, evec = scipy.linalg.eigh(a=asmall, b=msmall)
        lams = Vector(ev[0:num])
        if printrates:
            print(i, ":", list(lams))

        uvecs[:] = vecs * Matrix(evec[:, 0:num])
    return lams, uvecs
Exemplo n.º 3
0
 def calcSolution(k):
     # if callback_sol is set we need to recompute solution in every step
     if self.callback_sol is not None:
         sol.data = sol_start
     mat = Matrix(k + 1, k + 1, is_complex)
     for i in range(k + 1):
         mat[:, i] = H[i][:k + 1]
     rs = Vector(k + 1, is_complex)
     rs[:] = beta[:k + 1]
     y = mat.I * rs
     for i in range(k + 1):
         sol.data += y[i] * Q[i]
Exemplo n.º 4
0
 def arnoldi(A, Q, k):
     q = rhs.CreateVector()
     tmp.data = A * Q[k]
     q.data = pre * tmp
     h = Vector(m + 1, is_complex)
     h[:] = 0
     for i in range(k + 1):
         h[i] = innerproduct(Q[i], q)
         q.data += (-1) * h[i] * Q[i]
     h[k + 1] = norm(q)
     if abs(h[k + 1]) < 1e-12:
         return h, None
     q *= 1. / h[k + 1].real
     return h, q
Exemplo n.º 5
0
def Arnoldi(mat, tol=1e-10, maxiter=200):
    H = Matrix(maxiter, maxiter, complex=mat.is_complex)
    H[:, :] = 0
    v = mat.CreateVector(colvector=False)
    abv = MultiVector(v, 0)
    v.SetRandom()
    v /= Norm(v)

    for i in range(maxiter):
        abv.Append(v)
        v = (mat * v).Evaluate()
        for j in range(i + 1):
            H[j, i] = InnerProduct(v, abv[j])
            v -= H[j, i] * abv[j]
        if i + 1 < maxiter:
            H[i + 1, i] = Norm(v)
        v = 1 / Norm(v) * v

    lam, ev = scipy.linalg.eig(H)
    return Vector(lam), (abv * Matrix(ev)).Evaluate()
Exemplo n.º 6
0
    def _SolveImpl(self, rhs: BaseVector, sol: BaseVector):
        is_complex = rhs.is_complex
        A, pre, innerproduct, norm = self.mat, self.pre, self.innerproduct, self.norm
        n = len(rhs)
        m = self.maxiter
        sn = Vector(m, is_complex)
        cs = Vector(m, is_complex)
        sn[:] = 0
        cs[:] = 0
        if self.callback_sol is not None:
            sol_start = sol.CreateVector()
            sol_start.data = sol
        r = rhs.CreateVector()
        tmp = rhs.CreateVector()
        tmp.data = rhs - A * sol
        r.data = pre * tmp
        Q = []
        H = []
        Q.append(rhs.CreateVector())
        r_norm = norm(r)
        if self.CheckResidual(abs(r_norm)):
            return sol
        Q[0].data = 1. / r_norm * r
        beta = Vector(m + 1, is_complex)
        beta[:] = 0
        beta[0] = r_norm

        def arnoldi(A, Q, k):
            q = rhs.CreateVector()
            tmp.data = A * Q[k]
            q.data = pre * tmp
            h = Vector(m + 1, is_complex)
            h[:] = 0
            for i in range(k + 1):
                h[i] = innerproduct(Q[i], q)
                q.data += (-1) * h[i] * Q[i]
            h[k + 1] = norm(q)
            if abs(h[k + 1]) < 1e-12:
                return h, None
            q *= 1. / h[k + 1].real
            return h, q

        def givens_rotation(v1, v2):
            if v2 == 0:
                return 1, 0
            elif v1 == 0:
                return 0, v2 / abs(v2)
            else:
                t = sqrt((v1.conjugate() * v1 + v2.conjugate() * v2).real)
                cs = abs(v1) / t
                sn = v1 / abs(v1) * v2.conjugate() / t
                return cs, sn

        def apply_givens_rotation(h, cs, sn, k):
            for i in range(k):
                temp = cs[i] * h[i] + sn[i] * h[i + 1]
                h[i +
                  1] = -sn[i].conjugate() * h[i] + cs[i].conjugate() * h[i + 1]
                h[i] = temp
            cs[k], sn[k] = givens_rotation(h[k], h[k + 1])
            h[k] = cs[k] * h[k] + sn[k] * h[k + 1]
            h[k + 1] = 0

        def calcSolution(k):
            # if callback_sol is set we need to recompute solution in every step
            if self.callback_sol is not None:
                sol.data = sol_start
            mat = Matrix(k + 1, k + 1, is_complex)
            for i in range(k + 1):
                mat[:, i] = H[i][:k + 1]
            rs = Vector(k + 1, is_complex)
            rs[:] = beta[:k + 1]
            y = mat.I * rs
            for i in range(k + 1):
                sol.data += y[i] * Q[i]

        for k in range(m):
            h, q = arnoldi(A, Q, k)
            H.append(h)
            if q is None:
                break
            Q.append(q)
            apply_givens_rotation(h, cs, sn, k)
            beta[k + 1] = -sn[k].conjugate() * beta[k]
            beta[k] = cs[k] * beta[k]
            error = abs(beta[k + 1])
            if self.callback_sol is not None:
                calcSolution(k)
            if self.CheckResidual(error):
                break
            if self.restart is not None and (
                    k + 1 == self.restart
                    and not (self.restart == self.maxiter)):
                calcSolution(k)
                del Q
                restarted_solver = GMResSolver(mat=self.mat,
                                               pre=self.pre,
                                               tol=0,
                                               atol=self._final_residual,
                                               callback=self.callback,
                                               callback_sol=self.callback_sol,
                                               maxiter=self.maxiter,
                                               restart=self.restart,
                                               printrates=self.printrates)
                restarted_solver.iterations = self.iterations
                sol = restarted_solver.Solve(rhs=rhs,
                                             sol=sol,
                                             initialize=False)
                self.residuals += restarted_solver.residuals
                self.iterations = restarted_solver.iterations
                return sol
        calcSolution(k)
        return sol
Exemplo n.º 7
0
def GMRes(A,
          b,
          pre=None,
          freedofs=None,
          x=None,
          maxsteps=100,
          tol=1e-7,
          innerproduct=None,
          callback=None,
          restart=None,
          startiteration=0,
          printrates=True):
    """ Restarting preconditioned gmres solver for A*x=b. Minimizes the preconditioned
residuum pre*(b-A*x)

Parameters
----------

A : BaseMatrix
  The left hand side of the linear system.

b : BaseVector
  The right hand side of the linear system.

pre : BaseMatrix = None
  The preconditioner for the system. If no preconditioner is given, the freedofs
  of the system must be given.

freedofs : BitArray = None
  Freedofs to solve on, only necessary if no preconditioner is given.

x : BaseVector = None
  Startvector, if given it will be modified in the routine and returned. Will be created
  if not given.

maxsteps : int = 100
  Maximum iteration steps.

tol : float = 1e-7
  Tolerance to be computed to. Gmres breaks if norm(pre*(b-A*x)) < tol.

innerproduct : function = None
  Innerproduct to be used in iteration, all orthogonalizations/norms are computed with
  respect to that inner product.

callback : function = None
  If given, this function is called with the solution vector x in each step. Only for debugging
  purposes, since it requires the overhead of computing x in every step.

restart : int = None
  If given, gmres is restarted with the current solution x every 'restart' steps.

startiteration : int = 0
  Internal value to count total number of iterations in restarted setup, no user input required
  here.

printrates : bool = True
  Print norm of preconditioned residual in each step.
"""

    if not innerproduct:
        innerproduct = lambda x, y: y.InnerProduct(x, conjugate=True)
        norm = Norm
    else:
        norm = lambda x: sqrt(innerproduct(x, x).real)
    is_complex = b.is_complex
    if not pre:
        assert freedofs is not None
        pre = Projector(freedofs, True)
    n = len(b)
    m = maxsteps
    if not x:
        x = b.CreateVector()
        x[:] = 0

    if callback:
        xstart = x.CreateVector()
        xstart.data = x
    else:
        xstart = None
    sn = Vector(m, is_complex)
    cs = Vector(m, is_complex)
    sn[:] = 0
    cs[:] = 0

    r = b.CreateVector()
    tmp = b.CreateVector()
    tmp.data = b - A * x
    r.data = pre * tmp

    Q = []
    H = []
    Q.append(b.CreateVector())
    r_norm = norm(r)
    if abs(r_norm) < tol:
        return x
    Q[0].data = 1. / r_norm * r
    beta = Vector(m + 1, is_complex)
    beta[:] = 0
    beta[0] = r_norm

    def arnoldi(A, Q, k):
        q = b.CreateVector()
        tmp.data = A * Q[k]
        q.data = pre * tmp
        h = Vector(m + 1, is_complex)
        h[:] = 0
        for i in range(k + 1):
            h[i] = innerproduct(Q[i], q)
            q.data += (-1) * h[i] * Q[i]
        h[k + 1] = norm(q)
        if abs(h[k + 1]) < 1e-12:
            return h, None
        q *= 1. / h[k + 1].real
        return h, q

    def givens_rotation(v1, v2):
        if v2 == 0:
            return 1, 0
        elif v1 == 0:
            return 0, v2 / abs(v2)
        else:
            t = sqrt((v1.conjugate() * v1 + v2.conjugate() * v2).real)
            cs = abs(v1) / t
            sn = v1 / abs(v1) * v2.conjugate() / t
            return cs, sn

    def apply_givens_rotation(h, cs, sn, k):
        for i in range(k):
            temp = cs[i] * h[i] + sn[i] * h[i + 1]
            h[i + 1] = -sn[i].conjugate() * h[i] + cs[i].conjugate() * h[i + 1]
            h[i] = temp
        cs[k], sn[k] = givens_rotation(h[k], h[k + 1])
        h[k] = cs[k] * h[k] + sn[k] * h[k + 1]
        h[k + 1] = 0

    def calcSolution(k):
        mat = Matrix(k + 1, k + 1, is_complex)
        for i in range(k + 1):
            mat[:, i] = H[i][:k + 1]
        rs = Vector(k + 1, is_complex)
        rs[:] = beta[:k + 1]
        y = mat.I * rs
        if xstart:
            x.data = xstart
        for i in range(k + 1):
            x.data += y[i] * Q[i]

    for k in range(m):
        startiteration += 1
        h, q = arnoldi(A, Q, k)
        H.append(h)
        if q is None:
            break
        Q.append(q)
        apply_givens_rotation(h, cs, sn, k)
        beta[k + 1] = -sn[k].conjugate() * beta[k]
        beta[k] = cs[k] * beta[k]
        error = abs(beta[k + 1])
        if printrates:
            print("Step", startiteration, ", error = ", error)
        if callback:
            calcSolution(k)
            callback(x)
        if error < tol:
            break
        if restart and k + 1 == restart and not (restart == maxsteps):
            calcSolution(k)
            del Q
            return GMRes(A,
                         b,
                         freedofs=freedofs,
                         pre=pre,
                         x=x,
                         maxsteps=maxsteps - restart,
                         callback=callback,
                         tol=tol,
                         innerproduct=innerproduct,
                         restart=restart,
                         startiteration=startiteration,
                         printrates=printrates)
    calcSolution(k)
    return x