|
PISM, A Parallel Ice Sheet Model stable 0.4.1779
|
00001 // Copyright (C) 2009, 2010, 2011 Ed Bueler and 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 static char help[] = 00020 "Driver for testing PISM's boundary (surface and shelf-base) models without IceModel.\n"; 00021 00022 #include <set> 00023 #include <ctime> 00024 #include <string> 00025 #include <sstream> 00026 #include <vector> 00027 #include <petscda.h> 00028 #include "pism_const.hh" 00029 #include "grid.hh" 00030 #include "LocalInterpCtx.hh" 00031 #include "PISMIO.hh" 00032 #include "NCVariable.hh" 00033 00034 #include "coupler/PCFactory.hh" 00035 #include "coupler/PISMAtmosphere.hh" 00036 #include "coupler/PISMSurface.hh" 00037 #include "coupler/PISMOcean.hh" 00038 #include "eismint/pgrn_atmosphere.hh" 00039 00040 static void create_pa_eismint_greenland(IceGrid& g, const NCConfigVariable& conf, 00041 PISMAtmosphereModel* &result) { 00042 result = new PA_EISMINT_Greenland(g, conf); 00043 } 00044 00045 00046 static PetscErrorCode setupIceGridFromFile(string filename, IceGrid &grid) { 00047 PetscErrorCode ierr; 00048 00049 PISMIO nc(&grid); 00050 ierr = nc.get_grid(filename, "land_ice_thickness"); CHKERRQ(ierr); 00051 grid.compute_nprocs(); 00052 grid.compute_ownership_ranges(); 00053 ierr = grid.createDA(); CHKERRQ(ierr); 00054 return 0; 00055 } 00056 00057 static PetscErrorCode createVecs(IceGrid &grid, PISMVars &variables) { 00058 00059 PetscErrorCode ierr; 00060 IceModelVec2S *lat, *lon, *mask, *thk, *surfelev, *topg, *acab, *artm, *shelfbasetemp, *shelfbasemassflux; 00061 00062 lat = new IceModelVec2S; 00063 lon = new IceModelVec2S; 00064 mask = new IceModelVec2S; 00065 thk = new IceModelVec2S; 00066 surfelev = new IceModelVec2S; 00067 topg = new IceModelVec2S; 00068 00069 // the following are allocated by the pclimate code, but may or may not 00070 // actually be read by PISMAtmosphereModel *atmosphere and PISMOceanModel *ocean 00071 acab = new IceModelVec2S; 00072 artm = new IceModelVec2S; 00073 shelfbasetemp = new IceModelVec2S; 00074 shelfbasemassflux = new IceModelVec2S; 00075 00076 ierr = lat->create(grid, "lat", true); CHKERRQ(ierr); 00077 ierr = lat->set_attrs("mapping", "latitude", "degrees_north", "latitude"); CHKERRQ(ierr); 00078 ierr = variables.add(*lat); CHKERRQ(ierr); 00079 00080 ierr = lon->create(grid, "lon", true); CHKERRQ(ierr); 00081 ierr = lon->set_attrs("mapping", "longitude", "degrees_east", "longitude"); CHKERRQ(ierr); 00082 ierr = variables.add(*lon); CHKERRQ(ierr); 00083 00084 ierr = mask->create(grid, "mask", true); CHKERRQ(ierr); 00085 ierr = mask->set_attrs("", "grounded_dragging_floating integer mask", 00086 "", ""); CHKERRQ(ierr); 00087 ierr = variables.add(*mask); CHKERRQ(ierr); 00088 00089 ierr = thk->create(grid, "thk", true); CHKERRQ(ierr); 00090 ierr = thk->set_attrs("", "land ice thickness", 00091 "m", "land_ice_thickness"); CHKERRQ(ierr); 00092 ierr = variables.add(*thk); CHKERRQ(ierr); 00093 00094 ierr = surfelev->create(grid, "usurf", true); CHKERRQ(ierr); 00095 ierr = surfelev->set_attrs("", "ice upper surface elevation", 00096 "m", "surface_altitude"); CHKERRQ(ierr); 00097 ierr = variables.add(*surfelev); CHKERRQ(ierr); 00098 00099 ierr = topg->create(grid, "topg", true); CHKERRQ(ierr); 00100 ierr = topg->set_attrs("", "bedrock surface elevation", 00101 "m", "bedrock_altitude"); CHKERRQ(ierr); 00102 ierr = variables.add(*topg); CHKERRQ(ierr); 00103 00104 ierr = artm->create(grid, "artm", false); CHKERRQ(ierr); 00105 ierr = artm->set_attrs("climate_state", 00106 "annual average ice surface temperature, below firn processes", 00107 "K", 00108 ""); CHKERRQ(ierr); 00109 ierr = variables.add(*artm); CHKERRQ(ierr); 00110 00111 ierr = acab->create(grid, "acab", false); CHKERRQ(ierr); 00112 ierr = acab->set_attrs("climate_state", 00113 "ice-equivalent surface mass balance (accumulation/ablation) rate", 00114 "m s-1", 00115 ""); CHKERRQ(ierr); 00116 ierr = acab->set_glaciological_units("m year-1"); CHKERRQ(ierr); 00117 acab->write_in_glaciological_units = true; 00118 ierr = variables.add(*acab); CHKERRQ(ierr); 00119 00120 ierr = shelfbasetemp->create(grid, "shelfbasetemp", false); CHKERRQ(ierr); // no ghosts; NO HOR. DIFF.! 00121 ierr = shelfbasetemp->set_attrs( 00122 "climate_state", "absolute temperature at ice shelf base", 00123 "K", ""); CHKERRQ(ierr); 00124 // PROPOSED standard name = ice_shelf_basal_temperature 00125 ierr = variables.add(*shelfbasetemp); CHKERRQ(ierr); 00126 00127 // ice mass balance rate at the base of the ice shelf; sign convention for vshelfbasemass 00128 // matches standard sign convention for basal melt rate of grounded ice 00129 ierr = shelfbasemassflux->create(grid, "shelfbasemassflux", false); CHKERRQ(ierr); // no ghosts; NO HOR. DIFF.! 00130 ierr = shelfbasemassflux->set_attrs("climate_state", 00131 "ice mass flux from ice shelf base (positive flux is loss from ice shelf)", 00132 "m s-1", ""); CHKERRQ(ierr); 00133 // PROPOSED standard name = ice_shelf_basal_specific_mass_balance 00134 shelfbasemassflux->write_in_glaciological_units = true; 00135 ierr = shelfbasemassflux->set_glaciological_units("m year-1"); CHKERRQ(ierr); 00136 ierr = variables.add(*shelfbasemassflux); CHKERRQ(ierr); 00137 00138 00139 return 0; 00140 } 00141 00142 static PetscErrorCode readIceInfoFromFile(const char *filename, int start, 00143 PISMVars &variables) { 00144 PetscErrorCode ierr; 00145 // Get the names of all the variables allocated earlier: 00146 set<string> vars = variables.keys(); 00147 00148 // Remove artm, acab, shelfbasemassflux and shelfbasetemp: they are filled by 00149 // surface and ocean models and aren't necessarily read from files. 00150 vars.erase("artm"); 00151 vars.erase("acab"); 00152 vars.erase("shelfbasemassflux"); 00153 vars.erase("shelfbasetemp"); 00154 00155 set<string>::iterator i = vars.begin(); 00156 while (i != vars.end()) { 00157 IceModelVec *var = variables.get(*i); 00158 ierr = var->read(filename, start); CHKERRQ(ierr); 00159 i++; 00160 } 00161 00162 return 0; 00163 } 00164 00165 00166 static PetscErrorCode doneWithIceInfo(PISMVars &variables) { 00167 // Get the names of all the variables allocated earlier: 00168 set<string> vars = variables.keys(); 00169 00170 set<string>::iterator i = vars.begin(); 00171 while (i != vars.end()) { 00172 IceModelVec *var = variables.get(*i); 00173 delete var; 00174 i++; 00175 } 00176 00177 return 0; 00178 } 00179 00180 00181 static PetscErrorCode writePCCStateAtTimes(PISMVars &variables, 00182 PISMSurfaceModel *surface, 00183 PISMOceanModel* ocean, 00184 const char *filename, IceGrid* grid, 00185 PetscReal ys, PetscReal ye, PetscReal dt_years, 00186 NCConfigVariable &mapping) { 00187 00188 MPI_Comm com = grid->com; 00189 PetscErrorCode ierr; 00190 PISMIO nc(grid); 00191 NCGlobalAttributes global_attrs; 00192 IceModelVec2S *usurf, *artm, *acab, *shelfbasetemp, *shelfbasemassflux; 00193 00194 usurf = dynamic_cast<IceModelVec2S*>(variables.get("surface_altitude")); 00195 if (usurf == NULL) { SETERRQ(1, "usurf is not available"); } 00196 00197 artm = dynamic_cast<IceModelVec2S*>(variables.get("artm")); 00198 if (artm == NULL) { SETERRQ(1, "artm is not available"); } 00199 00200 acab = dynamic_cast<IceModelVec2S*>(variables.get("acab")); 00201 if (acab == NULL) { SETERRQ(1, "acab is not available"); } 00202 00203 shelfbasetemp = dynamic_cast<IceModelVec2S*>(variables.get("shelfbasetemp")); 00204 if (shelfbasetemp == NULL) { SETERRQ(1, "shelfbasetemp is not available"); } 00205 00206 shelfbasemassflux = dynamic_cast<IceModelVec2S*>(variables.get("shelfbasemassflux")); 00207 if (shelfbasemassflux == NULL) { SETERRQ(1, "shelfbasemassflux is not available"); } 00208 00209 global_attrs.init("global_attributes", com, grid->rank); 00210 global_attrs.set_string("Conventions", "CF-1.4"); 00211 global_attrs.set_string("source", string("pclimate ") + PISM_Revision); 00212 00213 // Create a string with space-separated command-line arguments: 00214 string history = pism_username_prefix() + pism_args_string(); 00215 00216 global_attrs.prepend_history(history); 00217 00218 ierr = nc.open_for_writing(filename, false, true); CHKERRQ(ierr); 00219 // append == false, check_dims == true 00220 ierr = nc.close(); CHKERRQ(ierr); 00221 00222 ierr = mapping.write(filename); CHKERRQ(ierr); 00223 ierr = global_attrs.write(filename); CHKERRQ(ierr); 00224 00225 PetscInt NN; // get number of times at which PISM boundary model state is written 00226 NN = (int) ceil((ye - ys) / dt_years); 00227 if (NN > 1000) 00228 SETERRQ(2,"PCLIMATE ERROR: refuse to write more than 1000 times!"); 00229 if (NN > 50) { 00230 ierr = PetscPrintf(com, 00231 "\nPCLIMATE ATTENTION: writing more than 50 times to '%s'!!\n\n", 00232 filename); CHKERRQ(ierr); 00233 } 00234 00235 DiagnosticTimeseries sea_level(grid, "sea_level", "t"); 00236 sea_level.set_units("m", "m"); 00237 sea_level.set_dimension_units("years", ""); 00238 sea_level.output_filename = filename; 00239 sea_level.set_attr("long_name", "sea level elevation"); 00240 00241 PetscScalar use_dt_years = dt_years; 00242 00243 set<string> vars_to_write; 00244 surface->add_vars_to_output("big", vars_to_write); 00245 ocean->add_vars_to_output("big", vars_to_write); 00246 00247 // write the states 00248 for (PetscInt k=0; k < NN; k++) { 00249 // use original dt_years to get correct subinterval starts: 00250 const PetscReal pccyear = ys + k * dt_years; 00251 ierr = nc.open_for_writing(filename, true, false); CHKERRQ(ierr); // append=true,check_dims=false 00252 ierr = nc.append_time(pccyear); CHKERRQ(ierr); 00253 00254 PetscScalar dt_update_years = PetscMin(use_dt_years, ye - pccyear); 00255 00256 char timestr[TEMPORARY_STRING_LENGTH]; 00257 snprintf(timestr, sizeof(timestr), 00258 " boundary models updated for [%11.3f a,%11.3f a] ...", 00259 pccyear, pccyear + dt_update_years); 00260 ierr = verbPrintf(2,com,"."); CHKERRQ(ierr); 00261 ierr = verbPrintf(3,com,"\n%s writing result to %s ..",timestr,filename); CHKERRQ(ierr); 00262 strncat(timestr,"\n",1); 00263 ierr = nc.write_history(timestr); CHKERRQ(ierr); // append the history 00264 ierr = nc.close(); CHKERRQ(ierr); 00265 00266 ierr = usurf->write(filename, NC_FLOAT); CHKERRQ(ierr); 00267 00268 // update surface and ocean models' outputs: 00269 ierr = surface->update(pccyear, dt_update_years); CHKERRQ(ierr); 00270 ierr = ocean->update(pccyear, dt_update_years); CHKERRQ(ierr); 00271 00272 ierr = surface->ice_surface_mass_flux(*acab); CHKERRQ(ierr); 00273 ierr = surface->ice_surface_temperature(*artm); CHKERRQ(ierr); 00274 00275 PetscReal current_sea_level; 00276 ierr = ocean->sea_level_elevation(current_sea_level); CHKERRQ(ierr); 00277 00278 sea_level.append(pccyear, current_sea_level); 00279 sea_level.interp(pccyear); 00280 00281 // ask ocean and surface models to write variables: 00282 ierr = surface->write_variables(vars_to_write, filename); CHKERRQ(ierr); 00283 ierr = ocean->write_variables(vars_to_write, filename); CHKERRQ(ierr); 00284 00285 // This ensures that even if a surface model wrote artm and acab we 00286 // over-write them with values that were actually used by IceModel. 00287 ierr = acab->write(filename, NC_FLOAT); CHKERRQ(ierr); 00288 ierr = artm->write(filename, NC_FLOAT); CHKERRQ(ierr); 00289 } 00290 ierr = verbPrintf(2,com,"\n"); CHKERRQ(ierr); 00291 00292 return 0; 00293 } 00294 00295 00296 int main(int argc, char *argv[]) { 00297 PetscErrorCode ierr; 00298 00299 MPI_Comm com; 00300 PetscMPIInt rank, size; 00301 00302 ierr = PetscInitialize(&argc, &argv, PETSC_NULL, help); CHKERRQ(ierr); 00303 00304 com = PETSC_COMM_WORLD; 00305 ierr = MPI_Comm_rank(com, &rank); CHKERRQ(ierr); 00306 ierr = MPI_Comm_size(com, &size); CHKERRQ(ierr); 00307 00308 /* This explicit scoping forces destructors to be called before PetscFinalize() */ 00309 { 00310 NCConfigVariable config, overrides, mapping; 00311 string inname, outname; 00312 00313 ierr = verbosityLevelFromOptions(); CHKERRQ(ierr); 00314 00315 ierr = verbPrintf(2,com, 00316 "PCLIMATE %s (surface and shelf-base boundary-models-only mode)\n", 00317 PISM_Revision); CHKERRQ(ierr); 00318 ierr = stop_on_version_option(); CHKERRQ(ierr); 00319 00320 // check required options 00321 vector<string> required; 00322 required.push_back("-i"); 00323 required.push_back("-o"); 00324 required.push_back("-ys"); 00325 required.push_back("-ye"); 00326 required.push_back("-dt"); 00327 ierr = show_usage_check_req_opts(com, "pclimate", required, 00328 " pclimate -i IN.nc -o OUT.nc -ys A -ye B -dt C [-atmosphere <name> -surface <name>] [OTHER PISM & PETSc OPTIONS]\n" 00329 "where:\n" 00330 " -i input file in NetCDF format\n" 00331 " -o output file in NetCDF format\n" 00332 " -ys start time A (= float) in years\n" 00333 " -ye end time B (= float), B > A, in years\n" 00334 " -dt time step C (= positive float) in years\n" 00335 "and set up the models:\n" 00336 " -atmosphere Chooses an atmosphere model; see User's Manual\n" 00337 " -surface Chooses a surface model; see User's Manual\n" 00338 " -ocean Chooses an ocean model; see User's Manual\n" 00339 ); CHKERRQ(ierr); 00340 00341 // read the config option database: 00342 ierr = init_config(com, rank, config, overrides); CHKERRQ(ierr); 00343 00344 bool override_used; 00345 ierr = PISMOptionsIsSet("-config_override", override_used); CHKERRQ(ierr); 00346 00347 // set an un-documented (!) flag to limit time-steps to 1 year. 00348 config.set_flag("pdd_limit_timestep", true); 00349 00350 IceGrid grid(com, rank, size, config); 00351 00352 bool flag; 00353 PetscReal ys = 0.0, ye = 0.0, dt_years = 0.0; 00354 ierr = PetscOptionsBegin(grid.com, "", "PCLIMATE options", ""); CHKERRQ(ierr); 00355 { 00356 ierr = PISMOptionsString("-i", "Input file name", inname, flag); CHKERRQ(ierr); 00357 ierr = PISMOptionsString("-o", "Output file name", outname, flag); CHKERRQ(ierr); 00358 00359 ierr = PISMOptionsReal("-ys", "Start year", ys, flag); CHKERRQ(ierr); 00360 ierr = PISMOptionsReal("-ye", "End year", ye, flag); CHKERRQ(ierr); 00361 ierr = PISMOptionsReal("-dt", "Time-step, in years", dt_years, flag); CHKERRQ(ierr); 00362 } 00363 ierr = PetscOptionsEnd(); CHKERRQ(ierr); 00364 00365 // initialize the computational grid: 00366 ierr = verbPrintf(2,com, 00367 " initializing grid from NetCDF file %s...\n", inname.c_str()); CHKERRQ(ierr); 00368 ierr = setupIceGridFromFile(inname,grid); CHKERRQ(ierr); 00369 00370 mapping.init("mapping", com, rank); 00371 00372 // These values may be used by surface, atmosphere of ocean models: 00373 grid.year = ys; 00374 grid.start_year = ys; 00375 grid.end_year = ye; 00376 00377 // allocate IceModelVecs needed by boundary models and put them in a dictionary: 00378 PISMVars variables; 00379 ierr = createVecs(grid, variables); CHKERRQ(ierr); 00380 00381 // read data from a PISM input file (including the projection parameters) 00382 NCTool nc(grid.com, grid.rank); 00383 int last_record; 00384 bool mapping_exists; 00385 ierr = nc.open_for_reading(inname.c_str()); CHKERRQ(ierr); 00386 ierr = nc.find_variable("mapping", NULL, mapping_exists); CHKERRQ(ierr); 00387 ierr = nc.get_nrecords(last_record); CHKERRQ(ierr); 00388 ierr = nc.close(); CHKERRQ(ierr); 00389 if (mapping_exists) { 00390 ierr = mapping.read(inname.c_str()); CHKERRQ(ierr); 00391 ierr = mapping.print(); CHKERRQ(ierr); 00392 } 00393 last_record -= 1; 00394 00395 ierr = verbPrintf(2,com, 00396 " reading fields lat,lon,mask,thk,topg,usurf from NetCDF file %s\n" 00397 " to fill fields in PISMVars ...\n", 00398 inname.c_str()); CHKERRQ(ierr); 00399 00400 ierr = readIceInfoFromFile(inname.c_str(), last_record, variables); CHKERRQ(ierr); 00401 00402 // Initialize boundary models: 00403 PAFactory pa(grid, config); 00404 PISMAtmosphereModel *atmosphere; 00405 pa.add_model("eismint_greenland", &create_pa_eismint_greenland); 00406 00407 PSFactory ps(grid, config); 00408 PISMSurfaceModel *surface; 00409 00410 POFactory po(grid, config); 00411 PISMOceanModel *ocean; 00412 00413 ierr = PetscOptionsBegin(grid.com, "", "PISM Boundary Models", ""); CHKERRQ(ierr); 00414 00415 pa.create(atmosphere); 00416 ps.create(surface); 00417 po.create(ocean); 00418 00419 surface->attach_atmosphere_model(atmosphere); 00420 ierr = surface->init(variables); CHKERRQ(ierr); 00421 ierr = ocean->init(variables); CHKERRQ(ierr); 00422 00423 ierr = PetscOptionsEnd(); CHKERRQ(ierr); // done initializing boundary models. 00424 00425 ierr = verbPrintf(2, com, 00426 "writing boundary model states to NetCDF file '%s' ...\n", 00427 outname.c_str()); CHKERRQ(ierr); 00428 00429 ierr = writePCCStateAtTimes(variables, surface, ocean, 00430 outname.c_str(), &grid, 00431 ys, ye, dt_years, 00432 mapping); CHKERRQ(ierr); 00433 00434 if (override_used) { 00435 ierr = verbPrintf(3, com, 00436 " recording config overrides in NetCDF file '%s' ...\n", 00437 outname.c_str()); CHKERRQ(ierr); 00438 overrides.update_from(config); 00439 ierr = overrides.write(outname.c_str()); CHKERRQ(ierr); 00440 } 00441 00442 delete surface; 00443 delete ocean; 00444 ierr = doneWithIceInfo(variables); CHKERRQ(ierr); 00445 00446 ierr = verbPrintf(2,com, "done.\n"); CHKERRQ(ierr); 00447 00448 } 00449 00450 ierr = PetscFinalize(); CHKERRQ(ierr); 00451 return 0; 00452 } 00453 00454
1.7.3