You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							155 lines
						
					
					
						
							5.8 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							155 lines
						
					
					
						
							5.8 KiB
						
					
					
				| /* -*- c++ -*- (enables emacs c++ mode) */ | |
| /*=========================================================================== | |
|   | |
|  Copyright (C) 2002-2012 Yves Renard | |
|   | |
|  This file is a part of GETFEM++ | |
|   | |
|  Getfem++  is  free software;  you  can  redistribute  it  and/or modify it | |
|  under  the  terms  of the  GNU  Lesser General Public License as published | |
|  by  the  Free Software Foundation;  either version 3 of the License,  or | |
|  (at your option) any later version along with the GCC Runtime Library | |
|  Exception either version 3.1 or (at your option) any later version. | |
|  This program  is  distributed  in  the  hope  that it will be useful,  but | |
|  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
|  or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public | |
|  License and GCC Runtime Library Exception for more details. | |
|  You  should  have received a copy of the GNU Lesser General Public License | |
|  along  with  this program;  if not, write to the Free Software Foundation, | |
|  Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA. | |
|   | |
|  As a special exception, you  may use  this file  as it is a part of a free | |
|  software  library  without  restriction.  Specifically,  if   other  files | |
|  instantiate  templates  or  use macros or inline functions from this file, | |
|  or  you compile this  file  and  link  it  with other files  to produce an | |
|  executable, this file  does  not  by itself cause the resulting executable | |
|  to be covered  by the GNU Lesser General Public License.  This   exception | |
|  does not  however  invalidate  any  other  reasons why the executable file | |
|  might be covered by the GNU Lesser General Public License. | |
|   | |
| ===========================================================================*/ | |
| 
 | |
| /**@file gmm_iter.h | |
|    @author  Yves Renard <Yves.Renard@insa-lyon.fr> | |
|    @date February 10, 2003. | |
|    @brief Iteration object. | |
| */ | |
| 
 | |
| #ifndef GMM_ITER_H__ | |
| #define GMM_ITER_H__ | |
|  | |
| #include "gmm_kernel.h" | |
|  | |
| namespace gmm { | |
| 
 | |
|   /**  The Iteration object calculates whether the solution has reached the | |
|        desired accuracy, or whether the maximum number of iterations has | |
|        been reached.  | |
|  | |
|        The method finished() checks the convergence.  The first() | |
|        method is used to determine the first iteration of the loop. | |
|   */ | |
|   class iteration { | |
|   protected : | |
|     double rhsn;       /* Right hand side norm.                            */ | |
|     size_type maxiter; /* Max. number of iterations.                       */ | |
|     int noise;         /* if noise > 0 iterations are printed.             */ | |
|     double resmax;     /* maximum residu.                                  */ | |
|     double resminreach, resadd; | |
|     double diverged_res; /* Threshold beyond which the iterative           */ | |
|                        /* is considered to diverge.                        */ | |
|     size_type nit;     /* iteration number.                                */ | |
|     double res;        /* last computed residu.                            */ | |
|     std::string name;  /* eventually, name of the method.                  */ | |
|     bool written; | |
|     void (*callback)(const gmm::iteration&); | |
|   public : | |
| 
 | |
|     void init(void) {  | |
|       nit = 0; res = 0.0; written = false;  | |
|       resminreach = 1E200; resadd = 0.0;  | |
|       callback = 0; | |
|     } | |
| 
 | |
|     iteration(double r = 1.0E-8, int noi = 0, size_type mit = size_type(-1), | |
| 	      double div_res = 1E200) | |
|       : rhsn(1.0), maxiter(mit), noise(noi), resmax(r), diverged_res(div_res) | |
|     { init(); } | |
| 
 | |
|     void  operator ++(int) {  nit++; written = false; resadd += res; } | |
|     void  operator ++() { (*this)++; } | |
| 
 | |
|     bool first(void) { return nit == 0; } | |
| 
 | |
|     /* get/set the "noisyness" (verbosity) of the solvers */ | |
|     int get_noisy(void) const { return noise; } | |
|     void set_noisy(int n) { noise = n; } | |
|     void reduce_noisy(void) { if (noise > 0) noise--; } | |
| 
 | |
|     double get_resmax(void) const { return resmax; } | |
|     void set_resmax(double r) { resmax = r; } | |
| 
 | |
|     double get_res() const { return res; } | |
|     void enforce_converged(bool c = true) | |
|     { if (c) res = double(0); else res = rhsn * resmax + double(1); } | |
| 
 | |
|     /* change the user-definable callback, called after each iteration */ | |
|     void set_callback(void (*t)(const gmm::iteration&)) { | |
|       callback = t; | |
|     } | |
| 
 | |
|     double get_diverged_residual(void) const { return diverged_res; } | |
|     void set_diverged_residual(double r) { diverged_res = r; } | |
| 
 | |
|     size_type get_iteration(void) const { return nit; } | |
|     void set_iteration(size_type i) { nit = i; } | |
|      | |
|     size_type get_maxiter(void) const { return maxiter; } | |
|     void set_maxiter(size_type i) { maxiter = i; } | |
| 
 | |
|     double get_rhsnorm(void) const { return rhsn; } | |
|     void set_rhsnorm(double r) { rhsn = r; } | |
|      | |
|     bool converged(void) { return res <= rhsn * resmax; } | |
|     bool converged(double nr) {  | |
|       res = gmm::abs(nr); resminreach = std::min(resminreach, res); | |
|       return converged(); | |
|     } | |
|     template <typename VECT> bool converged(const VECT &v) | |
|     { return converged(gmm::vect_norm2(v)); } | |
|     bool diverged(void) | |
|     { return (nit>=maxiter) || (res>=rhsn*diverged_res && nit > 4); } | |
|     bool diverged(double nr) {  | |
|       res = gmm::abs(nr); resminreach = std::min(resminreach, res); | |
|       return diverged(); | |
|     } | |
| 
 | |
|     bool finished(double nr) { | |
|       if (callback) callback(*this); | |
|       if (noise > 0 && !written) { | |
| 	double a = (rhsn == 0) ? 1.0 : rhsn; | |
| 	converged(nr); | |
| 	cout << name << " iter " << nit << " residual " | |
| 	     << gmm::abs(nr) / a; | |
| // 	if (nit % 100 == 0 && nit > 0) { | |
| // 	  cout << " (residual min " << resminreach / a << " mean val " | |
| // 	       << resadd / (100.0 * a) << " )"; | |
| // 	  resadd = 0.0; | |
| // 	} | |
| 	cout <<  endl; | |
| 	written = true; | |
|       } | |
|       return (converged(nr) || diverged(nr)); | |
|     } | |
|     template <typename VECT> bool finished_vect(const VECT &v) | |
|     { return finished(double(gmm::vect_norm2(v))); } | |
| 
 | |
| 
 | |
|     void set_name(const std::string &n) { name = n; } | |
|     const std::string &get_name(void) const { return name; } | |
| 
 | |
|   }; | |
| 
 | |
| } | |
| 
 | |
| #endif /* GMM_ITER_H__ */
 |