PISM, A Parallel Ice Sheet Model stable 0.4.1779

src/coupler/PASDirectForcing.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 surface and atmosphere models reading spatially-variable
00020 // time-dependent B.C. data from a file (-surface given and -atmosphere given).
00021 
00022 #ifndef _PASDIRECTFORCING_H_
00023 #define _PASDIRECTFORCING_H_
00024 
00025 #include "PISMSurface.hh"
00026 #include "PISMAtmosphere.hh"
00027 #include "iceModelVec2T.hh"
00028 
00029 template <class Model>
00030 class PDirectForcing : public Model
00031 {
00032 public:
00033   PDirectForcing(IceGrid &g, const NCConfigVariable &conf)
00034     : Model(g, conf) {}
00035 
00036   virtual ~PDirectForcing() {}
00037 
00038   virtual PetscErrorCode max_timestep(PetscReal t_years, PetscReal &dt_years)
00039   {
00040     PetscReal max_dt = -1;
00041 
00042     // "Periodize" the climate:
00043     t_years = my_mod(t_years);
00044 
00045     dt_years = temp.max_timestep(t_years);
00046 
00047     max_dt = smb.max_timestep(t_years);
00048 
00049     if (dt_years > 0) {
00050       if (max_dt > 0)
00051         dt_years = PetscMin(max_dt, dt_years);
00052     }
00053     else dt_years = max_dt;
00054 
00055     // If the user asked for periodized climate, limit time-steps so that PISM
00056     // never tries to average data over an interval that begins in one period and
00057     // ends in the next one.
00058     if (bc_period > 1e-6)
00059       dt_years = PetscMin(dt_years, bc_period - t_years);
00060 
00061     return 0;
00062   }
00063 
00064   virtual void add_vars_to_output(string keyword, set<string> &result)
00065   {
00066     if (keyword != "small") {
00067       result.insert(temp_name);
00068       result.insert(smb_name);
00069     }
00070   }
00071 
00072   virtual PetscErrorCode define_variables(set<string> vars, const NCTool &nc, nc_type nctype)
00073   {
00074     PetscErrorCode ierr;
00075 
00076     if (set_contains(vars, temp_name)) {
00077       ierr = temp.define(nc, nctype); CHKERRQ(ierr); 
00078     }
00079 
00080     if (set_contains(vars, smb_name)) {
00081       ierr = smb.define(nc, nctype); CHKERRQ(ierr);
00082     }
00083 
00084     return 0;
00085   }
00086 
00087   virtual PetscErrorCode write_variables(set<string> vars, string fname)
00088   {
00089     PetscErrorCode ierr;
00090 
00091     if (set_contains(vars, temp_name)) {
00092       ierr = temp.write(fname.c_str()); CHKERRQ(ierr);
00093     }
00094 
00095     if (set_contains(vars, smb_name)) {
00096       ierr = smb.write(fname.c_str()); CHKERRQ(ierr);
00097     }
00098 
00099     return 0;
00100   }
00101 
00102 protected:
00103   IceModelVec2T temp, smb;
00104   string filename, temp_name, smb_name;
00105 
00106   PetscReal bc_period, bc_reference_year;
00107   bool enable_time_averaging;
00108 
00109   PetscErrorCode process_options()
00110   {
00111     PetscErrorCode ierr;
00112     bool bc_file_set, bc_period_set, bc_ref_year_set;
00113   
00114     bc_period = 0;
00115     bc_reference_year = 0;
00116     enable_time_averaging = false;
00117 
00118     ierr = PetscOptionsBegin(Model::grid.com, "", "Direct forcing options", ""); CHKERRQ(ierr);
00119     {
00120       ierr = PISMOptionsString("-bc_file", "Specifies a file with top-surface boundary conditions",
00121                                filename, bc_file_set); CHKERRQ(ierr);
00122       ierr = PISMOptionsReal("-bc_period", "Specifies the length of the climate data period",
00123                              bc_period, bc_period_set); CHKERRQ(ierr);
00124       ierr = PISMOptionsReal("-bc_reference_year", "Boundary condition reference year",
00125                              bc_reference_year, bc_ref_year_set); CHKERRQ(ierr);
00126       ierr = PISMOptionsIsSet("-bc_time_average", "Enable time-averaging of boundary condition data",
00127                               enable_time_averaging); CHKERRQ(ierr);
00128     }
00129     ierr = PetscOptionsEnd(); CHKERRQ(ierr);
00130 
00131     if (bc_file_set == false) {
00132       PetscPrintf(Model::grid.com, "PISM ERROR: option -bc_file is required.\n");
00133       PISMEnd();
00134     }
00135 
00136     return 0;
00137   }
00138 
00139   PetscErrorCode set_vec_parameters(string temp_std_name, string smb_std_name)
00140   {
00141     PetscErrorCode ierr;
00142     unsigned int buffer_size = (unsigned int) Model::config.get("climate_forcing_buffer_size"),
00143       temp_n_records = 1, smb_n_records = 1;
00144 
00145     NCTool nc(Model::grid.com, Model::grid.rank);
00146     ierr = nc.open_for_reading(filename); CHKERRQ(ierr);
00147     ierr = nc.get_nrecords(temp_name, temp_std_name, temp_n_records); CHKERRQ(ierr);
00148     ierr = nc.get_nrecords(smb_name,  smb_std_name,  smb_n_records);  CHKERRQ(ierr);
00149     ierr = nc.close(); CHKERRQ(ierr);
00150 
00151     temp_n_records = PetscMin(temp_n_records, buffer_size);
00152     smb_n_records  = PetscMin(smb_n_records, buffer_size);
00153 
00154     if (temp_n_records < 1) {
00155       PetscPrintf(Model::grid.com, "PISM ERROR: Can't find '%s' (%s) in %s.\n",
00156                   temp_name.c_str(), temp_std_name.c_str(), filename.c_str());
00157       PISMEnd();
00158 
00159     }
00160 
00161     if (smb_n_records < 1) {
00162       PetscPrintf(Model::grid.com, "PISM ERROR: Can't find '%s' (%s) in %s.\n",
00163                   smb_name.c_str(), smb_std_name.c_str(), filename.c_str());
00164       PISMEnd();
00165 
00166     }
00167 
00168     temp.set_n_records(temp_n_records);
00169     smb.set_n_records(smb_n_records);
00170 
00171     temp.strict_timestep_limit = ! enable_time_averaging;
00172     smb.strict_timestep_limit   = ! enable_time_averaging;
00173 
00174     return 0;
00175   }
00176 
00177   virtual PetscErrorCode update_internal(PetscReal t_years, PetscReal dt_years)
00178   {
00179     PetscErrorCode ierr;
00180 
00181     // "Periodize" the climate:
00182     t_years = my_mod(t_years);
00183 
00184     if ((fabs(t_years - Model::t) < 1e-12) &&
00185         (fabs(dt_years - Model::dt) < 1e-12))
00186       return 0;
00187 
00188     Model::t  = t_years;
00189     Model::dt = dt_years;
00190 
00191     ierr = temp.update(Model::t, Model::dt); CHKERRQ(ierr);
00192     ierr = smb.update(Model::t, Model::dt); CHKERRQ(ierr);
00193 
00194     return 0;
00195   }
00196 
00197   PetscReal my_mod(PetscReal input)
00198   {
00199     if (bc_period < 0.01) return input;
00200 
00201     // compute time since the reference year:
00202     PetscReal delta = input - bc_reference_year;
00203 
00204     // compute delta mod bc_period:
00205     return delta - floor(delta / bc_period) * bc_period;
00206   }
00207 };
00208 
00209 class PSDirectForcing : public PDirectForcing<PISMSurfaceModel>
00210 {
00211 public:
00212   PSDirectForcing(IceGrid &g, const NCConfigVariable &conf)
00213     : PDirectForcing<PISMSurfaceModel>(g, conf)
00214   {
00215     temp_name = "artm";
00216     smb_name = "acab";
00217   }
00218   virtual ~PSDirectForcing() {}
00219 
00220   virtual void attach_atmosphere_model(PISMAtmosphereModel *input)
00221   { delete input; }
00222 
00223   virtual PetscErrorCode init(PISMVars &vars);
00224   virtual PetscErrorCode update(PetscReal t_years, PetscReal dt_years);
00225 
00226   virtual PetscErrorCode ice_surface_mass_flux(IceModelVec2S &result);
00227   virtual PetscErrorCode ice_surface_temperature(IceModelVec2S &result);
00228 };
00229 
00230 class PADirectForcing : public PDirectForcing<PISMAtmosphereModel>
00231 {
00232 public:
00233   PADirectForcing(IceGrid &g, const NCConfigVariable &conf)
00234     : PDirectForcing<PISMAtmosphereModel>(g, conf)
00235   {
00236     temp_name = "artm";
00237     smb_name  = "precip";
00238   }
00239 
00240   virtual ~PADirectForcing() {}
00241 
00242   virtual PetscErrorCode init(PISMVars &vars);
00243   virtual PetscErrorCode update(PetscReal t_years, PetscReal dt_years);
00244 
00245   virtual PetscErrorCode mean_precip(IceModelVec2S &result);
00246   virtual PetscErrorCode mean_annual_temp(IceModelVec2S &result); 
00247   virtual PetscErrorCode temp_snapshot(IceModelVec2S &result);
00248 
00249   virtual PetscErrorCode begin_pointwise_access();
00250   virtual PetscErrorCode end_pointwise_access();  
00251   virtual PetscErrorCode temp_time_series(int i, int j, int N,
00252                                           PetscReal *ts, PetscReal *values);
00253 };
00254 
00255 #endif /* _PASDIRECTFORCING_H_ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines