PISM, A Parallel Ice Sheet Model stable 0.4.1779

src/coupler/PAYearlyCycle.cc

Go to the documentation of this file.
00001 // Copyright (C) 2008-2011 Ed Bueler, Constantine Khroulev, Ricarda Winkelmann,
00002 // Gudfinna Adalgeirsdottir and Andy Aschwanden
00003 //
00004 // This file is part of PISM.
00005 //
00006 // PISM is free software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the Free Software
00008 // Foundation; either version 2 of the License, or (at your option) any later
00009 // version.
00010 //
00011 // PISM is distributed in the hope that it will be useful, but WITHOUT ANY
00012 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00013 // FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
00014 // details.
00015 //
00016 // You should have received a copy of the GNU General Public License
00017 // along with PISM; if not, write to the Free Software
00018 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00019 
00020 // Implementation of the atmosphere model using constant-in-time precipitation
00021 // and a cosine yearly cycle for near-surface air temperatures.
00022 
00023 // This includes the SeaRISE Greenland parameterization.
00024 
00025 #include "PISMAtmosphere.hh"
00026 
00028 PetscErrorCode PAYearlyCycle::init(PISMVars &vars) {
00029   PetscErrorCode ierr;
00030   bool regrid = false;
00031   int start = -1;
00032 
00033   variables = &vars;
00034 
00035   snow_temp_july_day = config.get("snow_temp_july_day");
00036 
00037   // Allocate internal IceModelVecs:
00038   ierr = temp_ma.create(grid, "airtemp_ma", false); CHKERRQ(ierr);
00039   ierr = temp_ma.set_attrs("diagnostic",
00040                            "mean annual near-surface air temperature (without sub-year time-dependence or forcing)",
00041                            "K", 
00042                            ""); CHKERRQ(ierr);  // no CF standard_name ??
00043   ierr = temp_ma.set_attr("source", reference);
00044 
00045   ierr = temp_mj.create(grid, "airtemp_mj", false); CHKERRQ(ierr);
00046   ierr = temp_mj.set_attrs("diagnostic",
00047                            "mean July near-surface air temperature (without sub-year time-dependence or forcing)",
00048                            "Kelvin",
00049                            ""); CHKERRQ(ierr);  // no CF standard_name ??
00050   ierr = temp_mj.set_attr("source", reference);
00051 
00052   ierr = precip.create(grid, "precip", false); CHKERRQ(ierr);
00053   ierr = precip.set_attrs("climate_state", 
00054                               "mean annual ice-equivalent precipitation rate",
00055                               "m s-1", 
00056                               ""); CHKERRQ(ierr); // no CF standard_name ??
00057   ierr = precip.set_glaciological_units("m year-1");
00058   precip.write_in_glaciological_units = true;
00059   precip.time_independent = true;
00060 
00061   ierr = find_pism_input(precip_filename, regrid, start); CHKERRQ(ierr);
00062 
00063   // read precipitation rate from file
00064   ierr = verbPrintf(2, grid.com, 
00065                     "    reading mean annual ice-equivalent precipitation rate 'precip'\n"
00066                     "      from %s ... \n",
00067                     precip_filename.c_str()); CHKERRQ(ierr); 
00068   if (regrid) {
00069     ierr = precip.regrid(precip_filename.c_str(), true); CHKERRQ(ierr); // fails if not found!
00070   } else {
00071     ierr = precip.read(precip_filename.c_str(), start); CHKERRQ(ierr); // fails if not found!
00072   }
00073   string precip_history = "read from " + precip_filename + "\n";
00074 
00075   ierr = precip.set_attr("history", precip_history); CHKERRQ(ierr);
00076 
00077   airtemp_var.init_2d("airtemp", grid);
00078   airtemp_var.set_string("pism_intent", "diagnostic");
00079   airtemp_var.set_string("long_name",
00080                          "snapshot of the near-surface air temperature");
00081   ierr = airtemp_var.set_units("K"); CHKERRQ(ierr);
00082 
00083   return 0;
00084 }
00085 
00086 void PAYearlyCycle::add_vars_to_output(string keyword, set<string> &result) {
00087   result.insert("precip");
00088 
00089   if (keyword == "big") {
00090     result.insert("airtemp_ma");
00091     result.insert("airtemp_mj");
00092     result.insert("airtemp");
00093   }
00094 }
00095 
00096 PetscErrorCode PAYearlyCycle::define_variables(set<string> vars, const NCTool &nc, nc_type nctype) {
00097   PetscErrorCode ierr;
00098   int varid;
00099 
00100   if (set_contains(vars, "airtemp")) {
00101     ierr = airtemp_var.define(nc, varid, nctype, false); CHKERRQ(ierr);
00102   }
00103 
00104   if (set_contains(vars, "airtemp_ma")) {
00105     ierr = temp_ma.define(nc, nctype); CHKERRQ(ierr);
00106   }
00107 
00108   if (set_contains(vars, "airtemp_mj")) {
00109     ierr = temp_mj.define(nc, nctype); CHKERRQ(ierr);
00110   }
00111 
00112   if (set_contains(vars, "precip")) {
00113     ierr = precip.define(nc, nctype); CHKERRQ(ierr);
00114   }
00115 
00116   return 0;
00117 }
00118 
00119 
00120 PetscErrorCode PAYearlyCycle::write_variables(set<string> vars, string filename) {
00121   PetscErrorCode ierr;
00122 
00123   if (set_contains(vars, "airtemp")) {
00124     IceModelVec2S airtemp;
00125     ierr = airtemp.create(grid, "airtemp", false); CHKERRQ(ierr);
00126     ierr = airtemp.set_metadata(airtemp_var, 0); CHKERRQ(ierr);
00127 
00128     ierr = temp_snapshot(airtemp); CHKERRQ(ierr);
00129 
00130     ierr = airtemp.write(filename.c_str()); CHKERRQ(ierr);
00131   }
00132 
00133   if (set_contains(vars, "airtemp_ma")) {
00134     ierr = temp_ma.write(filename.c_str()); CHKERRQ(ierr);
00135   }
00136 
00137   if (set_contains(vars, "airtemp_mj")) {
00138     ierr = temp_mj.write(filename.c_str()); CHKERRQ(ierr);
00139   }
00140 
00141   if (set_contains(vars, "precip")) {
00142     ierr = precip.write(filename.c_str()); CHKERRQ(ierr);
00143   }
00144 
00145   return 0;
00146 }
00147 
00149 PetscErrorCode PAYearlyCycle::mean_precip(IceModelVec2S &result) {
00150   PetscErrorCode ierr;
00151 
00152   string precip_history = "read from " + precip_filename + "\n";
00153 
00154   ierr = precip.copy_to(result); CHKERRQ(ierr);
00155   ierr = result.set_attr("history", precip_history); CHKERRQ(ierr);
00156 
00157   return 0;
00158 }
00159 
00161 PetscErrorCode PAYearlyCycle::mean_annual_temp(IceModelVec2S &result) {
00162   PetscErrorCode ierr;
00163 
00164   ierr = temp_ma.copy_to(result); CHKERRQ(ierr);
00165   ierr = result.set_attr("history",
00166                          "computed using " + reference + "\n"); CHKERRQ(ierr);
00167 
00168   return 0;
00169 }
00170 
00171 PetscErrorCode PAYearlyCycle::temp_time_series(int i, int j, int N,
00172                                                               PetscReal *ts, PetscReal *values) {
00173   // constants related to the standard yearly cycle
00174   const PetscReal
00175     radpersec = 2.0 * pi / secpera, // radians per second frequency for annual cycle
00176     sperd = 8.64e4, // exact number of seconds per day
00177     julydaysec = sperd * snow_temp_july_day;
00178 
00179   for (PetscInt k = 0; k < N; ++k) {
00180     double tk = ( ts[k] - floor(ts[k]) ) * secpera; // time from the beginning of a year, in seconds
00181     values[k] = temp_ma(i,j) + (temp_mj(i,j) - temp_ma(i,j)) * cos(radpersec * (tk - julydaysec));
00182   }
00183 
00184   return 0;
00185 }
00186 
00187 PetscErrorCode PAYearlyCycle::temp_snapshot(IceModelVec2S &result) {
00188   PetscErrorCode ierr;
00189   const PetscReal
00190     radpersec = 2.0 * pi / secpera, // radians per second frequency for annual cycle
00191     sperd = 8.64e4, // exact number of seconds per day
00192     julydaysec = sperd * config.get("snow_temp_july_day");
00193 
00194   double T = t + 0.5 * dt;
00195 
00196   double t_sec = ( T - floor(T) ) * secpera; // time from the beginning of a year, in seconds
00197 
00198   ierr = temp_mj.add(-1.0, temp_ma, result); CHKERRQ(ierr); // tmp = temp_mj - temp_ma
00199   ierr = result.scale(cos(radpersec * (t_sec - julydaysec))); CHKERRQ(ierr);
00200   ierr = result.add(1.0, temp_ma); CHKERRQ(ierr);
00201   // result = temp_ma + (temp_mj - temp_ma) * cos(radpersec * (T - julydaysec));
00202 
00203   string history = "computed using " + reference + "\n";
00204   ierr = result.set_attr("history", history); CHKERRQ(ierr);
00205 
00206   return 0;
00207 }
00208 
00209 PetscErrorCode PAYearlyCycle::begin_pointwise_access() {
00210   PetscErrorCode ierr;
00211 
00212   ierr = temp_ma.begin_access(); CHKERRQ(ierr);
00213   ierr = temp_mj.begin_access(); CHKERRQ(ierr);
00214 
00215   return 0;
00216 }
00217 
00218 PetscErrorCode PAYearlyCycle::end_pointwise_access() {
00219   PetscErrorCode ierr;
00220 
00221   ierr = temp_ma.end_access(); CHKERRQ(ierr);
00222   ierr = temp_mj.end_access(); CHKERRQ(ierr);
00223 
00224   return 0;
00225 }
00226 
00228 
00229 PetscErrorCode PA_SeaRISE_Greenland::init(PISMVars &vars) {
00230   PetscErrorCode ierr;
00231 
00232   ierr = verbPrintf(2, grid.com,
00233                     "* Initializing SeaRISE-Greenland atmosphere model based on the Fausto et al (2009)\n"
00234                     "  air temperature parameterization and using stored time-independent precipitation...\n"); CHKERRQ(ierr);
00235   
00236   reference =
00237     "R. S. Fausto, A. P. Ahlstrom, D. V. As, C. E. Boggild, and S. J. Johnsen, 2009. "
00238     "A new present-day temperature parameterization for Greenland. J. Glaciol. 55 (189), 95-105.";
00239 
00240   ierr = PAYearlyCycle::init(vars); CHKERRQ(ierr);
00241 
00242   // initialize pointers to fields the parameterization depends on:
00243   surfelev = dynamic_cast<IceModelVec2S*>(vars.get("surface_altitude"));
00244   if (!surfelev) SETERRQ(1, "ERROR: surface_altitude is not available");
00245 
00246   lat = dynamic_cast<IceModelVec2S*>(vars.get("latitude"));
00247   if (!lat) SETERRQ(1, "ERROR: latitude is not available");
00248 
00249   lon = dynamic_cast<IceModelVec2S*>(vars.get("longitude"));
00250   if (!lon) SETERRQ(1, "ERROR: longitude is not available");
00251 
00252   ierr = PISMOptionsIsSet("-paleo_precip", paleo_precipitation_correction); CHKERRQ(ierr);
00253 
00254   if (paleo_precipitation_correction) {
00255     PetscTruth dTforcing_set;
00256     char dT_file[PETSC_MAX_PATH_LEN];
00257 
00258     ierr = verbPrintf(2, grid.com, 
00259       "  reading delta T data from forcing file %s for -paleo_precip actions ...\n",
00260       dT_file);  CHKERRQ(ierr);
00261 
00262     ierr = PetscOptionsString("-dTforcing", "Specifies the air temperature offsets file",
00263                               "", "",
00264                               dT_file, PETSC_MAX_PATH_LEN, &dTforcing_set); CHKERRQ(ierr);
00265     if (!dTforcing_set) {
00266       ierr = PetscPrintf(grid.com, "ERROR: option -paleo_precip requires -dTforcing.\n"); CHKERRQ(ierr);
00267       PISMEnd();
00268     }
00269     dTforcing = new Timeseries(grid.com, grid.rank, "delta_T", "t");
00270     ierr = dTforcing->set_units("Celsius", ""); CHKERRQ(ierr);
00271     ierr = dTforcing->set_dimension_units("years", ""); CHKERRQ(ierr);
00272     ierr = dTforcing->set_attr("long_name", "near-surface air temperature offsets");
00273              CHKERRQ(ierr);
00274     ierr = dTforcing->read(dT_file); CHKERRQ(ierr);
00275   }
00276 
00277   return 0;
00278 }
00279 
00280 PetscErrorCode PA_SeaRISE_Greenland::mean_precip(IceModelVec2S &result) {
00281   PetscErrorCode ierr;
00282 
00283   ierr = PAYearlyCycle::mean_precip(result); CHKERRQ(ierr);
00284 
00285   if ((dTforcing != NULL) && paleo_precipitation_correction) {
00286     string history = "added the paleo-precipitation correction\n" + result.string_attr("history");
00287 
00288     PetscReal precipexpfactor = config.get("precip_exponential_factor_for_temperature");
00289     ierr = result.scale(exp( precipexpfactor * (*dTforcing)(t + 0.5 * dt) )); CHKERRQ(ierr);
00290 
00291     ierr = result.set_attr("history", history); CHKERRQ(ierr);
00292   }
00293 
00294   return 0;
00295 }
00296 
00300 PetscErrorCode PA_SeaRISE_Greenland::update(PetscReal t_years, PetscReal dt_years) {
00301   PetscErrorCode ierr;
00302 
00303   if ((fabs(t_years - t) < 1e-12) &&
00304       (fabs(dt_years - dt) < 1e-12))
00305     return 0;
00306 
00307   t  = t_years;
00308   dt = dt_years;
00309 
00310   const PetscReal 
00311     d_ma     = config.get("snow_temp_fausto_d_ma"),      // K
00312     gamma_ma = config.get("snow_temp_fausto_gamma_ma"),  // K m-1
00313     c_ma     = config.get("snow_temp_fausto_c_ma"),      // K (degN)-1
00314     kappa_ma = config.get("snow_temp_fausto_kappa_ma"),  // K (degW)-1
00315     d_mj     = config.get("snow_temp_fausto_d_mj"),      // SAME UNITS as for _ma ...
00316     gamma_mj = config.get("snow_temp_fausto_gamma_mj"),
00317     c_mj     = config.get("snow_temp_fausto_c_mj"),
00318     kappa_mj = config.get("snow_temp_fausto_kappa_mj");
00319   
00320   PetscScalar **lat_degN, **lon_degE, **h;
00321   ierr = surfelev->get_array(h);   CHKERRQ(ierr);
00322   ierr = lat->get_array(lat_degN); CHKERRQ(ierr);
00323   ierr = lon->get_array(lon_degE); CHKERRQ(ierr);
00324   ierr = temp_ma.begin_access();  CHKERRQ(ierr);
00325   ierr = temp_mj.begin_access();  CHKERRQ(ierr);
00326 
00327   for (PetscInt i = grid.xs; i<grid.xs+grid.xm; ++i) {
00328     for (PetscInt j = grid.ys; j<grid.ys+grid.ym; ++j) {
00329       temp_ma(i,j) = d_ma + gamma_ma * h[i][j] + c_ma * lat_degN[i][j]
00330                        + kappa_ma * (-lon_degE[i][j]);
00331       temp_mj(i,j) = d_mj + gamma_mj * h[i][j] + c_mj * lat_degN[i][j]
00332                        + kappa_mj * (-lon_degE[i][j]);
00333     }
00334   }
00335   
00336   ierr = surfelev->end_access();   CHKERRQ(ierr);
00337   ierr = lat->end_access(); CHKERRQ(ierr);
00338   ierr = lon->end_access(); CHKERRQ(ierr);
00339   ierr = temp_ma.end_access();  CHKERRQ(ierr);
00340   ierr = temp_mj.end_access();  CHKERRQ(ierr);
00341 
00342   return 0;
00343 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines