PISM, A Parallel Ice Sheet Model stable 0.4.1779

src/coupler/PSElevation.cc

Go to the documentation of this file.
00001 // Copyright (C) 2011 Andy Aschwanden 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 "PSElevation.hh"
00020 #include "PISMIO.hh"
00021 
00022 
00024 
00025 PetscErrorCode PSElevation::init(PISMVars &vars) {
00026   PetscErrorCode ierr;
00027 
00028   ierr = verbPrintf(2, grid.com,
00029                     "* Initializing the constant-in-time surface processes model PSElevation. Setting...\n"); CHKERRQ(ierr);
00030 
00031   ierr = PetscOptionsBegin(grid.com, "", "Elevation-dependent surface model options", ""); CHKERRQ(ierr);
00032   {
00033     PetscInt Nartmparam= 4;
00034     PetscReal artmarray[4] = {-5,0,1325,1350};
00035 
00036     ierr = PetscOptionsGetRealArray(PETSC_NULL, "-artm", artmarray, &Nartmparam, &elev_artm_set);
00037     CHKERRQ(ierr);
00038 
00039     artm_min = convert(artmarray[0],"Celsius","Kelvin");
00040     artm_max = convert(artmarray[1],"Celsius","Kelvin");
00041     z_artm_min = artmarray[2];
00042     z_artm_max = artmarray[3];
00043 
00044     PetscInt Nacabparam= 5;
00045     PetscReal acabarray[5] = {-3,4,1100,1450,1700};
00046 
00047     ierr = PetscOptionsGetRealArray(PETSC_NULL, "-acab", acabarray, &Nacabparam, &elev_acab_set);
00048     CHKERRQ(ierr);
00049 
00050     acab_min = convert(acabarray[0],"m year-1","m s-1");
00051     acab_max = convert(acabarray[1],"m year-1","m s-1");
00052     z_acab_min = acabarray[2];
00053     z_ELA = acabarray[3];
00054     z_acab_max = acabarray[4];
00055 
00056     PetscInt Nlimitsparam= 2;
00057     PetscReal limitsarray[2] = {0,0};
00058 
00059     ierr = PetscOptionsGetRealArray(PETSC_NULL, "-acab_limits", limitsarray, &Nlimitsparam, &acab_limits_set);
00060     CHKERRQ(ierr);
00061 
00062     if (acab_limits_set)
00063       {
00064         acab_limit_min = convert(limitsarray[0],"m year-1","m s-1");
00065         acab_limit_max = convert(limitsarray[1],"m year-1","m s-1");
00066       }
00067     else
00068       {
00069         acab_limit_min = acab_min;
00070         acab_limit_max = acab_max;
00071       }
00072 
00073   }
00074   ierr = PetscOptionsEnd(); CHKERRQ(ierr);
00075 
00076   ierr = verbPrintf(3, grid.com,
00077                     "     temperature at %.0f m a.s.l. = %.2f deg C\n"
00078                     "     temperature at %.0f m a.s.l. = %.2f deg C\n"
00079                     "     mass balance below %.0f m a.s.l. = %.2f m/a\n"
00080                     "     mass balance at  %.0f m a.s.l. = %.2f m/a\n"
00081                     "     mass balance at  %.0f m a.s.l. = %.2f m/a\n"
00082                     "     mass balance above %.0f m a.s.l. = %.2f m/a\n"
00083                     "     equilibrium line altitude z_ELA = %.2f m a.s.l.\n",
00084                     z_artm_min, artm_min, z_artm_max, artm_max, z_acab_min, convert(acab_limit_min,"m s-1","m year-1"), z_acab_min, acab_min, z_acab_max, convert(acab_max,"m s-1","m year-1"), z_acab_max, convert(acab_limit_max,"m s-1","m year-1"), z_ELA); CHKERRQ(ierr);
00085 
00086   // get access to ice upper surface elevation
00087   usurf = dynamic_cast<IceModelVec2S*>(vars.get("surface_altitude"));
00088   if (!usurf) SETERRQ(12, "ERROR: 'usurf' is not available or is wrong type in dictionary");
00089 
00090 
00091   // allocate NCSpatialVariables for storing temperature and surface mass balance fields
00092 
00093   acab.init_2d("acab", grid);
00094   acab.set_string("pism_intent", "diagnostic");
00095   acab.set_string("long_name",
00096                   "ice-equivalent surface mass balance (accumulation/ablation) rate");
00097   acab.set_string("standard_name",
00098                   "land_ice_surface_specific_mass_balance");
00099   ierr = acab.set_units("m s-1"); CHKERRQ(ierr);
00100   ierr = acab.set_glaciological_units("m year-1"); CHKERRQ(ierr);
00101 
00102   artm.init_2d("artm", grid);
00103   artm.set_string("pism_intent", "diagnostic");
00104   artm.set_string("long_name",
00105                   "ice temperature at the ice surface");
00106   ierr = artm.set_units("K"); CHKERRQ(ierr);
00107 
00108   // parameterizing the ice surface temperature 'artm'
00109   ierr = verbPrintf(2, grid.com,"    - parameterizing the ice surface temperature 'artm' ... \n"); CHKERRQ(ierr);
00110   ierr = verbPrintf(2, grid.com, 
00111                     "      ice temperature at the ice surface (artm) is piecewise-linear function\n"
00112                     "        of surface altitude (usurf):\n"
00113                     "                 /  %2.2f K                            for            usurf < %.f m\n"
00114                     "         artm = |   %5.2f K + %5.3f * (usurf - %.f m) for   %.f m < usurf < %.f m\n"
00115                     "                 \\  %5.2f K                            for   %.f m < usurf\n",
00116                     artm_min, z_artm_min,
00117                     artm_min, (artm_max-artm_min)/(z_artm_max-z_artm_min), z_artm_min, z_artm_min, z_artm_max,
00118                     artm_max, z_artm_max); CHKERRQ(ierr);
00119 
00120   // parameterizing the ice surface mass balance 'acab'
00121   ierr = verbPrintf(2, grid.com,"    - parameterizing the ice surface mass balance 'acab' ... \n"); CHKERRQ(ierr);
00122 
00123   if (acab_limits_set)
00124     {
00125       ierr = verbPrintf(2, grid.com,"    - option '-acab_limits' seen, limiting upper and lower bounds ... \n"); CHKERRQ(ierr);
00126     }
00127 
00128   ierr = verbPrintf(2, grid.com, 
00129                     "      surface mass balance (acab) is piecewise-linear function\n"
00130                     "        of surface altitue (usurf):\n"
00131                     "                  /  %5.2f m/a                       for          usurf < %3.f m\n"
00132                     "          acab = |    %5.3f 1/a * (usurf-%.0f m)     for %3.f m < usurf < %3.f m\n"
00133                     "                  \\   %5.3f 1/a * (usurf-%.0f m)     for %3.f m < usurf < %3.f m\n"
00134                     "                   \\ %5.2f m/a                       for %3.f m < usurf\n",
00135                     convert(acab_limit_min,"m s-1","m year-1"), z_acab_min,
00136                     convert(-acab_min,"m s-1","m year-1")/(z_ELA - z_acab_min),z_ELA, z_acab_min, z_ELA, 
00137                     convert(acab_max,"m s-1","m year-1")/(z_acab_max - z_ELA),z_ELA, z_ELA, z_acab_max, 
00138                     convert(acab_limit_max,"m s-1","m year-1"), z_acab_max); CHKERRQ(ierr);
00139 
00140 
00141   return 0;
00142 }
00143 
00144 PetscErrorCode PSElevation::ice_surface_mass_flux(IceModelVec2S &result) {
00145   PetscErrorCode ierr;
00146   PetscReal dabdz = -acab_min/(z_ELA - z_acab_min);
00147   PetscReal dacdz = acab_max/(z_acab_max - z_ELA);
00148   string history  = "elevation-dependent surface mass balance\n";
00149 
00150   ierr = result.begin_access();   CHKERRQ(ierr);
00151   ierr = usurf->begin_access();   CHKERRQ(ierr);
00152   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00153     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {      
00154       PetscReal z = (*usurf)(i,j);
00155       if (z < z_acab_min)
00156         {
00157           result(i,j) = acab_limit_min;
00158         }
00159       else if ((z >= z_acab_min) && (z < z_ELA))
00160         {
00161           result(i,j) = dabdz * (z - z_ELA);
00162         }
00163       else if ((z >= z_ELA) && (z <= z_acab_max))
00164         {
00165           result(i,j) = dacdz * (z - z_ELA);
00166         }
00167       else if (z > z_acab_max)
00168         {
00169           result(i,j) = acab_limit_max;
00170         }
00171       else
00172         {
00173           SETERRQ(1,"HOW DID I GET HERE? ... ending...\n");
00174         }
00175       ierr = verbPrintf(5, grid.com,"!!!!! z=%.2f, acab=%.2f\n",z,result(i,j)*secpera); CHKERRQ(ierr);
00176     }
00177   }
00178   ierr = usurf->end_access();   CHKERRQ(ierr);
00179   ierr = result.end_access();   CHKERRQ(ierr);
00180 
00181   ierr = result.set_attr("history", history); CHKERRQ(ierr);
00182 
00183   return 0;
00184 }
00185 
00186 PetscErrorCode PSElevation::ice_surface_temperature(IceModelVec2S &result) {
00187   PetscErrorCode ierr;
00188   string history  = "elevation-dependent ice surface temperature \n";
00189 
00190   ierr = result.begin_access();   CHKERRQ(ierr);
00191   ierr = usurf->begin_access();   CHKERRQ(ierr);
00192   PetscReal dTdz = (artm_max - artm_min)/(z_artm_max - z_artm_min);
00193   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00194     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {      
00195       PetscReal z = (*usurf)(i,j);
00196       if (z <= z_artm_min)
00197         {
00198           result(i,j) = artm_min;
00199         }
00200       else if ((z > z_artm_min) && (z < z_artm_max))
00201         {
00202           result(i,j) = artm_min + dTdz * (z - z_artm_min);    
00203         }
00204       else if (z >= z_artm_max)
00205         {
00206           result(i,j) = artm_max;
00207         }
00208       else
00209         {
00210           SETERRQ(1,"HOW DID I GET HERE? ... ending...\n");
00211         }        
00212       ierr = verbPrintf(5, grid.com,"!!!!! z=%.2f, artm_min=%.2f, dTdz=%.2f, dz=%.2f, artm=%.2f\n",z,artm_min,dTdz,z - z_artm_min,result(i,j)); CHKERRQ(ierr);
00213     }
00214   }
00215   ierr = usurf->end_access();   CHKERRQ(ierr);
00216   ierr = result.end_access();   CHKERRQ(ierr);
00217 
00218   ierr = result.set_attr("history", history); CHKERRQ(ierr);
00219 
00220   return 0;
00221 }
00222 
00223 void PSElevation::add_vars_to_output(string keyword, set<string> &result) {
00224   if (keyword != "small") {
00225     result.insert("artm");
00226     result.insert("acab");
00227   }
00228 }
00229 
00230 PetscErrorCode PSElevation::define_variables(set<string> vars, const NCTool &nc, nc_type nctype) {
00231   PetscErrorCode ierr;
00232   int varid;
00233 
00234   ierr = PISMSurfaceModel::define_variables(vars, nc, nctype); CHKERRQ(ierr);
00235 
00236   if (set_contains(vars, "artm")) {
00237     ierr = artm.define(nc, varid, nctype, true); CHKERRQ(ierr);
00238   }
00239 
00240   if (set_contains(vars, "acab")) {
00241     ierr = acab.define(nc, varid, nctype, true); CHKERRQ(ierr);
00242   }
00243 
00244   return 0;
00245 }
00246 
00247 PetscErrorCode PSElevation::write_variables(set<string> vars, string filename) {
00248   PetscErrorCode ierr;
00249 
00250   if (set_contains(vars, "artm")) {
00251     IceModelVec2S tmp;
00252     ierr = tmp.create(grid, "artm", false); CHKERRQ(ierr);
00253     ierr = tmp.set_metadata(artm, 0); CHKERRQ(ierr);
00254 
00255     ierr = ice_surface_temperature(tmp); CHKERRQ(ierr);
00256 
00257     ierr = tmp.write(filename.c_str()); CHKERRQ(ierr);
00258   }
00259 
00260   if (set_contains(vars, "acab")) {
00261     IceModelVec2S tmp;
00262     ierr = tmp.create(grid, "acab", false); CHKERRQ(ierr);
00263     ierr = tmp.set_metadata(acab, 0); CHKERRQ(ierr);
00264 
00265     ierr = ice_surface_mass_flux(tmp); CHKERRQ(ierr);
00266     tmp.write_in_glaciological_units = true;
00267     ierr = tmp.write(filename.c_str()); CHKERRQ(ierr);
00268   }
00269 
00270   return 0;
00271 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines