Ejemplo n.º 1
0
    def _SolveImpl(self, rhs: BaseVector, sol: BaseVector):
        d, w, s = [sol.CreateVector() for i in range(3)]
        conjugate = self.conjugate
        d.data = rhs - self.mat * sol
        w.data = self.pre * d
        s.data = w
        wdn = w.InnerProduct(d, conjugate=conjugate)
        if self.CheckResidual(sqrt(abs(wdn))):
            return

        while True:
            w.data = self.mat * s
            wd = wdn
            as_s = s.InnerProduct(w, conjugate=conjugate)
            if as_s == 0 or wd == 0: break
            alpha = wd / as_s
            sol.data += alpha * s
            d.data += (-alpha) * w

            w.data = self.pre * d

            wdn = w.InnerProduct(d, conjugate=conjugate)
            if self.CheckResidual(sqrt(abs(wdn))):
                return

            beta = wdn / wd
            s *= beta
            s.data += w
Ejemplo n.º 2
0
    def _SolveImpl(self, rhs: BaseVector, sol: BaseVector):
        r = rhs.CreateVector()
        d = sol.CreateVector()
        r.data = rhs - self.mat * sol
        d.data = self.pre * r
        res_norm = abs(InnerProduct(d, r))
        if self.CheckResidual(res_norm):
            return

        while True:
            sol.data += self.dampfactor * d
            r.data = rhs - self.mat * sol
            d.data = self.pre * r

            res_norm = abs(InnerProduct(d, r))
            if self.CheckResidual(res_norm):
                return
Ejemplo n.º 3
0
 def Solve(self,
           rhs: BaseVector,
           sol: Optional[BaseVector] = None,
           initialize: bool = True) -> BaseVector:
     old_status = _GetStatus()
     _PushStatus(self.name + " Solve")
     _SetThreadPercentage(0)
     if sol is None:
         sol = rhs.CreateVector()
         initialize = True
     if initialize:
         sol[:] = 0
     self.sol = sol
     self._SolveImpl(rhs=rhs, sol=sol)
     if old_status[0] != "idle":
         _PushStatus(old_status[0])
         _SetThreadPercentage(old_status[1])
     return sol
Ejemplo n.º 4
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
Ejemplo n.º 5
0
    def _SolveImpl(self, rhs: BaseVector, sol: BaseVector):
        pre, mat, u = self.pre, self.mat, sol
        v_new = rhs.CreateVector()
        v = rhs.CreateVector()
        v_old = rhs.CreateVector()
        w_new = rhs.CreateVector()
        w = rhs.CreateVector()
        w_old = rhs.CreateVector()
        z_new = rhs.CreateVector()
        z = rhs.CreateVector()
        mz = rhs.CreateVector()

        v.data = rhs - mat * u

        z.data = pre * v

        #First Step
        gamma = sqrt(InnerProduct(z, v))
        gamma_new = 0
        z.data = 1 / gamma * z
        v.data = 1 / gamma * v

        ResNorm = gamma
        ResNorm_old = gamma

        if self.CheckResidual(ResNorm):
            return

        eta_old = gamma
        c_old = 1
        c = 1
        s_new = 0
        s = 0
        s_old = 0

        v_old[:] = 0.0
        w_old[:] = 0.0
        w[:] = 0.0

        k = 1
        while True:
            mz.data = mat * z
            delta = InnerProduct(mz, z)
            v_new.data = mz - delta * v - gamma * v_old

            z_new.data = pre * v_new

            gamma_new = sqrt(InnerProduct(z_new, v_new))
            z_new *= 1 / gamma_new
            v_new *= 1 / gamma_new

            alpha0 = c * delta - c_old * s * gamma
            alpha1 = sqrt(alpha0 * alpha0 + gamma_new * gamma_new)  #**
            alpha2 = s * delta + c_old * c * gamma
            alpha3 = s_old * gamma

            c_new = alpha0 / alpha1
            s_new = gamma_new / alpha1

            w_new.data = z - alpha3 * w_old - alpha2 * w
            w_new.data = 1 / alpha1 * w_new

            u.data += c_new * eta_old * w_new
            eta = -s_new * eta_old

            #update of residuum
            ResNorm = abs(s_new) * ResNorm_old
            if self.CheckResidual(ResNorm):
                return
            k += 1

            # shift vectors by renaming
            v_old, v, v_new = v, v_new, v_old
            w_old, w, w_new = w, w_new, w_old
            z, z_new = z_new, z

            eta_old = eta

            s_old = s
            s = s_new

            c_old = c
            c = c_new

            gamma = gamma_new
            ResNorm_old = ResNorm
Ejemplo n.º 6
0
    def _SolveImpl(self, rhs: BaseVector, sol: BaseVector):
        u, mat, ep, pre1, pre2 = sol, self.mat, self.ep, self.pre, self.pre2
        r = rhs.CreateVector()
        v = rhs.CreateVector()
        v_tld = rhs.CreateVector()
        w = rhs.CreateVector()
        w_tld = rhs.CreateVector()
        y = rhs.CreateVector()
        y_tld = rhs.CreateVector()
        z = rhs.CreateVector()
        z_tld = rhs.CreateVector()
        p = rhs.CreateVector()
        p_tld = rhs.CreateVector()
        q = rhs.CreateVector()
        d = rhs.CreateVector()
        s = rhs.CreateVector()

        r.data = rhs - mat * u
        v_tld.data = r
        y.data = pre1 * v_tld

        rho = InnerProduct(y, y)
        rho = sqrt(rho)

        w_tld.data = r
        z.data = pre2.T * w_tld if pre2 else w_tld

        xi = InnerProduct(z, z)
        xi = sqrt(xi)

        gamma = 1.0
        eta = -1.0
        theta = 0.0

        for i in range(1, self.maxiter + 1):
            if (rho == 0.0):
                print('Breakdown in rho')
                return
            if (xi == 0.0):
                print('Breakdown in xi')
                return
            v.data = (1.0 / rho) * v_tld
            y.data = (1.0 / rho) * y

            w.data = (1.0 / xi) * w_tld
            z.data = (1.0 / xi) * z

            delta = InnerProduct(z, y)
            if (delta == 0.0):
                print('Breakdown in delta')
                return

            y_tld.data = pre2 * y if pre2 else y
            z_tld.data = pre1.T * z

            if (i > 1):
                p.data = (-xi * delta / ep) * p
                p.data += y_tld

                q.data = (-rho * delta / ep) * q
                q.data += z_tld
            else:
                p.data = y_tld
                q.data = z_tld

            p_tld.data = mat * p
            ep = InnerProduct(q, p_tld)
            if (ep == 0.0):
                print('Breakdown in epsilon')
                return

            beta = ep / delta
            if (beta == 0.0):
                print('Breakdown in beta')
                return

            v_tld.data = p_tld - beta * v

            y.data = pre1 * v_tld

            rho_1 = rho
            rho = InnerProduct(y, y)
            rho = sqrt(rho)

            w_tld.data = mat.T * q
            w_tld.data -= beta * w

            z.data = pre2.T * w_tld if pre2 else w_tld

            xi = InnerProduct(z, z)
            xi = sqrt(xi)

            gamma_1 = gamma
            theta_1 = theta

            theta = rho / (gamma_1 * abs(beta))
            gamma = 1.0 / sqrt(1.0 + theta * theta)
            if (gamma == 0.0):
                print('Breakdown in gamma')
                return

            eta = -eta * rho_1 * gamma * gamma / (beta * gamma_1 * gamma_1)

            if (i > 1):
                d.data = (theta_1 * theta_1 * gamma * gamma) * d
                d.data += eta * p

                s.data = (theta_1 * theta_1 * gamma * gamma) * s
                s.data += eta * p_tld

            else:
                d.data = eta * p
                s.data = eta * p_tld

            u.data += d
            r.data -= s

            #Projected residuum: Better terminating condition necessary?
            v.data = self.pre * r
            ResNorm = sqrt(InnerProduct(r, v))
            # ResNorm = sqrt( np.dot(r.FV().NumPy()[fdofs],r.FV().NumPy()[fdofs]))
            #ResNorm = sqrt(InnerProduct(r,r))
            if self.CheckResidual(ResNorm):
                return