IFPACK  Development
 All Classes Files Functions Variables Enumerations Friends
krylov_dh.c
00001 /*@HEADER
00002 // ***********************************************************************
00003 //
00004 //       Ifpack: Object-Oriented Algebraic Preconditioner Package
00005 //                 Copyright (2002) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ***********************************************************************
00040 //@HEADER
00041 */
00042 
00043 #include "Euclid_dh.h"
00044 #include "krylov_dh.h"
00045 #include "Mem_dh.h"
00046 #include "Parser_dh.h"
00047 #include "Mat_dh.h"
00048 
00049 
00050 #undef __FUNC__
00051 #define __FUNC__ "bicgstab_euclid"
00052 void
00053 bicgstab_euclid (Mat_dh A, Euclid_dh ctx, double *x, double *b, int *itsOUT)
00054 {
00055   START_FUNC_DH int its, m = ctx->m;
00056   bool monitor;
00057   int maxIts = ctx->maxIts;
00058   double atol = ctx->atol, rtol = ctx->rtol;
00059 
00060   /* scalars */
00061   double alpha, alpha_1,
00062     beta_1,
00063     widget, widget_1, rho_1, rho_2, s_norm, eps, exit_a, b_iprod, r_iprod;
00064 
00065   /* vectors */
00066   double *t, *s, *s_hat, *v, *p, *p_hat, *r, *r_hat;
00067 
00068   monitor = Parser_dhHasSwitch (parser_dh, "-monitor");
00069 
00070   /* allocate working space */
00071   t = (double *) MALLOC_DH (m * sizeof (double));
00072   s = (double *) MALLOC_DH (m * sizeof (double));
00073   s_hat = (double *) MALLOC_DH (m * sizeof (double));
00074   v = (double *) MALLOC_DH (m * sizeof (double));
00075   p = (double *) MALLOC_DH (m * sizeof (double));
00076   p_hat = (double *) MALLOC_DH (m * sizeof (double));
00077   r = (double *) MALLOC_DH (m * sizeof (double));
00078   r_hat = (double *) MALLOC_DH (m * sizeof (double));
00079 
00080   /* r = b - Ax */
00081   Mat_dhMatVec (A, x, s);   /* s = Ax */
00082   CopyVec (m, b, r);        /* r = b */
00083   Axpy (m, -1.0, s, r);     /* r = b-Ax */
00084   CopyVec (m, r, r_hat);    /* r_hat = r */
00085 
00086   /* compute stopping criteria */
00087   b_iprod = InnerProd (m, b, b);
00088   CHECK_V_ERROR;
00089   exit_a = atol * atol * b_iprod;
00090   CHECK_V_ERROR;        /* absolute stopping criteria */
00091   eps = rtol * rtol * b_iprod;  /* relative stoping criteria (residual reduction) */
00092 
00093   its = 0;
00094   while (1)
00095     {
00096       ++its;
00097       rho_1 = InnerProd (m, r_hat, r);
00098       if (rho_1 == 0)
00099     {
00100       SET_V_ERROR ("(r_hat . r) = 0; method fails");
00101     }
00102 
00103       if (its == 1)
00104     {
00105       CopyVec (m, r, p);    /* p = r_0 */
00106       CHECK_V_ERROR;
00107     }
00108       else
00109     {
00110       beta_1 = (rho_1 / rho_2) * (alpha_1 / widget_1);
00111 
00112       /* p_i = r_(i-1) + beta_(i-1)*( p_(i-1) - w_(i-1)*v_(i-1) ) */
00113       Axpy (m, -widget_1, v, p);
00114       CHECK_V_ERROR;
00115       ScaleVec (m, beta_1, p);
00116       CHECK_V_ERROR;
00117       Axpy (m, 1.0, r, p);
00118       CHECK_V_ERROR;
00119     }
00120 
00121       /* solve M*p_hat = p_i */
00122       Euclid_dhApply (ctx, p, p_hat);
00123       CHECK_V_ERROR;
00124 
00125       /* v_i = A*p_hat */
00126       Mat_dhMatVec (A, p_hat, v);
00127       CHECK_V_ERROR;
00128 
00129       /* alpha_i = rho_(i-1) / (r_hat^T . v_i ) */
00130       {
00131     double tmp = InnerProd (m, r_hat, v);
00132     CHECK_V_ERROR;
00133     alpha = rho_1 / tmp;
00134       }
00135 
00136       /* s = r_(i-1) - alpha_i*v_i */
00137       CopyVec (m, r, s);
00138       CHECK_V_ERROR;
00139       Axpy (m, -alpha, v, s);
00140       CHECK_V_ERROR;
00141 
00142       /* check norm of s; if small enough:
00143        * set x_i = x_(i-1) + alpha_i*p_i and stop.
00144        * (Actually, we use the square of the norm)
00145        */
00146       s_norm = InnerProd (m, s, s);
00147       if (s_norm < exit_a)
00148     {
00149       SET_INFO ("reached absolute stopping criteria");
00150       break;
00151     }
00152 
00153       /* solve M*s_hat = s */
00154       Euclid_dhApply (ctx, s, s_hat);
00155       CHECK_V_ERROR;
00156 
00157       /* t = A*s_hat */
00158       Mat_dhMatVec (A, s_hat, t);
00159       CHECK_V_ERROR;
00160 
00161       /* w_i = (t . s)/(t . t) */
00162       {
00163     double tmp1, tmp2;
00164     tmp1 = InnerProd (m, t, s);
00165     CHECK_V_ERROR;
00166     tmp2 = InnerProd (m, t, t);
00167     CHECK_V_ERROR;
00168     widget = tmp1 / tmp2;
00169       }
00170 
00171       /* x_i = x_(i-1) + alpha_i*p_hat + w_i*s_hat */
00172       Axpy (m, alpha, p_hat, x);
00173       CHECK_V_ERROR;
00174       Axpy (m, widget, s_hat, x);
00175       CHECK_V_ERROR;
00176 
00177       /* r_i = s - w_i*t */
00178       CopyVec (m, s, r);
00179       CHECK_V_ERROR;
00180       Axpy (m, -widget, t, r);
00181       CHECK_V_ERROR;
00182 
00183       /* check convergence; continue if necessary;
00184        * for continuation it is necessary thea w != 0.
00185        */
00186       r_iprod = InnerProd (m, r, r);
00187       CHECK_V_ERROR;
00188       if (r_iprod < eps)
00189     {
00190       SET_INFO ("stipulated residual reduction achieved");
00191       break;
00192     }
00193 
00194       /* monitor convergence */
00195       if (monitor && myid_dh == 0)
00196     {
00197       fprintf (stderr, "[it = %i] %e\n", its, sqrt (r_iprod / b_iprod));
00198     }
00199 
00200       /* prepare for next iteration */
00201       rho_2 = rho_1;
00202       widget_1 = widget;
00203       alpha_1 = alpha;
00204 
00205       if (its >= maxIts)
00206     {
00207       its = -its;
00208       break;
00209     }
00210     }
00211 
00212   *itsOUT = its;
00213 
00214   FREE_DH (t);
00215   FREE_DH (s);
00216   FREE_DH (s_hat);
00217   FREE_DH (v);
00218   FREE_DH (p);
00219   FREE_DH (p_hat);
00220   FREE_DH (r);
00221   FREE_DH (r_hat);
00222 END_FUNC_DH}
00223 
00224 #undef __FUNC__
00225 #define __FUNC__ "cg_euclid"
00226 void
00227 cg_euclid (Mat_dh A, Euclid_dh ctx, double *x, double *b, int *itsOUT)
00228 {
00229   START_FUNC_DH int its, m = A->m;
00230   double *p, *r, *s;
00231   double alpha, beta, gamma, gamma_old, eps, bi_prod, i_prod;
00232   bool monitor;
00233   int maxIts = ctx->maxIts;
00234   /* double atol = ctx->atol */
00235   double rtol = ctx->rtol;
00236 
00237   monitor = Parser_dhHasSwitch (parser_dh, "-monitor");
00238 
00239   /* compute square of absolute stopping threshold  */
00240   /* bi_prod = <b,b> */
00241   bi_prod = InnerProd (m, b, b);
00242   CHECK_V_ERROR;
00243   eps = (rtol * rtol) * bi_prod;
00244 
00245   p = (double *) MALLOC_DH (m * sizeof (double));
00246   s = (double *) MALLOC_DH (m * sizeof (double));
00247   r = (double *) MALLOC_DH (m * sizeof (double));
00248 
00249   /* r = b - Ax */
00250   Mat_dhMatVec (A, x, r);   /* r = Ax */
00251   CHECK_V_ERROR;
00252   ScaleVec (m, -1.0, r);    /* r = b */
00253   CHECK_V_ERROR;
00254   Axpy (m, 1.0, b, r);      /* r = r + b */
00255   CHECK_V_ERROR;
00256 
00257   /* solve Mp = r */
00258   Euclid_dhApply (ctx, r, p);
00259   CHECK_V_ERROR;
00260 
00261   /* gamma = <r,p> */
00262   gamma = InnerProd (m, r, p);
00263   CHECK_V_ERROR;
00264 
00265   its = 0;
00266   while (1)
00267     {
00268       ++its;
00269 
00270       /* s = A*p */
00271       Mat_dhMatVec (A, p, s);
00272       CHECK_V_ERROR;
00273 
00274       /* alpha = gamma / <s,p> */
00275       {
00276     double tmp = InnerProd (m, s, p);
00277     CHECK_V_ERROR;
00278     alpha = gamma / tmp;
00279     gamma_old = gamma;
00280       }
00281 
00282       /* x = x + alpha*p */
00283       Axpy (m, alpha, p, x);
00284       CHECK_V_ERROR;
00285 
00286       /* r = r - alpha*s */
00287       Axpy (m, -alpha, s, r);
00288       CHECK_V_ERROR;
00289 
00290       /* solve Ms = r */
00291       Euclid_dhApply (ctx, r, s);
00292       CHECK_V_ERROR;
00293 
00294       /* gamma = <r,s> */
00295       gamma = InnerProd (m, r, s);
00296       CHECK_V_ERROR;
00297 
00298       /* set i_prod for convergence test */
00299       i_prod = InnerProd (m, r, r);
00300       CHECK_V_ERROR;
00301 
00302       if (monitor && myid_dh == 0)
00303     {
00304       fprintf (stderr, "iter = %i  rel. resid. norm: %e\n", its,
00305            sqrt (i_prod / bi_prod));
00306     }
00307 
00308       /* check for convergence */
00309       if (i_prod < eps)
00310     break;
00311 
00312       /* beta = gamma / gamma_old */
00313       beta = gamma / gamma_old;
00314 
00315       /* p = s + beta p */
00316       ScaleVec (m, beta, p);
00317       CHECK_V_ERROR;
00318       Axpy (m, 1.0, s, p);
00319       CHECK_V_ERROR;
00320 
00321       if (its >= maxIts)
00322     {
00323       its = -its;
00324       break;
00325     }
00326     }
00327 
00328   *itsOUT = its;
00329 
00330   FREE_DH (p);
00331   FREE_DH (s);
00332   FREE_DH (r);
00333 END_FUNC_DH}
 All Classes Files Functions Variables Enumerations Friends