PISM, A Parallel Ice Sheet Model stable 0.4.1779

src/base/iMadaptive.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 "iceModel.hh"
00020 #include <petscvec.h>
00021 #include "Mask.hh"
00022 
00024 
00034 PetscErrorCode IceModel::computeMax3DVelocities() {
00035   PetscErrorCode ierr;
00036   PetscScalar *u, *v, *w;
00037   PetscScalar locCFLmaxdt = config.get("maximum_time_step_years") * secpera;
00038 
00039   IceModelVec3 *u3, *v3, *w3;
00040 
00041   ierr = stress_balance->get_3d_velocity(u3, v3, w3); CHKERRQ(ierr);
00042 
00043   ierr = vH.begin_access(); CHKERRQ(ierr);
00044   ierr = u3->begin_access(); CHKERRQ(ierr);
00045   ierr = v3->begin_access(); CHKERRQ(ierr);
00046   ierr = w3->begin_access(); CHKERRQ(ierr);
00047 
00048   // update global max of abs of velocities for CFL; only velocities under surface
00049   PetscReal   maxu=0.0, maxv=0.0, maxw=0.0;
00050   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00051     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00052       const PetscInt      ks = grid.kBelowHeight(vH(i,j));
00053       ierr = u3->getInternalColumn(i,j,&u); CHKERRQ(ierr);
00054       ierr = v3->getInternalColumn(i,j,&v); CHKERRQ(ierr);
00055       ierr = w3->getInternalColumn(i,j,&w); CHKERRQ(ierr);
00056       for (PetscInt k=0; k<ks; ++k) {
00057         const PetscScalar absu = PetscAbs(u[k]),
00058                           absv = PetscAbs(v[k]);
00059         maxu = PetscMax(maxu,absu);
00060         maxv = PetscMax(maxv,absv);
00061         // make sure the denominator below is positive:
00062         PetscScalar tempdenom = (0.001/secpera) / (grid.dx + grid.dy);  
00063         tempdenom += PetscAbs(absu/grid.dx) + PetscAbs(absv/grid.dy);
00064         locCFLmaxdt = PetscMin(locCFLmaxdt,1.0 / tempdenom); 
00065         maxw = PetscMax(maxw, PetscAbs(w[k]));        
00066       }
00067     }
00068   }
00069 
00070   ierr = u3->end_access(); CHKERRQ(ierr);
00071   ierr = v3->end_access(); CHKERRQ(ierr);
00072   ierr = w3->end_access(); CHKERRQ(ierr);
00073   ierr = vH.end_access(); CHKERRQ(ierr);
00074 
00075   ierr = PetscGlobalMax(&maxu, &gmaxu, grid.com); CHKERRQ(ierr);
00076   ierr = PetscGlobalMax(&maxv, &gmaxv, grid.com); CHKERRQ(ierr);
00077   ierr = PetscGlobalMax(&maxw, &gmaxw, grid.com); CHKERRQ(ierr);
00078   ierr = PetscGlobalMin(&locCFLmaxdt, &CFLmaxdt, grid.com); CHKERRQ(ierr);
00079   return 0;
00080 }
00081 
00082 
00084 
00092 PetscErrorCode IceModel::computeMax2DSlidingSpeed() {
00093   PetscErrorCode ierr;
00094   PISMVector2 **vel;
00095   PetscScalar locCFLmaxdt2D = config.get("maximum_time_step_years") * secpera;
00096 
00097   MaskQuery mask(vMask);
00098 
00099   IceModelVec2V *vel_advective;
00100   ierr = stress_balance->get_advective_2d_velocity(vel_advective); CHKERRQ(ierr); 
00101 
00102   ierr = vel_advective->get_array(vel); CHKERRQ(ierr);
00103   ierr = vMask.begin_access(); CHKERRQ(ierr);
00104   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00105     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00106       if (mask.icy(i, j)) {
00107         PetscScalar denom = PetscAbs(vel[i][j].u)/grid.dx + PetscAbs(vel[i][j].v)/grid.dy;
00108         denom += (0.01/secpera)/(grid.dx + grid.dy);  // make sure it's pos.
00109         locCFLmaxdt2D = PetscMin(locCFLmaxdt2D,1.0/denom);
00110       }
00111     }
00112   }
00113   ierr = vel_advective->end_access(); CHKERRQ(ierr);
00114   ierr = vMask.end_access(); CHKERRQ(ierr);
00115 
00116   ierr = PetscGlobalMin(&locCFLmaxdt2D, &CFLmaxdt2D, grid.com); CHKERRQ(ierr);
00117   return 0;
00118 }
00119 
00120 
00122 
00127 PetscErrorCode IceModel::adaptTimeStepDiffusivity() {
00128   PetscErrorCode ierr;
00129 
00130   bool do_skip = config.get_flag("do_skip");
00131   
00132   const PetscScalar adaptTimeStepRatio = config.get("adaptive_timestepping_ratio");
00133 
00134   const PetscInt skip_max = static_cast<PetscInt>(config.get("skip_max"));
00135 
00136   const PetscScalar DEFAULT_ADDED_TO_GDMAX_ADAPT = 1.0e-2;
00137 
00138   ierr = stress_balance->get_max_diffusivity(gDmax); CHKERRQ(ierr); 
00139 
00140   const PetscScalar  
00141           gridfactor = 1.0/(grid.dx*grid.dx) + 1.0/(grid.dy*grid.dy);
00142   dt_from_diffus = adaptTimeStepRatio
00143                      * 2 / ((gDmax + DEFAULT_ADDED_TO_GDMAX_ADAPT) * gridfactor);
00144   if (do_skip && (skipCountDown == 0)) {
00145     const PetscScalar  conservativeFactor = 0.95;
00146     // typically "dt" in next line is from CFL for advection in temperature equation,
00147     //   but in fact it might be from other restrictions, e.g. CFL for mass continuity
00148     //   in basal sliding case, or max_dt
00149     skipCountDown = (PetscInt) floor(conservativeFactor * (dt / dt_from_diffus));
00150     skipCountDown = ( skipCountDown >  skip_max) ?  skip_max :  skipCountDown;
00151   } // if  skipCountDown > 0 then it will get decremented at the mass balance step
00152   if (dt_from_diffus < dt) {
00153     dt = dt_from_diffus;
00154     adaptReasonFlag = 'd';
00155   }
00156   return 0;
00157 }
00158 
00159 
00161 
00167 PetscErrorCode IceModel::determineTimeStep(const bool doTemperatureCFL) {
00168   PetscErrorCode ierr;
00169 
00170   bool do_mass_conserve = config.get_flag("do_mass_conserve"),
00171     do_energy = config.get_flag("do_energy");
00172 
00173   const PetscScalar timeToEnd = (grid.end_year - grid.year) * secpera;
00174   if (dt_force > 0.0) {
00175     dt = dt_force; // override usual dt mechanism
00176     adaptReasonFlag = 'f';
00177     if (timeToEnd < dt) {
00178       dt = timeToEnd;
00179       adaptReasonFlag = 'e';
00180     }
00181   } else {
00182     dt = config.get("maximum_time_step_years") * secpera;
00183     bool use_ssa_velocity = config.get_flag("use_ssa_velocity");
00184 
00185     adaptReasonFlag = 'm';
00186 
00187     if ((do_energy == PETSC_TRUE) && (doTemperatureCFL == PETSC_TRUE)) {
00188       // CFLmaxdt is set by computeMax3DVelocities() in call to velocity() iMvelocity.cc
00189       dt_from_cfl = CFLmaxdt;
00190       if (dt_from_cfl < dt) {
00191         dt = dt_from_cfl;
00192         adaptReasonFlag = 'c';
00193       }
00194     }
00195     if (btu) {
00196       PetscReal btu_dt;
00197       ierr = btu->max_timestep(grid.year, btu_dt); CHKERRQ(ierr); // returns years
00198       btu_dt *= secpera;
00199       if (btu_dt < dt) {
00200         dt = btu_dt;
00201         adaptReasonFlag = 'b';
00202       }
00203     }
00204     if (do_mass_conserve && use_ssa_velocity) {
00205       // CFLmaxdt2D is set by broadcastSSAVelocity()
00206       if (CFLmaxdt2D < dt) {
00207         dt = CFLmaxdt2D;
00208         adaptReasonFlag = 'u';
00209       }
00210     }
00211     if (do_mass_conserve) {
00212       // note: if do_skip then skipCountDown = floor(dt_from_cfl/dt_from_diffus)
00213       ierr = adaptTimeStepDiffusivity(); CHKERRQ(ierr); // might set adaptReasonFlag = 'd'
00214     }
00215 
00216     if ((maxdt_temporary > 0.0) && (maxdt_temporary < dt)) {
00217       dt = maxdt_temporary;
00218       adaptReasonFlag = 't';
00219     }
00220     if (timeToEnd < dt) {
00221       dt = timeToEnd;
00222       adaptReasonFlag = 'e';
00223     }
00224     if ((adaptReasonFlag == 'm') || (adaptReasonFlag == 't') || (adaptReasonFlag == 'e')) {
00225       if (skipCountDown > 1) skipCountDown = 1; 
00226     }
00227   }    
00228   return 0;
00229 }
00230 
00231 
00233 
00242 PetscErrorCode IceModel::countCFLViolations(PetscScalar* CFLviol) {
00243   PetscErrorCode  ierr;
00244 
00245   const PetscScalar cflx = grid.dx / (dt_years_TempAge * secpera),
00246                     cfly = grid.dy / (dt_years_TempAge * secpera);
00247 
00248   PetscScalar *u, *v;
00249   IceModelVec3 *u3, *v3, *dummy;
00250   ierr = stress_balance->get_3d_velocity(u3, v3, dummy); CHKERRQ(ierr);
00251 
00252   ierr = vH.begin_access(); CHKERRQ(ierr);
00253   ierr = u3->begin_access(); CHKERRQ(ierr);
00254   ierr = v3->begin_access(); CHKERRQ(ierr);
00255 
00256   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00257     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00258       const PetscInt  fks = grid.kBelowHeight(vH(i,j));
00259 
00260       ierr = u3->getInternalColumn(i,j,&u); CHKERRQ(ierr);
00261       ierr = v3->getInternalColumn(i,j,&v); CHKERRQ(ierr);
00262 
00263       // check horizontal CFL conditions at each point
00264       for (PetscInt k=0; k<=fks; k++) {
00265         if (PetscAbs(u[k]) > cflx)  *CFLviol += 1.0;
00266         if (PetscAbs(v[k]) > cfly)  *CFLviol += 1.0;
00267       }
00268     }
00269   }
00270 
00271   ierr = vH.end_access(); CHKERRQ(ierr);
00272   ierr = u3->end_access();  CHKERRQ(ierr);
00273   ierr = v3->end_access();  CHKERRQ(ierr);
00274 
00275   return 0;
00276 }
00277 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines