PISM, A Parallel Ice Sheet Model stable 0.4.1779

src/base/columnSystem.cc

Go to the documentation of this file.
00001 // Copyright (C) 2004-2011 Jed Brown, Ed Bueler and Constantine Khroulev
00002 //
00003 // This file is part of PISM.
00004 //
00005 // PISM is free software; you can redistribute it and/or modify it under the
00006 // terms of the GNU General Public License as published by the Free Software
00007 // Foundation; either version 2 of the License, or (at your option) any later
00008 // version.
00009 //
00010 // PISM is distributed in the hope that it will be useful, but WITHOUT ANY
00011 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00012 // FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
00013 // details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with PISM; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018 
00019 #include <petsc.h>
00020 #include "pism_const.hh"
00021 #include "iceModelVec.hh"
00022 #include "columnSystem.hh"
00023 
00024 
00026 
00042 columnSystemCtx::columnSystemCtx(PetscInt my_nmax, string my_prefix) : nmax(my_nmax), prefix(my_prefix) {
00043   if (nmax < 1) {
00044     PetscPrintf(PETSC_COMM_WORLD,
00045       "columnSystemCtx ERROR: nmax of system too small\n");
00046     PISMEnd();
00047   }
00048   if (nmax > 1000000) {
00049     PetscPrintf(PETSC_COMM_WORLD,
00050       "columnSystemCtx ERROR: nmax of system unreasonable (> 10^6)\n");
00051     PISMEnd();
00052   }
00053   Lp   = new PetscScalar[nmax-1];
00054   L    = Lp-1; // ptr arith.; note L[0]=Lp[-1] not allocated
00055   D    = new PetscScalar[nmax];
00056   U    = new PetscScalar[nmax-1];
00057   rhs  = new PetscScalar[nmax];
00058   work = new PetscScalar[nmax];
00059 
00060   resetColumn();
00061 
00062   indicesValid = false;
00063 
00064 }
00065 
00066 
00067 columnSystemCtx::~columnSystemCtx() {
00068   delete [] Lp;
00069   delete [] D;
00070   delete [] U;
00071   delete [] rhs;
00072   delete [] work;
00073 }
00074 
00075 
00077 PetscErrorCode columnSystemCtx::resetColumn() {
00078   PetscErrorCode ierr;
00079   ierr = PetscMemzero(Lp,   (nmax-1)*sizeof(PetscScalar)); CHKERRQ(ierr);
00080   ierr = PetscMemzero(U,    (nmax-1)*sizeof(PetscScalar)); CHKERRQ(ierr);
00081   ierr = PetscMemzero(D,    (nmax)*sizeof(PetscScalar)); CHKERRQ(ierr);
00082   ierr = PetscMemzero(rhs,  (nmax)*sizeof(PetscScalar)); CHKERRQ(ierr);
00083   ierr = PetscMemzero(work, (nmax)*sizeof(PetscScalar)); CHKERRQ(ierr);
00084   return 0;
00085 }
00086 
00087 
00089 PetscScalar columnSystemCtx::norm1(const PetscInt n) const {
00090   if (n > nmax) {
00091     PetscPrintf(PETSC_COMM_WORLD,"PISM ERROR:  n > nmax in columnSystemCtx::norm1()\n");
00092     PISMEnd();
00093   }
00094   if (n == 1)  return fabs(D[0]);   // only 1x1 case is special
00095   PetscScalar z = fabs(D[0]) + fabs(L[1]);
00096   for (PetscInt k = 1; k < n; k++) {  // k is column index (zero-based)
00097     z = PetscMax(z, fabs(U[k-1])) + fabs(D[k]) + fabs(L[k+1]);
00098   }
00099   z = PetscMax(z, fabs(U[n-2]) + fabs(D[n-1]));
00100   return z;
00101 }
00102 
00103 
00105 
00117 PetscScalar columnSystemCtx::ddratio(const PetscInt n) const {
00118   if (n > nmax) {
00119     PetscPrintf(PETSC_COMM_WORLD,"PISM ERROR:  n > nmax in columnSystemCtx::ddratio()\n");
00120     PISMEnd();
00121   }
00122   const PetscScalar scale = norm1(n);
00123 
00124   if ( (fabs(D[0]) / scale) < 1.0e-12)  return -1.0;
00125   PetscScalar z = fabs(U[0]) / fabs(D[0]);
00126 
00127   for (PetscInt k = 1; k < n-1; k++) {  // k is row index (zero-based)
00128     if ( (fabs(D[k]) / scale) < 1.0e-12)  return -1.0;
00129     const PetscScalar s = fabs(L[k]) + fabs(U[k]);
00130     z = PetscMax(z, s / fabs(D[k]) );
00131   } 
00132 
00133   if ( (fabs(D[n-1]) / scale) < 1.0e-12)  return -1.0;
00134   z = PetscMax(z, fabs(L[n-1]) / fabs(D[n-1]) );
00135 
00136   return z;
00137 }
00138 
00139 
00140 PetscErrorCode columnSystemCtx::setIndicesAndClearThisColumn(
00141                   PetscInt my_i, PetscInt my_j, PetscInt my_ks) {
00142   if (indicesValid) {  SETERRQ(3,
00143      "setIndicesAndClearThisColumn() called twice in same column"); }
00144   i = my_i;
00145   j = my_j;
00146   ks = my_ks;
00147 
00148   resetColumn();
00149   
00150   indicesValid = true;
00151   return 0;
00152 }
00153 
00154 
00156 
00163 PetscErrorCode columnSystemCtx::viewVectorValues(PetscViewer viewer,
00164                                                  PetscScalar *v, PetscInt m, const char* info) const {
00165   PetscErrorCode ierr;
00166 
00167   if (v==NULL) {
00168     SETERRQ1(2,"columnSystem ERROR: can't view '%s' by v=NULL pointer ... ending ...\n", info);
00169   }
00170   if (m<1) {
00171     SETERRQ1(3,"columnSystem ERROR: can't view '%s' because m<1 ... ending ...\n",info);
00172   }
00173 
00174   PetscTruth iascii;
00175   if (!viewer) {
00176     ierr = PetscViewerASCIIGetStdout(PETSC_COMM_SELF,&viewer); CHKERRQ(ierr);
00177   }
00178   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii); CHKERRQ(ierr);
00179   if (!iascii) { SETERRQ(1,"Only ASCII viewer for ColumnSystem\n"); }
00180 
00181   ierr = PetscViewerASCIIPrintf(viewer,
00182      "\n%% viewing ColumnSystem column object with description '%s' (columns  [k value])\n",
00183      info); CHKERRQ(ierr);
00184   ierr = PetscViewerASCIIPrintf(viewer,
00185       "%s_with_index = [...\n",info); CHKERRQ(ierr);
00186   for (PetscInt k=0; k<m; k++) {
00187     ierr = PetscViewerASCIIPrintf(viewer,
00188       "  %5d %.12f",k,v[k]); CHKERRQ(ierr);
00189     if (k == m-1) { 
00190       ierr = PetscViewerASCIIPrintf(viewer, "];\n"); CHKERRQ(ierr);
00191     } else {
00192       ierr = PetscViewerASCIIPrintf(viewer, ";\n"); CHKERRQ(ierr);
00193     }
00194   }
00195   ierr = PetscViewerASCIIPrintf(viewer,
00196       "%s = %s_with_index(:,2);\n\n",info,info); CHKERRQ(ierr);
00197   return 0;
00198 }
00199 
00200 
00202 
00207 PetscErrorCode columnSystemCtx::viewMatrix(PetscViewer viewer, const char* info) const {
00208   PetscErrorCode ierr;
00209   PetscTruth iascii;
00210   if (!viewer) {
00211     ierr = PetscViewerASCIIGetStdout(PETSC_COMM_SELF,&viewer); CHKERRQ(ierr);
00212   }
00213   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii); CHKERRQ(ierr);
00214   if (!iascii) { SETERRQ(1,"Only ASCII viewer for ColumnSystem\n"); }
00215 
00216   if (L==NULL) {
00217     SETERRQ1(2,"columnSystemCtx ERROR: can't matrix '%s' because L==NULL ... ending ...\n", info);
00218   }
00219   if (D==NULL) {
00220     SETERRQ1(3,"columnSystemCtx ERROR: can't matrix '%s' because D==NULL ... ending ...\n", info);
00221   }
00222   if (U==NULL) {
00223     SETERRQ1(4,"columnSystemCtx ERROR: can't matrix '%s' because U==NULL ... ending ...\n", info);
00224   }
00225 
00226   if (nmax < 2) {
00227     ierr = PetscViewerASCIIPrintf(viewer,
00228       "\n\n<nmax >= 2 required to view columnSystemCtx tridiagonal matrix '%s' ... skipping view\n",info);
00229     CHKERRQ(ierr);
00230     return 0;
00231   }
00232 
00233   if (nmax > 500) {
00234     ierr = PetscViewerASCIIPrintf(viewer,
00235       "\n\n<nmax > 500: columnSystemCtx matrix too big to display as full; viewing tridiagonal matrix '%s' by diagonals ...\n",info); CHKERRQ(ierr);
00236     char vinfo[PETSC_MAX_PATH_LEN];
00237     snprintf(vinfo,PETSC_MAX_PATH_LEN, "%s_super_diagonal_U", info);
00238     ierr = viewVectorValues(viewer,U,nmax-1,vinfo); CHKERRQ(ierr);
00239     snprintf(vinfo,PETSC_MAX_PATH_LEN, "%s_diagonal_D", info);
00240     ierr = viewVectorValues(viewer,D,nmax,vinfo); CHKERRQ(ierr);
00241     snprintf(vinfo,PETSC_MAX_PATH_LEN, "%s_sub_diagonal_L", info);
00242     ierr = viewVectorValues(viewer,Lp,nmax-1,vinfo); CHKERRQ(ierr);
00243   } else {
00244     ierr = PetscViewerASCIIPrintf(viewer,
00245         "\n%s = [...\n",info); CHKERRQ(ierr);
00246     for (PetscInt k=0; k<nmax; k++) {    // k+1 is row  (while j+1 is column)
00247       if (k == 0) {              // viewing first row
00248         ierr = PetscViewerASCIIPrintf(viewer,"%.12f %.12f ",D[k],U[k]); CHKERRQ(ierr);
00249         for (PetscInt n=2; n<nmax; n++) {
00250           ierr = PetscViewerASCIIPrintf(viewer,"%3.1f ",0.0); CHKERRQ(ierr);
00251         }
00252       } else if (k < nmax-1) {   // viewing generic row
00253         for (PetscInt n=0; n<k-1; n++) {
00254           ierr = PetscViewerASCIIPrintf(viewer,"%3.1f ",0.0); CHKERRQ(ierr);
00255         }
00256         ierr = PetscViewerASCIIPrintf(viewer,"%.12f %.12f %.12f ",L[k],D[k],U[k]); CHKERRQ(ierr);
00257         for (PetscInt n=k+2; n<nmax; n++) {
00258           ierr = PetscViewerASCIIPrintf(viewer,"%3.1f ",0.0); CHKERRQ(ierr);
00259         }
00260       } else {                   // viewing last row
00261         for (PetscInt n=0; n<k-1; n++) {
00262           ierr = PetscViewerASCIIPrintf(viewer,"%3.1f ",0.0); CHKERRQ(ierr);
00263         }
00264         ierr = PetscViewerASCIIPrintf(viewer,"%.12f %.12f ",L[k],D[k]); CHKERRQ(ierr);
00265       }
00266       
00267       if (k == nmax-1) {
00268         ierr = PetscViewerASCIIPrintf(viewer,"];\n\n"); CHKERRQ(ierr);  // end final row
00269       } else {
00270         ierr = PetscViewerASCIIPrintf(viewer,";\n"); CHKERRQ(ierr);  // end of generic row
00271       }
00272     }
00273   }
00274   
00275   return 0;
00276 }
00277 
00278 
00280 PetscErrorCode columnSystemCtx::viewSystem(PetscViewer viewer) const {
00281   PetscErrorCode ierr;
00282   char  info[PETSC_MAX_PATH_LEN];
00283   snprintf(info,PETSC_MAX_PATH_LEN, "%s_A", prefix.c_str());
00284   ierr = viewMatrix(viewer,info); CHKERRQ(ierr);
00285   snprintf(info,PETSC_MAX_PATH_LEN, "%s_rhs", prefix.c_str());
00286   ierr = viewVectorValues(viewer,rhs,nmax,info); CHKERRQ(ierr);
00287   return 0;
00288 }
00289 
00290 
00292 
00302 PetscErrorCode columnSystemCtx::solveTridiagonalSystem(
00303                   const PetscInt n, PetscScalar **x) {
00304 #ifdef PISM_DEBUG
00305   if (x == NULL) { SETERRQ(-999,"x is NULL in columnSystemCtx"); }
00306   if (*x == NULL) { SETERRQ(-998,"*x is NULL in columnSystemCtx"); }
00307   if (n < 1) { SETERRQ(-997,"instance size n < 1 in columnSystemCtx"); }
00308   if (n > nmax) { SETERRQ(-996,"instance size n too large in columnSystemCtx"); }
00309 
00310   if (!indicesValid) { SETERRQ(-995,"column indices not valid in columnSystemCtx"); }
00311 #endif
00312   PetscScalar b;
00313   b = D[0];
00314   if (b == 0.0) { return 1; }
00315   (*x)[0] = rhs[0]/b;
00316   for (int k=1; k<n; ++k) {
00317     work[k] = U[k-1]/b;
00318     b = D[k] - L[k] * work[k];
00319     if (b == 0.0) { return k+1; }
00320     (*x)[k] = (rhs[k] - L[k] * (*x)[k-1]) / b;
00321   }
00322   for (int k=n-2; k>=0; --k) {
00323     (*x)[k] -= work[k+1] * (*x)[k+1];
00324   }
00325 
00326   indicesValid = false;
00327   return 0;
00328 }
00329 
00330 
00332 PetscErrorCode columnSystemCtx::reportColumnZeroPivotErrorMFile(const PetscErrorCode errindex) {
00333   PetscErrorCode ierr;
00334   char fname[PETSC_MAX_PATH_LEN];
00335   snprintf(fname, PETSC_MAX_PATH_LEN, "%s_i%d_j%d_ZERO_PIVOT_ERROR_%d.m",
00336            prefix.c_str(),i,j,errindex);
00337   ierr = viewColumnInfoMFile(fname, NULL, 0); CHKERRQ(ierr);
00338   return 0;
00339 }
00340 
00341 
00343 
00371 PetscErrorCode columnSystemCtx::viewColumnInfoMFile(PetscScalar *x, PetscInt n) {
00372   PetscErrorCode ierr;
00373   char fname[PETSC_MAX_PATH_LEN];
00374   snprintf(fname, PETSC_MAX_PATH_LEN, "%s_i%d_j%d.m", prefix.c_str(), i,j);
00375   ierr = viewColumnInfoMFile(fname, x, n); CHKERRQ(ierr);
00376   return 0;
00377 }
00378 
00379 
00381 
00385 PetscErrorCode columnSystemCtx::viewColumnInfoMFile(char *filename, PetscScalar *x, PetscInt n) {
00386   PetscErrorCode ierr;
00387   PetscViewer viewer;
00388   ierr = PetscViewerCreate(PETSC_COMM_SELF, &viewer);CHKERRQ(ierr);
00389   ierr = PetscViewerSetType(viewer, PETSC_VIEWER_ASCII);CHKERRQ(ierr);
00390   ierr = PetscViewerSetFormat(viewer, PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
00391   ierr = PetscViewerFileSetName(viewer, filename);CHKERRQ(ierr);
00392   ierr = PetscViewerASCIIPrintf(viewer,
00393         "%%  system has 1-norm = %.3e  and  diagonal-dominance ratio = %.5f\n",
00394         norm1(n), ddratio(n)); CHKERRQ(ierr);
00395   ierr = viewSystem(viewer); CHKERRQ(ierr);
00396   if ((x != NULL) && (n > 0)) {
00397     char  info[PETSC_MAX_PATH_LEN];
00398     snprintf(info,PETSC_MAX_PATH_LEN, "%s_x", prefix.c_str());
00399     ierr = viewVectorValues(viewer, x, n, info); CHKERRQ(ierr);
00400   }
00401   ierr = PetscViewerDestroy(viewer); CHKERRQ(ierr);
00402   return 0;
00403 }
00404 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines