def phiv(self, h, v): """ Computes phi(h*Hm)*v and two other vectors :param h: factor :param v: vector to apply phi(h*Hm) to :returns: 3-tuple of vectors ``( phi(h/3*Hm)*v, phi(2h/3*Hm)*v, phi(h*Hm)*v )`` """ # if Df is nearly singular, Df^-1 * (exp(Df)-1)*v is numerically ill-conditioned, but should give v # check norm of Jacobian: if self.rhs.normDf(self.y[-1]) < np.finfo(np.double).eps: return (v,v,v) # if v is too small, phi*v is also almost zero. # must check for this since arnoldi iterations needs v != 0 if norm(v) < np.finfo(np.double).eps: res = np.zeros_like(v) return (res,res,res) # use flag argument to find correct KrylovPhi instance pk = KrylovPhi(self.rhs, exp4=self, tau=h) # compute Krylov subspace approximation of phi(h*A)*v pk.compute(v) p1,p2,p3 = pk.phi3() if self.stats: self.stats["RHSevals"] += pk.m-1 # dimension of Krylov space minus 1 corresponds to number of applyA calls return (p1, p2, p3)
def phiv(self, h, v, flag=-1, reuse=False): """ Computes phi(h*Hm)*v and two other vectors :param h: factor :param v: vector to apply phi(h*Hm) to :param flag: if it is in (0,1,2), use corresponding instance of ``PhiKrylov`` :param reuse: if True, attempt to reuse the old Krylov space :returns: 3-tuple of vectors ``( phi(h/3*Hm)*v, phi(2h/3*Hm)*v, phi(h*Hm)*v )`` """ # if Df is nearly singular, Df^-1 * (exp(Df)-1)*v is numerically ill-conditioned, but should give v # check norm of Jacobian: if self.rhs.normDf(self.y[-1]) < np.finfo(np.double).eps: return (v,v,v) # if v is too small, phi*v is also almost zero. # must check for this since arnoldi iterations needs v != 0 if norm(v) < np.finfo(np.double).eps: res = np.zeros_like(v) return (res,res,res) # use flag argument to find correct KrylovPhi instance if not flag in [0,1,2]: pk = KrylovPhi(self.rhs, exp4=self, tau=h) reuse = False else: pk = self.krylov[flag] pk.tau = h if np.isscalar(v) or len(v) <= pk.m_max: reuse = False # reuse already computed krylov space if reuse: p1,p2,p3 = pk.phi3() else: # compute Krylov subspace approximation of phi(h*A)*v pk.compute(v) if self.stats: # dimension of Krylov space minus 1 corresponds to number of applyA calls self.stats["RHSevals"] += pk.m-1 p1,p2,p3 = pk.phi3() return (p1, p2, p3)