|
PISM, A Parallel Ice Sheet Model stable 0.4.1779
|
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 }
1.7.3