|
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 "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
1.7.3