PISM, A Parallel Ice Sheet Model stable 0.4.1779

src/coupler/PAForcing.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 forcing using spatially-variable time-dependent air
00021 // temperature and precipitaiton anomalies (-atmosphere ...,forcing).
00022 
00023 #include "PISMAtmosphere.hh"
00024 
00025 PAForcing::PAForcing(IceGrid &g, const NCConfigVariable &conf, PISMAtmosphereModel *input)
00026   : PAModifier(g, conf, input) {
00027   temp_anomaly = NULL;
00028   precip_anomaly = NULL;
00029 }
00030 
00031 PAForcing::~PAForcing() {
00032   delete temp_anomaly;
00033   delete precip_anomaly;
00034 }
00035 
00036 PetscErrorCode PAForcing::init(PISMVars &vars) {
00037   PetscErrorCode ierr;
00038   PetscTruth temp_anomaly_set, precip_anomaly_set;
00039   char temp_anomalies_file[PETSC_MAX_PATH_LEN],
00040     precip_anomalies_file[PETSC_MAX_PATH_LEN];
00041 
00042   ierr = input_model->init(vars); CHKERRQ(ierr);
00043 
00044   ierr = verbPrintf(2, grid.com,
00045      "* Initializing air temperature and precipitation forcing...\n"); CHKERRQ(ierr);
00046 
00047   ierr = PetscOptionsBegin(grid.com, "", 
00048                            "Air temperature and precipitation forcing", ""); CHKERRQ(ierr);
00049 
00050   ierr = PetscOptionsString("-anomaly_temp",
00051                             "Specifies the air temperature anomalies file",
00052                             "", "",
00053                             temp_anomalies_file, PETSC_MAX_PATH_LEN, &temp_anomaly_set);
00054                             CHKERRQ(ierr);
00055   ierr = PetscOptionsString("-anomaly_precip", 
00056                             "Specifies the precipitation anomalies file",
00057                             "", "",
00058                             precip_anomalies_file, PETSC_MAX_PATH_LEN, &precip_anomaly_set);
00059                             CHKERRQ(ierr);
00060 
00061   ierr = PetscOptionsEnd(); CHKERRQ(ierr);
00062 
00063   if (! (temp_anomaly_set || precip_anomaly_set) ) {
00064     ierr = verbPrintf(2, grid.com, "  NOTE: Forcing is inactive...\n"); CHKERRQ(ierr);
00065   }
00066 
00067   // check on whether we should read temperature anomalies
00068   if (temp_anomaly_set) {
00069 
00070     ierr = verbPrintf(2,grid.com,
00071                       "    reading air temperature anomalies from %s ...\n",
00072                       temp_anomalies_file); CHKERRQ(ierr);
00073     temp_anomaly = new IceModelVec2T;
00074     temp_anomaly->set_n_records((unsigned int) config.get("climate_forcing_buffer_size"));
00075     ierr = temp_anomaly->create(grid, "temp_anomaly", false); CHKERRQ(ierr);
00076     ierr = temp_anomaly->set_attrs("climate_forcing",
00077                                    "near-surface temperature anomalies",
00078                                    "Kelvin", ""); CHKERRQ(ierr);
00079     ierr = temp_anomaly->init(temp_anomalies_file); CHKERRQ(ierr);
00080   }
00081 
00082   // check on whether we should read precipitation anomalies
00083   if (precip_anomaly_set) {
00084     ierr = verbPrintf(2,grid.com,
00085                       "    reading ice-equivalent precipitation rate anomalies from %s ...\n",
00086                       precip_anomalies_file); CHKERRQ(ierr);
00087 
00088     precip_anomaly = new IceModelVec2T;
00089     precip_anomaly->set_n_records((unsigned int) config.get("climate_forcing_buffer_size")); 
00090     ierr = precip_anomaly->create(grid, "precip_anomaly", false); CHKERRQ(ierr);
00091     ierr = precip_anomaly->set_attrs("climate_forcing",
00092                                          "anomalies of ice-equivalent precipitation rate",
00093                                          "m s-1", ""); CHKERRQ(ierr);
00094     ierr = precip_anomaly->init(precip_anomalies_file); CHKERRQ(ierr);
00095     ierr = precip_anomaly->set_glaciological_units("m year-1");
00096     precip_anomaly->write_in_glaciological_units = true;
00097   }
00098 
00099   airtemp_var.init_2d("airtemp_plus_forcing", grid);
00100   airtemp_var.set_string("pism_intent", "diagnostic");
00101   airtemp_var.set_string("long_name",
00102                          "snapshot of the near-surface air temperature (including forcing)");
00103   ierr = airtemp_var.set_units("K"); CHKERRQ(ierr);
00104 
00105   return 0;
00106 }
00107 
00108 PetscErrorCode PAForcing::max_timestep(PetscReal t_years,
00109                                        PetscReal &dt_years) {
00110   PetscErrorCode ierr;
00111   PetscReal max_dt = -1;
00112   
00113   ierr = input_model->max_timestep(t_years, dt_years); CHKERRQ(ierr);
00114 
00115   if (temp_anomaly != NULL) {
00116     max_dt = temp_anomaly->max_timestep(t_years);
00117 
00118     if (dt_years > 0) {
00119       if (max_dt > 0)
00120         dt_years = PetscMin(max_dt, dt_years);
00121     }
00122     else dt_years = max_dt;
00123   }
00124 
00125   if (precip_anomaly != NULL) {
00126     dt_years = precip_anomaly->max_timestep(t_years);
00127 
00128     if (dt_years > 0) {
00129       if (max_dt > 0)
00130         dt_years = PetscMin(max_dt, dt_years);
00131     }
00132     else dt_years = max_dt;
00133   }
00134 
00135   return 0;
00136 }
00137 
00138 void PAForcing::add_vars_to_output(string keyword, set<string> &result) {
00139   if (keyword == "big") {
00140     result.insert("airtemp_plus_forcing");
00141 
00142     if (temp_anomaly != NULL)
00143       result.insert("temp_anomaly");
00144 
00145     if (precip_anomaly != NULL)
00146       result.insert("precip_anomaly");
00147   }
00148 
00149   input_model->add_vars_to_output(keyword, result);
00150 }
00151 
00152 PetscErrorCode PAForcing::define_variables(set<string> vars, const NCTool &nc, nc_type nctype) {
00153   PetscErrorCode ierr;
00154   int varid;
00155 
00156   ierr = input_model->define_variables(vars, nc, nctype); CHKERRQ(ierr);
00157 
00158   if (set_contains(vars, "airtemp_plus_forcing")) {
00159     ierr = airtemp_var.define(nc, varid, nctype, false); CHKERRQ(ierr);
00160   }
00161 
00162   if (temp_anomaly != NULL) {
00163     if (set_contains(vars, "temp_anomaly")) {
00164       ierr = temp_anomaly->define(nc, nctype); CHKERRQ(ierr);
00165     }
00166   }
00167 
00168   if (precip_anomaly != NULL) {
00169     if (set_contains(vars, "precip_anomaly")) {
00170       ierr = precip_anomaly->define(nc, nctype); CHKERRQ(ierr);
00171     }
00172   }
00173 
00174   return 0;
00175 }
00176 
00177 
00178 PetscErrorCode PAForcing::write_variables(set<string> vars,  string filename) {
00179   PetscErrorCode ierr;
00180   double T = t + 0.5 * dt;
00181 
00182   if (set_contains(vars, "airtemp_plus_forcing")) {
00183     IceModelVec2S airtemp;
00184     ierr = airtemp.create(grid, "airtemp_plus_forcing", false); CHKERRQ(ierr);
00185     ierr = airtemp.set_metadata(airtemp_var, 0); CHKERRQ(ierr);
00186 
00187     ierr = temp_snapshot(airtemp); CHKERRQ(ierr);
00188 
00189     ierr = airtemp.write(filename.c_str()); CHKERRQ(ierr);
00190     vars.erase("airtemp_plus_forcing");
00191   }
00192 
00193   if (temp_anomaly != NULL) {
00194     if (set_contains(vars, "temp_anomaly")) {
00195       ierr = temp_anomaly->update(T, 0); CHKERRQ(ierr);
00196       ierr = temp_anomaly->interp(T); CHKERRQ(ierr);
00197       ierr = temp_anomaly->write(filename.c_str()); CHKERRQ(ierr);
00198       vars.erase("temp_anomaly");
00199     }
00200   }
00201 
00202   if (precip_anomaly != NULL) {
00203     if (set_contains(vars, "precip_anomaly")) {
00204       ierr = precip_anomaly->update(T, 0); CHKERRQ(ierr);
00205       ierr = precip_anomaly->interp(T); CHKERRQ(ierr);
00206       ierr = precip_anomaly->write(filename.c_str()); CHKERRQ(ierr);
00207       vars.erase("precip_anomaly");
00208     }
00209 
00210   }
00211 
00212   ierr = input_model->write_variables(vars, filename); CHKERRQ(ierr);
00213 
00214   return 0;
00215 }
00216 
00217 PetscErrorCode PAForcing::update(PetscReal t_years, PetscReal dt_years) {
00218   PetscErrorCode ierr;
00219 
00220   if ((fabs(t_years - t) < 1e-12) &&
00221       (fabs(dt_years - dt) < 1e-12))
00222     return 0;
00223 
00224   t  = t_years;
00225   dt = dt_years;
00226 
00227   ierr = input_model->update(t_years, dt_years); CHKERRQ(ierr);
00228 
00229   if (temp_anomaly != NULL) {
00230     ierr = temp_anomaly->update(t_years, dt_years); CHKERRQ(ierr);
00231   }
00232 
00233   if (precip_anomaly != NULL) {
00234     ierr = precip_anomaly->update(t_years, dt_years); CHKERRQ(ierr);
00235   }
00236 
00237   return 0;
00238 }
00239 
00240 PetscErrorCode PAForcing::mean_precip(IceModelVec2S &result) {
00241   PetscErrorCode ierr;
00242 
00243   ierr = input_model->mean_precip(result); CHKERRQ(ierr);
00244 
00245   if (precip_anomaly != NULL) {
00246     string history = "added average over time-step of precipitation anomalies\n" + result.string_attr("history");
00247 
00248     double anomaly;
00249 
00250     ierr = precip_anomaly->begin_access(); CHKERRQ(ierr);
00251     ierr = result.begin_access(); CHKERRQ(ierr);
00252     for (PetscInt i = grid.xs; i<grid.xs+grid.xm; ++i) {
00253       for (PetscInt j = grid.ys; j<grid.ys+grid.ym; ++j) {
00254         ierr = precip_anomaly->average(i, j, t, dt, anomaly); CHKERRQ(ierr);
00255         result(i,j) += anomaly;
00256       }
00257     }
00258     ierr = result.end_access(); CHKERRQ(ierr);
00259     ierr = precip_anomaly->end_access(); CHKERRQ(ierr);
00260 
00261     ierr = result.set_attr("history", history); CHKERRQ(ierr);
00262   }
00263 
00264   return 0;
00265 }
00266 
00267 PetscErrorCode PAForcing::mean_annual_temp(IceModelVec2S &result) {
00268   PetscErrorCode ierr;
00269 
00270   ierr = input_model->mean_annual_temp(result); CHKERRQ(ierr);
00271   
00272   if (temp_anomaly != NULL) {
00273     string history = "added annual average of temperature anomalies\n"
00274                      + result.string_attr("history");
00275     // if the temperature anomaly has sub-annual cycle we need to average it
00276     // FIXME: if the anomaly is provided with a flag indicating it is already
00277     //        mean annual, then we could save some work
00278     
00279     // average over the year starting at t
00280     ierr = temp_anomaly->update(t, 1.0); CHKERRQ(ierr);
00281     PetscScalar av_ij;
00282     ierr = temp_anomaly->begin_access(); CHKERRQ(ierr);
00283     ierr = result.begin_access(); CHKERRQ(ierr);
00284     for (PetscInt i = grid.xs; i<grid.xs+grid.xm; ++i) {
00285       for (PetscInt j = grid.ys; j<grid.ys+grid.ym; ++j) {
00286         ierr = temp_anomaly->average(i,j,t,1.0,av_ij); CHKERRQ(ierr);
00287         result(i,j) += av_ij;
00288       }
00289     }
00290     ierr = temp_anomaly->end_access(); CHKERRQ(ierr);
00291     ierr = result.end_access(); CHKERRQ(ierr);
00292 
00293     ierr = result.set_attr("history", history); CHKERRQ(ierr);
00294   }
00295 
00296   return 0;
00297 }
00298 
00299 PetscErrorCode PAForcing::begin_pointwise_access() {
00300   PetscErrorCode ierr;
00301 
00302   ierr = input_model->begin_pointwise_access(); CHKERRQ(ierr);
00303 
00304   if (temp_anomaly != NULL) {
00305     ierr = temp_anomaly->begin_access(); CHKERRQ(ierr);
00306   }
00307 
00308   return 0;
00309 }
00310 
00311 PetscErrorCode PAForcing::end_pointwise_access() {
00312   PetscErrorCode ierr;
00313 
00314   ierr = input_model->end_pointwise_access(); CHKERRQ(ierr);
00315 
00316   if (temp_anomaly != NULL) {
00317     ierr = temp_anomaly->end_access(); CHKERRQ(ierr);
00318   }
00319 
00320   return 0;
00321 }
00322 
00323 PetscErrorCode PAForcing::temp_time_series(int i, int j, int N,
00324                                            PetscReal *ts, PetscReal *values) {
00325   PetscErrorCode ierr;
00326   
00327   ierr = input_model->temp_time_series(i, j, N, ts, values); CHKERRQ(ierr);
00328 
00329   if (temp_anomaly != NULL) {
00330     PetscScalar *tmp = new PetscScalar[N];
00331 
00332     ierr = temp_anomaly->interp(i, j, N, ts, tmp); CHKERRQ(ierr);
00333 
00334     for (PetscInt k = 0; k < N; k++)
00335       values[k] += tmp[k];
00336 
00337     delete tmp;
00338   }
00339 
00340   return 0;
00341 }
00342 
00343 PetscErrorCode PAForcing::temp_snapshot(IceModelVec2S &result) {
00344   PetscErrorCode ierr;
00345 
00346   ierr = input_model->temp_snapshot(result); CHKERRQ(ierr);
00347 
00348   if (temp_anomaly != NULL) {
00349     string history = "added temperature anomalies at midpoint of time-step\n"
00350                      + result.string_attr("history");
00351 
00352     ierr = temp_anomaly->update(t, dt); CHKERRQ(ierr);
00353     ierr = temp_anomaly->interp(t); CHKERRQ(ierr);
00354     ierr = result.add(1.0, *temp_anomaly); CHKERRQ(ierr);
00355 
00356     ierr = result.set_attr("history", history); CHKERRQ(ierr);
00357   }
00358 
00359   return 0;
00360 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines