00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <cstring>
00021 #include <cstdlib>
00022 #include <petscda.h>
00023 #include "nc_util.hh"
00024 #include "iceModel.hh"
00025
00026 #include "PISMIO.hh"
00027
00029
00034 PetscErrorCode IceModel::bootstrapFromFile(const char *filename) {
00035 PetscErrorCode ierr;
00036
00037 PISMIO nc(&grid);
00038 ierr = nc.open_for_reading(filename); CHKERRQ(ierr);
00039
00040 ierr = verbPrintf(2, grid.com,
00041 "bootstrapping by PISM default method from file %s\n",filename); CHKERRQ(ierr);
00042
00043
00044
00045 ierr = verbPrintf(2, grid.com,
00046 " rescaling computational box for ice from -boot_from file and\n"
00047 " user options to dimensions:\n"
00048 " [-%6.2f km, %6.2f km] x [-%6.2f km, %6.2f km] x [0 m, %6.2f m]\n",
00049 grid.Lx/1000.0,grid.Lx/1000.0,grid.Ly/1000.0,grid.Ly/1000.0,grid.Lz);
00050 CHKERRQ(ierr);
00051
00052 bool hExists=false, maskExists=false;
00053 ierr = nc.find_variable("usurf", "surface_altitude", NULL, hExists); CHKERRQ(ierr);
00054 ierr = nc.find_variable("mask", NULL, maskExists); CHKERRQ(ierr);
00055
00056
00057
00058
00059 grid_info g;
00060 ierr = nc.get_grid_info(g); CHKERRQ(ierr);
00061
00062 LocalInterpCtx *lic = new LocalInterpCtx(g, NULL, NULL, grid);
00063
00064 ierr = nc.close(); CHKERRQ(ierr);
00065
00066
00067
00068
00069 if (maskExists) {
00070 ierr = verbPrintf(2, grid.com,
00071 " WARNING: 'mask' found; IGNORING IT!\n"); CHKERRQ(ierr);
00072 }
00073 if (hExists) {
00074 ierr = verbPrintf(2, grid.com,
00075 " WARNING: surface elevation 'usurf' found; IGNORING IT!\n");
00076 CHKERRQ(ierr);
00077 }
00078
00079
00080 ierr = verbPrintf(2, grid.com,
00081 " reading 2D model state variables by regridding ...\n"); CHKERRQ(ierr);
00082
00083 ierr = vLongitude.regrid(filename, *lic, false); CHKERRQ(ierr);
00084 ierr = vLatitude.regrid(filename, *lic, false); CHKERRQ(ierr);
00085 ierr = vH.regrid(filename, *lic,
00086 config.get("bootstrapping_H_value_no_var")); CHKERRQ(ierr);
00087 ierr = vbed.regrid(filename, *lic,
00088 config.get("bootstrapping_bed_value_no_var")); CHKERRQ(ierr);
00089 ierr = vHmelt.regrid(filename, *lic,
00090 config.get("bootstrapping_Hmelt_value_no_var")); CHKERRQ(ierr);
00091 ierr = vbmr.regrid(filename, *lic,
00092 config.get("bootstrapping_bmelt_value_no_var")); CHKERRQ(ierr);
00093 ierr = vtillphi.regrid(filename, *lic,
00094 config.get("bootstrapping_tillphi_value_no_var")); CHKERRQ(ierr);
00095 ierr = vGhf.regrid(filename, *lic,
00096 config.get("bootstrapping_geothermal_flux_value_no_var"));
00097 CHKERRQ(ierr);
00098 ierr = vuplift.regrid(filename, *lic,
00099 config.get("bootstrapping_uplift_value_no_var")); CHKERRQ(ierr);
00100
00101 bool Lz_set;
00102 ierr = PISMOptionsIsSet("-Lz", Lz_set); CHKERRQ(ierr);
00103 if ( !Lz_set ) {
00104 PetscReal thk_min, thk_max;
00105 ierr = vH.range(thk_min, thk_max); CHKERRQ(ierr);
00106
00107 ierr = verbPrintf(2, grid.com,
00108 " Setting Lz to 1.5 * max(ice thickness) = %3.3f meters...\n",
00109 1.5 * thk_max);
00110
00111
00112 grid.Lz = 1.5 * thk_max;
00113
00114 ierr = grid.compute_vertical_levels();
00115
00116 CHKERRQ(ierr);
00117 }
00118
00119
00120 ierr = setMaskSurfaceElevation_bootstrap(); CHKERRQ(ierr);
00121
00122
00123 if (config.get_flag("do_age")) {
00124 ierr = verbPrintf(2, grid.com,
00125 " setting initial age to %.4f years\n", config.get("initial_age_of_ice_years"));
00126 CHKERRQ(ierr);
00127 tau3.set(config.get("initial_age_of_ice_years") * secpera);
00128 }
00129
00130 ierr = verbPrintf(2, grid.com,
00131 " filling in ice and bedrock temperatures using surface temperatures and quartic guess\n");
00132 CHKERRQ(ierr);
00133 ierr = putTempAtDepth(); CHKERRQ(ierr);
00134
00135 if (config.get_flag("do_cold_ice_methods") == false) {
00136 ierr = verbPrintf(2, grid.com,
00137 " ice enthalpy set from temperature, as cold ice (zero liquid fraction)\n");
00138 CHKERRQ(ierr);
00139 }
00140
00141 ierr = verbPrintf(2, grid.com, "done reading %s; bootstrapping done\n",filename); CHKERRQ(ierr);
00142
00143 delete lic;
00144
00145 return 0;
00146 }
00147
00148
00150
00155 PetscErrorCode IceModel::readShelfStreamBCFromFile(const char *filename) {
00156 PetscErrorCode ierr;
00157 IceModelVec2S vbcflag;
00158 IceModelVec2V vel_bc;
00159 PISMIO nc(&grid);
00160
00161
00162 int maskid, ubarid, vbarid, bcflagid;
00163
00164 bool maskExists=false, ubarExists=false, vbarExists=false, bcflagExists=false;
00165
00166 ierr = nc.open_for_reading(filename); CHKERRQ(ierr);
00167
00168 ierr = nc.find_variable("mask", &maskid, maskExists); CHKERRQ(ierr);
00169 ierr = nc.find_variable("ubar", &ubarid, ubarExists); CHKERRQ(ierr);
00170 ierr = nc.find_variable("vbar", &vbarid, vbarExists); CHKERRQ(ierr);
00171 ierr = nc.find_variable("bcflag", &bcflagid, bcflagExists); CHKERRQ(ierr);
00172
00173 if ( (!ubarExists) || (!vbarExists)) {
00174 ierr = PetscPrintf(grid.com,"-ssaBC set but (ubar,vbar) not found in file %s\n",filename);
00175 CHKERRQ(ierr);
00176 PetscEnd();
00177 }
00178 if (!bcflagExists) {
00179 ierr = PetscPrintf(grid.com,
00180 "-ssaBC set but bcflag (location of Dirichlet b.c.) not found in file %s\n",
00181 filename);
00182 CHKERRQ(ierr);
00183 PetscEnd();
00184 }
00185 ierr = vbcflag.create(grid, "bcflag", false); CHKERRQ(ierr);
00186
00187 ierr = vel_bc.create(grid, "vel_bc", false); CHKERRQ(ierr);
00188 ierr = vel_bc.set_attrs("diagnostic",
00189 "vertical mean of horizontal ice velocity in the X direction",
00190 "m s-1", "land_ice_vertical_mean_x_velocity", 0); CHKERRQ(ierr);
00191 ierr = vel_bc.set_attrs("diagnostic",
00192 "vertical mean of horizontal ice velocity in the Y direction",
00193 "m s-1", "land_ice_vertical_mean_y_velocity", 1); CHKERRQ(ierr);
00194 ierr = vel_bc.set_glaciological_units("m year-1");
00195 vel_bc.write_in_glaciological_units = true;
00196
00197
00198
00199
00200 grid_info g;
00201 ierr = nc.get_grid_info_2d(g); CHKERRQ(ierr);
00202 ierr = nc.close(); CHKERRQ(ierr);
00203
00204 LocalInterpCtx lic(g, NULL, NULL, grid);
00205
00206 if (maskExists) {
00207 vMask.interpolation_mask.number_allowed = 2;
00208 vMask.interpolation_mask.allowed_levels[0] = MASK_SHEET;
00209 vMask.interpolation_mask.allowed_levels[1] = MASK_FLOATING;
00210 vMask.use_interpolation_mask = true;
00211 ierr = vMask.regrid(filename, lic, true); CHKERRQ(ierr);
00212 } else {
00213 ierr = verbPrintf(3, grid.com, " mask not found; leaving current values alone ...\n");
00214 CHKERRQ(ierr);
00215 }
00216 ierr = vel_bc.regrid(filename, lic, true); CHKERRQ(ierr);
00217
00218
00219 vbcflag.interpolation_mask.number_allowed = 2;
00220 vbcflag.interpolation_mask.allowed_levels[0] = 0;
00221 vbcflag.interpolation_mask.allowed_levels[1] = 1;
00222 vbcflag.use_interpolation_mask = true;
00223 ierr = vbcflag.regrid(filename, lic, true); CHKERRQ(ierr);
00224
00225
00226
00227
00228
00229 ierr = uvbar.set(0.0); CHKERRQ(ierr);
00230 PetscScalar **mask, **bc;
00231 ierr = vbcflag.get_array(bc); CHKERRQ(ierr);
00232 ierr = vMask.get_array(mask); CHKERRQ(ierr);
00233 ierr = vel_bc.begin_access(); CHKERRQ(ierr);
00234 ierr = uvbar.begin_access(); CHKERRQ(ierr);
00235
00236 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00237 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00238 if (PetscAbs(bc[i][j] - 1.0) < 0.1) {
00239
00240 uvbar(i-1,j,0) = vel_bc(i,j).u;
00241 uvbar(i,j,0) = vel_bc(i,j).u;
00242 uvbar(i,j-1,1) = vel_bc(i,j).v;
00243 uvbar(i,j,1) = vel_bc(i,j).v;
00244 mask[i][j] = MASK_SHEET;
00245 } else {
00246 uvbar(i-1,j,0) = 0.0;
00247 uvbar(i,j,0) = 0.0;
00248 uvbar(i,j-1,1) = 0.0;
00249 uvbar(i,j,1) = 0.0;
00250 }
00251 }
00252 }
00253 ierr = vbcflag.end_access(); CHKERRQ(ierr);
00254 ierr = vMask.end_access(); CHKERRQ(ierr);
00255 ierr = vel_bc.end_access(); CHKERRQ(ierr);
00256 ierr = uvbar.end_access(); CHKERRQ(ierr);
00257
00258
00259 ierr = update_viewers(); CHKERRQ(ierr);
00260 return 0;
00261 }
00262
00263
00265
00268 PetscErrorCode IceModel::setMaskSurfaceElevation_bootstrap() {
00269 PetscErrorCode ierr;
00270 PetscScalar **h, **bed, **H, **mask;
00271
00272 bool do_ocean_kill = config.get_flag("ocean_kill");
00273
00274 double ocean_rho = config.get("sea_water_density");
00275
00276 ierr = verbPrintf(2, grid.com,
00277 " determining surface elevation by usurf = topg + thk where grounded\n"
00278 " and by flotation crit usurf = (1-rho_i/rho_w) thk where floating\n"); CHKERRQ(ierr);
00279
00280 ierr = verbPrintf(2, grid.com,
00281 " preliminary determination of mask for grounded/floating and sheet/dragging\n"); CHKERRQ(ierr);
00282 if (do_ocean_kill) {
00283 ierr = verbPrintf(2, grid.com,
00284 " option -ocean_kill seen: floating ice mask=3; ice free ocean mask=7\n"); CHKERRQ(ierr);
00285 }
00286
00287 if (ocean == PETSC_NULL) { SETERRQ(1,"PISM ERROR: ocean == PETSC_NULL"); }
00288 PetscReal currentSeaLevel;
00289 ierr = ocean->sea_level_elevation(grid.year, 0, currentSeaLevel); CHKERRQ(ierr);
00290
00291 ierr = vh.get_array(h); CHKERRQ(ierr);
00292 ierr = vH.get_array(H); CHKERRQ(ierr);
00293 ierr = vbed.get_array(bed); CHKERRQ(ierr);
00294 ierr = vMask.get_array(mask); CHKERRQ(ierr);
00295
00296 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00297 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00298
00299 if (H[i][j] < 0.0) {
00300 SETERRQ3(2,"Thickness H=%5.4f is negative at point i=%d, j=%d",H[i][j],i,j);
00301 }
00302
00303 if (H[i][j] < 0.001) {
00304 if (bed[i][j] < 0.0) {
00305 h[i][j] = 0.0;
00306 mask[i][j] = do_ocean_kill ? MASK_OCEAN_AT_TIME_0 : MASK_FLOATING;
00307 } else {
00308 h[i][j] = bed[i][j];
00309 mask[i][j] = MASK_SHEET;
00310 }
00311 } else {
00312 const PetscScalar
00313 hgrounded = bed[i][j] + H[i][j],
00314 hfloating = currentSeaLevel + (1.0 - ice->rho/ocean_rho) * H[i][j];
00315
00316 if (hgrounded > hfloating) {
00317 h[i][j] = hgrounded;
00318 mask[i][j] = MASK_SHEET;
00319 } else {
00320 h[i][j] = hfloating;
00321 mask[i][j] = MASK_FLOATING;
00322 }
00323 }
00324 }
00325 }
00326
00327 ierr = vh.end_access(); CHKERRQ(ierr);
00328 ierr = vH.end_access(); CHKERRQ(ierr);
00329 ierr = vbed.end_access(); CHKERRQ(ierr);
00330 ierr = vMask.end_access(); CHKERRQ(ierr);
00331
00332
00333 ierr = vh.beginGhostComm(); CHKERRQ(ierr);
00334 ierr = vh.endGhostComm(); CHKERRQ(ierr);
00335 ierr = vMask.beginGhostComm(); CHKERRQ(ierr);
00336 ierr = vMask.endGhostComm(); CHKERRQ(ierr);
00337 return 0;
00338 }
00339
00340
00342
00371 PetscErrorCode IceModel::putTempAtDepth() {
00372 PetscErrorCode ierr;
00373 PetscScalar **H, **bed, **Ghf;
00374
00375 PetscScalar *T = new PetscScalar[grid.Mz];
00376
00377 double ocean_rho = config.get("sea_water_density");
00378 double bed_thermal_k = config.get("bedrock_thermal_conductivity");
00379 const bool do_cold = config.get_flag("do_cold_ice_methods");
00380
00381 if (surface != NULL) {
00382 ierr = surface->ice_surface_temperature(grid.year, 0.0, artm); CHKERRQ(ierr);
00383 } else {
00384 SETERRQ(1, "PISM ERROR: surface == NULL");
00385 }
00386
00387 IceModelVec3 *result;
00388 if (do_cold)
00389 result = &T3;
00390 else
00391 result = &Enth3;
00392
00393 ierr = artm.begin_access(); CHKERRQ(ierr);
00394 ierr = vH.get_array(H); CHKERRQ(ierr);
00395 ierr = vbed.get_array(bed); CHKERRQ(ierr);
00396 ierr = vGhf.get_array(Ghf); CHKERRQ(ierr);
00397
00398 ierr = result->begin_access(); CHKERRQ(ierr);
00399 ierr = Tb3.begin_access(); CHKERRQ(ierr);
00400 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00401 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00402 const PetscScalar HH = H[i][j];
00403 const PetscInt ks = grid.kBelowHeight(HH);
00404
00405
00406 const PetscScalar g = Ghf[i][j];
00407 const PetscScalar beta = (4.0/21.0) * (g / (2.0 * ice->k * HH * HH * HH));
00408 const PetscScalar alpha = (g / (2.0 * HH * ice->k)) - 2.0 * HH * HH * beta;
00409 for (PetscInt k = 0; k < ks; k++) {
00410 const PetscScalar depth = HH - grid.zlevels[k];
00411 const PetscScalar Tpmp = ice->meltingTemp - ice->beta_CC_grad * depth;
00412 const PetscScalar d2 = depth * depth;
00413
00414 T[k] = PetscMin(Tpmp,artm(i,j) + alpha * d2 + beta * d2 * d2);
00415
00416 }
00417 for (PetscInt k = ks; k < grid.Mz; k++)
00418 T[k] = artm(i,j);
00419
00420
00421
00422 const PetscScalar floating_base = - (ice->rho/ocean_rho) * H[i][j];
00423 const PetscScalar T_top_bed = (bed[i][j] < floating_base)
00424 ? ice->meltingTemp : T[0];
00425 ierr = bootstrapSetBedrockColumnTemp(i,j,T_top_bed,Ghf[i][j],bed_thermal_k); CHKERRQ(ierr);
00426
00427 if (!do_cold) {
00428 for (PetscInt k = 0; k < grid.Mz; ++k) {
00429 const PetscScalar depth = HH - grid.zlevels[k];
00430 const PetscScalar pressure =
00431 EC->getPressureFromDepth(depth);
00432
00433 ierr = EC->getEnthPermissive(T[k], 0.0, pressure, T[k]); CHKERRQ(ierr);
00434 }
00435 }
00436
00437 ierr = result->setInternalColumn(i,j,T); CHKERRQ(ierr);
00438
00439 }
00440 }
00441 ierr = vH.end_access(); CHKERRQ(ierr);
00442 ierr = vbed.end_access(); CHKERRQ(ierr);
00443 ierr = vGhf.end_access(); CHKERRQ(ierr);
00444 ierr = result->end_access(); CHKERRQ(ierr);
00445 ierr = Tb3.end_access(); CHKERRQ(ierr);
00446 ierr = artm.end_access(); CHKERRQ(ierr);
00447
00448 delete [] T;
00449
00450 ierr = result->beginGhostComm(); CHKERRQ(ierr);
00451 ierr = result->endGhostComm(); CHKERRQ(ierr);
00452
00453 if (do_cold) {
00454 ierr = setEnth3FromT3_ColdIce(); CHKERRQ(ierr);
00455 }
00456
00457 return 0;
00458 }
00459
00460
00462
00471 PetscErrorCode IceModel::bootstrapSetBedrockColumnTemp(PetscInt i, PetscInt j,
00472 PetscScalar Ttopbedrock, PetscScalar geothermflux,
00473 PetscScalar bed_thermal_k) {
00474 PetscScalar *Tb;
00475 Tb = new PetscScalar[grid.Mbz];
00476 for (PetscInt kb = 0; kb < grid.Mbz; kb++)
00477 Tb[kb] = Ttopbedrock - (geothermflux / bed_thermal_k) * grid.zblevels[kb];
00478 PetscErrorCode ierr = Tb3.setInternalColumn(i,j,Tb); CHKERRQ(ierr);
00479 delete [] Tb;
00480 return 0;
00481 }
00482