PISM, A Parallel Ice Sheet Model  stable v0.5
src/base/iMenergy.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 "Mask.hh"
00021 #include "bedrockThermalUnit.hh"
00022 #include "PISMSurface.hh"
00023 #include "PISMOcean.hh"
00024 #include "enthalpyConverter.hh"
00025 
00028 
00030 
00043 PetscErrorCode IceModel::energyStep() {
00044   PetscErrorCode  ierr;
00045 
00046   PetscScalar  myCFLviolcount = 0.0,   // these are counts but they are type "PetscScalar"
00047                myVertSacrCount = 0.0,  //   because that type works with PISMGlobalSum()
00048                myBulgeCount = 0.0;
00049   PetscScalar gVertSacrCount, gBulgeCount;
00050 
00051   // always count CFL violations for sanity check (but can occur only if -skip N with N>1)
00052   ierr = countCFLViolations(&myCFLviolcount); CHKERRQ(ierr);
00053 
00054   // operator-splitting occurs here (ice and bedrock energy updates are split):
00055   //   tell PISMBedThermalUnit* btu that we have an ice base temp; it will return
00056   //   the z=0 value of geothermal flux when called inside temperatureStep() or
00057   //   enthalpyAndDrainageStep()
00058   ierr = get_bed_top_temp(bedtoptemp); CHKERRQ(ierr);
00059   ierr = btu->update(t_TempAge, dt_TempAge); CHKERRQ(ierr);  // has ptr to bedtoptemp
00060 
00061   if (config.get_flag("do_cold_ice_methods")) {
00062     // new temperature values go in vTnew; also updates Hmelt:
00063     ierr = temperatureStep(&myVertSacrCount,&myBulgeCount); CHKERRQ(ierr);  
00064 
00065     ierr = T3.beginGhostCommTransfer(vWork3d); CHKERRQ(ierr);
00066     ierr = T3.endGhostCommTransfer(vWork3d); CHKERRQ(ierr);
00067 
00068     // compute_enthalpy_cold() updates ghosts of Enth3 using a
00069     // begin/endGhostComm pair. Is not optimized because this
00070     // (do_cold_ice_methods) is a rare case.
00071     ierr = compute_enthalpy_cold(T3, Enth3);  CHKERRQ(ierr);
00072 
00073   } else {
00074     // new enthalpy values go in vWork3d; also updates (and communicates) Hmelt
00075     PetscScalar myLiquifiedVol = 0.0, gLiquifiedVol;
00076 
00077     ierr = enthalpyAndDrainageStep(&myVertSacrCount,&myLiquifiedVol,&myBulgeCount);
00078        CHKERRQ(ierr);
00079 
00080     ierr = Enth3.beginGhostCommTransfer(vWork3d); CHKERRQ(ierr);
00081     ierr = Enth3.endGhostCommTransfer(vWork3d); CHKERRQ(ierr);
00082 
00083     ierr = PISMGlobalSum(&myLiquifiedVol, &gLiquifiedVol, grid.com); CHKERRQ(ierr);
00084     if (gLiquifiedVol > 0.0) {
00085       ierr = verbPrintf(1,grid.com,
00086         "\n PISM WARNING: fully-liquified cells detected: volume liquified = %.3f km^3\n\n",
00087         gLiquifiedVol / 1.0e9); CHKERRQ(ierr);
00088     }
00089   }
00090 
00091   // Both cases above update the basal melt rate field; here we update its
00092   // ghosts, which are needed to compute tauc locally
00093   ierr = vbmr.beginGhostComm(); CHKERRQ(ierr);
00094   ierr = vbmr.endGhostComm(); CHKERRQ(ierr);
00095 
00096   ierr = PISMGlobalSum(&myCFLviolcount, &CFLviolcount, grid.com); CHKERRQ(ierr);
00097 
00098   ierr = PISMGlobalSum(&myVertSacrCount, &gVertSacrCount, grid.com); CHKERRQ(ierr);
00099   if (gVertSacrCount > 0.0) { // count of when BOMBPROOF switches to lower accuracy
00100     const PetscScalar bfsacrPRCNT = 100.0 * (gVertSacrCount / (grid.Mx * grid.My));
00101     const PetscScalar BPSACR_REPORT_VERB2_PERCENT = 5.0; // only report if above 5%
00102     if (   (bfsacrPRCNT > BPSACR_REPORT_VERB2_PERCENT) 
00103         && (getVerbosityLevel() > 2)                    ) {
00104       char tempstr[50] = "";
00105       snprintf(tempstr,50, "  [BPsacr=%.4f%%] ", bfsacrPRCNT);
00106       stdout_flags = tempstr + stdout_flags;
00107     }
00108   }
00109 
00110   ierr = PISMGlobalSum(&myBulgeCount, &gBulgeCount, grid.com); CHKERRQ(ierr);
00111   if (gBulgeCount > 0.0) {   // count of when advection bulges are limited;
00112                              //    frequently it is identically zero
00113     char tempstr[50] = "";
00114     snprintf(tempstr,50, " BULGE=%d ", static_cast<int>(ceil(gBulgeCount)) );
00115     stdout_flags = tempstr + stdout_flags;
00116   }
00117 
00118   return 0;
00119 }
00120 
00121 
00124 PetscErrorCode IceModel::get_bed_top_temp(IceModelVec2S &result) {
00125   PetscErrorCode  ierr;
00126   PetscReal sea_level = 0,
00127     T0 = config.get("water_melting_point_temperature"),
00128     beta_CC_grad_sea_water = (config.get("beta_CC") * config.get("sea_water_density") *
00129                               config.get("standard_gravity")); // K m-1
00130 
00131   // will need coupler fields in ice-free land and 
00132   if (surface != PETSC_NULL) {
00133     ierr = surface->ice_surface_temperature(artm); CHKERRQ(ierr);
00134   } else {
00135     SETERRQ(grid.com, 1,"PISM ERROR: surface == PETSC_NULL");
00136   }
00137   if (ocean != PETSC_NULL) {
00138     ierr = ocean->sea_level_elevation(sea_level); CHKERRQ(ierr);
00139   } else {
00140     SETERRQ(grid.com, 5,"PISM ERROR: ocean == PETSC_NULL");
00141   }
00142 
00143   // start by grabbing 2D basal enthalpy field at z=0; converted to temperature if needed, below
00144   ierr = Enth3.getHorSlice(result, 0.0); CHKERRQ(ierr);
00145 
00146   MaskQuery mask(vMask);
00147 
00148   ierr = vbed.begin_access(); CHKERRQ(ierr);
00149   ierr = result.begin_access(); CHKERRQ(ierr);
00150   ierr = vH.begin_access(); CHKERRQ(ierr);
00151   ierr = vMask.begin_access(); CHKERRQ(ierr);
00152   ierr = artm.begin_access(); CHKERRQ(ierr);
00153   for (PetscInt   i = grid.xs; i < grid.xs+grid.xm; ++i) {
00154     for (PetscInt j = grid.ys; j < grid.ys+grid.ym; ++j) {
00155       if (mask.grounded(i,j)) {
00156         if (mask.ice_free(i,j)) { // no ice: sees air temp
00157           result(i,j) = artm(i,j);
00158         } else { // ice: sees temp of base of ice
00159           const PetscReal pressure = EC->getPressureFromDepth(vH(i,j));
00160           PetscReal temp;
00161           // ignore return code when getting temperature: we are committed to
00162           //   this enthalpy field; getAbsTemp() only returns temperatures at or
00163           //   below pressure melting
00164           EC->getAbsTemp(result(i,j), pressure, temp);
00165           result(i,j) = temp;
00166         }
00167       } else { // floating: apply pressure melting temp as top of bedrock temp
00168         result(i,j) = T0 - (sea_level - vbed(i,j)) * beta_CC_grad_sea_water;
00169       }
00170     }
00171   }
00172   ierr = vH.end_access(); CHKERRQ(ierr);
00173   ierr = result.end_access(); CHKERRQ(ierr);
00174   ierr = vMask.end_access(); CHKERRQ(ierr);
00175   ierr = artm.end_access(); CHKERRQ(ierr);
00176   ierr = vbed.end_access(); CHKERRQ(ierr);
00177 
00178   return 0;
00179 }
00180 
00181 
00184 bool IceModel::checkThinNeigh(PetscScalar E, PetscScalar NE, PetscScalar N, PetscScalar NW, 
00185                               PetscScalar W, PetscScalar SW, PetscScalar S, PetscScalar SE) {
00186   // FIXME: silly hard-wired critical level, but we want to avoid config.get() in loops.
00187   const PetscScalar THIN = 100.0;  // thin = (at most 100m thick)
00188   return (   (E < THIN) || (NE < THIN) || (N < THIN) || (NW < THIN)
00189           || (W < THIN) || (SW < THIN) || (S < THIN) || (SE < THIN) );
00190 }
00191 
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines