|
PISM, A Parallel Ice Sheet Model stable 0.4.1779
|
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
1.7.3