PISM, A Parallel Ice Sheet Model stable 0.4.1779

src/coupler/PASLapseRates.hh

Go to the documentation of this file.
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_ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines