PISM, A Parallel Ice Sheet Model  stable v0.5
src/base/iMage.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 <petscdmda.h>
00020 #include "iceModelVec.hh"
00021 #include "columnSystem.hh"
00022 #include "iceModel.hh"
00023 #include "PISMStressBalance.hh"
00024 #include "IceGrid.hh"
00025 #include "pism_options.hh"
00026 
00028 class ageSystemCtx : public columnSystemCtx {
00029 
00030 public:
00031   ageSystemCtx(PetscInt my_Mz, string my_prefix);
00032   PetscErrorCode initAllColumns();
00033 
00034   PetscErrorCode solveThisColumn(PetscScalar **x, PetscErrorCode &pivoterrorindex);  
00035 
00036 public:
00037   // constants which should be set before calling initForAllColumns()
00038   PetscScalar  dx,
00039                dy,
00040                dtAge,
00041                dzEQ;
00042   // pointers which should be set before calling initForAllColumns()
00043   PetscScalar  *u,
00044                *v,
00045                *w;
00046   IceModelVec3 *tau3;
00047 
00048 protected: // used internally
00049   PetscScalar nuEQ;
00050   bool        initAllDone;
00051 };
00052 
00053 
00054 ageSystemCtx::ageSystemCtx(PetscInt my_Mz, string my_prefix)
00055       : columnSystemCtx(my_Mz, my_prefix) { // size of system is Mz
00056   initAllDone = false;
00057   // set values so we can check if init was called on all
00058   dx = -1.0;
00059   dy = -1.0;
00060   dtAge = -1.0;
00061   dzEQ = -1.0;
00062   u = NULL;
00063   v = NULL;
00064   w = NULL;
00065   tau3 = NULL;
00066 }
00067 
00068 
00069 PetscErrorCode ageSystemCtx::initAllColumns() {
00070   // check whether each parameter & pointer got set
00071   if (dx <= 0.0) { SETERRQ(PETSC_COMM_SELF, 2,"un-initialized dx in ageSystemCtx"); }
00072   if (dy <= 0.0) { SETERRQ(PETSC_COMM_SELF, 3,"un-initialized dy in ageSystemCtx"); }
00073   if (dtAge <= 0.0) { SETERRQ(PETSC_COMM_SELF, 4,"un-initialized dtAge in ageSystemCtx"); }
00074   if (dzEQ <= 0.0) { SETERRQ(PETSC_COMM_SELF, 5,"un-initialized dzEQ in ageSystemCtx"); }
00075   if (u == NULL) { SETERRQ(PETSC_COMM_SELF, 6,"un-initialized pointer u in ageSystemCtx"); }
00076   if (v == NULL) { SETERRQ(PETSC_COMM_SELF, 7,"un-initialized pointer v in ageSystemCtx"); }
00077   if (w == NULL) { SETERRQ(PETSC_COMM_SELF, 8,"un-initialized pointer w in ageSystemCtx"); }
00078   if (tau3 == NULL) { SETERRQ(PETSC_COMM_SELF, 9,"un-initialized pointer tau3 in ageSystemCtx"); }
00079   nuEQ = dtAge / dzEQ; // derived constant
00080   initAllDone = true;
00081   return 0;
00082 }
00083 
00085 
00135 PetscErrorCode ageSystemCtx::solveThisColumn(PetscScalar **x, PetscErrorCode &pivoterrorindex) {
00136   PetscErrorCode ierr;
00137   if (!initAllDone) {  SETERRQ(PETSC_COMM_SELF, 2,
00138      "solveThisColumn() should only be called after initAllColumns() in ageSystemCtx"); }
00139 
00140   // set up system: 0 <= k < ks
00141   for (PetscInt k = 0; k < ks; k++) {
00142     planeStar<PetscScalar> ss;  // note ss.ij = tau[k]
00143     ierr = tau3->getPlaneStar_fine(i,j,k,&ss); CHKERRQ(ierr);
00144     // do lowest-order upwinding, explicitly for horizontal
00145     rhs[k] =  (u[k] < 0) ? u[k] * (ss.e -  ss.ij) / dx
00146                          : u[k] * (ss.ij  - ss.w) / dx;
00147     rhs[k] += (v[k] < 0) ? v[k] * (ss.n -  ss.ij) / dy
00148                          : v[k] * (ss.ij  - ss.s) / dy;
00149     // note it is the age eqn: dage/dt = 1.0 and we have moved the hor.
00150     //   advection terms over to right:
00151     rhs[k] = ss.ij + dtAge * (1.0 - rhs[k]);
00152 
00153     // do lowest-order upwinding, *implicitly* for vertical
00154     PetscScalar AA = nuEQ * w[k];
00155     if (k > 0) {
00156       if (AA >= 0) { // upward velocity
00157         L[k] = - AA;
00158         D[k] = 1.0 + AA;
00159         U[k] = 0.0;
00160       } else { // downward velocity; note  -AA >= 0
00161         L[k] = 0.0;
00162         D[k] = 1.0 - AA;
00163         U[k] = + AA;
00164       }
00165     } else { // k == 0 case
00166       // note L[0] not an allocated location
00167       if (AA > 0) { // if strictly upward velocity apply boundary condition:
00168                     // age = 0 because ice is being added to base
00169         D[0] = 1.0;
00170         U[0] = 0.0;
00171         rhs[0] = 0.0;
00172       } else { // downward velocity; note  -AA >= 0
00173         D[0] = 1.0 - AA;
00174         U[0] = + AA;
00175         // keep rhs[0] as is
00176       }
00177     }
00178   }  // done "set up system: 0 <= k < ks"
00179       
00180   // surface b.c. at ks
00181   if (ks>0) {
00182     L[ks] = 0;
00183     D[ks] = 1.0;   // ignore U[ks]
00184     rhs[ks] = 0.0;  // age zero at surface
00185   }
00186 
00187   // solve it
00188   pivoterrorindex = solveTridiagonalSystem(ks+1,x);
00189   return 0;
00190 }
00191 
00192 
00194 
00228 PetscErrorCode IceModel::ageStep() {
00229   PetscErrorCode  ierr;
00230 
00231   // set up fine grid in ice
00232   PetscInt    fMz = grid.Mz_fine;
00233   PetscScalar fdz = grid.dz_fine;
00234 
00235   PetscScalar *x;  
00236   x = new PetscScalar[fMz]; // space for solution
00237 
00238   bool viewOneColumn;
00239   ierr = PISMOptionsIsSet("-view_sys", viewOneColumn); CHKERRQ(ierr);
00240 
00241   ageSystemCtx system(fMz, "age"); // linear system to solve in each column
00242   system.dx    = grid.dx;
00243   system.dy    = grid.dy;
00244   system.dtAge = dt_TempAge;
00245   system.dzEQ  = fdz;
00246   // pointers to values in current column
00247   system.u     = new PetscScalar[fMz];
00248   system.v     = new PetscScalar[fMz];
00249   system.w     = new PetscScalar[fMz];
00250   // system needs access to tau3 for planeStar()
00251   system.tau3  = &tau3;
00252   // this checks that all needed constants and pointers got set
00253   ierr = system.initAllColumns(); CHKERRQ(ierr);
00254 
00255   IceModelVec3 *u3, *v3, *w3;
00256   ierr = stress_balance->get_3d_velocity(u3, v3, w3); CHKERRQ(ierr); 
00257 
00258   ierr = vH.begin_access(); CHKERRQ(ierr);
00259   ierr = tau3.begin_access(); CHKERRQ(ierr);
00260   ierr = u3->begin_access(); CHKERRQ(ierr);
00261   ierr = v3->begin_access(); CHKERRQ(ierr);
00262   ierr = w3->begin_access(); CHKERRQ(ierr);
00263   ierr = vWork3d.begin_access(); CHKERRQ(ierr);
00264 
00265   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00266     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00267       // this should *not* be replaced by a call to grid.kBelowHeight()
00268       const PetscInt  fks = static_cast<PetscInt>(floor(vH(i,j)/fdz));
00269 
00270       if (fks == 0) { // if no ice, set the entire column to zero age
00271         ierr = vWork3d.setColumn(i,j,0.0); CHKERRQ(ierr);
00272       } else { // general case: solve advection PDE; start by getting 3D velocity ...
00273 
00274         ierr = u3->getValColumn(i,j,fks,system.u); CHKERRQ(ierr);
00275         ierr = v3->getValColumn(i,j,fks,system.v); CHKERRQ(ierr);
00276         ierr = w3->getValColumn(i,j,fks,system.w); CHKERRQ(ierr);
00277 
00278         ierr = system.setIndicesAndClearThisColumn(i,j,fks); CHKERRQ(ierr);
00279 
00280         // solve the system for this column; call checks that params set
00281         PetscErrorCode pivoterr;
00282         ierr = system.solveThisColumn(&x,pivoterr); CHKERRQ(ierr);
00283 
00284         if (pivoterr != 0) {
00285           ierr = PetscPrintf(PETSC_COMM_SELF,
00286             "\n\ntridiagonal solve of ageSystemCtx in ageStep() FAILED at (%d,%d)\n"
00287                 " with zero pivot position %d; viewing system to m-file ... \n",
00288             i, j, pivoterr); CHKERRQ(ierr);
00289           ierr = system.reportColumnZeroPivotErrorMFile(pivoterr); CHKERRQ(ierr);
00290           SETERRQ(grid.com, 1,"PISM ERROR in ageStep()\n");
00291         }
00292         if (viewOneColumn && issounding(i,j)) {
00293           ierr = PetscPrintf(PETSC_COMM_SELF,
00294             "\n\nin ageStep(): viewing ageSystemCtx at (i,j)=(%d,%d) to m-file ... \n\n",
00295             i, j); CHKERRQ(ierr);
00296           ierr = system.viewColumnInfoMFile(x, fMz); CHKERRQ(ierr);
00297         }
00298 
00299         // x[k] contains age for k=0,...,ks, but set age of ice above (and at) surface to zero years
00300         for (PetscInt k=fks+1; k<fMz; k++) {
00301           x[k] = 0.0;
00302         }
00303         
00304         // put solution in IceModelVec3
00305         ierr = vWork3d.setValColumnPL(i,j,x); CHKERRQ(ierr);
00306       }
00307     }
00308   }
00309 
00310   ierr = vH.end_access(); CHKERRQ(ierr);
00311   ierr = tau3.end_access();  CHKERRQ(ierr);
00312   ierr = u3->end_access();  CHKERRQ(ierr);
00313   ierr = v3->end_access();  CHKERRQ(ierr);
00314   ierr = w3->end_access();  CHKERRQ(ierr);
00315   ierr = vWork3d.end_access();  CHKERRQ(ierr);
00316 
00317   delete [] x;  
00318   delete [] system.u;  delete [] system.v;  delete [] system.w;
00319 
00320   ierr = tau3.beginGhostCommTransfer(vWork3d); CHKERRQ(ierr);
00321   ierr = tau3.endGhostCommTransfer(vWork3d); CHKERRQ(ierr);
00322 
00323   return 0;
00324 }
00325 
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines