|
PISM, A Parallel Ice Sheet Model stable 0.4.1779
|
00001 // Copyright (C) 2011 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 // Implementation of lapse rate corrections for 00020 // * ice-surface temperature and ice-surface mass balance (-surface ...,lapse_rate) and 00021 // * near-surface air temperature and precipitation (-atmosphere ...,lapse_rate). 00022 00023 #ifndef _PASLAPSERATES_H_ 00024 #define _PASLAPSERATES_H_ 00025 00026 #include "PISMSurface.hh" 00027 #include "PISMAtmosphere.hh" 00028 00029 template <class Model, class Mod> 00030 class PLapseRates : public Mod 00031 { 00032 public: 00033 PLapseRates(IceGrid &g, const NCConfigVariable &conf, Model* in) 00034 : Mod(g, conf, in) 00035 { 00036 surface = thk = NULL; 00037 temp_lapse_rate = 0; 00038 } 00039 00040 virtual ~PLapseRates() {} 00041 00042 virtual PetscErrorCode update(PetscReal t_years, PetscReal dt_years) 00043 { 00044 PetscErrorCode ierr; 00045 00046 PetscReal &m_t = Mod::t; 00047 PetscReal &m_dt = Mod::dt; 00048 00049 // "Periodize" the climate: 00050 t_years = my_mod(t_years); 00051 00052 if ((fabs(t_years - m_t) < 1e-12) && 00053 (fabs(dt_years - m_dt) < 1e-12)) 00054 return 0; 00055 00056 m_t = t_years; 00057 m_dt = dt_years; 00058 00059 ierr = Mod::input_model->update(t_years, dt_years); CHKERRQ(ierr); 00060 00061 ierr = reference_surface.update(m_t, m_dt); CHKERRQ(ierr); 00062 00063 if (enable_time_averaging) { 00064 ierr = reference_surface.interp(m_t + 0.5*m_dt); CHKERRQ(ierr); 00065 } else { 00066 ierr = reference_surface.get_record_years(m_t); CHKERRQ(ierr); 00067 } 00068 00069 return 0; 00070 } 00071 00072 virtual PetscErrorCode max_timestep(PetscReal t_years, PetscReal &dt_years) { 00073 PetscErrorCode ierr; 00074 PetscReal max_dt = -1; 00075 00076 // "Periodize" the climate: 00077 t_years = my_mod(t_years); 00078 00079 ierr = Mod::input_model->max_timestep(t_years, dt_years); CHKERRQ(ierr); 00080 00081 max_dt = reference_surface.max_timestep(t_years); 00082 00083 if (dt_years > 0) { 00084 if (max_dt > 0) 00085 dt_years = PetscMin(max_dt, dt_years); 00086 } 00087 else dt_years = max_dt; 00088 00089 // If the user asked for periodized climate, limit time-steps so that PISM 00090 // never tries to average data over an interval that begins in one period and 00091 // ends in the next one. 00092 if (bc_period > 1e-6) 00093 dt_years = PetscMin(dt_years, bc_period - t_years); 00094 00095 return 0; 00096 } 00097 00098 protected: 00099 IceModelVec2T reference_surface; 00100 IceModelVec2S *surface, *thk; 00101 PetscReal bc_period, bc_reference_year, temp_lapse_rate; 00102 bool enable_time_averaging; 00103 00104 virtual PetscErrorCode init_internal(PISMVars &vars) 00105 { 00106 PetscErrorCode ierr; 00107 string filename; 00108 bool bc_file_set, bc_period_set, bc_ref_year_set, temp_lapse_rate_set; 00109 00110 IceGrid &g = Mod::grid; 00111 00112 enable_time_averaging = false; 00113 bc_period = 0; 00114 bc_reference_year = 0; 00115 00116 ierr = PetscOptionsBegin(g.com, "", "Lapse rate options", ""); CHKERRQ(ierr); 00117 { 00118 ierr = PISMOptionsString("-bc_file", "Specifies a file with top-surface boundary conditions", 00119 filename, bc_file_set); CHKERRQ(ierr); 00120 ierr = PISMOptionsReal("-bc_period", "Specifies the length of the climate data period", 00121 bc_period, bc_period_set); CHKERRQ(ierr); 00122 ierr = PISMOptionsReal("-bc_reference_year", "Boundary condition reference year", 00123 bc_reference_year, bc_ref_year_set); CHKERRQ(ierr); 00124 ierr = PISMOptionsIsSet("-bc_time_average", "Enable time-averaging of boundary condition data", 00125 enable_time_averaging); CHKERRQ(ierr); 00126 ierr = PISMOptionsReal("-temp_lapse_rate", 00127 "Elevation lapse rate for the temperature, in K per km", 00128 temp_lapse_rate, temp_lapse_rate_set); CHKERRQ(ierr); 00129 } 00130 ierr = PetscOptionsEnd(); CHKERRQ(ierr); 00131 00132 if (bc_file_set == false) { 00133 PetscPrintf(g.com, "PISM ERROR: option -bc_file is required.\n"); 00134 PISMEnd(); 00135 } 00136 00137 unsigned int buffer_size = (unsigned int) Mod::config.get("climate_forcing_buffer_size"), 00138 ref_surface_n_records = 1; 00139 00140 NCTool nc(g.com, g.rank); 00141 ierr = nc.open_for_reading(filename); CHKERRQ(ierr); 00142 ierr = nc.get_nrecords("usurf", "surface_altitude", ref_surface_n_records); CHKERRQ(ierr); 00143 ierr = nc.close(); CHKERRQ(ierr); 00144 00145 ref_surface_n_records = PetscMin(ref_surface_n_records, buffer_size); 00146 00147 if (ref_surface_n_records == 0) { 00148 PetscPrintf(g.com, "PISM ERROR: can't find reference surface elevation (usurf) in %s.\n", 00149 filename.c_str()); 00150 PISMEnd(); 00151 } 00152 00153 ierr = verbPrintf(2,g.com, 00154 " reading reference surface elevation from %s ...\n", 00155 filename.c_str()); CHKERRQ(ierr); 00156 00157 reference_surface.set_n_records(ref_surface_n_records); 00158 ierr = reference_surface.create(g, "usurf", false); CHKERRQ(ierr); 00159 ierr = reference_surface.set_attrs("climate_forcing", 00160 "reference surface for lapse rate corrections", 00161 "m", "surface_altitude"); CHKERRQ(ierr); 00162 ierr = reference_surface.init(filename); CHKERRQ(ierr); 00163 00164 reference_surface.strict_timestep_limit = ! enable_time_averaging; 00165 00166 surface = dynamic_cast<IceModelVec2S*>(vars.get("surface_altitude")); 00167 if (!surface) SETERRQ(1, "ERROR: 'usurf' is not available or is wrong type in dictionary"); 00168 00169 thk = dynamic_cast<IceModelVec2S*>(vars.get("land_ice_thickness")); 00170 if (!thk) SETERRQ(1, "ERROR: 'ice thickness' is not available or is wrong type in dictionary"); 00171 00172 return 0; 00173 } 00174 00175 PetscErrorCode lapse_rate_correction(IceModelVec2S &result, PetscReal lapse_rate) 00176 { 00177 PetscErrorCode ierr; 00178 00179 if (PetscAbs(lapse_rate) < 1e-12) 00180 return 0; 00181 00182 ierr = thk->begin_access(); CHKERRQ(ierr); 00183 ierr = surface->begin_access(); CHKERRQ(ierr); 00184 ierr = reference_surface.begin_access(); CHKERRQ(ierr); 00185 ierr = result.begin_access(); CHKERRQ(ierr); 00186 00187 IceGrid &g = Mod::grid; 00188 00189 for (PetscInt i = g.xs; i < g.xs + g.xm; ++i) { 00190 for (PetscInt j = g.ys; j < g.ys + g.ym; ++j) { 00191 if ((*thk)(i,j) > 0) 00192 result(i,j) -= lapse_rate * ((*surface)(i,j) - reference_surface(i,j)); 00193 } 00194 } 00195 00196 ierr = result.end_access(); CHKERRQ(ierr); 00197 ierr = reference_surface.end_access(); CHKERRQ(ierr); 00198 ierr = surface->end_access(); CHKERRQ(ierr); 00199 ierr = thk->end_access(); CHKERRQ(ierr); 00200 00201 return 0; 00202 } 00203 00205 PetscReal my_mod(PetscReal in) { 00206 if (bc_period < 1e-6) return in; 00207 00208 // compute time since the reference year: 00209 PetscReal delta = in - bc_reference_year; 00210 00211 // compute delta mod bc_period: 00212 return delta - floor(delta / bc_period) * bc_period; 00213 } 00214 }; 00215 00216 class PSLapseRates : public PLapseRates<PISMSurfaceModel,PSModifier> 00217 { 00218 public: 00219 PSLapseRates(IceGrid &g, const NCConfigVariable &conf, PISMSurfaceModel* in) 00220 : PLapseRates<PISMSurfaceModel,PSModifier>(g, conf, in) 00221 { 00222 smb_lapse_rate = 0; 00223 } 00224 00225 virtual ~PSLapseRates() {} 00226 00227 virtual PetscErrorCode init(PISMVars &vars); 00228 virtual PetscErrorCode ice_surface_mass_flux(IceModelVec2S &result); 00229 virtual PetscErrorCode ice_surface_temperature(IceModelVec2S &result); 00230 protected: 00231 PetscReal smb_lapse_rate; 00232 }; 00233 00234 class PALapseRates : public PLapseRates<PISMAtmosphereModel,PAModifier> 00235 { 00236 public: 00237 PALapseRates(IceGrid &g, const NCConfigVariable &conf, PISMAtmosphereModel* in) 00238 : PLapseRates<PISMAtmosphereModel,PAModifier>(g, conf, in) 00239 { 00240 precip_lapse_rate = 0; 00241 } 00242 00243 virtual ~PALapseRates() {} 00244 00245 virtual PetscErrorCode init(PISMVars &vars); 00246 00247 virtual PetscErrorCode mean_precip(IceModelVec2S &result); 00248 virtual PetscErrorCode mean_annual_temp(IceModelVec2S &result); 00249 00250 virtual PetscErrorCode begin_pointwise_access(); 00251 virtual PetscErrorCode end_pointwise_access(); 00252 00253 virtual PetscErrorCode temp_time_series(int i, int j, int N, 00254 PetscReal *ts, PetscReal *values); 00255 virtual PetscErrorCode temp_snapshot(IceModelVec2S &result); 00256 protected: 00257 PetscReal precip_lapse_rate; 00258 }; 00259 00260 #endif /* _PASLAPSERATES_H_ */
1.7.3