def __call__(self, x0=None, **kwargs): ## > runs cg with/without preconditioner """ Runs the conjugate gradient minimization. Parameters ---------- x0 : field, *optional* Starting guess for the minimization. tol : scalar, *optional* Tolerance specifying convergence; measured by current relative residual (default: 1E-4). clevel : integer, *optional* Number of times the tolerance should be undershot before exiting (default: 1). limii : integer, *optional* Maximum number of iterations performed (default: 10 * b.dim()). Returns ------- x : field Latest `x` of the minimization. convergence : integer Latest convergence level indicating whether the minimization has converged or not. """ self.x = field(self.b.domain, val=x0, target=self.b.target) if (self.W is None): return self._calc_without(**kwargs) else: return self._calc_with(**kwargs)
def __call__(self,x0=None,**kwargs): ## > runs cg with/without preconditioner """ Runs the conjugate gradient minimization. Parameters ---------- x0 : field, *optional* Starting guess for the minimization. tol : scalar, *optional* Tolerance specifying convergence; measured by current relative residual (default: 1E-4). clevel : integer, *optional* Number of times the tolerance should be undershot before exiting (default: 1). limii : integer, *optional* Maximum number of iterations performed (default: 10 * b.dim()). Returns ------- x : field Latest `x` of the minimization. convergence : integer Latest convergence level indicating whether the minimization has converged or not. """ self.x = field(self.b.domain,val=x0,target=self.b.target) if(self.W is None): return self._calc_without(**kwargs) else: return self._calc_with(**kwargs)
def _briefing(self, x): ## > prepares x for `multiply` ## inspect x if (not isinstance(x, field)): return field(self.domain, val=x, target=None), False ## check x.domain elif (x.domain == self.domain): return x, False elif (x.domain == self.codomain): return x, True ## transform else: return x.transform(target=self.codomain, overwrite=False), True
def _briefing(self,x): ## > prepares x for `multiply` ## inspect x if(not isinstance(x,field)): return field(self.domain,val=x,target=None),False ## check x.domain elif(x.domain==self.domain): return x,False elif(x.domain==self.codomain): return x,True ## transform else: return x.transform(target=self.codomain,overwrite=False),True
def _calc_without(self, tol=1E-4, clevel=1, limii=None): ## > runs cg without preconditioner clevel = int(clevel) if (limii is None): limii = 10 * self.b.domain.dim(split=False) else: limii = int(limii) r = self.b - self.A(self.x) d = field(self.b.domain, val=np.copy(r.val), target=self.b.target) gamma = r.dot(d) if (gamma == 0): return self.x, clevel + 1 delta_ = np.absolute(gamma)**(-0.5) convergence = 0 ii = 1 while (True): q = self.A(d) alpha = gamma / d.dot(q) ## positive definite if (not np.isfinite(alpha)): self.note.cprint( "\niteration : %08u alpha = NAN\n... dead." % ii) return self.x, 0 self.x += alpha * d if (np.signbit(np.real(alpha))): about.warnings.cprint( "WARNING: positive definiteness of A violated.") r = self.b - self.A(self.x) elif (ii % self.reset == 0): r = self.b - self.A(self.x) else: r -= alpha * q gamma_ = gamma gamma = r.dot(r) beta = max(0, gamma / gamma_) ## positive definite d = r + beta * d delta = delta_ * np.absolute(gamma)**0.5 self.note.cflush( "\niteration : %08u alpha = %3.1E beta = %3.1E delta = %3.1E" % (ii, np.real(alpha), np.real(beta), np.real(delta))) if (gamma == 0): convergence = clevel + 1 self.note.cprint(" convergence level : INF\n... done.") break elif (np.absolute(delta) < tol): convergence += 1 self.note.cflush(" convergence level : %u" % convergence) if (convergence == clevel): self.note.cprint("\n... done.") break else: convergence = max(0, convergence - 1) if (ii == limii): self.note.cprint("\n... quit.") break if (self.spam is not None): self.spam(self.x, ii) ii += 1 if (self.spam is not None): self.spam(self.x, ii) return self.x, convergence
def _calc_without(self,tol=1E-4,clevel=1,limii=None): ## > runs cg without preconditioner clevel = int(clevel) if(limii is None): limii = 10*self.b.domain.dim(split=False) else: limii = int(limii) r = self.b-self.A(self.x) d = field(self.b.domain,val=np.copy(r.val),target=self.b.target) gamma = r.dot(d) if(gamma==0): return self.x,clevel+1 delta_ = np.absolute(gamma)**(-0.5) convergence = 0 ii = 1 while(True): q = self.A(d) alpha = gamma/d.dot(q) ## positive definite if(not np.isfinite(alpha)): self.note.cprint("\niteration : %08u alpha = NAN\n... dead."%ii) return self.x,0 self.x += alpha*d if(np.signbit(np.real(alpha))): about.warnings.cprint("WARNING: positive definiteness of A violated.") r = self.b-self.A(self.x) elif(ii%self.reset==0): r = self.b-self.A(self.x) else: r -= alpha*q gamma_ = gamma gamma = r.dot(r) beta = max(0,gamma/gamma_) ## positive definite d = r+beta*d delta = delta_*np.absolute(gamma)**0.5 self.note.cflush("\niteration : %08u alpha = %3.1E beta = %3.1E delta = %3.1E"%(ii,np.real(alpha),np.real(beta),np.real(delta))) if(gamma==0): convergence = clevel+1 self.note.cprint(" convergence level : INF\n... done.") break elif(np.absolute(delta)<tol): convergence += 1 self.note.cflush(" convergence level : %u"%convergence) if(convergence==clevel): self.note.cprint("\n... done.") break else: convergence = max(0,convergence-1) if(ii==limii): self.note.cprint("\n... quit.") break if(self.spam is not None): self.spam(self.x,ii) ii += 1 if(self.spam is not None): self.spam(self.x,ii) return self.x,convergence