|
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 <cstring> 00020 #include "iceModel.hh" 00021 #include "Mask.hh" 00022 00023 #include <petscsys.h> 00024 #include <stdarg.h> 00025 #include <stdlib.h> 00026 00028 00035 PetscErrorCode IceModel::volumeArea(PetscScalar& gvolume, PetscScalar& garea, 00036 PetscScalar& gvolSIA, PetscScalar& gvolstream, 00037 PetscScalar& gvolshelf) { 00038 00039 PetscErrorCode ierr; 00040 PetscScalar volume=0.0, area=0.0, volSIA=0.0, volstream=0.0, volshelf=0.0; 00041 00042 ierr = vH.begin_access(); CHKERRQ(ierr); 00043 ierr = vMask.begin_access(); CHKERRQ(ierr); 00044 ierr = cell_area.begin_access(); CHKERRQ(ierr); 00045 MaskQuery mask(vMask); 00046 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00047 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00048 if (vH(i,j) > 0) { 00049 area += cell_area(i,j); 00050 const PetscScalar dv = cell_area(i,j) * vH(i,j); 00051 volume += dv; 00052 00053 if (mask.ocean(i,j)) volshelf += dv; 00054 } 00055 } 00056 } 00057 00058 ierr = cell_area.end_access(); CHKERRQ(ierr); 00059 ierr = vMask.end_access(); CHKERRQ(ierr); 00060 ierr = vH.end_access(); CHKERRQ(ierr); 00061 00062 ierr = PetscGlobalSum(&volume, &gvolume, grid.com); CHKERRQ(ierr); 00063 ierr = PetscGlobalSum(&area, &garea, grid.com); CHKERRQ(ierr); 00064 ierr = PetscGlobalSum(&volSIA, &gvolSIA, grid.com); CHKERRQ(ierr); 00065 ierr = PetscGlobalSum(&volstream, &gvolstream, grid.com); CHKERRQ(ierr); 00066 ierr = PetscGlobalSum(&volshelf, &gvolshelf, grid.com); CHKERRQ(ierr); 00067 return 0; 00068 } 00069 00070 00077 PetscErrorCode IceModel::energyStats(PetscScalar iarea, PetscScalar &gmeltfrac, 00078 PetscScalar >emp0) { 00079 PetscErrorCode ierr; 00080 PetscScalar meltarea = 0.0, temp0 = 0.0; 00081 const PetscScalar a = grid.dx * grid.dy * 1e-3 * 1e-3; // area unit (km^2) 00082 00083 ierr = vH.begin_access(); CHKERRQ(ierr); 00084 00085 // use Enth3 to get stats 00086 ierr = Enth3.getHorSlice(vWork2d[0], 0.0); CHKERRQ(ierr); // z=0 slice 00087 PetscScalar **Enthbase; 00088 ierr = vWork2d[0].get_array(Enthbase); CHKERRQ(ierr); 00089 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00090 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00091 if (vH(i,j) > 0) { 00092 // accumulate area of base which is at melt point 00093 if (EC->isTemperate(Enthbase[i][j], EC->getPressureFromDepth(vH(i,j)) )) // FIXME task #7297 00094 meltarea += a; 00095 } 00096 // if you happen to be at center, record absolute basal temp there 00097 if (i == (grid.Mx - 1)/2 && j == (grid.My - 1)/2) { 00098 ierr = EC->getAbsTemp(Enthbase[i][j],EC->getPressureFromDepth(vH(i,j)), temp0); // FIXME task #7297 00099 CHKERRQ(ierr); 00100 } 00101 } 00102 } 00103 ierr = vWork2d[0].end_access(); CHKERRQ(ierr); 00104 00105 ierr = vH.end_access(); CHKERRQ(ierr); 00106 00107 // communication 00108 ierr = PetscGlobalSum(&meltarea, &gmeltfrac, grid.com); CHKERRQ(ierr); 00109 ierr = PetscGlobalMax(&temp0, >emp0, grid.com); CHKERRQ(ierr); 00110 00111 // normalize fraction correctly 00112 if (iarea > 0.0) gmeltfrac = gmeltfrac / iarea; 00113 else gmeltfrac = 0.0; 00114 00115 return 0; 00116 } 00117 00118 00123 PetscErrorCode IceModel::ageStats(PetscScalar ivol, PetscScalar &gorigfrac) { 00124 PetscErrorCode ierr; 00125 00126 gorigfrac = -1.0; // result value if not do_age 00127 00128 if (!config.get_flag("do_age")) 00129 return 0; // leave now 00130 00131 const PetscScalar a = grid.dx * grid.dy * 1e-3 * 1e-3, // area unit (km^2) 00132 currtime = grid.year * secpera; // seconds 00133 00134 PetscScalar *tau, origvol = 0.0; 00135 ierr = vH.begin_access(); CHKERRQ(ierr); 00136 ierr = tau3.begin_access(); CHKERRQ(ierr); 00137 00138 // compute local original volume 00139 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00140 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00141 if (vH(i,j) > 0) { 00142 // accumulate volume of ice which is original 00143 ierr = tau3.getInternalColumn(i,j,&tau); CHKERRQ(ierr); 00144 const PetscInt ks = grid.kBelowHeight(vH(i,j)); 00145 for (PetscInt k=1; k<=ks; k++) { 00146 // ice in segment is original if it is as old as one year less than current time 00147 if (0.5*(tau[k-1]+tau[k]) > currtime - secpera) 00148 origvol += a * 1.0e-3 * (grid.zlevels[k] - grid.zlevels[k-1]); 00149 } 00150 } 00151 } 00152 } 00153 00154 ierr = vH.end_access(); CHKERRQ(ierr); 00155 ierr = tau3.end_access(); CHKERRQ(ierr); 00156 00157 // communicate to turn into global original fraction 00158 ierr = PetscGlobalSum(&origvol, &gorigfrac, grid.com); CHKERRQ(ierr); 00159 00160 // normalize fraction correctly 00161 if (ivol > 0.0) gorigfrac = gorigfrac / ivol; 00162 else gorigfrac = 0.0; 00163 00164 return 0; 00165 } 00166 00167 00168 PetscErrorCode IceModel::summary(bool tempAndAge) { 00169 PetscErrorCode ierr; 00170 PetscScalar divideH; 00171 PetscScalar gdivideH, gdivideT, gvolume, garea; 00172 PetscScalar gvolSIA, gvolstream, gvolshelf; 00173 PetscScalar meltfrac = 0.0, origfrac = 0.0; 00174 00175 // get volumes in m^3 and areas in m^2 00176 ierr = volumeArea(gvolume, garea, gvolSIA, gvolstream, gvolshelf); CHKERRQ(ierr); 00177 00178 // get thick0 = gdivideH 00179 ierr = vH.begin_access(); CHKERRQ(ierr); 00180 divideH = 0; 00181 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00182 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00183 if (i == (grid.Mx - 1)/2 && j == (grid.My - 1)/2) { 00184 divideH = vH(i,j); 00185 } 00186 } 00187 } 00188 ierr = vH.end_access(); CHKERRQ(ierr); 00189 ierr = PetscGlobalMax(÷H, &gdivideH, grid.com); CHKERRQ(ierr); 00190 00191 if (tempAndAge || (getVerbosityLevel() >= 3)) { 00192 ierr = energyStats(garea, meltfrac, gdivideT); CHKERRQ(ierr); 00193 } 00194 00195 if ((tempAndAge || (getVerbosityLevel() >= 3)) && (config.get_flag("do_age"))) { 00196 ierr = ageStats(gvolume, origfrac); CHKERRQ(ierr); 00197 } 00198 00199 // report CFL violations 00200 if (CFLviolcount > 0.0) { 00201 const PetscScalar CFLviolpercent = 100.0 * CFLviolcount / (grid.Mx * grid.Mz * grid.Mz); 00202 // at default verbosity level, only report CFL viols if above: 00203 const PetscScalar CFLVIOL_REPORT_VERB2_PERCENT = 0.1; 00204 if ( (CFLviolpercent > CFLVIOL_REPORT_VERB2_PERCENT) 00205 || (getVerbosityLevel() > 2) ) { 00206 char tempstr[90] = ""; 00207 snprintf(tempstr,90, 00208 " [!CFL#=%1.0f (=%5.2f%% of 3D grid)] ", 00209 CFLviolcount,CFLviolpercent); 00210 stdout_flags = tempstr + stdout_flags; 00211 } 00212 } 00213 00214 // main report: 'S' line 00215 ierr = summaryPrintLine(PETSC_FALSE,(PetscTruth)tempAndAge,grid.year,dt, 00216 gvolume,garea,meltfrac,gdivideH,gdivideT); CHKERRQ(ierr); 00217 00218 return 0; 00219 } 00220 00221 00223 00259 PetscErrorCode IceModel::summaryPrintLine( 00260 PetscTruth printPrototype, bool tempAndAge, 00261 PetscScalar year, PetscScalar delta_t, 00262 PetscScalar volume, PetscScalar area, 00263 PetscScalar /* meltfrac */, PetscScalar H0, PetscScalar T0) { 00264 00265 PetscErrorCode ierr; 00266 const bool do_energy = config.get_flag("do_energy"); 00267 00268 const int log10scale = static_cast<int>(config.get("summary_volarea_scale_factor_log10")); 00269 const double scale = pow(10.0, static_cast<double>(log10scale)); 00270 char volscalestr[10] = " ", // for special case: blank when 10^0 = 1 scaling 00271 areascalestr[10] = " "; // ditto 00272 if (log10scale != 0) { 00273 snprintf(volscalestr, sizeof(volscalestr), "10^%1d_", log10scale); 00274 strcpy(areascalestr,volscalestr); 00275 } 00276 00277 // this version keeps track of what has been done so as to minimize stdout: 00278 static string stdout_flags_count0; 00279 static int mass_cont_sub_counter = 0; 00280 static double mass_cont_sub_dtsum = 0.0; 00281 00282 if (printPrototype == PETSC_TRUE) { 00283 if (do_energy) { 00284 ierr = verbPrintf(2,grid.com, 00285 "P YEAR: ivol iarea thick0 temp0\n"); 00286 ierr = verbPrintf(2,grid.com, 00287 "U years %skm^3 %skm^2 m K\n", 00288 volscalestr,areascalestr); 00289 } else { 00290 ierr = verbPrintf(2,grid.com, 00291 "P YEAR: ivol iarea thick0\n"); 00292 ierr = verbPrintf(2,grid.com, 00293 "U years %skm^3 %skm^2 m\n", 00294 volscalestr,areascalestr); 00295 } 00296 } else { 00297 if (mass_cont_sub_counter == 0) 00298 stdout_flags_count0 = stdout_flags; 00299 if (delta_t > 0.0) { 00300 mass_cont_sub_counter++; 00301 mass_cont_sub_dtsum += delta_t; 00302 } 00303 if ((tempAndAge == PETSC_TRUE) || (!do_energy) || (getVerbosityLevel() > 2)) { 00304 char tempstr[90] = ""; 00305 const PetscScalar major_dt_years = mass_cont_sub_dtsum / secpera; 00306 if (mass_cont_sub_counter == 1) { 00307 snprintf(tempstr,90, " (dt=%.5f)", major_dt_years); 00308 } else { 00309 snprintf(tempstr,90, " (dt=%.5f in %d substeps; av dt_sub_mass_cont=%.5f)", 00310 major_dt_years, mass_cont_sub_counter, major_dt_years / mass_cont_sub_counter); 00311 } 00312 stdout_flags_count0 += tempstr; 00313 if (delta_t > 0.0) { // avoids printing an empty line if we have not done anything 00314 stdout_flags_count0 += "\n"; 00315 ierr = verbPrintf(2,grid.com, stdout_flags_count0.c_str()); CHKERRQ(ierr); 00316 } 00317 if (stdout_ssa.length() > 0) { 00318 stdout_ssa += "\n"; 00319 ierr = verbPrintf(2,grid.com, stdout_ssa.c_str()); CHKERRQ(ierr); 00320 } 00321 if (do_energy) { 00322 ierr = verbPrintf(2,grid.com, 00323 "S %12.5f: %8.5f %7.4f %10.3f %9.4f\n", 00324 year, volume/(scale*1.0e9), area/(scale*1.0e6), H0, T0); CHKERRQ(ierr); 00325 } else { 00326 ierr = verbPrintf(2,grid.com, 00327 "S %12.5f: %8.5f %7.4f %10.3f\n", 00328 year, volume/(scale*1.0e9), area/(scale*1.0e6), H0); CHKERRQ(ierr); 00329 } 00330 mass_cont_sub_counter = 0; 00331 mass_cont_sub_dtsum = 0.0; 00332 } 00333 } 00334 return 0; 00335 } 00336 00338 PetscErrorCode IceModel::compute_ice_volume(PetscScalar &result) { 00339 PetscErrorCode ierr; 00340 PetscScalar volume=0.0; 00341 00342 ierr = vH.begin_access(); CHKERRQ(ierr); 00343 ierr = cell_area.begin_access(); CHKERRQ(ierr); 00344 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00345 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00346 if (vH(i,j) > 0) 00347 volume += vH(i,j) * cell_area(i,j); 00348 } 00349 } 00350 ierr = cell_area.end_access(); CHKERRQ(ierr); 00351 ierr = vH.end_access(); CHKERRQ(ierr); 00352 00353 ierr = PetscGlobalSum(&volume, &result, grid.com); CHKERRQ(ierr); 00354 return 0; 00355 } 00356 00357 00359 PetscErrorCode IceModel::compute_ice_volume_temperate(PetscScalar &result) { 00360 PetscErrorCode ierr; 00361 PetscScalar volume=0.0; 00362 00363 PetscScalar *Enth; // do NOT delete this pointer: space returned by 00364 // getInternalColumn() is allocated already 00365 ierr = vH.begin_access(); CHKERRQ(ierr); 00366 ierr = Enth3.begin_access(); CHKERRQ(ierr); 00367 ierr = cell_area.begin_access(); CHKERRQ(ierr); 00368 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00369 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00370 if (vH(i,j) > 0) { 00371 const PetscInt ks = grid.kBelowHeight(vH(i,j)); 00372 ierr = Enth3.getInternalColumn(i,j,&Enth); CHKERRQ(ierr); 00373 for (PetscInt k=0; k<ks; ++k) { 00374 if (EC->isTemperate(Enth[k],EC->getPressureFromDepth(vH(i,j)))) { // FIXME task #7297 00375 volume += (grid.zlevels[k+1] - grid.zlevels[k]) * cell_area(i,j); 00376 } 00377 } 00378 if (EC->isTemperate(Enth[ks],EC->getPressureFromDepth(vH(i,j)))) { // FIXME task #7297 00379 volume += (vH(i,j) - grid.zlevels[ks]) * cell_area(i,j); 00380 } 00381 } 00382 } 00383 } 00384 ierr = cell_area.end_access(); CHKERRQ(ierr); 00385 ierr = Enth3.end_access(); CHKERRQ(ierr); 00386 ierr = vH.end_access(); CHKERRQ(ierr); 00387 00388 ierr = PetscGlobalSum(&volume, &result, grid.com); CHKERRQ(ierr); 00389 return 0; 00390 } 00391 00393 PetscErrorCode IceModel::compute_ice_volume_cold(PetscScalar &result) { 00394 PetscErrorCode ierr; 00395 PetscScalar volume=0.0; 00396 00397 PetscScalar *Enth; // do NOT delete this pointer: space returned by 00398 // getInternalColumn() is allocated already 00399 ierr = vH.begin_access(); CHKERRQ(ierr); 00400 ierr = Enth3.begin_access(); CHKERRQ(ierr); 00401 ierr = cell_area.begin_access(); CHKERRQ(ierr); 00402 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00403 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00404 if (vH(i,j) > 0) { 00405 const PetscInt ks = grid.kBelowHeight(vH(i,j)); 00406 ierr = Enth3.getInternalColumn(i,j,&Enth); CHKERRQ(ierr); 00407 for (PetscInt k=0; k<ks; ++k) { 00408 if (!EC->isTemperate(Enth[k],EC->getPressureFromDepth(vH(i,j)))) { // FIXME task #7297 00409 volume += (grid.zlevels[k+1] - grid.zlevels[k]) * cell_area(i,j); 00410 } 00411 } 00412 if (!EC->isTemperate(Enth[ks],EC->getPressureFromDepth(vH(i,j)))) { // FIXME task #7297 00413 volume += (vH(i,j) - grid.zlevels[ks]) * cell_area(i,j); 00414 } 00415 } 00416 } 00417 } 00418 ierr = cell_area.end_access(); CHKERRQ(ierr); 00419 ierr = Enth3.end_access(); CHKERRQ(ierr); 00420 ierr = vH.end_access(); CHKERRQ(ierr); 00421 00422 ierr = PetscGlobalSum(&volume, &result, grid.com); CHKERRQ(ierr); 00423 return 0; 00424 } 00425 00427 PetscErrorCode IceModel::compute_ice_area(PetscScalar &result) { 00428 PetscErrorCode ierr; 00429 PetscScalar area=0.0; 00430 00431 ierr = vH.begin_access(); CHKERRQ(ierr); 00432 ierr = cell_area.begin_access(); CHKERRQ(ierr); 00433 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00434 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00435 if (vH(i,j) > 0) 00436 area += cell_area(i,j); 00437 } 00438 } 00439 ierr = cell_area.end_access(); CHKERRQ(ierr); 00440 ierr = vH.end_access(); CHKERRQ(ierr); 00441 00442 ierr = PetscGlobalSum(&area, &result, grid.com); CHKERRQ(ierr); 00443 return 0; 00444 } 00445 00447 PetscErrorCode IceModel::compute_ice_area_temperate(PetscScalar &result) { 00448 PetscErrorCode ierr; 00449 PetscScalar area=0.0; 00450 00451 ierr = Enth3.getHorSlice(vWork2d[0], 0.0); CHKERRQ(ierr); // z=0 slice 00452 PetscScalar **Enthbase; 00453 ierr = vWork2d[0].get_array(Enthbase); CHKERRQ(ierr); 00454 00455 ierr = vH.begin_access(); CHKERRQ(ierr); 00456 ierr = cell_area.begin_access(); CHKERRQ(ierr); 00457 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00458 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00459 if ( (vH(i,j) > 0) && (EC->isTemperate(Enthbase[i][j],EC->getPressureFromDepth(vH(i,j)))) ) // FIXME task #7297 00460 area += cell_area(i,j); 00461 } 00462 } 00463 ierr = cell_area.end_access(); CHKERRQ(ierr); 00464 ierr = vH.end_access(); CHKERRQ(ierr); 00465 00466 ierr = PetscGlobalSum(&area, &result, grid.com); CHKERRQ(ierr); 00467 return 0; 00468 } 00469 00471 PetscErrorCode IceModel::compute_ice_area_cold(PetscScalar &result) { 00472 PetscErrorCode ierr; 00473 PetscScalar area=0.0; 00474 00475 ierr = Enth3.getHorSlice(vWork2d[0], 0.0); CHKERRQ(ierr); // z=0 slice 00476 PetscScalar **Enthbase; 00477 ierr = vWork2d[0].get_array(Enthbase); CHKERRQ(ierr); 00478 00479 ierr = vH.begin_access(); CHKERRQ(ierr); 00480 ierr = cell_area.begin_access(); CHKERRQ(ierr); 00481 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00482 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00483 if ( (vH(i,j) > 0) && (!EC->isTemperate(Enthbase[i][j],EC->getPressureFromDepth(vH(i,j)))) ) // FIXME task #7297 00484 area += cell_area(i,j); 00485 } 00486 } 00487 ierr = cell_area.end_access(); CHKERRQ(ierr); 00488 ierr = vH.end_access(); CHKERRQ(ierr); 00489 00490 ierr = PetscGlobalSum(&area, &result, grid.com); CHKERRQ(ierr); 00491 return 0; 00492 } 00493 00495 PetscErrorCode IceModel::compute_ice_area_grounded(PetscScalar &result) { 00496 PetscErrorCode ierr; 00497 PetscScalar area=0.0; 00498 00499 MaskQuery mask(vMask); 00500 00501 ierr = vMask.begin_access(); CHKERRQ(ierr); 00502 ierr = cell_area.begin_access(); CHKERRQ(ierr); 00503 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00504 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00505 if (mask.grounded_ice(i,j)) 00506 area += cell_area(i,j); 00507 } 00508 } 00509 ierr = cell_area.end_access(); CHKERRQ(ierr); 00510 ierr = vMask.end_access(); CHKERRQ(ierr); 00511 00512 ierr = PetscGlobalSum(&area, &result, grid.com); CHKERRQ(ierr); 00513 return 0; 00514 } 00515 00517 PetscErrorCode IceModel::compute_ice_area_floating(PetscScalar &result) { 00518 PetscErrorCode ierr; 00519 PetscScalar area=0.0; 00520 00521 MaskQuery mask(vMask); 00522 00523 ierr = vMask.begin_access(); CHKERRQ(ierr); 00524 ierr = cell_area.begin_access(); CHKERRQ(ierr); 00525 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00526 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00527 if (mask.floating_ice(i,j)) 00528 area += cell_area(i,j); 00529 } 00530 } 00531 ierr = cell_area.end_access(); CHKERRQ(ierr); 00532 ierr = vMask.end_access(); CHKERRQ(ierr); 00533 00534 ierr = PetscGlobalSum(&area, &result, grid.com); CHKERRQ(ierr); 00535 return 0; 00536 } 00537 00538 00540 00546 PetscErrorCode IceModel::compute_ice_enthalpy(PetscScalar &result) { 00547 PetscErrorCode ierr; 00548 PetscScalar enthalpysum = 0.0; 00549 00550 PetscScalar *Enth; // do NOT delete this pointer: space returned by 00551 // getInternalColumn() is allocated already 00552 ierr = vH.begin_access(); CHKERRQ(ierr); 00553 ierr = Enth3.begin_access(); CHKERRQ(ierr); 00554 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00555 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00556 if (vH(i,j) > 0) { 00557 const PetscInt ks = grid.kBelowHeight(vH(i,j)); 00558 ierr = Enth3.getInternalColumn(i,j,&Enth); CHKERRQ(ierr); 00559 for (PetscInt k=0; k<ks; ++k) { 00560 enthalpysum += Enth[k] * (grid.zlevels[k+1] - grid.zlevels[k]); 00561 } 00562 enthalpysum += Enth[ks] * (vH(i,j) - grid.zlevels[ks]); 00563 } 00564 } 00565 } 00566 ierr = vH.end_access(); CHKERRQ(ierr); 00567 ierr = Enth3.end_access(); CHKERRQ(ierr); 00568 00569 enthalpysum *= config.get("ice_density") * (grid.dx * grid.dy); 00570 00571 ierr = PetscGlobalSum(&enthalpysum, &result, grid.com); CHKERRQ(ierr); 00572 return 0; 00573 } 00574 00576 PetscErrorCode IceModel::compute_by_name(string name, PetscScalar &result) { 00577 PetscErrorCode ierr, errcode = 1; 00578 00579 if (name == "ivol") { 00580 errcode = 0; 00581 ierr = compute_ice_volume(result); CHKERRQ(ierr); 00582 } 00583 00584 if (name == "ivoltemp") { 00585 errcode = 0; 00586 ierr = compute_ice_volume_temperate(result); CHKERRQ(ierr); 00587 } 00588 00589 if (name == "ivoltempf") { 00590 errcode = 0; 00591 PetscScalar ivol; 00592 ierr = compute_ice_volume(ivol); CHKERRQ(ierr); 00593 ierr = compute_ice_volume_temperate(result); CHKERRQ(ierr); 00594 result /= ivol; 00595 } 00596 00597 if (name == "ivolcold") { 00598 errcode = 0; 00599 ierr = compute_ice_volume_cold(result); CHKERRQ(ierr); 00600 } 00601 00602 if (name == "ivolcoldf") { 00603 errcode = 0; 00604 PetscScalar ivol; 00605 ierr = compute_ice_volume(ivol); CHKERRQ(ierr); 00606 ierr = compute_ice_volume_cold(result); CHKERRQ(ierr); 00607 result /= ivol; 00608 } 00609 00610 if (name == "imass") { 00611 errcode = 0; 00612 PetscScalar ice_density = config.get("ice_density"); 00613 ierr = compute_ice_volume(result); CHKERRQ(ierr); 00614 result *= ice_density; 00615 } 00616 00617 if (name == "iarea") { 00618 errcode = 0; 00619 ierr = compute_ice_area(result); CHKERRQ(ierr); 00620 } 00621 00622 if (name == "iareatemp") { 00623 errcode = 0; 00624 ierr = compute_ice_area_temperate(result); CHKERRQ(ierr); 00625 } 00626 00627 if (name == "iareatempf") { 00628 errcode = 0; 00629 PetscScalar iarea; 00630 ierr = compute_ice_area(iarea); CHKERRQ(ierr); 00631 ierr = compute_ice_area_temperate(result); CHKERRQ(ierr); 00632 result /= iarea; 00633 } 00634 00635 if (name == "iareacold") { 00636 errcode = 0; 00637 ierr = compute_ice_area_cold(result); CHKERRQ(ierr); 00638 } 00639 00640 if (name == "iareacoldf") { 00641 errcode = 0; 00642 PetscScalar iarea; 00643 ierr = compute_ice_area(iarea); CHKERRQ(ierr); 00644 ierr = compute_ice_area_cold(result); CHKERRQ(ierr); 00645 result /= iarea; 00646 } 00647 00648 if (name == "iareag") { 00649 errcode = 0; 00650 ierr = compute_ice_area_grounded(result); CHKERRQ(ierr); 00651 } 00652 00653 if (name == "iareaf") { 00654 errcode = 0; 00655 ierr = compute_ice_area_floating(result); CHKERRQ(ierr); 00656 } 00657 00658 if (name == "dt") { 00659 errcode = 0; 00660 result = dt; 00661 } 00662 00663 if (name == "divoldt") { 00664 errcode = 0; 00665 result = dvoldt; 00666 } 00667 00668 if (name == "dimassdt") { 00669 errcode = 0; 00670 PetscScalar ice_density = config.get("ice_density"); 00671 result = dvoldt * ice_density; 00672 } 00673 00674 if (name == "ienthalpy") { 00675 errcode = 0; 00676 ierr = compute_ice_enthalpy(result); CHKERRQ(ierr); 00677 } 00678 00679 if (name == "basal_ice_flux") { 00680 errcode = 0; 00681 result = total_basal_ice_flux; 00682 } 00683 00684 if (name == "surface_ice_flux") { 00685 errcode = 0; 00686 result = total_surface_ice_flux; 00687 } 00688 00689 if (name == "sub_shelf_ice_flux") { 00690 errcode = 0; 00691 result = total_sub_shelf_ice_flux; 00692 } 00693 00694 if (name == "nonneg_rule_flux") { 00695 errcode = 0; 00696 result = nonneg_rule_flux; 00697 } 00698 00699 if (name == "ocean_kill_flux") { 00700 errcode = 0; 00701 result = ocean_kill_flux; 00702 } 00703 00704 if (name == "float_kill_flux") { 00705 errcode = 0; 00706 result = float_kill_flux; 00707 } 00708 00709 return errcode; 00710 } 00711 00712 00732 PetscErrorCode IceModel::ice_mass_bookkeeping() { 00733 PetscErrorCode ierr; 00734 00735 bool include_bmr_in_continuity = config.get_flag("include_bmr_in_continuity"); 00736 00737 // note acab and shelfbmassflux are IceModelVec2S owned by IceModel 00738 if (surface != PETSC_NULL) { 00739 ierr = surface->ice_surface_mass_flux(acab); 00740 CHKERRQ(ierr); 00741 } else { SETERRQ(2,"PISM ERROR: surface == PETSC_NULL"); } 00742 00743 if (ocean != PETSC_NULL) { 00744 ierr = ocean->shelf_base_mass_flux(shelfbmassflux); 00745 CHKERRQ(ierr); 00746 } else { SETERRQ(2,"PISM ERROR: ocean == PETSC_NULL"); } 00747 00748 PetscScalar my_total_surface_ice_flux = 0.0, my_total_basal_ice_flux = 0.0, 00749 my_total_sub_shelf_ice_flux = 0.0; 00750 00751 ierr = acab.begin_access(); CHKERRQ(ierr); 00752 ierr = cell_area.begin_access(); CHKERRQ(ierr); 00753 ierr = shelfbmassflux.begin_access(); CHKERRQ(ierr); 00754 ierr = vH.begin_access(); CHKERRQ(ierr); 00755 ierr = vMask.begin_access(); CHKERRQ(ierr); 00756 ierr = vbmr.begin_access(); CHKERRQ(ierr); 00757 00758 MaskQuery mask(vMask); 00759 00760 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00761 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00762 // ignore ice-free cells: 00763 if (mask.ice_free(i,j)) 00764 continue; 00765 00766 my_total_surface_ice_flux += acab(i,j) * cell_area(i,j); // note the "+="! 00767 00768 if (include_bmr_in_continuity) { 00769 if (mask.ocean(i,j)) { 00770 my_total_sub_shelf_ice_flux -= shelfbmassflux(i,j) * cell_area(i,j); // note the "-="! 00771 } else { 00772 my_total_basal_ice_flux -= vbmr(i,j) * cell_area(i,j); // note the "-="! 00773 } 00774 } 00775 00776 } // j 00777 } // i 00778 00779 ierr = acab.end_access(); CHKERRQ(ierr); 00780 ierr = cell_area.end_access(); CHKERRQ(ierr); 00781 ierr = shelfbmassflux.end_access(); CHKERRQ(ierr); 00782 ierr = vH.end_access(); CHKERRQ(ierr); 00783 ierr = vMask.end_access(); CHKERRQ(ierr); 00784 ierr = vbmr.end_access(); CHKERRQ(ierr); 00785 00786 PetscScalar ice_density = config.get("ice_density"); 00787 my_total_surface_ice_flux *= ice_density; 00788 my_total_sub_shelf_ice_flux *= ice_density; 00789 my_total_basal_ice_flux *= ice_density; 00790 00791 ierr = PetscGlobalSum(&my_total_surface_ice_flux, &total_surface_ice_flux, grid.com); CHKERRQ(ierr); 00792 ierr = PetscGlobalSum(&my_total_sub_shelf_ice_flux, &total_sub_shelf_ice_flux, grid.com); CHKERRQ(ierr); 00793 ierr = PetscGlobalSum(&my_total_basal_ice_flux, &total_basal_ice_flux, grid.com); CHKERRQ(ierr); 00794 00795 return 0; 00796 } 00797
1.7.3