00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <cmath>
00020 #include <cstring>
00021 #include <petscda.h>
00022 #include "iceModel.hh"
00023
00024
00026
00043 PetscErrorCode IceModel::computeDrivingStress(IceModelVec2S &vtaudx, IceModelVec2S &vtaudy) {
00044 PetscErrorCode ierr;
00045
00046 const PetscScalar n = ice->exponent(),
00047 etapow = (2.0 * n + 2.0)/n,
00048 invpow = 1.0 / etapow,
00049 dinvpow = (- n - 2.0) / (2.0 * n + 2.0);
00050 const PetscScalar minThickEtaTransform = 5.0;
00051 const PetscScalar dx=grid.dx, dy=grid.dy;
00052
00053 bool compute_surf_grad_inward_ssa = config.get_flag("compute_surf_grad_inward_ssa");
00054 bool use_eta = config.get_flag("use_eta_transformation");
00055
00056 ierr = vh.begin_access(); CHKERRQ(ierr);
00057 ierr = vH.begin_access(); CHKERRQ(ierr);
00058 ierr = vbed.begin_access(); CHKERRQ(ierr);
00059 ierr = vMask.begin_access(); CHKERRQ(ierr);
00060
00061 ierr = vtaudx.begin_access(); CHKERRQ(ierr);
00062 ierr = vtaudy.begin_access(); CHKERRQ(ierr);
00063
00064 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00065 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00066 const PetscScalar pressure = ice->rho * standard_gravity * vH(i,j);
00067 if (pressure <= 0.0) {
00068 vtaudx(i,j) = 0.0;
00069 vtaudy(i,j) = 0.0;
00070 } else {
00071 PetscScalar h_x = 0.0, h_y = 0.0;
00072
00073 if (vMask.is_grounded(i,j) && (use_eta == true)) {
00074
00075 if (vH(i,j) > 0.0) {
00076 const PetscScalar myH = (vH(i,j) < minThickEtaTransform) ?
00077 minThickEtaTransform : vH(i,j);
00078 const PetscScalar eta = pow(myH, etapow), factor = invpow * pow(eta, dinvpow);
00079 h_x = factor * (pow(vH(i+1,j),etapow) - pow(vH(i-1,j),etapow)) / (2*dx);
00080 h_y = factor * (pow(vH(i,j+1),etapow) - pow(vH(i,j-1),etapow)) / (2*dy);
00081 }
00082
00083
00084
00085 h_x += vbed.diff_x(i,j);
00086 h_y += vbed.diff_y(i,j);
00087 } else {
00088 if (compute_surf_grad_inward_ssa) {
00089 h_x = vh.diff_x_p(i,j);
00090 h_y = vh.diff_y_p(i,j);
00091 } else {
00092 h_x = vh.diff_x(i,j);
00093 h_y = vh.diff_y(i,j);
00094 }
00095 }
00096
00097 vtaudx(i,j) = - pressure * h_x;
00098 vtaudy(i,j) = - pressure * h_y;
00099 }
00100 }
00101 }
00102
00103 ierr = vbed.end_access(); CHKERRQ(ierr);
00104 ierr = vh.end_access(); CHKERRQ(ierr);
00105 ierr = vH.end_access(); CHKERRQ(ierr);
00106 ierr = vMask.end_access(); CHKERRQ(ierr);
00107 ierr = vtaudx.end_access(); CHKERRQ(ierr);
00108 ierr = vtaudy.end_access(); CHKERRQ(ierr);
00109
00110 return 0;
00111 }
00112
00113
00115
00128 PetscErrorCode IceModel::updateSurfaceElevationAndMask() {
00129 PetscErrorCode ierr;
00130
00131 ierr = update_mask(); CHKERRQ(ierr);
00132 ierr = update_surface_elevation(); CHKERRQ(ierr);
00133
00134 return 0;
00135 }
00136
00137 PetscErrorCode IceModel::update_mask() {
00138 PetscErrorCode ierr;
00139 PetscScalar **bed, **H, **mask;
00140
00141 if (ocean == PETSC_NULL) { SETERRQ(1,"PISM ERROR: ocean == PETSC_NULL"); }
00142 PetscReal currentSeaLevel;
00143 ierr = ocean->sea_level_elevation(grid.year, dt / secpera, currentSeaLevel); CHKERRQ(ierr);
00144
00145 bool use_ssa_when_grounded = config.get_flag("use_ssa_when_grounded"),
00146 use_ssa_velocity = config.get_flag("use_ssa_velocity");
00147
00148 double ocean_rho = config.get("sea_water_density");
00149
00150 ierr = vH.get_array(H); CHKERRQ(ierr);
00151 ierr = vbed.get_array(bed); CHKERRQ(ierr);
00152 ierr = vMask.get_array(mask); CHKERRQ(ierr);
00153
00154 #ifdef LOCAL_GHOST_UPDATE
00155 PetscInt GHOSTS = 2;
00156 #else
00157 PetscInt GHOSTS = 0;
00158 #endif
00159 for (PetscInt i = grid.xs - GHOSTS; i < grid.xs+grid.xm + GHOSTS; ++i) {
00160 for (PetscInt j = grid.ys - GHOSTS; j < grid.ys+grid.ym + GHOSTS; ++j) {
00161
00162 const PetscScalar hgrounded = bed[i][j] + vH(i,j),
00163 hfloating = currentSeaLevel + (1.0 - ice->rho/ocean_rho) * vH(i,j);
00164
00165
00166 if (vMask.value(i,j) == MASK_OCEAN_AT_TIME_0)
00167 continue;
00168
00169 if (vMask.is_floating(i,j)) {
00170
00171 if (hgrounded > hfloating+1.0) {
00172 if (use_ssa_velocity) {
00173 if (use_ssa_when_grounded) {
00174 mask[i][j] = MASK_DRAGGING_SHEET;
00175 } else {
00176 mask[i][j] = MASK_SHEET;
00177 }
00178 } else {
00179
00180 mask[i][j] = MASK_SHEET;
00181 }
00182 }
00183
00184 } else {
00185
00186
00187 if (hgrounded > hfloating-1.0) {
00188
00189
00190 if (use_ssa_velocity && use_ssa_when_grounded)
00191 mask[i][j] = MASK_DRAGGING_SHEET;
00192
00193 } else {
00194 mask[i][j] = MASK_FLOATING;
00195 }
00196
00197 }
00198 }
00199 }
00200
00201 ierr = vH.end_access(); CHKERRQ(ierr);
00202 ierr = vbed.end_access(); CHKERRQ(ierr);
00203 ierr = vMask.end_access(); CHKERRQ(ierr);
00204
00205 #ifndef LOCAL_GHOST_UPDATE
00206 ierr = vMask.beginGhostComm(); CHKERRQ(ierr);
00207 ierr = vMask.endGhostComm(); CHKERRQ(ierr);
00208 #endif
00209
00210 return 0;
00211 }
00212
00213 PetscErrorCode IceModel::update_surface_elevation() {
00214 PetscErrorCode ierr;
00215 PetscScalar **h, **bed, **H, **mask;
00216
00217 if (ocean == PETSC_NULL) { SETERRQ(1,"PISM ERROR: ocean == PETSC_NULL"); }
00218 PetscReal currentSeaLevel;
00219 ierr = ocean->sea_level_elevation(grid.year, dt / secpera, currentSeaLevel); CHKERRQ(ierr);
00220
00221 bool is_dry_simulation = config.get_flag("is_dry_simulation");
00222
00223 double ocean_rho = config.get("sea_water_density");
00224
00225 ierr = vh.get_array(h); CHKERRQ(ierr);
00226 ierr = vH.get_array(H); CHKERRQ(ierr);
00227 ierr = vbed.get_array(bed); CHKERRQ(ierr);
00228 ierr = vMask.get_array(mask); CHKERRQ(ierr);
00229
00230 #ifdef LOCAL_GHOST_UPDATE
00231 PetscInt GHOSTS = 2;
00232 #else
00233 PetscInt GHOSTS = 0;
00234 #endif
00235 for (PetscInt i = grid.xs - GHOSTS; i < grid.xs+grid.xm + GHOSTS; ++i) {
00236 for (PetscInt j = grid.ys - GHOSTS; j < grid.ys+grid.ym + GHOSTS; ++j) {
00237
00238 if (vH(i,j) < 0) {
00239 SETERRQ2(1,"Thickness negative at point i=%d, j=%d",i,j);
00240 }
00241
00242 const PetscScalar hgrounded = bed[i][j] + vH(i,j),
00243 hfloating = currentSeaLevel + (1.0 - ice->rho/ocean_rho) * vH(i,j);
00244
00245 if (is_dry_simulation) {
00246
00247
00248 h[i][j] = hgrounded;
00249 continue;
00250 }
00251
00252 if (vMask.value(i,j) == MASK_OCEAN_AT_TIME_0) {
00253
00254
00255
00256
00257
00258
00259 h[i][j] = hfloating;
00260 continue;
00261 }
00262
00263 if (vMask.is_floating(i,j)) {
00264 h[i][j] = hfloating;
00265 } else {
00266 h[i][j] = hgrounded;
00267 }
00268 }
00269
00270 }
00271
00272 ierr = vh.end_access(); CHKERRQ(ierr);
00273 ierr = vH.end_access(); CHKERRQ(ierr);
00274 ierr = vbed.end_access(); CHKERRQ(ierr);
00275 ierr = vMask.end_access(); CHKERRQ(ierr);
00276
00277 #ifndef LOCAL_GHOST_UPDATE
00278 ierr = vh.beginGhostComm(); CHKERRQ(ierr);
00279 ierr = vh.endGhostComm(); CHKERRQ(ierr);
00280 #endif
00281
00282 return 0;
00283 }
00284
00286
00328 PetscErrorCode IceModel::massContExplicitStep() {
00329 PetscErrorCode ierr;
00330
00331 const PetscScalar dx = grid.dx, dy = grid.dy;
00332 bool do_ocean_kill = config.get_flag("ocean_kill"),
00333 floating_ice_killed = config.get_flag("floating_ice_killed"),
00334 include_bmr_in_continuity = config.get_flag("include_bmr_in_continuity"),
00335 do_superpose = config.get_flag("do_superpose");
00336
00337 if (surface != NULL) {
00338 ierr = surface->ice_surface_mass_flux(grid.year, dt / secpera, acab); CHKERRQ(ierr);
00339 } else { SETERRQ(1,"PISM ERROR: surface == NULL"); }
00340
00341 if (ocean != NULL) {
00342 ierr = ocean->shelf_base_mass_flux(grid.year, dt / secpera, shelfbmassflux); CHKERRQ(ierr);
00343 } else { SETERRQ(2,"PISM ERROR: ocean == NULL"); }
00344
00345 const PetscScalar inC_fofv = 1.0e-4 * PetscSqr(secpera),
00346 outC_fofv = 2.0 / pi;
00347
00348 IceModelVec2S vHnew = vWork2d[0];
00349 ierr = vH.copy_to(vHnew); CHKERRQ(ierr);
00350
00351 PetscScalar **bmr_gnded;
00352
00353 ierr = vH.begin_access(); CHKERRQ(ierr);
00354 ierr = vbmr.get_array(bmr_gnded); CHKERRQ(ierr);
00355 ierr = uvbar.begin_access(); CHKERRQ(ierr);
00356 ierr = vel_basal.begin_access(); CHKERRQ(ierr);
00357 ierr = acab.begin_access(); CHKERRQ(ierr);
00358 ierr = shelfbmassflux.begin_access(); CHKERRQ(ierr);
00359 ierr = vMask.begin_access(); CHKERRQ(ierr);
00360 ierr = vHnew.begin_access(); CHKERRQ(ierr);
00361
00362 ierr = vel_ssa.begin_access(); CHKERRQ(ierr);
00363
00364 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00365 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00366
00367
00368
00369
00370
00371
00372 PetscScalar He, Hw, Hn, Hs;
00373 if ( do_superpose && (vMask.value(i,j) == MASK_DRAGGING_SHEET) ) {
00374 const PetscScalar
00375 fv = 1.0 - outC_fofv * atan( inC_fofv *
00376 ( PetscSqr(vel_ssa(i, j).u) + PetscSqr(vel_ssa(i, j).v) ) ),
00377 fve = 1.0 - outC_fofv * atan( inC_fofv *
00378 ( PetscSqr(vel_ssa(i+1,j).u) + PetscSqr(vel_ssa(i+1,j).v) ) ),
00379 fvw = 1.0 - outC_fofv * atan( inC_fofv *
00380 ( PetscSqr(vel_ssa(i-1,j).u) + PetscSqr(vel_ssa(i-1,j).v) ) ),
00381 fvn = 1.0 - outC_fofv * atan( inC_fofv *
00382 ( PetscSqr(vel_ssa(i,j+1).u) + PetscSqr(vel_ssa(i,j+1).v) ) ),
00383 fvs = 1.0 - outC_fofv * atan( inC_fofv *
00384 ( PetscSqr(vel_ssa(i,j-1).u) + PetscSqr(vel_ssa(i,j-1).v) ) );
00385 const PetscScalar fvH = fv * vH(i,j);
00386 He = 0.5 * (fvH + fve * vH(i+1,j));
00387 Hw = 0.5 * (fvw * vH(i-1,j) + fvH);
00388 Hn = 0.5 * (fvH + fvn * vH(i,j+1));
00389 Hs = 0.5 * (fvs * vH(i,j-1) + fvH);
00390 } else {
00391 He = 0.5 * (vH(i,j) + vH(i+1,j));
00392 Hw = 0.5 * (vH(i-1,j) + vH(i,j));
00393 Hn = 0.5 * (vH(i,j) + vH(i,j+1));
00394 Hs = 0.5 * (vH(i,j-1) + vH(i,j));
00395 }
00396
00397
00398
00399 PetscScalar divQ = 0.0;
00400 if (computeSIAVelocities == PETSC_TRUE) {
00401 divQ = (uvbar(i,j,0) * He - uvbar(i-1,j,0) * Hw) / dx
00402 + (uvbar(i,j,1) * Hn - uvbar(i,j-1,1) * Hs) / dy;
00403 }
00404
00405
00406
00407 divQ += vel_basal(i,j).u * ( vel_basal(i,j).u < 0 ? vH(i+1,j)-vH(i,j)
00408 : vH(i,j)-vH(i-1,j) ) / dx
00409 + vel_basal(i,j).v * ( vel_basal(i,j).v < 0 ? vH(i,j+1)-vH(i,j)
00410 : vH(i,j)-vH(i,j-1) ) / dy;
00411
00412 divQ += vH(i,j) * ( (vel_basal(i+1,j).u - vel_basal(i-1,j).u) / (2.0*dx)
00413 + (vel_basal(i,j+1).v - vel_basal(i,j-1).v) / (2.0*dy) );
00414
00415 vHnew(i,j) += (acab(i,j) - divQ) * dt;
00416
00417 if (include_bmr_in_continuity) {
00418 if (vMask.is_floating(i,j)) {
00419 vHnew(i,j) -= shelfbmassflux(i,j) * dt;
00420 } else {
00421 vHnew(i,j) -= bmr_gnded[i][j] * dt;
00422 }
00423 }
00424
00425
00426 if (vHnew(i,j) < 0)
00427 vHnew(i,j) = 0.0;
00428
00429
00430
00431
00432
00433
00434 if ( do_ocean_kill && (vMask.value(i,j) == MASK_OCEAN_AT_TIME_0) )
00435 vHnew(i,j) = 0.0;
00436
00437
00438
00439 if ( floating_ice_killed && vMask.is_floating(i,j) )
00440 vHnew(i,j) = 0.0;
00441
00442 }
00443 }
00444
00445 ierr = vbmr.end_access(); CHKERRQ(ierr);
00446 ierr = vMask.end_access(); CHKERRQ(ierr);
00447 ierr = uvbar.end_access(); CHKERRQ(ierr);
00448 ierr = vel_basal.end_access(); CHKERRQ(ierr);
00449 ierr = vel_ssa.end_access(); CHKERRQ(ierr);
00450 ierr = acab.end_access(); CHKERRQ(ierr);
00451 ierr = shelfbmassflux.end_access(); CHKERRQ(ierr);
00452 ierr = vH.end_access(); CHKERRQ(ierr);
00453 ierr = vHnew.end_access(); CHKERRQ(ierr);
00454
00455
00456 ierr = vHnew.add(-1.0, vH, vdHdt); CHKERRQ(ierr);
00457 ierr = vdHdt.scale(1.0/dt); CHKERRQ(ierr);
00458
00459
00460 {
00461 PetscScalar dvol=0.0;
00462
00463 ierr = vdHdt.begin_access(); CHKERRQ(ierr);
00464
00465 if (cell_area.was_created()) {
00466 ierr = cell_area.begin_access(); CHKERRQ(ierr);
00467 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00468 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00469 dvol += vdHdt(i,j) * cell_area(i,j);
00470 }
00471 }
00472 ierr = cell_area.end_access(); CHKERRQ(ierr);
00473 } else {
00474 const PetscScalar a = grid.dx * grid.dy;
00475 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00476 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00477 dvol += vdHdt(i,j) * a;
00478 }
00479 }
00480 }
00481
00482 ierr = vdHdt.end_access(); CHKERRQ(ierr);
00483 ierr = PetscGlobalSum(&dvol, &dvoldt, grid.com); CHKERRQ(ierr);
00484 }
00485
00486
00487 PetscScalar ice_area;
00488 ierr = compute_ice_area(ice_area); CHKERRQ(ierr);
00489
00490 ierr = vdHdt.sum(gdHdtav); CHKERRQ(ierr);
00491 gdHdtav = gdHdtav / ice_area;
00492
00493
00494
00495 ierr = vHnew.beginGhostComm(vH); CHKERRQ(ierr);
00496 ierr = vHnew.endGhostComm(vH); CHKERRQ(ierr);
00497
00498
00499
00500 ierr = check_maximum_thickness(); CHKERRQ(ierr);
00501
00502 return 0;
00503 }
00504