|
PISM, A Parallel Ice Sheet Model
stable v0.5
|
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
1.7.5.1