PISM, A Parallel Ice Sheet Model  stable v0.5
src/base/iceModel_diagnostics.cc
Go to the documentation of this file.
00001 // Copyright (C) 2010, 2011, 2012 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 #include "pism_options.hh"
00020 #include "iceModel_diagnostics.hh"
00021 #include "PISMDiagnostic.hh"
00022 #include "Mask.hh"
00023 
00024 #include "PISMBedDef.hh"
00025 #include "PISMYieldStress.hh"
00026 #include "PISMStressBalance.hh"
00027 #include "PISMSurface.hh"
00028 #include "PISMOcean.hh"
00029 #include "enthalpyConverter.hh"
00030 #include "ShallowStressBalance.hh"
00031 #include "SSB_Modifier.hh"
00032 #include "bedrockThermalUnit.hh"
00033 
00034 PetscErrorCode IceModel::init_diagnostics() {
00035 
00036   // Add IceModel diagnostics:
00037   diagnostics["cts"]              = new IceModel_cts(this, grid, variables);
00038   diagnostics["enthalpybase"]     = new IceModel_enthalpybase(this, grid, variables);
00039   diagnostics["enthalpysurf"]     = new IceModel_enthalpysurf(this, grid, variables);
00040   diagnostics["hardav"]           = new IceModel_hardav(this, grid, variables);
00041   diagnostics["liqfrac"]          = new IceModel_liqfrac(this, grid, variables);
00042   diagnostics["proc_ice_area"]    = new IceModel_proc_ice_area(this, grid, variables);
00043   diagnostics["rank"]             = new IceModel_rank(this, grid, variables);
00044   diagnostics["temp"]             = new IceModel_temp(this, grid, variables);
00045   diagnostics["temp_pa"]          = new IceModel_temp_pa(this, grid, variables);
00046   diagnostics["tempbase"]         = new IceModel_tempbase(this, grid, variables);
00047   diagnostics["tempicethk"]       = new IceModel_tempicethk(this, grid, variables);
00048   diagnostics["tempicethk_basal"] = new IceModel_tempicethk_basal(this, grid, variables);
00049   diagnostics["temppabase"]       = new IceModel_temppabase(this, grid, variables);
00050   diagnostics["tempsurf"]         = new IceModel_tempsurf(this, grid, variables);
00051   diagnostics["dHdt"]             = new IceModel_dHdt(this, grid, variables);
00052 
00053   if (config.get_flag("compute_cumulative_acab")) {
00054     diagnostics["acab_cumulative"]  = new IceModel_acab_cumulative(this, grid, variables);
00055   }
00056 
00057   ts_diagnostics["ivol"]          = new IceModel_ivol(this, grid, variables);
00058   ts_diagnostics["slvol"]         = new IceModel_slvol(this, grid, variables);
00059   ts_diagnostics["divoldt"]       = new IceModel_divoldt(this, grid, variables);
00060   ts_diagnostics["iarea"]         = new IceModel_iarea(this, grid, variables);
00061   ts_diagnostics["imass"]         = new IceModel_imass(this, grid, variables);
00062   ts_diagnostics["dimassdt"]      = new IceModel_dimassdt(this, grid, variables);
00063   ts_diagnostics["ivoltemp"]      = new IceModel_ivoltemp(this, grid, variables);
00064   ts_diagnostics["ivoltempf"]     = new IceModel_ivoltempf(this, grid, variables);
00065   ts_diagnostics["ivolcold"]      = new IceModel_ivolcold(this, grid, variables);
00066   ts_diagnostics["ivolcoldf"]     = new IceModel_ivolcoldf(this, grid, variables);
00067   ts_diagnostics["ivolg"]         = new IceModel_ivolg(this, grid, variables);
00068   ts_diagnostics["ivolf"]         = new IceModel_ivolf(this, grid, variables);
00069   ts_diagnostics["iareatemp"]     = new IceModel_iareatemp(this, grid, variables);
00070   ts_diagnostics["iareatempf"]    = new IceModel_iareatempf(this, grid, variables);
00071   ts_diagnostics["iareacold"]     = new IceModel_iareacold(this, grid, variables);
00072   ts_diagnostics["iareacoldf"]    = new IceModel_iareacoldf(this, grid, variables);
00073   ts_diagnostics["iareag"]        = new IceModel_iareag(this, grid, variables);
00074   ts_diagnostics["iareaf"]        = new IceModel_iareaf(this, grid, variables);
00075   ts_diagnostics["dt"]            = new IceModel_dt(this, grid, variables);
00076   ts_diagnostics["max_diffusivity"] = new IceModel_max_diffusivity(this, grid, variables);
00077   ts_diagnostics["ienthalpy"]     = new IceModel_ienthalpy(this, grid, variables);
00078   ts_diagnostics["max_hor_vel"]   = new IceModel_max_hor_vel(this, grid, variables);
00079 
00080 
00081   ts_diagnostics["surface_ice_flux"]   = new IceModel_surface_flux(this, grid, variables);
00082   ts_diagnostics["cumulative_surface_ice_flux"]   = new IceModel_cumulative_surface_flux(this, grid, variables);
00083   ts_diagnostics["basal_ice_flux"]     = new IceModel_basal_flux(this, grid, variables);
00084   ts_diagnostics["cumulative_basal_ice_flux"]     = new IceModel_cumulative_basal_flux(this, grid, variables);
00085   ts_diagnostics["sub_shelf_ice_flux"] = new IceModel_sub_shelf_flux(this, grid, variables);
00086   ts_diagnostics["cumulative_sub_shelf_ice_flux"] = new IceModel_cumulative_sub_shelf_flux(this, grid, variables);
00087   ts_diagnostics["nonneg_rule_flux"]   = new IceModel_nonneg_flux(this, grid, variables);
00088   ts_diagnostics["cumulative_nonneg_rule_flux"]   = new IceModel_cumulative_nonneg_flux(this, grid, variables);
00089   ts_diagnostics["ocean_kill_flux"]    = new IceModel_ocean_kill_flux(this, grid, variables);
00090   ts_diagnostics["cumulative_ocean_kill_flux"]    = new IceModel_cumulative_ocean_kill_flux(this, grid, variables);
00091   ts_diagnostics["float_kill_flux"]    = new IceModel_float_kill_flux(this, grid, variables);
00092   ts_diagnostics["cumulative_float_kill_flux"]    = new IceModel_cumulative_float_kill_flux(this, grid, variables);
00093   ts_diagnostics["discharge_flux"]    = new IceModel_discharge_flux(this, grid, variables);
00094   ts_diagnostics["cumulative_discharge_flux"]    = new IceModel_cumulative_discharge_flux(this, grid, variables);
00095 
00096 
00097   // Get diagnostics supported by the stress balance object:
00098   stress_balance->get_diagnostics(diagnostics);
00099 
00100   // Get diagnostics supported by the surface model:
00101   surface->get_diagnostics(diagnostics);
00102 
00103   // Get diagnostics supported by the ocean model:
00104   ocean->get_diagnostics(diagnostics);
00105 
00106   // Get diagnostics supported by the bed deformation model:
00107   if (beddef) {
00108     beddef->get_diagnostics(diagnostics);
00109   }
00110 
00111   if (basal_yield_stress) {
00112     basal_yield_stress->get_diagnostics(diagnostics);
00113   }
00114 
00115   bool print_list_and_stop = false;
00116 
00117   PetscErrorCode ierr = PISMOptionsIsSet("-list_diagnostics",
00118                                          "List available diagnostic quantities and stop",
00119                                          print_list_and_stop); CHKERRQ(ierr);
00120   if (print_list_and_stop) {
00121     ierr = list_diagnostics(); CHKERRQ(ierr);
00122 
00123     PISMEnd();
00124   }
00125 
00126   return 0;
00127 }
00128 
00129 PetscErrorCode IceModel::list_diagnostics() {
00130 
00131   PetscPrintf(grid.com, "\n");
00132 
00133   // quantities with dedicated storage
00134   {
00135     map<string, NCSpatialVariable> list;
00136     set<string> vars = variables.keys();
00137 
00138     set<string>::iterator i = vars.begin();
00139     while (i != vars.end()) {
00140       list[*i] = variables.get(*i)->get_metadata();
00141       ++i;
00142     }
00143 
00144 
00145     if (beddef != NULL)
00146       beddef->add_vars_to_output("big", list);
00147 
00148     if (btu != NULL)
00149       btu->add_vars_to_output("big", list);
00150 
00151     if (basal_yield_stress != NULL)
00152       basal_yield_stress->add_vars_to_output("big", list);
00153 
00154     if (stress_balance != NULL)
00155       stress_balance->add_vars_to_output("big", list);
00156 
00157     if (ocean != NULL)
00158       ocean->add_vars_to_output("big", list);
00159 
00160     if (surface != NULL)
00161       surface->add_vars_to_output("big", list);
00162 
00163     for (int d = 3; d > 1; --d) {
00164 
00165       PetscPrintf(grid.com,
00166                   "======== Available %dD quantities with dedicated storage ========\n",
00167                   d);
00168 
00169       map<string,NCSpatialVariable>::iterator j = list.begin();
00170       while(j != list.end()) {
00171 
00172         if ((j->second).get_ndims() == d) {
00173           NCSpatialVariable var = j->second;
00174 
00175           string name = j->first,
00176             units = var.get_string("units"),
00177             glaciological_units = var.get_string("glaciological_units"),
00178             long_name = var.get_string("long_name");
00179 
00180           if (glaciological_units.empty() == false)
00181             units = glaciological_units;
00182 
00183             PetscPrintf(grid.com,
00184                         "   Name: %s [%s]\n"
00185                         "       - %s\n\n", name.c_str(), units.c_str(), long_name.c_str());
00186         }
00187 
00188         ++j;
00189       }
00190     }
00191 
00192   }
00193 
00194   // 2D and 3D diagnostics
00195   for (int d = 3; d > 1; --d) {
00196 
00197     PetscPrintf(grid.com,
00198                 "======== Available %dD diagnostic quantities ========\n",
00199                 d);
00200 
00201     map<string, PISMDiagnostic*>::iterator j = diagnostics.begin();
00202     while (j != diagnostics.end()) {
00203       PISMDiagnostic *diag = j->second;
00204 
00205       string name = j->first,
00206         units = diag->get_metadata().get_string("units"),
00207         glaciological_units = diag->get_metadata().get_string("glaciological_units");
00208 
00209       if (glaciological_units.empty() == false)
00210         units = glaciological_units;
00211 
00212       if (diag->get_metadata().get_ndims() == d) {
00213 
00214         PetscPrintf(grid.com, "   Name: %s [%s]\n", name.c_str(), units.c_str());
00215 
00216         for (int k = 0; k < diag->get_nvars(); ++k) {
00217           NCSpatialVariable var = diag->get_metadata(k);
00218 
00219           string long_name = var.get_string("long_name");
00220 
00221           PetscPrintf(grid.com, "      -  %s\n", long_name.c_str());
00222         }
00223 
00224         PetscPrintf(grid.com, "\n");
00225 
00226       }
00227 
00228       ++j;
00229     }
00230   }
00231 
00232   // scalar time-series
00233   PetscPrintf(grid.com, "======== Available time-series ========\n");
00234 
00235   map<string, PISMTSDiagnostic*>::iterator j = ts_diagnostics.begin();
00236   while (j != ts_diagnostics.end()) {
00237     PISMTSDiagnostic *diag = j->second;
00238 
00239     string name = j->first,
00240       long_name = diag->get_string("long_name"),
00241       units = diag->get_string("units"),
00242       glaciological_units = diag->get_string("glaciological_units");
00243 
00244     if (glaciological_units.empty() == false)
00245       units = glaciological_units;
00246 
00247     PetscPrintf(grid.com,
00248                 "   Name: %s [%s]\n"
00249                 "      -  %s\n\n",
00250                 name.c_str(), units.c_str(), long_name.c_str());
00251 
00252     ++j;
00253   }
00254 
00255   return 0;
00256 }
00257 
00258 
00259 
00260 IceModel_hardav::IceModel_hardav(IceModel *m, IceGrid &g, PISMVars &my_vars)
00261   : PISMDiag<IceModel>(m, g, my_vars) {
00262 
00263   // set metadata:
00264   vars[0].init_2d("hardav", grid);
00265 
00266   const PetscScalar power = 1.0 / model->config.get("Glen_exponent");
00267   char unitstr[TEMPORARY_STRING_LENGTH];
00268   snprintf(unitstr, sizeof(unitstr), "Pa s%f", power);
00269 
00270   set_attrs("vertical average of ice hardness", "",
00271             unitstr, unitstr, 0);
00272 
00273   vars[0].set("valid_min", 0);
00274   vars[0].set("_FillValue", -0.01);
00275 }
00276 
00278 PetscErrorCode IceModel_hardav::compute(IceModelVec* &output) {
00279   PetscErrorCode ierr;
00280   const PetscScalar fillval = -0.01;
00281   PetscScalar *Eij; // columns of enthalpy values
00282 
00283   IceFlowLaw *flow_law = model->stress_balance->get_stressbalance()->get_flow_law();
00284   if (flow_law == NULL) {
00285     flow_law = model->stress_balance->get_ssb_modifier()->get_flow_law();
00286     if (flow_law == NULL) {
00287       PetscPrintf(grid.com, "ERROR: Can't compute vertically-averaged hardness: no flow law is used.\n");
00288       PISMEnd();
00289     }
00290   }
00291 
00292   IceModelVec2S *result = new IceModelVec2S;
00293   ierr = result->create(grid, "hardav", false); CHKERRQ(ierr);
00294   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00295 
00296   ierr = model->Enth3.begin_access(); CHKERRQ(ierr);
00297   ierr = model->vH.begin_access(); CHKERRQ(ierr);
00298   ierr = result->begin_access(); CHKERRQ(ierr);
00299   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00300     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00301       ierr = model->Enth3.getInternalColumn(i,j,&Eij); CHKERRQ(ierr);
00302       const PetscScalar H = model->vH(i,j);
00303       if (H > 0.0) {
00304         (*result)(i,j) = flow_law->averaged_hardness(H, grid.kBelowHeight(H),
00305                                                      &grid.zlevels[0], Eij);
00306       } else { // put negative value below valid range
00307         (*result)(i,j) = fillval;
00308       }
00309     }
00310   }
00311   ierr = model->Enth3.end_access(); CHKERRQ(ierr);
00312   ierr = model->vH.end_access(); CHKERRQ(ierr);
00313   ierr = result->end_access(); CHKERRQ(ierr);
00314 
00315   output = result;
00316   return 0;
00317 }
00318 
00319 
00320 IceModel_rank::IceModel_rank(IceModel *m, IceGrid &g, PISMVars &my_vars)
00321   : PISMDiag<IceModel>(m, g, my_vars) {
00322 
00323   // set metadata:
00324   vars[0].init_2d("rank", grid);
00325 
00326   set_attrs("processor rank", "", "", "", 0);
00327   vars[0].time_independent = true;
00328 }
00329 
00330 PetscErrorCode IceModel_rank::compute(IceModelVec* &output) {
00331   PetscErrorCode ierr;
00332 
00333   IceModelVec2S *result = new IceModelVec2S;
00334   ierr = result->create(grid, "rank", false); CHKERRQ(ierr);
00335   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00336 
00337   ierr = result->begin_access(); CHKERRQ(ierr);
00338   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i)
00339     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j)
00340       (*result)(i,j) = grid.rank;
00341   ierr = result->end_access();
00342 
00343   output = result;
00344   return 0;
00345 }
00346 
00347 
00348 IceModel_cts::IceModel_cts(IceModel *m, IceGrid &g, PISMVars &my_vars)
00349   : PISMDiag<IceModel>(m, g, my_vars) {
00350 
00351   // set metadata:
00352   vars[0].init_3d("cts", grid, g.zlevels);
00353 
00354   set_attrs("cts = E/E_s(p), so cold-temperate transition surface is at cts = 1", "",
00355             "", "", 0);
00356 }
00357 
00358 PetscErrorCode IceModel_cts::compute(IceModelVec* &output) {
00359   PetscErrorCode ierr;
00360 
00361   // update vertical levels (in case the grid was extended
00362   vars[0].set_levels(grid.zlevels);
00363 
00364   IceModelVec3 *result = new IceModelVec3;
00365   ierr = result->create(grid, "cts", false); CHKERRQ(ierr);
00366   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00367 
00368   ierr = model->setCTSFromEnthalpy(*result); CHKERRQ(ierr);
00369 
00370   output = result;
00371   return 0;
00372 }
00373 
00374 IceModel_proc_ice_area::IceModel_proc_ice_area(IceModel *m, IceGrid &g, PISMVars &my_vars)
00375   : PISMDiag<IceModel>(m, g, my_vars) {
00376 
00377   // set metadata:
00378   vars[0].init_2d("proc_ice_area", grid);
00379 
00380   set_attrs("number of cells containing ice in a processor's domain", "",
00381             "", "", 0);
00382   vars[0].time_independent = true;
00383 }
00384 
00385 PetscErrorCode IceModel_proc_ice_area::compute(IceModelVec* &output) {
00386   PetscErrorCode ierr;
00387   IceModelVec2S *thickness;
00388 
00389   thickness = dynamic_cast<IceModelVec2S*>(variables.get("land_ice_thickness"));
00390   if (thickness == NULL) SETERRQ(grid.com, 1, "land_ice_thickness is not available");
00391 
00392   IceModelVec2S *result = new IceModelVec2S;
00393   ierr = result->create(grid, "proc_ice_area", false); CHKERRQ(ierr);
00394   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00395 
00396   PetscInt ice_filled_cells = 0;
00397 
00398   ierr = thickness->begin_access(); CHKERRQ(ierr);
00399   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i)
00400     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j)
00401       if ((*thickness)(i,j) > 0) {
00402         ice_filled_cells += 1;
00403       }
00404   ierr = thickness->end_access(); CHKERRQ(ierr);
00405 
00406   ierr = result->begin_access(); CHKERRQ(ierr);
00407   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i)
00408     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j)
00409       (*result)(i,j) = ice_filled_cells;
00410   ierr = result->end_access();
00411 
00412   output = result;
00413   return 0;
00414 }
00415 
00416 
00417 IceModel_temp::IceModel_temp(IceModel *m, IceGrid &g, PISMVars &my_vars)
00418   : PISMDiag<IceModel>(m, g, my_vars) {
00419 
00420   // set metadata:
00421   vars[0].init_3d("temp", grid, g.zlevels);
00422 
00423   set_attrs("ice temperature", "land_ice_temperature", "K", "K", 0);
00424   vars[0].set("valid_min", 0);
00425 }
00426 
00427 PetscErrorCode IceModel_temp::compute(IceModelVec* &output) {
00428   PetscErrorCode ierr;
00429 
00430   // update vertical levels (in case the grid was extended
00431   vars[0].set_levels(grid.zlevels);
00432 
00433   IceModelVec3 *result = new IceModelVec3;
00434   ierr = result->create(grid, "temp", false); CHKERRQ(ierr);
00435   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00436 
00437   IceModelVec2S *thickness;
00438   IceModelVec3 *enthalpy;
00439 
00440   thickness = dynamic_cast<IceModelVec2S*>(variables.get("land_ice_thickness"));
00441   if (thickness == NULL) SETERRQ(grid.com, 1, "land_ice_thickness is not available");
00442 
00443   enthalpy = dynamic_cast<IceModelVec3*>(variables.get("enthalpy"));
00444   if (enthalpy == NULL) SETERRQ(grid.com, 1, "enthalpy is not available");
00445 
00446   PetscScalar *Tij, *Enthij; // columns of these values
00447   ierr = result->begin_access(); CHKERRQ(ierr);
00448   ierr = enthalpy->begin_access(); CHKERRQ(ierr);
00449   ierr = thickness->begin_access(); CHKERRQ(ierr);
00450   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00451     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00452       ierr = result->getInternalColumn(i,j,&Tij); CHKERRQ(ierr);
00453       ierr = enthalpy->getInternalColumn(i,j,&Enthij); CHKERRQ(ierr);
00454       for (PetscInt k=0; k<grid.Mz; ++k) {
00455         const PetscScalar depth = (*thickness)(i,j) - grid.zlevels[k];
00456         ierr = model->EC->getAbsTemp(Enthij[k],
00457                                      model->EC->getPressureFromDepth(depth),
00458                                      Tij[k]);
00459         if (ierr) {
00460           PetscPrintf(grid.com,
00461                       "\n\nEnthalpyConverter.getAbsTemp() error at i=%d,j=%d,k=%d\n\n",
00462                       i,j,k);
00463         }
00464         CHKERRQ(ierr);
00465       }
00466     }
00467   }
00468   ierr = enthalpy->end_access(); CHKERRQ(ierr);
00469   ierr = result->end_access(); CHKERRQ(ierr);
00470   ierr = thickness->end_access(); CHKERRQ(ierr);
00471 
00472   output = result;
00473   return 0;
00474 }
00475 
00476 
00477 IceModel_temp_pa::IceModel_temp_pa(IceModel *m, IceGrid &g, PISMVars &my_vars)
00478   : PISMDiag<IceModel>(m, g, my_vars) {
00479 
00480   // set metadata:
00481   vars[0].init_3d("temp_pa", grid, g.zlevels);
00482 
00483   set_attrs("pressure-adjusted ice temperature (degrees above pressure-melting point)", "",
00484             "deg_C", "deg_C", 0);
00485   vars[0].set("valid_max", 0);
00486 }
00487 
00488 PetscErrorCode IceModel_temp_pa::compute(IceModelVec* &output) {
00489   PetscErrorCode ierr;
00490   bool cold_mode = model->config.get_flag("do_cold_ice_methods");
00491   PetscReal melting_point_temp = model->config.get("water_melting_point_temperature");
00492 
00493   // update vertical levels (in case the grid was extended
00494   vars[0].set_levels(grid.zlevels);
00495 
00496   IceModelVec3 *result = new IceModelVec3;
00497   ierr = result->create(grid, "temp_pa", false); CHKERRQ(ierr);
00498   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00499 
00500   IceModelVec2S *thickness;
00501   IceModelVec3 *enthalpy;
00502 
00503   thickness = dynamic_cast<IceModelVec2S*>(variables.get("land_ice_thickness"));
00504   if (thickness == NULL) SETERRQ(grid.com, 1, "land_ice_thickness is not available");
00505 
00506   enthalpy = dynamic_cast<IceModelVec3*>(variables.get("enthalpy"));
00507   if (enthalpy == NULL) SETERRQ(grid.com, 1, "enthalpy is not available");
00508 
00509   PetscScalar *Tij, *Enthij; // columns of these values
00510   ierr = result->begin_access(); CHKERRQ(ierr);
00511   ierr = enthalpy->begin_access(); CHKERRQ(ierr);
00512   ierr = thickness->begin_access(); CHKERRQ(ierr);
00513   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00514     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00515       ierr = result->getInternalColumn(i,j,&Tij); CHKERRQ(ierr);
00516       ierr = enthalpy->getInternalColumn(i,j,&Enthij); CHKERRQ(ierr);
00517       for (PetscInt k=0; k<grid.Mz; ++k) {
00518         const PetscScalar depth = (*thickness)(i,j) - grid.zlevels[k],
00519           p = model->EC->getPressureFromDepth(depth);
00520         ierr = model->EC->getPATemp(Enthij[k], p, Tij[k]);
00521         if (ierr) {
00522           PetscPrintf(grid.com,
00523                       "\n\nEnthalpyConverter.getAbsTemp() error at i=%d,j=%d,k=%d\n\n",
00524                       i,j,k);
00525         }
00526         CHKERRQ(ierr);
00527 
00528         if (cold_mode) { // if ice is temperate then its pressure-adjusted temp
00529           // is 273.15
00530           if ( model->EC->isTemperate(Enthij[k],p) && ((*thickness)(i,j) > 0)) {
00531             Tij[k] = melting_point_temp;
00532           }
00533         }
00534 
00535       }
00536     }
00537   }
00538   ierr = enthalpy->end_access(); CHKERRQ(ierr);
00539   ierr = result->end_access(); CHKERRQ(ierr);
00540   ierr = thickness->end_access(); CHKERRQ(ierr);
00541 
00542   ierr = result->shift(-melting_point_temp); CHKERRQ(ierr);
00543 
00544   output = result;
00545   return 0;
00546 }
00547 
00548 IceModel_temppabase::IceModel_temppabase(IceModel *m, IceGrid &g, PISMVars &my_vars)
00549   : PISMDiag<IceModel>(m, g, my_vars) {
00550 
00551   // set metadata:
00552   vars[0].init_2d("temppabase", grid);
00553 
00554   set_attrs("pressure-adjusted ice temperature at the base of ice", "",
00555             "Celsius", "Celsius", 0);
00556 }
00557 
00558 PetscErrorCode IceModel_temppabase::compute(IceModelVec* &output) {
00559   PetscErrorCode ierr;
00560 
00561   bool cold_mode = model->config.get_flag("do_cold_ice_methods");
00562   PetscReal melting_point_temp = model->config.get("water_melting_point_temperature");
00563 
00564   IceModelVec2S *result = new IceModelVec2S;
00565   ierr = result->create(grid, "temp_pa_base", false); CHKERRQ(ierr);
00566   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00567 
00568   IceModelVec2S *thickness;
00569   IceModelVec3 *enthalpy;
00570 
00571   thickness = dynamic_cast<IceModelVec2S*>(variables.get("land_ice_thickness"));
00572   if (thickness == NULL) SETERRQ(grid.com, 1, "land_ice_thickness is not available");
00573 
00574   enthalpy = dynamic_cast<IceModelVec3*>(variables.get("enthalpy"));
00575   if (enthalpy == NULL) SETERRQ(grid.com, 1, "enthalpy is not available");
00576 
00577   PetscScalar *Enthij; // columns of these values
00578   ierr = result->begin_access(); CHKERRQ(ierr);
00579   ierr = enthalpy->begin_access(); CHKERRQ(ierr);
00580   ierr = thickness->begin_access(); CHKERRQ(ierr);
00581   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00582     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00583       ierr = enthalpy->getInternalColumn(i,j,&Enthij); CHKERRQ(ierr);
00584 
00585       const PetscScalar depth = (*thickness)(i,j),
00586         p = model->EC->getPressureFromDepth(depth);
00587       ierr = model->EC->getPATemp(Enthij[0], p,
00588                                   (*result)(i,j));
00589       if (ierr) {
00590         PetscPrintf(grid.com,
00591                     "\n\nEnthalpyConverter.getAbsTemp() error at i=%d,j=%d\n\n",
00592                     i,j);
00593       }
00594       CHKERRQ(ierr);
00595 
00596       if (cold_mode) { // if ice is temperate then its pressure-adjusted temp
00597         // is 273.15
00598         if ( model->EC->isTemperate(Enthij[0],p) && ((*thickness)(i,j) > 0)) {
00599           (*result)(i,j) = melting_point_temp;
00600         }
00601       }
00602     }
00603   }
00604   ierr = enthalpy->end_access(); CHKERRQ(ierr);
00605   ierr = result->end_access(); CHKERRQ(ierr);
00606   ierr = thickness->end_access(); CHKERRQ(ierr);
00607 
00608   ierr = result->shift(-melting_point_temp); CHKERRQ(ierr);
00609 
00610   output = result;
00611   return 0;
00612 }
00613 
00614 IceModel_enthalpysurf::IceModel_enthalpysurf(IceModel *m, IceGrid &g, PISMVars &my_vars)
00615   : PISMDiag<IceModel>(m, g, my_vars) {
00616 
00617   // set metadata:
00618   vars[0].init_2d("enthalpysurf", grid);
00619 
00620   set_attrs("ice enthalpy at 1m below the ice surface", "",
00621             "J kg-1", "J kg-1", 0);
00622   vars[0].set("_FillValue", -0.01);
00623 }
00624 
00625 PetscErrorCode IceModel_enthalpysurf::compute(IceModelVec* &output) {
00626   PetscErrorCode ierr;
00627 
00628   IceModelVec2S *result = new IceModelVec2S;
00629   ierr = result->create(grid, "enthalpysurf", false); CHKERRQ(ierr);
00630   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00631 
00632   PetscScalar fill_value = -0.01;
00633 
00634   // compute levels corresponding to 1 m below the ice surface:
00635 
00636   ierr = model->vH.begin_access(); CHKERRQ(ierr);
00637   ierr = result->begin_access(); CHKERRQ(ierr);
00638   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00639     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00640       (*result)(i,j) = PetscMax(model->vH(i,j) - 1.0, 0.0);
00641     }
00642   }
00643   ierr = result->end_access(); CHKERRQ(ierr);
00644 
00645   ierr = model->Enth3.getSurfaceValues(*result, *result); CHKERRQ(ierr);  // z=0 slice
00646 
00647   ierr = result->begin_access(); CHKERRQ(ierr);
00648   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00649     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00650       if (model->vH(i,j) <= 1.0)
00651         (*result)(i,j) = fill_value;
00652     }
00653   }
00654   ierr = result->end_access(); CHKERRQ(ierr);
00655   ierr = model->vH.end_access(); CHKERRQ(ierr);
00656 
00657 
00658   output = result;
00659   return 0;
00660 }
00661 
00662 IceModel_enthalpybase::IceModel_enthalpybase(IceModel *m, IceGrid &g, PISMVars &my_vars)
00663   : PISMDiag<IceModel>(m, g, my_vars) {
00664 
00665   // set metadata:
00666   vars[0].init_2d("enthalpybase", grid);
00667 
00668   set_attrs("ice enthalpy at the base of ice", "",
00669             "J kg-1", "J kg-1", 0);
00670   vars[0].set("_FillValue", -0.01);
00671 }
00672 
00673 PetscErrorCode IceModel_enthalpybase::compute(IceModelVec* &output) {
00674   PetscErrorCode ierr;
00675 
00676   IceModelVec2S *result = new IceModelVec2S;
00677   ierr = result->create(grid, "enthalpybase", false); CHKERRQ(ierr);
00678   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00679 
00680   ierr = model->Enth3.getHorSlice(*result, 0.0); CHKERRQ(ierr);  // z=0 slice
00681 
00682   ierr = result->mask_by(model->vH, -0.01); CHKERRQ(ierr);
00683 
00684   output = result;
00685   return 0;
00686 }
00687 
00688 
00689 IceModel_tempbase::IceModel_tempbase(IceModel *m, IceGrid &g, PISMVars &my_vars)
00690   : PISMDiag<IceModel>(m, g, my_vars) {
00691 
00692   // set metadata:
00693   vars[0].init_2d("tempbase", grid);
00694 
00695   set_attrs("ice temperature at the base of ice", "",
00696             "K", "K", 0);
00697   vars[0].set("_FillValue", -0.01);
00698 }
00699 
00700 PetscErrorCode IceModel_tempbase::compute(IceModelVec* &output) {
00701   PetscErrorCode ierr;
00702 
00703   IceModelVec2S *result, *thickness;
00704 
00705   IceModel_enthalpybase enth(model, grid, variables);
00706 
00707   ierr = enth.compute(output); CHKERRQ(ierr);
00708   result = dynamic_cast<IceModelVec2S*>(output);
00709   if (result == NULL) SETERRQ(grid.com, 1, "dynamic_cast failure");
00710 
00711   // result contains basal enthalpy; note that it is allocated by
00712   // enth.compute().
00713 
00714   thickness = dynamic_cast<IceModelVec2S*>(variables.get("land_ice_thickness"));
00715   if (thickness == NULL) SETERRQ(grid.com, 1, "land_ice_thickness is not available");
00716 
00717   ierr = result->begin_access(); CHKERRQ(ierr);
00718   ierr = thickness->begin_access(); CHKERRQ(ierr);
00719 
00720   for (PetscInt   i = grid.xs; i < grid.xs+grid.xm; ++i) {
00721     for (PetscInt j = grid.ys; j < grid.ys+grid.ym; ++j) {
00722       PetscReal depth = (*thickness)(i,j),
00723         pressure = model->EC->getPressureFromDepth(depth);
00724       if (depth > 0) {
00725         ierr = model->EC->getAbsTemp((*result)(i,j),
00726                                      pressure,
00727                                      (*result)(i,j));
00728         CHKERRQ(ierr);
00729       } else {
00730         (*result)(i,j) = -0.01;
00731       }
00732     }
00733   }
00734 
00735   ierr = thickness->end_access(); CHKERRQ(ierr);
00736   ierr = result->end_access(); CHKERRQ(ierr);
00737 
00738   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00739   output = result;
00740   return 0;
00741 }
00742 
00743 IceModel_tempsurf::IceModel_tempsurf(IceModel *m, IceGrid &g, PISMVars &my_vars)
00744   : PISMDiag<IceModel>(m, g, my_vars) {
00745 
00746   // set metadata:
00747   vars[0].init_2d("tempsurf", grid);
00748 
00749   set_attrs("ice temperature at 1m below the ice surface", "",
00750             "K", "K", 0);
00751   vars[0].set("_FillValue", -0.01);
00752 }
00753 
00754 PetscErrorCode IceModel_tempsurf::compute(IceModelVec* &output) {
00755   PetscErrorCode ierr;
00756 
00757   IceModelVec2S *result, *thickness;
00758 
00759   thickness = dynamic_cast<IceModelVec2S*>(variables.get("land_ice_thickness"));
00760   if (thickness == NULL) SETERRQ(grid.com, 1, "land_ice_thickness is not available");
00761 
00762   IceModel_enthalpysurf enth(model, grid, variables);
00763 
00764   ierr = enth.compute(output); CHKERRQ(ierr);
00765   result = dynamic_cast<IceModelVec2S*>(output);
00766   if (result == NULL) SETERRQ(grid.com, 1, "dynamic_cast failure");
00767 
00768   // result contains surface enthalpy; note that it is allocated by
00769   // enth.compute().
00770 
00771   ierr = result->begin_access(); CHKERRQ(ierr);
00772   ierr = thickness->begin_access(); CHKERRQ(ierr);
00773 
00774   PetscReal depth = 1.0,
00775     pressure = model->EC->getPressureFromDepth(depth);
00776   for (PetscInt   i = grid.xs; i < grid.xs+grid.xm; ++i) {
00777     for (PetscInt j = grid.ys; j < grid.ys+grid.ym; ++j) {
00778       if ((*thickness)(i,j) > 1) {
00779         ierr = model->EC->getAbsTemp((*result)(i,j),
00780                                      pressure,
00781                                      (*result)(i,j)); CHKERRQ(ierr);
00782       } else {
00783         (*result)(i,j) = -0.01;
00784       }
00785     }
00786   }
00787 
00788   ierr = thickness->end_access(); CHKERRQ(ierr);
00789   ierr = result->end_access(); CHKERRQ(ierr);
00790 
00791   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00792   output = result;
00793   return 0;
00794 }
00795 
00796 
00797 IceModel_liqfrac::IceModel_liqfrac(IceModel *m, IceGrid &g, PISMVars &my_vars)
00798   : PISMDiag<IceModel>(m, g, my_vars) {
00799 
00800   // set metadata:
00801   vars[0].init_3d("liqfrac", grid, g.zlevels);
00802 
00803   set_attrs("liquid water fraction in ice (between 0 and 1)", "",
00804             "1", "1", 0);
00805   vars[0].set("valid_min", 0);
00806   vars[0].set("valid_max", 1);
00807 }
00808 
00809 PetscErrorCode IceModel_liqfrac::compute(IceModelVec* &output) {
00810   PetscErrorCode ierr;
00811 
00812   // update vertical levels (in case the grid was extended
00813   vars[0].set_levels(grid.zlevels);
00814 
00815   IceModelVec3 *result = new IceModelVec3;
00816   ierr = result->create(grid, "liqfrac", false); CHKERRQ(ierr);
00817   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00818 
00819   bool cold_mode = model->config.get_flag("do_cold_ice_methods");
00820 
00821   if (cold_mode) {
00822     ierr = result->set(0.0); CHKERRQ(ierr);
00823   } else {
00824     ierr = model->compute_liquid_water_fraction(model->Enth3, *result); CHKERRQ(ierr);
00825   }
00826 
00827   output = result;
00828   return 0;
00829 }
00830 
00831 IceModel_tempicethk::IceModel_tempicethk(IceModel *m, IceGrid &g, PISMVars &my_vars)
00832   : PISMDiag<IceModel>(m, g, my_vars) {
00833   PetscScalar fill_value = -0.01;
00834 
00835   // set metadata:
00836   vars[0].init_2d("tempicethk", grid);
00837 
00838   set_attrs("temperate ice thickness (total column content)", "",
00839             "m", "m", 0);
00840   vars[0].set("_FillValue", fill_value);
00841 }
00842 
00843 PetscErrorCode IceModel_tempicethk::compute(IceModelVec* &output) {
00844   PetscErrorCode ierr;
00845 
00846   IceModelVec2S *result = new IceModelVec2S;
00847   ierr = result->create(grid, "tempicethk", false); CHKERRQ(ierr);
00848   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00849 
00850   PetscScalar *Enth;
00851 
00852   ierr = result->begin_access(); CHKERRQ(ierr);
00853   ierr = model->Enth3.begin_access(); CHKERRQ(ierr);
00854   ierr = model->vH.begin_access(); CHKERRQ(ierr);
00855   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00856     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00857       if (model->vH(i,j) > 0.) {
00858         ierr = model->Enth3.getInternalColumn(i,j,&Enth); CHKERRQ(ierr);
00859         PetscScalar tithk = 0.;
00860         const PetscInt ks = grid.kBelowHeight(model->vH(i,j));
00861 
00862         for (PetscInt k=0; k<ks; ++k) { // FIXME issue #15
00863           PetscReal pressure = model->EC->getPressureFromDepth(model->vH(i,j) - grid.zlevels[k]);
00864 
00865           if (model->EC->isTemperate(Enth[k], pressure)) {
00866             tithk += grid.zlevels[k+1] - grid.zlevels[k];
00867           }
00868         }
00869 
00870         PetscReal pressure = model->EC->getPressureFromDepth(model->vH(i,j) - grid.zlevels[ks]);
00871         if (model->EC->isTemperate(Enth[ks], pressure)) {
00872           tithk += model->vH(i,j) - grid.zlevels[ks];
00873         }
00874 
00875         (*result)(i,j) = tithk;
00876       }
00877     }
00878   }
00879   ierr = model->Enth3.end_access(); CHKERRQ(ierr);
00880   ierr = model->vH.end_access(); CHKERRQ(ierr);
00881   ierr = result->end_access(); CHKERRQ(ierr);
00882 
00883   PetscScalar fill_value = -0.01;
00884   ierr = result->mask_by(model->vH, fill_value); CHKERRQ(ierr);
00885 
00886   output = result;
00887   return 0;
00888 }
00889 
00890 IceModel_tempicethk_basal::IceModel_tempicethk_basal(IceModel *m, IceGrid &g, PISMVars &my_vars)
00891   : PISMDiag<IceModel>(m, g, my_vars) {
00892   PetscScalar fill_value = -0.01;
00893 
00894   // set metadata:
00895   vars[0].init_2d("tempicethk_basal", grid);
00896 
00897   set_attrs("thickness of the basal layer of temperate ice", "",
00898             "m", "m", 0);
00899   vars[0].set("_FillValue", fill_value);
00900 }
00901 
00905 PetscErrorCode IceModel_tempicethk_basal::compute(IceModelVec* &output) {
00906   PetscErrorCode ierr;
00907 
00908   IceModelVec2S *result = new IceModelVec2S;
00909   ierr = result->create(grid, "tempicethk_basal", false); CHKERRQ(ierr);
00910   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00911 
00912   PetscScalar *Enth, fill_value = -0.01;
00913   EnthalpyConverter *EC = model->EC;
00914 
00915   ierr = result->begin_access(); CHKERRQ(ierr);
00916   ierr = model->vH.begin_access(); CHKERRQ(ierr);
00917   ierr = model->Enth3.begin_access(); CHKERRQ(ierr);
00918   for (PetscInt   i = grid.xs; i < grid.xs+grid.xm; ++i) {
00919     for (PetscInt j = grid.ys; j < grid.ys+grid.ym; ++j) {
00920       PetscReal thk = model->vH(i,j);
00921 
00922       // if we have no ice, go on to the next grid point (this cell will be
00923       // marked as "missing" later)
00924       if (thk < 0.1)
00925         continue;
00926 
00927       ierr = model->Enth3.getInternalColumn(i,j,&Enth); CHKERRQ(ierr);
00928       PetscReal pressure;
00929       PetscInt ks = grid.kBelowHeight(thk),
00930         k = 0;
00931 
00932       while (k <= ks) {         // FIXME issue #15
00933         pressure = EC->getPressureFromDepth(thk - grid.zlevels[k]);
00934 
00935         if (EC->isTemperate(Enth[k],pressure))
00936           k++;
00937         else
00938           break;
00939       }
00940       // after this loop 'pressure' is equal to the pressure at the first level
00941       // that is cold
00942 
00943       // no temperate ice at all; go to the next grid point
00944       if (k == 0) {
00945         (*result)(i,j) = 0;
00946         continue;
00947       }
00948 
00949       // the whole column is temperate (except, possibly, some ice between
00950       // zlevels[ks] and the total thickness; we ignore it)
00951       if (k == ks + 1) {
00952         (*result)(i,j) = grid.zlevels[ks];
00953         continue;
00954       }
00955 
00956       PetscReal
00957         pressure_0 = EC->getPressureFromDepth(thk - grid.zlevels[k-1]),
00958         dz = grid.zlevels[k] - grid.zlevels[k-1],
00959         slope1 = (Enth[k] - Enth[k-1]) / dz,
00960         slope2 = (EC->getEnthalpyCTS(pressure) - EC->getEnthalpyCTS(pressure_0)) / dz;
00961 
00962       if (slope1 != slope2) {
00963         (*result)(i,j) = grid.zlevels[k-1] +
00964           (EC->getEnthalpyCTS(pressure_0) - Enth[k-1]) / (slope1 - slope2);
00965 
00966         // check if the resulting thickness is valid:
00967         (*result)(i,j) = PetscMax((*result)(i,j), grid.zlevels[k-1]);
00968         (*result)(i,j) = PetscMin((*result)(i,j), grid.zlevels[k]);
00969       } else {
00970         SETERRQ4(grid.com, 1, "This should never happen: (i=%d, j=%d, k=%d, ks=%d)\n",
00971                  i, j, k, ks);
00972       }
00973     }
00974   }
00975   ierr = model->Enth3.end_access(); CHKERRQ(ierr);
00976   ierr = model->vH.end_access(); CHKERRQ(ierr);
00977   ierr = result->end_access(); CHKERRQ(ierr);
00978 
00979   ierr = result->mask_by(model->vH, fill_value); CHKERRQ(ierr);
00980 
00981   output = result;
00982   return 0;
00983 }
00984 
00985 IceModel_acab_cumulative::IceModel_acab_cumulative(IceModel *m, IceGrid &g, PISMVars &my_vars)
00986   : PISMDiag<IceModel>(m, g, my_vars) {
00987 
00988   // set metadata:
00989   vars[0].init_2d("cumulative_climatic_mass_balance", grid);
00990 
00991   set_attrs("cumulative ice-equivalent climatic mass balance", "",
00992             "m", "m", 0);
00993 }
00994 
00995 PetscErrorCode IceModel_acab_cumulative::compute(IceModelVec* &output) {
00996   PetscErrorCode ierr;
00997 
00998   IceModelVec2S *result = new IceModelVec2S;
00999   ierr = result->create(grid, "acab_cumulative", false); CHKERRQ(ierr);
01000   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
01001   result->write_in_glaciological_units = true;
01002 
01003   ierr = result->copy_from(model->acab_cumulative); CHKERRQ(ierr);
01004 
01005   output = result;
01006   return 0;
01007 }
01008 
01009 IceModel_ivol::IceModel_ivol(IceModel *m, IceGrid &g, PISMVars &my_vars)
01010   : PISMTSDiag<IceModel>(m, g, my_vars) {
01011 
01012   // set metadata:
01013   ts = new DiagnosticTimeseries(&grid, "ivol", time_dimension_name);
01014 
01015   ts->set_units("m3", "");
01016   ts->set_dimension_units(time_units, "");
01017 
01018   ts->set_attr("long_name", "total ice volume");
01019   ts->set_attr("valid_min", 0.0);
01020 }
01021 
01022 PetscErrorCode IceModel_ivol::update(PetscReal a, PetscReal b) {
01023   PetscErrorCode ierr;
01024   PetscReal value;
01025 
01026   ierr = model->compute_ice_volume(value); CHKERRQ(ierr);
01027 
01028   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01029 
01030   return 0;
01031 }
01032 
01033 IceModel_slvol::IceModel_slvol(IceModel *m, IceGrid &g, PISMVars &my_vars)
01034   : PISMTSDiag<IceModel>(m, g, my_vars) {
01035 
01036   // set metadata:
01037   ts = new DiagnosticTimeseries(&grid, "slvol", time_dimension_name);
01038 
01039   ts->set_units("m", "");
01040   ts->set_dimension_units(time_units, "");
01041 
01042   ts->set_attr("long_name", "total sea-level relevant ice IN SEA-LEVEL EQUIVALENT");
01043   ts->set_attr("valid_min", 0.0);
01044 }
01045 
01046 PetscErrorCode IceModel_slvol::update(PetscReal a, PetscReal b) {
01047   PetscErrorCode ierr;
01048   PetscReal value;
01049 
01050   ierr = model->compute_sealevel_volume(value); CHKERRQ(ierr);
01051 
01052   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01053 
01054   return 0;
01055 }
01056 
01057 IceModel_divoldt::IceModel_divoldt(IceModel *m, IceGrid &g, PISMVars &my_vars)
01058   : PISMTSDiag<IceModel>(m, g, my_vars) {
01059 
01060   // set metadata:
01061   // set metadata:
01062   ts = new DiagnosticTimeseries(&grid, "divoldt", time_dimension_name);
01063 
01064   ts->set_units("m3 s-1", "");
01065   ts->set_dimension_units(time_units, "");
01066   ts->rate_of_change = true;
01067 
01068   ts->set_attr("long_name", "total ice volume rate of change");
01069 }
01070 
01071 PetscErrorCode IceModel_divoldt::update(PetscReal a, PetscReal b) {
01072   PetscErrorCode ierr;
01073   PetscReal value;
01074 
01075   ierr = model->compute_ice_volume(value); CHKERRQ(ierr);
01076 
01077   // note that "value" below *should* be the ice volume
01078   ts->append(value, a, b);
01079 
01080   return 0;
01081 }
01082 
01083 
01084 IceModel_iarea::IceModel_iarea(IceModel *m, IceGrid &g, PISMVars &my_vars)
01085   : PISMTSDiag<IceModel>(m, g, my_vars) {
01086 
01087   // set metadata:
01088   // set metadata:
01089   ts = new DiagnosticTimeseries(&grid, "iarea", time_dimension_name);
01090 
01091   ts->set_units("m2", "");
01092   ts->set_dimension_units(time_units, "");
01093   ts->set_attr("long_name", "total ice area");
01094   ts->set_attr("valid_min", 0.0);
01095 }
01096 
01097 PetscErrorCode IceModel_iarea::update(PetscReal a, PetscReal b) {
01098   PetscErrorCode ierr;
01099   PetscReal value;
01100 
01101   ierr = model->compute_ice_area(value); CHKERRQ(ierr);
01102 
01103   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01104 
01105   return 0;
01106 }
01107 
01108 IceModel_imass::IceModel_imass(IceModel *m, IceGrid &g, PISMVars &my_vars)
01109   : PISMTSDiag<IceModel>(m, g, my_vars) {
01110 
01111   // set metadata:
01112   // set metadata:
01113   ts = new DiagnosticTimeseries(&grid, "imass", time_dimension_name);
01114 
01115   ts->set_units("kg", "");
01116   ts->set_dimension_units(time_units, "");
01117   ts->set_attr("long_name", "total ice mass");
01118   ts->set_attr("valid_min", 0.0);
01119 }
01120 
01121 PetscErrorCode IceModel_imass::update(PetscReal a, PetscReal b) {
01122   PetscErrorCode ierr;
01123   PetscReal value;
01124 
01125   ierr = model->compute_ice_volume(value); CHKERRQ(ierr);
01126 
01127   ierr = ts->append(value * grid.config.get("ice_density"), a, b); CHKERRQ(ierr);
01128 
01129   return 0;
01130 }
01131 
01132 
01133 IceModel_dimassdt::IceModel_dimassdt(IceModel *m, IceGrid &g, PISMVars &my_vars)
01134   : PISMTSDiag<IceModel>(m, g, my_vars) {
01135 
01136   // set metadata:
01137   // set metadata:
01138   ts = new DiagnosticTimeseries(&grid, "dimassdt", time_dimension_name);
01139 
01140   ts->set_units("kg s-1", "");
01141   ts->set_dimension_units(time_units, "");
01142   ts->set_attr("long_name", "total ice mass rate of change");
01143 
01144   ts->rate_of_change = true;
01145 }
01146 
01147 PetscErrorCode IceModel_dimassdt::update(PetscReal a, PetscReal b) {
01148   PetscErrorCode ierr;
01149   PetscReal value;
01150 
01151   ierr = model->compute_ice_volume(value); CHKERRQ(ierr);
01152 
01153   ierr = ts->append(value * grid.config.get("ice_density"), a, b); CHKERRQ(ierr);
01154 
01155   return 0;
01156 }
01157 
01158 
01159 IceModel_ivoltemp::IceModel_ivoltemp(IceModel *m, IceGrid &g, PISMVars &my_vars)
01160   : PISMTSDiag<IceModel>(m, g, my_vars) {
01161 
01162   // set metadata:
01163   // set metadata:
01164   ts = new DiagnosticTimeseries(&grid, "ivoltemp", time_dimension_name);
01165 
01166   ts->set_units("m3", "");
01167   ts->set_dimension_units(time_units, "");
01168   ts->set_attr("long_name", "total volume of temperate ice");
01169   ts->set_attr("valid_min", 0.0);
01170 }
01171 
01172 PetscErrorCode IceModel_ivoltemp::update(PetscReal a, PetscReal b) {
01173   PetscErrorCode ierr;
01174   PetscReal value;
01175 
01176   ierr = model->compute_ice_volume_temperate(value); CHKERRQ(ierr);
01177 
01178   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01179 
01180   return 0;
01181 }
01182 
01183 IceModel_ivoltempf::IceModel_ivoltempf(IceModel *m, IceGrid &g, PISMVars &my_vars)
01184   : PISMTSDiag<IceModel>(m, g, my_vars) {
01185 
01186   // set metadata:
01187   // set metadata:
01188   ts = new DiagnosticTimeseries(&grid, "ivoltempf", time_dimension_name);
01189 
01190   ts->set_units("1", "");
01191   ts->set_dimension_units(time_units, "");
01192   ts->set_attr("long_name", "temperate ice volume fraction");
01193   ts->set_attr("valid_min", 0.0);
01194   ts->set_attr("valid_max", 1.0);
01195 }
01196 
01197 PetscErrorCode IceModel_ivoltempf::update(PetscReal a, PetscReal b) {
01198   PetscErrorCode ierr;
01199   PetscReal value, ivol;
01200 
01201   ierr = model->compute_ice_volume(ivol); CHKERRQ(ierr);
01202   ierr = model->compute_ice_volume_temperate(value); CHKERRQ(ierr);
01203 
01204   if (ivol > 0) {
01205     value /= ivol;
01206   } else {
01207     value = 0;
01208   }
01209 
01210   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01211 
01212   return 0;
01213 }
01214 
01215 IceModel_ivolcold::IceModel_ivolcold(IceModel *m, IceGrid &g, PISMVars &my_vars)
01216   : PISMTSDiag<IceModel>(m, g, my_vars) {
01217 
01218   // set metadata:
01219   // set metadata:
01220   ts = new DiagnosticTimeseries(&grid, "ivolcold", time_dimension_name);
01221 
01222   ts->set_units("m3", "");
01223   ts->set_dimension_units(time_units, "");
01224   ts->set_attr("long_name", "total volume of cold ice");
01225   ts->set_attr("valid_min", 0.0);
01226 }
01227 
01228 PetscErrorCode IceModel_ivolcold::update(PetscReal a, PetscReal b) {
01229   PetscErrorCode ierr;
01230   PetscReal value;
01231 
01232   ierr = model->compute_ice_volume_cold(value); CHKERRQ(ierr);
01233 
01234   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01235 
01236   return 0;
01237 }
01238 
01239 IceModel_ivolcoldf::IceModel_ivolcoldf(IceModel *m, IceGrid &g, PISMVars &my_vars)
01240   : PISMTSDiag<IceModel>(m, g, my_vars) {
01241 
01242   // set metadata:
01243   // set metadata:
01244   ts = new DiagnosticTimeseries(&grid, "ivolcoldf", time_dimension_name);
01245 
01246   ts->set_units("1", "");
01247   ts->set_dimension_units(time_units, "");
01248   ts->set_attr("long_name", "cold ice volume fraction");
01249   ts->set_attr("valid_min", 0.0);
01250   ts->set_attr("valid_max", 1.0);
01251 }
01252 
01253 PetscErrorCode IceModel_ivolcoldf::update(PetscReal a, PetscReal b) {
01254   PetscErrorCode ierr;
01255   PetscReal value, ivol;
01256 
01257   ierr = model->compute_ice_volume(ivol); CHKERRQ(ierr);
01258   ierr = model->compute_ice_volume_cold(value); CHKERRQ(ierr);
01259 
01260   if (ivol > 0) {
01261     value /= ivol;
01262   } else {
01263     value = 0;
01264   }
01265 
01266   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01267 
01268   return 0;
01269 }
01270 IceModel_iareatemp::IceModel_iareatemp(IceModel *m, IceGrid &g, PISMVars &my_vars)
01271   : PISMTSDiag<IceModel>(m, g, my_vars) {
01272 
01273   // set metadata:
01274   // set metadata:
01275   ts = new DiagnosticTimeseries(&grid, "iareatemp", time_dimension_name);
01276 
01277   ts->set_units("m2", "");
01278   ts->set_dimension_units(time_units, "");
01279   ts->set_attr("long_name", "ice-covered area where basal ice is temperate");
01280   ts->set_attr("valid_min", 0.0);
01281 }
01282 
01283 PetscErrorCode IceModel_iareatemp::update(PetscReal a, PetscReal b) {
01284   PetscErrorCode ierr;
01285   PetscReal value;
01286 
01287   ierr = model->compute_ice_area_temperate(value); CHKERRQ(ierr);
01288 
01289   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01290 
01291   return 0;
01292 }
01293 
01294 IceModel_iareatempf::IceModel_iareatempf(IceModel *m, IceGrid &g, PISMVars &my_vars)
01295   : PISMTSDiag<IceModel>(m, g, my_vars) {
01296 
01297   // set metadata:
01298   // set metadata:
01299   ts = new DiagnosticTimeseries(&grid, "iareatempf", time_dimension_name);
01300 
01301   ts->set_units("1", "");
01302   ts->set_dimension_units(time_units, "");
01303   ts->set_attr("long_name", "fraction of ice-covered area where basal ice is temperate");
01304   ts->set_attr("valid_min", 0.0);
01305   ts->set_attr("valid_max", 1.0);
01306 }
01307 
01308 PetscErrorCode IceModel_iareatempf::update(PetscReal a, PetscReal b) {
01309   PetscErrorCode ierr;
01310   PetscReal value, iarea;
01311 
01312   ierr = model->compute_ice_area(iarea); CHKERRQ(ierr);
01313   ierr = model->compute_ice_area_temperate(value); CHKERRQ(ierr);
01314 
01315   if (iarea > 0) {
01316     value /= iarea;
01317   } else {
01318     value = 0;
01319   }
01320 
01321   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01322 
01323   return 0;
01324 }
01325 
01326 IceModel_iareacold::IceModel_iareacold(IceModel *m, IceGrid &g, PISMVars &my_vars)
01327   : PISMTSDiag<IceModel>(m, g, my_vars) {
01328 
01329   // set metadata:
01330   // set metadata:
01331   ts = new DiagnosticTimeseries(&grid, "iareacold", time_dimension_name);
01332 
01333   ts->set_units("m2", "");
01334   ts->set_dimension_units(time_units, "");
01335   ts->set_attr("long_name", "ice-covered area where basal ice is cold");
01336   ts->set_attr("valid_min", 0.0);
01337 }
01338 
01339 PetscErrorCode IceModel_iareacold::update(PetscReal a, PetscReal b) {
01340   PetscErrorCode ierr;
01341   PetscReal value;
01342 
01343   ierr = model->compute_ice_area_cold(value); CHKERRQ(ierr);
01344 
01345   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01346 
01347   return 0;
01348 }
01349 
01350 IceModel_iareacoldf::IceModel_iareacoldf(IceModel *m, IceGrid &g, PISMVars &my_vars)
01351   : PISMTSDiag<IceModel>(m, g, my_vars) {
01352 
01353   // set metadata:
01354   // set metadata:
01355   ts = new DiagnosticTimeseries(&grid, "iareacoldf", time_dimension_name);
01356 
01357   ts->set_units("1", "");
01358   ts->set_dimension_units(time_units, "");
01359   ts->set_attr("long_name", "fraction of ice-covered area where basal ice is cold");
01360   ts->set_attr("valid_min", 0.0);
01361   ts->set_attr("valid_max", 1.0);
01362 }
01363 
01364 PetscErrorCode IceModel_iareacoldf::update(PetscReal a, PetscReal b) {
01365   PetscErrorCode ierr;
01366   PetscReal value, iarea;
01367 
01368   ierr = model->compute_ice_area(iarea); CHKERRQ(ierr);
01369   ierr = model->compute_ice_area_cold(value); CHKERRQ(ierr);
01370 
01371   if (iarea > 0) {
01372     value /= iarea;
01373   } else {
01374     value = 0;
01375   }
01376 
01377   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01378 
01379   return 0;
01380 }
01381 
01382 IceModel_ienthalpy::IceModel_ienthalpy(IceModel *m, IceGrid &g, PISMVars &my_vars)
01383   : PISMTSDiag<IceModel>(m, g, my_vars) {
01384 
01385   // set metadata:
01386   ts = new DiagnosticTimeseries(&grid, "ienthalpy", time_dimension_name);
01387 
01388   ts->set_units("J", "");
01389   ts->set_dimension_units(time_units, "");
01390   ts->set_attr("long_name", "total ice enthalpy");
01391   ts->set_attr("valid_min", 0.0);
01392 }
01393 
01394 PetscErrorCode IceModel_ienthalpy::update(PetscReal a, PetscReal b) {
01395   PetscErrorCode ierr;
01396   PetscReal value;
01397 
01398   ierr = model->compute_ice_enthalpy(value); CHKERRQ(ierr);
01399 
01400   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01401 
01402   return 0;
01403 }
01404 
01405 IceModel_iareag::IceModel_iareag(IceModel *m, IceGrid &g, PISMVars &my_vars)
01406   : PISMTSDiag<IceModel>(m, g, my_vars) {
01407 
01408   // set metadata:
01409   ts = new DiagnosticTimeseries(&grid, "iareag", time_dimension_name);
01410 
01411   ts->set_units("m2", "");
01412   ts->set_dimension_units(time_units, "");
01413   ts->set_attr("long_name", "total grounded ice area");
01414 }
01415 
01416 PetscErrorCode IceModel_iareag::update(PetscReal a, PetscReal b) {
01417   PetscErrorCode ierr;
01418   PetscReal value;
01419 
01420   ierr = model->compute_ice_area_grounded(value); CHKERRQ(ierr);
01421 
01422   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01423 
01424   return 0;
01425 }
01426 
01427 IceModel_iareaf::IceModel_iareaf(IceModel *m, IceGrid &g, PISMVars &my_vars)
01428   : PISMTSDiag<IceModel>(m, g, my_vars) {
01429 
01430   // set metadata:
01431   ts = new DiagnosticTimeseries(&grid, "iareaf", time_dimension_name);
01432 
01433   ts->set_units("m2", "");
01434   ts->set_dimension_units(time_units, "");
01435   ts->set_attr("long_name", "total floating ice area");
01436 }
01437 
01438 PetscErrorCode IceModel_iareaf::update(PetscReal a, PetscReal b) {
01439   PetscErrorCode ierr;
01440   PetscReal value;
01441 
01442   ierr = model->compute_ice_area_floating(value); CHKERRQ(ierr);
01443 
01444   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01445 
01446   return 0;
01447 }
01448 
01449 IceModel_dt::IceModel_dt(IceModel *m, IceGrid &g, PISMVars &my_vars)
01450   : PISMTSDiag<IceModel>(m, g, my_vars) {
01451 
01452   // set metadata:
01453   ts = new DiagnosticTimeseries(&grid, "dt", time_dimension_name);
01454 
01455   ts->set_units("second", "year");
01456   ts->set_dimension_units(time_units, "");
01457   ts->set_attr("long_name", "mass continuity time step");
01458 }
01459 
01460 PetscErrorCode IceModel_dt::update(PetscReal a, PetscReal b) {
01461   PetscErrorCode ierr;
01462 
01463   ierr = ts->append(model->dt, a, b); CHKERRQ(ierr);
01464 
01465   return 0;
01466 }
01467 
01468 IceModel_max_diffusivity::IceModel_max_diffusivity(IceModel *m, IceGrid &g, PISMVars &my_vars)
01469   : PISMTSDiag<IceModel>(m, g, my_vars) {
01470 
01471   // set metadata:
01472   ts = new DiagnosticTimeseries(&grid, "max_diffusivity", time_dimension_name);
01473 
01474   ts->set_units("m2 s-1", "");
01475   ts->set_dimension_units(time_units, "");
01476   ts->set_attr("long_name", "maximum diffusivity");
01477 }
01478 
01479 PetscErrorCode IceModel_max_diffusivity::update(PetscReal a, PetscReal b) {
01480   PetscErrorCode ierr;
01481   PetscReal value;
01482 
01483   ierr = model->stress_balance->get_max_diffusivity(value); CHKERRQ(ierr);
01484 
01485   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01486 
01487   return 0;
01488 }
01489 
01490 IceModel_surface_flux::IceModel_surface_flux(IceModel *m, IceGrid &g, PISMVars &my_vars)
01491   : PISMTSDiag<IceModel>(m, g, my_vars) {
01492 
01493   // set metadata:
01494   ts = new DiagnosticTimeseries(&grid, "surface_ice_flux", time_dimension_name);
01495 
01496   ts->set_units("kg s-1", "");
01497   ts->set_dimension_units(time_units, "");
01498   ts->set_attr("long_name", "total over ice domain of top surface ice mass flux");
01499   ts->rate_of_change = true;
01500 }
01501 
01502 PetscErrorCode IceModel_surface_flux::update(PetscReal a, PetscReal b) {
01503   PetscErrorCode ierr;
01504   PetscReal value;
01505 
01506   value = model->cumulative_surface_ice_flux;
01507 
01508   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01509 
01510   return 0;
01511 }
01512 
01513 IceModel_cumulative_surface_flux::IceModel_cumulative_surface_flux(IceModel *m, IceGrid &g, PISMVars &my_vars)
01514   : PISMTSDiag<IceModel>(m, g, my_vars) {
01515 
01516   // set metadata:
01517   ts = new DiagnosticTimeseries(&grid, "cumulative_surface_ice_flux", time_dimension_name);
01518 
01519   ts->set_units("kg", "");
01520   ts->set_dimension_units(time_units, "");
01521   ts->set_attr("long_name", "cumulative total over ice domain of top surface ice mass flux");
01522 }
01523 
01524 PetscErrorCode IceModel_cumulative_surface_flux::update(PetscReal a, PetscReal b) {
01525   PetscErrorCode ierr;
01526   PetscReal value;
01527 
01528   value = model->cumulative_surface_ice_flux;
01529 
01530   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01531 
01532   return 0;
01533 }
01534 
01535 IceModel_basal_flux::IceModel_basal_flux(IceModel *m, IceGrid &g, PISMVars &my_vars)
01536   : PISMTSDiag<IceModel>(m, g, my_vars) {
01537 
01538   // set metadata:
01539   ts = new DiagnosticTimeseries(&grid, "basal_ice_flux", time_dimension_name);
01540 
01541   ts->set_units("kg s-1", "");
01542   ts->set_dimension_units(time_units, "");
01543   ts->set_attr("long_name", "total basal ice flux");
01544   ts->rate_of_change = true;
01545 }
01546 
01547 PetscErrorCode IceModel_basal_flux::update(PetscReal a, PetscReal b) {
01548   PetscErrorCode ierr;
01549   PetscReal value;
01550 
01551   value = model->cumulative_basal_ice_flux;
01552 
01553   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01554 
01555   return 0;
01556 }
01557 
01558 IceModel_cumulative_basal_flux::IceModel_cumulative_basal_flux(IceModel *m, IceGrid &g, PISMVars &my_vars)
01559   : PISMTSDiag<IceModel>(m, g, my_vars) {
01560 
01561   // set metadata:
01562   ts = new DiagnosticTimeseries(&grid, "cumulative_basal_ice_flux", time_dimension_name);
01563 
01564   ts->set_units("kg", "");
01565   ts->set_dimension_units(time_units, "");
01566   ts->set_attr("long_name", "cumulative total basal ice flux");
01567 }
01568 
01569 PetscErrorCode IceModel_cumulative_basal_flux::update(PetscReal a, PetscReal b) {
01570   PetscErrorCode ierr;
01571   PetscReal value;
01572 
01573   value = model->cumulative_basal_ice_flux;
01574 
01575   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01576 
01577   return 0;
01578 }
01579 
01580 IceModel_sub_shelf_flux::IceModel_sub_shelf_flux(IceModel *m, IceGrid &g, PISMVars &my_vars)
01581   : PISMTSDiag<IceModel>(m, g, my_vars) {
01582 
01583   // set metadata:
01584   ts = new DiagnosticTimeseries(&grid, "sub_shelf_ice_flux", time_dimension_name);
01585 
01586   ts->set_units("kg s-1", "");
01587   ts->set_dimension_units(time_units, "");
01588   ts->set_attr("long_name", "total sub-shelf ice flux");
01589   ts->rate_of_change = true;
01590 }
01591 
01592 PetscErrorCode IceModel_sub_shelf_flux::update(PetscReal a, PetscReal b) {
01593   PetscErrorCode ierr;
01594   PetscReal value;
01595 
01596   value = model->cumulative_sub_shelf_ice_flux;
01597 
01598   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01599 
01600   return 0;
01601 }
01602 
01603 IceModel_cumulative_sub_shelf_flux::IceModel_cumulative_sub_shelf_flux(IceModel *m, IceGrid &g, PISMVars &my_vars)
01604   : PISMTSDiag<IceModel>(m, g, my_vars) {
01605 
01606   // set metadata:
01607   ts = new DiagnosticTimeseries(&grid, "cumulative_sub_shelf_ice_flux", time_dimension_name);
01608 
01609   ts->set_units("kg", "");
01610   ts->set_dimension_units(time_units, "");
01611   ts->set_attr("long_name", "cumulative total sub-shelf ice flux");
01612 }
01613 
01614 PetscErrorCode IceModel_cumulative_sub_shelf_flux::update(PetscReal a, PetscReal b) {
01615   PetscErrorCode ierr;
01616   PetscReal value;
01617 
01618   value = model->cumulative_sub_shelf_ice_flux;
01619 
01620   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01621 
01622   return 0;
01623 }
01624 
01625 IceModel_nonneg_flux::IceModel_nonneg_flux(IceModel *m, IceGrid &g, PISMVars &my_vars)
01626   : PISMTSDiag<IceModel>(m, g, my_vars) {
01627 
01628   // set metadata:
01629   ts = new DiagnosticTimeseries(&grid, "nonneg_flux", time_dimension_name);
01630 
01631   ts->set_units("kg s-1", "");
01632   ts->set_dimension_units(time_units, "");
01633   ts->set_attr("long_name", "'numerical' ice flux resulting from enforcing the 'thk >= 0' rule");
01634   ts->rate_of_change = true;
01635 }
01636 
01637 PetscErrorCode IceModel_nonneg_flux::update(PetscReal a, PetscReal b) {
01638   PetscErrorCode ierr;
01639   PetscReal value;
01640 
01641   value = model->cumulative_nonneg_rule_flux;
01642 
01643   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01644 
01645   return 0;
01646 }
01647 
01648 IceModel_cumulative_nonneg_flux::IceModel_cumulative_nonneg_flux(IceModel *m, IceGrid &g, PISMVars &my_vars)
01649   : PISMTSDiag<IceModel>(m, g, my_vars) {
01650 
01651   // set metadata:
01652   ts = new DiagnosticTimeseries(&grid, "cumulative_nonneg_flux", time_dimension_name);
01653 
01654   ts->set_units("kg", "");
01655   ts->set_dimension_units(time_units, "");
01656   ts->set_attr("long_name", "cumulative 'numerical' ice flux resulting from enforcing the 'thk >= 0' rule");
01657 }
01658 
01659 PetscErrorCode IceModel_cumulative_nonneg_flux::update(PetscReal a, PetscReal b) {
01660   PetscErrorCode ierr;
01661   PetscReal value;
01662 
01663   value = model->cumulative_nonneg_rule_flux;
01664 
01665   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01666 
01667   return 0;
01668 }
01669 
01670 IceModel_ocean_kill_flux::IceModel_ocean_kill_flux(IceModel *m, IceGrid &g, PISMVars &my_vars)
01671   : PISMTSDiag<IceModel>(m, g, my_vars) {
01672 
01673   // set metadata:
01674   ts = new DiagnosticTimeseries(&grid, "ocean_kill_flux", time_dimension_name);
01675 
01676   ts->set_units("kg s-1", "");
01677   ts->set_dimension_units(time_units, "");
01678   ts->set_attr("long_name", "-ocean_kill flux");
01679   ts->rate_of_change = true;
01680 }
01681 
01682 PetscErrorCode IceModel_ocean_kill_flux::update(PetscReal a, PetscReal b) {
01683   PetscErrorCode ierr;
01684   PetscReal value;
01685 
01686   value = model->cumulative_ocean_kill_flux;
01687 
01688   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01689 
01690   return 0;
01691 }
01692 
01693 IceModel_cumulative_ocean_kill_flux::IceModel_cumulative_ocean_kill_flux(IceModel *m, IceGrid &g, PISMVars &my_vars)
01694   : PISMTSDiag<IceModel>(m, g, my_vars) {
01695 
01696   // set metadata:
01697   ts = new DiagnosticTimeseries(&grid, "cumulative_ocean_kill_flux", time_dimension_name);
01698 
01699   ts->set_units("kg", "");
01700   ts->set_dimension_units(time_units, "");
01701   ts->set_attr("long_name", "cumulative -ocean_kill flux");
01702 }
01703 
01704 PetscErrorCode IceModel_cumulative_ocean_kill_flux::update(PetscReal a, PetscReal b) {
01705   PetscErrorCode ierr;
01706   PetscReal value;
01707 
01708   value = model->cumulative_ocean_kill_flux;
01709 
01710   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01711 
01712   return 0;
01713 }
01714 
01715 IceModel_float_kill_flux::IceModel_float_kill_flux(IceModel *m, IceGrid &g, PISMVars &my_vars)
01716   : PISMTSDiag<IceModel>(m, g, my_vars) {
01717 
01718   // set metadata:
01719   ts = new DiagnosticTimeseries(&grid, "float_kill_flux", time_dimension_name);
01720 
01721   ts->set_units("kg s-1", "");
01722   ts->set_dimension_units(time_units, "");
01723   ts->set_attr("long_name", "-float_kill flux");
01724   ts->rate_of_change = true;
01725 }
01726 
01727 PetscErrorCode IceModel_float_kill_flux::update(PetscReal a, PetscReal b) {
01728   PetscErrorCode ierr;
01729   PetscReal value;
01730 
01731   value = model->cumulative_float_kill_flux;
01732 
01733   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01734 
01735   return 0;
01736 }
01737 
01738 IceModel_cumulative_float_kill_flux::IceModel_cumulative_float_kill_flux(IceModel *m, IceGrid &g, PISMVars &my_vars)
01739   : PISMTSDiag<IceModel>(m, g, my_vars) {
01740 
01741   // set metadata:
01742   ts = new DiagnosticTimeseries(&grid, "cumulative_float_kill_flux", time_dimension_name);
01743 
01744   ts->set_units("kg", "");
01745   ts->set_dimension_units(time_units, "");
01746   ts->set_attr("long_name", "cumulative -float_kill flux");
01747 }
01748 
01749 PetscErrorCode IceModel_cumulative_float_kill_flux::update(PetscReal a, PetscReal b) {
01750   PetscErrorCode ierr;
01751   PetscReal value;
01752 
01753   value = model->cumulative_float_kill_flux;
01754 
01755   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01756 
01757   return 0;
01758 }
01759 
01760 IceModel_discharge_flux::IceModel_discharge_flux(IceModel *m, IceGrid &g, PISMVars &my_vars)
01761   : PISMTSDiag<IceModel>(m, g, my_vars) {
01762 
01763   // set metadata:
01764   ts = new DiagnosticTimeseries(&grid, "discharge_flux", time_dimension_name);
01765 
01766   ts->set_units("kg s-1", "");
01767   ts->set_dimension_units(time_units, "");
01768   ts->set_attr("long_name", "discharge (calving & icebergs) flux");
01769   ts->rate_of_change = true;
01770 }
01771 
01772 PetscErrorCode IceModel_discharge_flux::update(PetscReal a, PetscReal b) {
01773   PetscErrorCode ierr;
01774   PetscReal value;
01775 
01776   value = model->cumulative_discharge_flux;
01777 
01778   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01779 
01780   return 0;
01781 }
01782 
01783 IceModel_cumulative_discharge_flux::IceModel_cumulative_discharge_flux(IceModel *m, IceGrid &g, PISMVars &my_vars)
01784   : PISMTSDiag<IceModel>(m, g, my_vars) {
01785 
01786   // set metadata:
01787   ts = new DiagnosticTimeseries(&grid, "cumulative_discharge_flux", time_dimension_name);
01788 
01789   ts->set_units("kg", "");
01790   ts->set_dimension_units(time_units, "");
01791   ts->set_attr("long_name", "cumulative discharge (calving etc.) flux");
01792 }
01793 
01794 PetscErrorCode IceModel_cumulative_discharge_flux::update(PetscReal a, PetscReal b) {
01795   PetscErrorCode ierr;
01796   PetscReal value;
01797 
01798   value = model->cumulative_discharge_flux;
01799 
01800   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01801 
01802   return 0;
01803 }
01804 
01805 IceModel_dHdt::IceModel_dHdt(IceModel *m, IceGrid &g, PISMVars &my_vars)
01806   : PISMDiag<IceModel>(m, g, my_vars) {
01807 
01808   // set metadata:
01809   vars[0].init_2d("dHdt", grid);
01810 
01811   set_attrs("ice thickness rate of change", "tendency_of_land_ice_thickness",
01812             "m s-1", "m year-1", 0);
01813 
01814   vars[0].set("valid_min",  convert(-1e6, "m/year", "m/s"));
01815   vars[0].set("valid_max",  convert( 1e6, "m/year", "m/s"));
01816   vars[0].set("_FillValue", convert( 2e6, "m/year", "m/s"));
01817   vars[0].set_string("cell_methods", "time: mean");
01818 
01819   last_ice_thickness.create(grid, "last_ice_thickness", false);
01820   last_ice_thickness.set_attrs("internal",
01821                                "ice thickness at the time of the last report of dHdt",
01822                                "m", "land_ice_thickness");
01823 
01824   last_report_time = GSL_NAN;
01825 }
01826 
01827 PetscErrorCode IceModel_dHdt::compute(IceModelVec* &output) {
01828   PetscErrorCode ierr;
01829 
01830   IceModelVec2S *result = new IceModelVec2S;
01831   ierr = result->create(grid, "dHdt", false); CHKERRQ(ierr);
01832   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
01833   result->write_in_glaciological_units = true;
01834 
01835   if (gsl_isnan(last_report_time)) {
01836     ierr = result->set(convert(2e6, "m/year", "m/s")); CHKERRQ(ierr);
01837   } else {
01838 
01839     ierr = result->begin_access(); CHKERRQ(ierr);
01840     ierr = last_ice_thickness.begin_access(); CHKERRQ(ierr);
01841     ierr = model->vH.begin_access(); CHKERRQ(ierr);
01842 
01843     PetscReal dt = grid.time->current() - last_report_time;
01844     for (PetscInt   i = grid.xs; i < grid.xs+grid.xm; ++i) {
01845       for (PetscInt j = grid.ys; j < grid.ys+grid.ym; ++j) {
01846         (*result)(i, j) = (model->vH(i, j) - last_ice_thickness(i, j)) / dt;
01847       }
01848     }
01849 
01850     ierr = model->vH.end_access(); CHKERRQ(ierr);
01851     ierr = last_ice_thickness.end_access(); CHKERRQ(ierr);
01852     ierr = result->end_access(); CHKERRQ(ierr);
01853 
01854   }
01855 
01856   // Save the ice thickness and the corresponding time:
01857   ierr = this->update_cumulative(); CHKERRQ(ierr);
01858 
01859   output = result;
01860   return 0;
01861 }
01862 
01863 PetscErrorCode IceModel_dHdt::update_cumulative() {
01864   PetscErrorCode ierr;
01865   ierr = model->vH.begin_access(); CHKERRQ(ierr);
01866   ierr = last_ice_thickness.begin_access(); CHKERRQ(ierr);
01867 
01868   for (PetscInt   i = grid.xs; i < grid.xs+grid.xm; ++i) {
01869     for (PetscInt j = grid.ys; j < grid.ys+grid.ym; ++j) {
01870       last_ice_thickness(i, j) = model->vH(i, j);
01871     }
01872   }
01873 
01874   ierr = last_ice_thickness.end_access(); CHKERRQ(ierr);
01875   ierr = model->vH.end_access(); CHKERRQ(ierr);
01876 
01877   last_report_time = grid.time->current();
01878 
01879   return 0;
01880 }
01881 
01882 IceModel_ivolg::IceModel_ivolg(IceModel *m, IceGrid &g, PISMVars &my_vars)
01883   : PISMTSDiag<IceModel>(m, g, my_vars) {
01884 
01885   // set metadata:
01886   ts = new DiagnosticTimeseries(&grid, "ivolg", time_dimension_name);
01887 
01888   ts->set_units("m3", "");
01889   ts->set_dimension_units(time_units, "");
01890   ts->set_attr("long_name", "total grounded ice volume");
01891 }
01892 
01893 PetscErrorCode IceModel_ivolg::update(PetscReal a, PetscReal b) {
01894   PetscErrorCode ierr;
01895   PetscReal volume=0.0, value;
01896 
01897   MaskQuery mask(model->vMask);
01898 
01899   ierr = model->vH.begin_access(); CHKERRQ(ierr);
01900   ierr = model->vMask.begin_access(); CHKERRQ(ierr);
01901   ierr = model->cell_area.begin_access(); CHKERRQ(ierr);
01902   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
01903     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
01904       if (mask.grounded_ice(i,j))
01905         volume += model->cell_area(i,j) * model->vH(i,j);;
01906     }
01907   }
01908   ierr = model->cell_area.end_access(); CHKERRQ(ierr);
01909   ierr = model->vMask.end_access(); CHKERRQ(ierr);
01910   ierr = model->vH.end_access(); CHKERRQ(ierr);
01911 
01912   ierr = PISMGlobalSum(&volume, &value, grid.com); CHKERRQ(ierr);
01913 
01914   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01915 
01916   return 0;
01917 }
01918 
01919 IceModel_ivolf::IceModel_ivolf(IceModel *m, IceGrid &g, PISMVars &my_vars)
01920   : PISMTSDiag<IceModel>(m, g, my_vars) {
01921 
01922   // set metadata:
01923   ts = new DiagnosticTimeseries(&grid, "ivolf", time_dimension_name);
01924 
01925   ts->set_units("m3", "");
01926   ts->set_dimension_units(time_units, "");
01927   ts->set_attr("long_name", "total floating ice volume");
01928 }
01929 
01930 PetscErrorCode IceModel_ivolf::update(PetscReal a, PetscReal b) {
01931   PetscErrorCode ierr;
01932   PetscReal volume=0.0, value;
01933 
01934   MaskQuery mask(model->vMask);
01935 
01936   ierr = model->vH.begin_access(); CHKERRQ(ierr);
01937   ierr = model->vMask.begin_access(); CHKERRQ(ierr);
01938   ierr = model->cell_area.begin_access(); CHKERRQ(ierr);
01939   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
01940     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
01941       if (mask.floating_ice(i,j))
01942         volume += model->cell_area(i,j) * model->vH(i,j);;
01943     }
01944   }
01945   ierr = model->cell_area.end_access(); CHKERRQ(ierr);
01946   ierr = model->vMask.end_access(); CHKERRQ(ierr);
01947   ierr = model->vH.end_access(); CHKERRQ(ierr);
01948 
01949   ierr = PISMGlobalSum(&volume, &value, grid.com); CHKERRQ(ierr);
01950 
01951   ierr = ts->append(value, a, b); CHKERRQ(ierr);
01952 
01953   return 0;
01954 }
01955 
01957 
01967 IceModel_max_hor_vel::IceModel_max_hor_vel(IceModel *m, IceGrid &g, PISMVars &my_vars)
01968   : PISMTSDiag<IceModel>(m, g, my_vars) {
01969 
01970   // set metadata:
01971   ts = new DiagnosticTimeseries(&grid, "max_hor_vel", time_dimension_name);
01972 
01973   ts->set_units("m/second", "m/year");
01974   ts->set_dimension_units(time_units, "");
01975   ts->set_attr("long_name", "maximum abs component of horizontal ice velocity over grid in last time step during time-series reporting interval");
01976 }
01977 
01978 PetscErrorCode IceModel_max_hor_vel::update(PetscReal a, PetscReal b) {
01979   PetscErrorCode ierr;
01980 
01981   double gmaxu = model->gmaxu, gmaxv = model->gmaxv;
01982 
01983   ierr = ts->append(gmaxu > gmaxv ? gmaxu : gmaxv, a, b); CHKERRQ(ierr);
01984 
01985   return 0;
01986 }
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines