|
PISM, A Parallel Ice Sheet Model stable 0.4.1779
|
00001 // Copyright (C) 2009--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 //This file contains various initialization routines. See the IceModel::init() 00020 //documentation comment in iceModel.cc for the order in which they are called. 00021 00022 #include <petscda.h> 00023 #include "iceModel.hh" 00024 #include "PISMIO.hh" 00025 #include "SIAFD.hh" 00026 #include "SSAFD.hh" 00027 #include "SSAFEM.hh" 00028 #include "Mask.hh" 00029 00031 00035 PetscErrorCode IceModel::set_grid_defaults() { 00036 PetscErrorCode ierr; 00037 bool Mx_set, My_set, Mz_set, Lz_set, boot_file_set; 00038 string filename; 00039 grid_info gi; 00040 00041 // Get the bootstrapping file name: 00042 00043 ierr = PISMOptionsString("-boot_file", "Specifies the file to bootstrap from", 00044 filename, boot_file_set); CHKERRQ(ierr); 00045 00046 if (!boot_file_set) { 00047 ierr = PetscPrintf(grid.com, 00048 "PISM ERROR: Please specify an input file using -i or -boot_file.\n"); 00049 CHKERRQ(ierr); 00050 PISMEnd(); 00051 } 00052 00053 // Use a bootstrapping file to set some grid parameters (they can be 00054 // overridden later, in IceModel::set_grid_from_options()). 00055 00056 // Determine the grid extent from a bootstrapping file: 00057 PISMIO nc(&grid); 00058 bool x_dim_exists, y_dim_exists, t_exists, time_exists; 00059 ierr = nc.open_for_reading(filename.c_str()); CHKERRQ(ierr); 00060 00061 ierr = nc.find_dimension("x", NULL, x_dim_exists); CHKERRQ(ierr); 00062 ierr = nc.find_dimension("y", NULL, y_dim_exists); CHKERRQ(ierr); 00063 ierr = nc.find_variable("t", NULL, t_exists); CHKERRQ(ierr); 00064 ierr = nc.find_variable("time", NULL, time_exists); CHKERRQ(ierr); 00065 00066 // Try to deduce grid information from present spatial fields. This is bad, 00067 // because theoretically these fields may use different grids. We need a 00068 // better way of specifying PISM's computational grid at bootstrapping. 00069 vector<string> names; 00070 names.push_back("land_ice_thickness"); 00071 names.push_back("bedrock_altitude"); 00072 names.push_back("thk"); 00073 names.push_back("topg"); 00074 for (unsigned int i = 0; i < names.size(); ++i) { 00075 ierr = nc.get_grid_info(names[i], gi); 00076 if (ierr == 0) break; 00077 } 00078 00079 if (ierr != 0) { 00080 PetscPrintf(grid.com, "ERROR: no geometry information found in '%s'.\n", 00081 filename.c_str()); 00082 PISMEnd(); 00083 } 00084 00085 bool mapping_exists; 00086 ierr = nc.find_variable("mapping", NULL, mapping_exists); CHKERRQ(ierr); 00087 if (mapping_exists) { 00088 ierr = mapping.read(filename.c_str()); CHKERRQ(ierr); 00089 ierr = mapping.print(); CHKERRQ(ierr); 00090 } 00091 00092 ierr = nc.close(); CHKERRQ(ierr); 00093 00094 // Set the grid center and horizontal extent: 00095 grid.x0 = gi.x0; 00096 grid.y0 = gi.y0; 00097 grid.Lx = gi.Lx; 00098 grid.Ly = gi.Ly; 00099 00100 // read grid.year if no option overrides it (avoids unnecessary reporting) 00101 bool ys_set; 00102 ierr = PISMOptionsIsSet("-ys", ys_set); CHKERRQ(ierr); 00103 if (!ys_set) { 00104 if (t_exists || time_exists) { 00105 grid.year = gi.time / secpera; // set year from read-in time variable 00106 ierr = verbPrintf(2, grid.com, 00107 " time t = %5.4f years found; setting current year\n", 00108 grid.year); CHKERRQ(ierr); 00109 } else { 00110 grid.year = 0.0; 00111 ierr = verbPrintf(2, grid.com, 00112 " time dimension was not found; setting current year to 0.0 years\n", 00113 grid.year); CHKERRQ(ierr); 00114 } 00115 } 00116 grid.start_year = grid.year; 00117 00118 // Grid dimensions should not be deduced from a bootstrapping file, so we 00119 // check if these options are set and stop if they are not. 00120 ierr = PISMOptionsIsSet("-Mx", Mx_set); CHKERRQ(ierr); 00121 ierr = PISMOptionsIsSet("-My", My_set); CHKERRQ(ierr); 00122 ierr = PISMOptionsIsSet("-Mz", Mz_set); CHKERRQ(ierr); 00123 if ( !(Mx_set && My_set && Mz_set) ) { 00124 ierr = PetscPrintf(grid.com, 00125 "PISM ERROR: All of -boot_file, -Mx, -My, -Mz are required for bootstrapping.\n"); 00126 CHKERRQ(ierr); 00127 PISMEnd(); 00128 } 00129 00130 ierr = PISMOptionsIsSet("-Lz", Lz_set); CHKERRQ(ierr); 00131 if ( !Lz_set ) { 00132 ierr = verbPrintf(2, grid.com, 00133 "PISM WARNING: -Lz is not set; trying to deduce it using the bootstrapping file...\n"); 00134 CHKERRQ(ierr); 00135 } 00136 00137 return 0; 00138 } 00139 00141 00144 PetscErrorCode IceModel::set_grid_from_options() { 00145 PetscErrorCode ierr; 00146 bool Mx_set, My_set, Mz_set, Lx_set, Ly_set, Lz_set, 00147 z_spacing_set, periodicity_set; 00148 PetscReal x_scale = grid.Lx / 1000.0, 00149 y_scale = grid.Ly / 1000.0, 00150 z_scale = grid.Lz; 00151 00152 // Process the options: 00153 00154 // Read -Lx and -Ly. 00155 ierr = PISMOptionsReal("-Ly", "Half of the grid extent in the X direction, in km", 00156 y_scale, Ly_set); CHKERRQ(ierr); 00157 ierr = PISMOptionsReal("-Lx", "Half of the grid extent in the Y direction, in km", 00158 x_scale, Lx_set); CHKERRQ(ierr); 00159 // Vertical extent (in the ice and bedrock, correspondingly): 00160 ierr = PISMOptionsReal("-Lz", "Grid extent in the Z (vertical) direction in the ice, in meters", 00161 z_scale, Lz_set); CHKERRQ(ierr); 00162 00163 // Read -Mx, -My, -Mz and -Mbz. 00164 ierr = PISMOptionsInt("-My", "Number of grid points in the X direction", 00165 grid.My, My_set); CHKERRQ(ierr); 00166 ierr = PISMOptionsInt("-Mx", "Number of grid points in the Y direction", 00167 grid.Mx, Mx_set); CHKERRQ(ierr); 00168 ierr = PISMOptionsInt("-Mz", "Number of grid points in the Z (vertical) direction in the ice", 00169 grid.Mz, Mz_set); CHKERRQ(ierr); 00170 00171 string keyword; 00172 set<string> z_spacing_choices; 00173 z_spacing_choices.insert("quadratic"); 00174 z_spacing_choices.insert("equal"); 00175 // Determine the vertical grid spacing in the ice: 00176 ierr = PISMOptionsList(grid.com, "-z_spacing", "Vertical spacing in the ice.", 00177 z_spacing_choices, "quadratic", keyword, z_spacing_set); CHKERRQ(ierr); 00178 00179 if (keyword == "quadratic") { 00180 grid.ice_vertical_spacing = QUADRATIC; 00181 } else { 00182 grid.ice_vertical_spacing = EQUAL; 00183 } 00184 00185 // Determine grid periodicity: 00186 set<string> periodicity_choices; 00187 periodicity_choices.insert("none"); 00188 periodicity_choices.insert("x"); 00189 periodicity_choices.insert("y"); 00190 periodicity_choices.insert("xy"); 00191 ierr = PISMOptionsList(grid.com, "-periodicity", "Horizontal grid periodicity.", 00192 periodicity_choices, "none", keyword, periodicity_set); CHKERRQ(ierr); 00193 if (periodicity_set) { 00194 if (keyword == "none") 00195 grid.periodicity = NONE; 00196 else if (keyword == "x") 00197 grid.periodicity = X_PERIODIC; 00198 else if (keyword == "y") 00199 grid.periodicity = Y_PERIODIC; 00200 else if (keyword == "xy") 00201 grid.periodicity = XY_PERIODIC; 00202 } 00203 00204 // Use the information obtained above: 00205 if (Lx_set) grid.Lx = x_scale * 1000.0; // convert to meters 00206 if (Ly_set) grid.Ly = y_scale * 1000.0; // convert to meters 00207 if (Lz_set) grid.Lz = z_scale; // in meters already 00208 00209 ierr = grid.compute_horizontal_spacing(); CHKERRQ(ierr); 00210 ierr = grid.compute_vertical_levels(); CHKERRQ(ierr); 00211 00212 // At this point all the fields except for da2, xs, xm, ys, ym should be 00213 // filled. We're ready to call grid.createDA(). 00214 return 0; 00215 } 00216 00218 00231 PetscErrorCode IceModel::grid_setup() { 00232 PetscErrorCode ierr; 00233 bool i_set; 00234 string filename; 00235 00236 ierr = PetscOptionsBegin(grid.com, "", 00237 "Options controlling input and computational grid parameters", 00238 ""); CHKERRQ(ierr); 00239 00240 ierr = verbPrintf(3, grid.com, 00241 "Setting up the computational grid...\n"); CHKERRQ(ierr); 00242 00243 // Check if we are initializing from a PISM output file: 00244 ierr = PISMOptionsString("-i", "Specifies a PISM input file", 00245 filename, i_set); CHKERRQ(ierr); 00246 00247 if (i_set) { 00248 PISMIO nc(&grid); 00249 string source; 00250 00251 // Get the 'source' global attribute to check if we are given a PISM output 00252 // file: 00253 ierr = nc.open_for_reading(filename.c_str()); CHKERRQ(ierr); 00254 ierr = nc.get_att_text(NC_GLOBAL, "source", source); CHKERRQ(ierr); 00255 00256 bool mapping_exists; 00257 ierr = nc.find_variable("mapping", NULL, mapping_exists); CHKERRQ(ierr); 00258 if (mapping_exists) { 00259 ierr = mapping.read(filename.c_str()); CHKERRQ(ierr); 00260 ierr = mapping.print(); CHKERRQ(ierr); 00261 } 00262 00263 ierr = nc.close(); CHKERRQ(ierr); 00264 00265 // If it's missing, print a warning 00266 if (source.empty()) { 00267 ierr = verbPrintf(1, grid.com, 00268 "PISM WARNING: file '%s' does not have the 'source' global attribute.\n" 00269 " If '%s' is a PISM output file, please run the following to get rid of this warning:\n" 00270 " ncatted -a source,global,c,c,PISM %s\n", 00271 filename.c_str(), filename.c_str(), filename.c_str()); CHKERRQ(ierr); 00272 } else if (source.find("PISM") == string::npos) { 00273 // If the 'source' attribute does not contain the string "PISM", then print 00274 // a message and stop: 00275 ierr = verbPrintf(1, grid.com, 00276 "PISM WARNING: '%s' does not seem to be a PISM output file.\n" 00277 " If it is, please make sure that the 'source' global attribute contains the string \"PISM\".\n", 00278 filename.c_str()); CHKERRQ(ierr); 00279 } 00280 00281 vector<string> names; 00282 names.push_back("enthalpy"); 00283 names.push_back("temp"); 00284 for (unsigned int i = 0; i < names.size(); ++i) { 00285 ierr = nc.get_grid(filename, names[i]); 00286 if (ierr == 0) break; 00287 } 00288 00289 if (ierr != 0) { 00290 PetscPrintf(grid.com, "PISM ERROR: file %s has neither enthalpy nor temperature in it!\n", 00291 filename.c_str()); CHKERRQ(ierr); 00292 PISMEnd(); 00293 } 00294 00295 grid.start_year = grid.year; // can be overridden using the -ys option 00296 00297 // These options are ignored because we're getting *all* the grid 00298 // parameters from a file. 00299 ierr = ignore_option(grid.com, "-Mx"); CHKERRQ(ierr); 00300 ierr = ignore_option(grid.com, "-My"); CHKERRQ(ierr); 00301 ierr = ignore_option(grid.com, "-Mz"); CHKERRQ(ierr); 00302 ierr = ignore_option(grid.com, "-Mbz"); CHKERRQ(ierr); 00303 ierr = ignore_option(grid.com, "-Lx"); CHKERRQ(ierr); 00304 ierr = ignore_option(grid.com, "-Ly"); CHKERRQ(ierr); 00305 ierr = ignore_option(grid.com, "-Lz"); CHKERRQ(ierr); 00306 ierr = ignore_option(grid.com, "-z_spacing"); CHKERRQ(ierr); 00307 ierr = ignore_option(grid.com, "-zb_spacing"); CHKERRQ(ierr); 00308 } else { 00309 ierr = set_grid_defaults(); CHKERRQ(ierr); 00310 ierr = set_grid_from_options(); CHKERRQ(ierr); 00311 } 00312 00313 bool Nx_set, Ny_set; 00314 ierr = PISMOptionsInt("-Nx", "Number of processors in the x direction", 00315 grid.Nx, Nx_set); CHKERRQ(ierr); 00316 ierr = PISMOptionsInt("-Ny", "Number of processors in the y direction", 00317 grid.Ny, Ny_set); CHKERRQ(ierr); 00318 00319 if (Nx_set ^ Ny_set) { 00320 ierr = PetscPrintf(grid.com, 00321 "PISM ERROR: Please set both -Nx and -Ny.\n"); 00322 CHKERRQ(ierr); 00323 PISMEnd(); 00324 } 00325 00326 if ((!Nx_set) && (!Ny_set)) { 00327 grid.compute_nprocs(); 00328 grid.compute_ownership_ranges(); 00329 } else { 00330 00331 if ((grid.Mx / grid.Nx) < 2) { 00332 ierr = PetscPrintf(grid.com, 00333 "PISM ERROR: Can't split %d grid points between %d processors.\n", 00334 grid.Mx, grid.Nx); 00335 CHKERRQ(ierr); 00336 PISMEnd(); 00337 } 00338 00339 if ((grid.My / grid.Ny) < 2) { 00340 ierr = PetscPrintf(grid.com, 00341 "PISM ERROR: Can't split %d grid points between %d processors.\n", 00342 grid.My, grid.Ny); 00343 CHKERRQ(ierr); 00344 PISMEnd(); 00345 } 00346 00347 if (grid.Nx * grid.Ny != grid.size) { 00348 ierr = PetscPrintf(grid.com, 00349 "PISM ERROR: Nx * Ny has to be equal to %d.\n", 00350 grid.size); 00351 CHKERRQ(ierr); 00352 PISMEnd(); 00353 } 00354 00355 bool procs_x_set, procs_y_set; 00356 vector<PetscInt> tmp_x, tmp_y; 00357 ierr = PISMOptionsIntArray("-procs_x", "Processor ownership ranges (x direction)", 00358 tmp_x, procs_x_set); CHKERRQ(ierr); 00359 ierr = PISMOptionsIntArray("-procs_y", "Processor ownership ranges (y direction)", 00360 tmp_y, procs_y_set); CHKERRQ(ierr); 00361 00362 if (procs_x_set ^ procs_y_set) { 00363 ierr = PetscPrintf(grid.com, 00364 "PISM ERROR: Please set both -procs_x and -procs_y.\n"); 00365 CHKERRQ(ierr); 00366 PISMEnd(); 00367 } 00368 00369 if (procs_x_set && procs_y_set) { 00370 if (tmp_x.size() != (unsigned int)grid.Nx) { 00371 ierr = PetscPrintf(grid.com, 00372 "PISM ERROR: -Nx has to be equal to the -procs_x size.\n"); 00373 CHKERRQ(ierr); 00374 PISMEnd(); 00375 } 00376 00377 if (tmp_y.size() != (unsigned int)grid.Ny) { 00378 ierr = PetscPrintf(grid.com, 00379 "PISM ERROR: -Ny has to be equal to the -procs_y size.\n"); 00380 CHKERRQ(ierr); 00381 PISMEnd(); 00382 } 00383 00384 grid.procs_x.resize(grid.Nx); 00385 grid.procs_y.resize(grid.Ny); 00386 00387 for (PetscInt j=0; j < grid.Nx; j++) 00388 grid.procs_x[j] = tmp_x[j]; 00389 00390 for (PetscInt j=0; j < grid.Ny; j++) 00391 grid.procs_y[j] = tmp_y[j]; 00392 } else { 00393 grid.compute_ownership_ranges(); 00394 } 00395 } // -Nx and -Ny set 00396 00397 // Process -y, -ys, -ye. We are reading these options here because couplers 00398 // might need to know what year it is. 00399 ierr = set_time_from_options(); CHKERRQ(ierr); 00400 00401 grid.check_parameters(); 00402 00403 ierr = grid.createDA(); CHKERRQ(ierr); 00404 00405 ierr = PetscOptionsEnd(); CHKERRQ(ierr); 00406 00407 return 0; 00408 } 00409 00411 00431 PetscErrorCode IceModel::model_state_setup() { 00432 PetscErrorCode ierr; 00433 bool i_set; 00434 string filename; 00435 00436 // Check if we are initializing from a PISM output file: 00437 ierr = PISMOptionsString("-i", "Specifies a PISM input file", 00438 filename, i_set); CHKERRQ(ierr); 00439 00440 if (i_set) { 00441 ierr = initFromFile(filename.c_str()); CHKERRQ(ierr); 00442 00443 ierr = regrid(0); CHKERRQ(ierr); 00444 // Check consistency of geometry after initialization: 00445 ierr = updateSurfaceElevationAndMask(); CHKERRQ(ierr); 00446 } else { 00447 ierr = set_vars_from_options(); CHKERRQ(ierr); 00448 } 00449 00450 // Initialize a bed deformation model (if needed); this should go after 00451 // the regrid() call. 00452 if (beddef) { 00453 ierr = beddef->init(variables); CHKERRQ(ierr); 00454 last_bed_def_update = grid.year; 00455 } 00456 00457 if (btu) { 00458 ierr = get_bed_top_temp(bedtoptemp); CHKERRQ(ierr); 00459 ierr = btu->init(variables); CHKERRQ(ierr); 00460 } 00461 00462 if (basal_yield_stress) { 00463 ierr = basal_yield_stress->init(variables); CHKERRQ(ierr); 00464 } 00465 00466 // a report on whether PISM-PIK modifications of IceModel are in use 00467 const bool pg = config.get_flag("part_grid"), 00468 pr = config.get_flag("part_redist"), 00469 ki = config.get_flag("kill_icebergs"); 00470 if (pg || pr || ki) { 00471 ierr = verbPrintf(2, grid.com, 00472 " PISM-PIK mass/geometry methods are in use: "); CHKERRQ(ierr); 00473 00474 if (pg) { ierr = verbPrintf(2, grid.com, "part_grid,"); CHKERRQ(ierr); } 00475 if (pr) { ierr = verbPrintf(2, grid.com, "part_redist,"); CHKERRQ(ierr); } 00476 if (ki) { ierr = verbPrintf(2, grid.com, "kill_icebergs"); CHKERRQ(ierr); } 00477 00478 ierr = verbPrintf(2, grid.com, "\n"); CHKERRQ(ierr); 00479 } 00480 00481 ierr = stampHistoryCommand(); CHKERRQ(ierr); 00482 00483 return 0; 00484 } 00485 00487 00493 PetscErrorCode IceModel::set_vars_from_options() { 00494 PetscErrorCode ierr; 00495 bool boot_file_set; 00496 string filename; 00497 00498 ierr = verbPrintf(3, grid.com, 00499 "Setting initial values of model state variables...\n"); CHKERRQ(ierr); 00500 00501 ierr = PISMOptionsString("-boot_file", "Specifies the file to bootstrap from", 00502 filename, boot_file_set); CHKERRQ(ierr); 00503 00504 if (boot_file_set) { 00505 ierr = bootstrapFromFile(filename.c_str()); CHKERRQ(ierr); 00506 } else { 00507 ierr = PetscPrintf(grid.com, "PISM ERROR: No input file specified.\n"); CHKERRQ(ierr); 00508 PISMEnd(); 00509 } 00510 00511 return 0; 00512 } 00513 00515 PetscErrorCode IceModel::allocate_flowlaw() { 00516 PetscErrorCode ierr; 00517 00518 if (ice != NULL) 00519 return 0; 00520 00521 // Initialize the IceFlowLaw object: 00522 if (!config.get_flag("do_cold_ice_methods")) { 00523 ierr = verbPrintf(2, grid.com, 00524 " setting flow law to polythermal type ...\n"); CHKERRQ(ierr); 00525 ierr = verbPrintf(3, grid.com, 00526 " (= Glen-Paterson-Budd-Lliboutry-Duval type)\n"); CHKERRQ(ierr); 00527 00528 // new flowlaw which has dependence on enthalpy, not temperature 00529 ice = new GPBLDIce(grid.com, "", config); 00530 } else { 00531 ierr = verbPrintf(2, grid.com, 00532 " doing cold ice methods ...\n"); CHKERRQ(ierr); 00533 00534 00535 // FIXME: the semantics of IceFlowLaw should be cleared up; lots of PISM 00536 // (e.g. verification and EISMINT II and EISMINT-Greenland) are cold, 00537 // but the really important cases (e.g. SeaRISE-Greenland) are polythermal 00538 // in cold case we may have various IceFlowLaw s, e.g. set by derived classes 00539 ierr = iceFactory.setFromOptions(); CHKERRQ(ierr); 00540 ierr = iceFactory.create(&ice); CHKERRQ(ierr); 00541 } 00542 00543 // set options specific to this particular ice type: 00544 ierr = ice->setFromOptions(); CHKERRQ(ierr); 00545 00546 return 0; 00547 } 00548 00550 PetscErrorCode IceModel::allocate_enthalpy_converter() { 00551 PetscErrorCode ierr; 00552 00553 if (EC != NULL) 00554 return 0; 00555 00556 EC = new EnthalpyConverter(config); 00557 if (getVerbosityLevel() > 3) { 00558 PetscViewer viewer; 00559 ierr = PetscViewerASCIIGetStdout(PETSC_COMM_WORLD,&viewer); CHKERRQ(ierr); 00560 ierr = EC->viewConstants(viewer); CHKERRQ(ierr); 00561 } 00562 00563 return 0; 00564 } 00565 00567 PetscErrorCode IceModel::allocate_stressbalance() { 00568 PetscErrorCode ierr; 00569 00570 if (stress_balance != NULL) 00571 return 0; 00572 00573 bool 00574 use_ssa_velocity = config.get_flag("use_ssa_velocity"), 00575 do_sia = config.get_flag("do_sia"); 00576 00577 // If both SIA and SSA are "on", the SIA and SSA velocities are always added 00578 // up (there is no switch saying "do the hybrid"). 00579 if (stress_balance == NULL) { 00580 ShallowStressBalance *my_stress_balance; 00581 00582 SSB_Modifier *modifier; 00583 if (do_sia) { 00584 modifier = new SIAFD(grid, *ice, *EC, config); 00585 } else { 00586 modifier = new SSBM_Trivial(grid, *ice, *EC, config); 00587 } 00588 00589 if (use_ssa_velocity) { 00590 string ssa_method = config.get_string("ssa_method"); 00591 if( ssa_method == "fd" ) { 00592 my_stress_balance = new SSAFD(grid, *basal, *ice, *EC, config); 00593 } else if(ssa_method == "fem") { 00594 my_stress_balance = new SSAFEM(grid, *basal, *ice, *EC, config); 00595 } else { 00596 SETERRQ(1,"SSA algorithm flag should be one of \"fd\" or \"fem\""); 00597 } 00598 } else { 00599 my_stress_balance = new SSB_Trivial(grid, *basal, *ice, *EC, config); 00600 } 00601 00602 // ~PISMStressBalance() will de-allocate my_stress_balance and modifier. 00603 stress_balance = new PISMStressBalance(grid, my_stress_balance, 00604 modifier, ocean, config); 00605 00606 // Note that in PISM stress balance computations are diagnostic, i.e. do not 00607 // have a state that changes in time. This means that this call can be here 00608 // and not in model_state_setup() and we don't need to re-initialize after 00609 // the "diagnostic time step". 00610 ierr = stress_balance->init(variables); CHKERRQ(ierr); 00611 00612 if (config.get_flag("include_bmr_in_continuity")) { 00613 ierr = stress_balance->set_basal_melt_rate(&vbmr); CHKERRQ(ierr); 00614 } 00615 } 00616 00617 return 0; 00618 } 00619 00621 PetscErrorCode IceModel::allocate_bedrock_thermal_unit() { 00622 00623 if (btu != NULL) 00624 return 0; 00625 00626 btu = new PISMBedThermalUnit(grid, config); 00627 00628 return 0; 00629 } 00630 00632 PetscErrorCode IceModel::allocate_basal_yield_stress() { 00633 PetscErrorCode ierr; 00634 00635 if (basal_yield_stress != NULL) 00636 return 0; 00637 00638 bool use_ssa_velocity = config.get_flag("use_ssa_velocity"); 00639 00640 if (use_ssa_velocity) { 00641 bool hold_tauc; 00642 ierr = PISMOptionsIsSet("-hold_tauc", hold_tauc); CHKERRQ(ierr); 00643 00644 if (hold_tauc) { 00645 basal_yield_stress = new PISMConstantYieldStress(grid, config); 00646 } else { 00647 basal_yield_stress = new PISMDefaultYieldStress(grid, config); 00648 } 00649 } 00650 00651 return 0; 00652 } 00653 00655 PetscErrorCode IceModel::allocate_basal_resistance_law() { 00656 00657 if (basal != NULL) 00658 return 0; 00659 00660 bool do_pseudo_plastic_till = config.get_flag("do_pseudo_plastic_till"); 00661 00662 PetscScalar pseudo_plastic_q = config.get("pseudo_plastic_q"), 00663 pseudo_plastic_uthreshold = config.get("pseudo_plastic_uthreshold") / secpera, 00664 plastic_regularization = config.get("plastic_regularization") / secpera; 00665 00666 basal = new IceBasalResistancePlasticLaw(plastic_regularization, 00667 do_pseudo_plastic_till, 00668 pseudo_plastic_q, 00669 pseudo_plastic_uthreshold); 00670 00671 return 0; 00672 } 00673 00675 00680 PetscErrorCode IceModel::allocate_submodels() { 00681 PetscErrorCode ierr; 00682 00683 // these two have to go first 00684 ierr = allocate_flowlaw(); CHKERRQ(ierr); 00685 ierr = allocate_enthalpy_converter(); CHKERRQ(ierr); 00686 00687 // this has to happen before allocate_stressbalance() is called 00688 ierr = allocate_basal_resistance_law(); CHKERRQ(ierr); 00689 00690 ierr = allocate_stressbalance(); CHKERRQ(ierr); 00691 00692 ierr = allocate_basal_yield_stress(); CHKERRQ(ierr); 00693 00694 ierr = allocate_bedrock_thermal_unit(); CHKERRQ(ierr); 00695 00696 ierr = allocate_bed_deformation(); CHKERRQ(ierr); 00697 00698 return 0; 00699 } 00700 00701 00703 PetscErrorCode IceModel::init_couplers() { 00704 PetscErrorCode ierr; 00705 00706 ierr = verbPrintf(3, grid.com, 00707 "Initializing boundary models...\n"); CHKERRQ(ierr); 00708 00709 if (surface != PETSC_NULL) { 00710 ierr = surface->init(variables); CHKERRQ(ierr); 00711 } else { SETERRQ(2,"PISM ERROR: surface == PETSC_NULL"); } 00712 00713 if (ocean != PETSC_NULL) { 00714 ierr = ocean->init(variables); CHKERRQ(ierr); 00715 } else { SETERRQ(2,"PISM ERROR: ocean == PETSC_NULL"); } 00716 00717 return 0; 00718 } 00719 00720 00722 PetscErrorCode IceModel::allocate_internal_objects() { 00723 PetscErrorCode ierr; 00724 PetscInt WIDE_STENCIL = grid.max_stencil_width; 00725 00726 // various internal quantities 00727 // 2d work vectors 00728 for (int j = 0; j < nWork2d; j++) { 00729 char namestr[30]; 00730 snprintf(namestr, sizeof(namestr), "work_vector_%d", j); 00731 ierr = vWork2d[j].create(grid, namestr, true, WIDE_STENCIL); CHKERRQ(ierr); 00732 } 00733 00734 ierr = vWork2dV.create(grid, "vWork2dV", true); CHKERRQ(ierr); 00735 ierr = vWork2dV.set_attrs("internal", "velocity work vector", "", ""); CHKERRQ(ierr); 00736 00737 // 3d work vectors 00738 ierr = vWork3d.create(grid,"work_vector_3d",false); CHKERRQ(ierr); 00739 ierr = vWork3d.set_attrs( 00740 "internal", 00741 "e.g. new values of temperature or age or enthalpy during time step", 00742 "", ""); CHKERRQ(ierr); 00743 00744 return 0; 00745 } 00746 00747 00749 PetscErrorCode IceModel::misc_setup() { 00750 PetscErrorCode ierr; 00751 00752 ierr = verbPrintf(3, grid.com, "Finishing initialization...\n"); CHKERRQ(ierr); 00753 00754 ierr = set_output_size("-o_size", "Sets the 'size' of an output file.", 00755 "medium", output_vars); CHKERRQ(ierr); 00756 00757 ierr = init_ocean_kill(); CHKERRQ(ierr); 00758 ierr = init_diagnostics(); CHKERRQ(ierr); 00759 ierr = init_snapshots(); CHKERRQ(ierr); 00760 ierr = init_backups(); CHKERRQ(ierr); 00761 ierr = init_timeseries(); CHKERRQ(ierr); 00762 ierr = init_extras(); CHKERRQ(ierr); 00763 ierr = init_viewers(); CHKERRQ(ierr); 00764 00765 // compute (possibly corrected) cell areas: 00766 ierr = compute_cell_areas(); CHKERRQ(ierr); 00767 00768 event_step = grid.profiler->create("step", "time spent doing time-stepping"); 00769 event_velocity = grid.profiler->create("velocity", "time spent updating ice velocity"); 00770 00771 event_energy = grid.profiler->create("energy", "time spent inside energy time-stepping"); 00772 event_age = grid.profiler->create("age", "time spent inside age time-stepping"); 00773 event_mass = grid.profiler->create("masscont", "time spent inside mass continuity time-stepping"); 00774 00775 event_beddef = grid.profiler->create("bed_def", "time spent updating the bed deformation model"); 00776 00777 event_output = grid.profiler->create("output", "time spent writing an output file"); 00778 event_snapshots = grid.profiler->create("snapshots", "time spent writing snapshots"); 00779 event_backups = grid.profiler->create("backups", "time spent writing backups"); 00780 00781 return 0; 00782 } 00783 00785 PetscErrorCode IceModel::set_time_from_options() { 00786 PetscErrorCode ierr; 00787 00788 // read options about year of start, year of end, number of run years; 00789 // note grid.year has already been set from input file or defaults 00790 PetscReal usrStartYear = grid.start_year, 00791 usrEndYear = grid.end_year, 00792 usrRunYears = grid.end_year - grid.start_year; 00793 bool ysSet = false, yeSet = false, ySet = false; 00794 00795 ierr = PetscOptionsBegin(grid.com, "", "Time: start year, end year and run length", ""); CHKERRQ(ierr); 00796 { 00797 ierr = PISMOptionsReal("-ys", "Start year", usrStartYear, ysSet); CHKERRQ(ierr); 00798 ierr = PISMOptionsReal("-ye", "End year", usrEndYear, yeSet); CHKERRQ(ierr); 00799 ierr = PISMOptionsReal("-y", "years; Run length", usrRunYears, ySet); CHKERRQ(ierr); 00800 } 00801 ierr = PetscOptionsEnd(); CHKERRQ(ierr); 00802 00803 00804 if (ysSet && yeSet && ySet) { 00805 ierr = PetscPrintf(grid.com, "PISM ERROR: all of -y, -ys, -ye are set. Exiting...\n"); 00806 CHKERRQ(ierr); 00807 PISMEnd(); 00808 } 00809 if (ySet && yeSet) { 00810 ierr = PetscPrintf(grid.com, "PISM ERROR: using -y and -ye together is not allowed. Exiting...\n"); CHKERRQ(ierr); 00811 PISMEnd(); 00812 } 00813 00814 // Set the start year if -ys is set, use the default (stored in 00815 // grid.start_year) otherwise. 00816 if (ysSet == PETSC_TRUE) { 00817 grid.start_year = usrStartYear; 00818 grid.year = usrStartYear; 00819 } else { 00820 grid.year = grid.start_year; 00821 } 00822 00823 if (yeSet == PETSC_TRUE) { 00824 if (usrEndYear < grid.start_year) { 00825 ierr = PetscPrintf(grid.com, 00826 "PISM ERROR: -ye (%3.3f) is less than -ys (%3.3f) (or input file year or default).\n" 00827 "PISM cannot run backward in time.\n", 00828 usrEndYear, grid.start_year); CHKERRQ(ierr); 00829 PISMEnd(); 00830 } 00831 grid.end_year = usrEndYear; 00832 } else if (ySet == PETSC_TRUE) { 00833 grid.end_year = grid.start_year + usrRunYears; 00834 } else { 00835 grid.end_year = grid.start_year + config.get("run_length_years"); 00836 } 00837 00838 t_years_TempAge = grid.year; 00839 00840 return 0; 00841 } 00842 00844 PetscErrorCode IceModel::init_ocean_kill() { 00845 PetscErrorCode ierr; 00846 string filename; 00847 bool flag; 00848 00849 if (!config.get_flag("ocean_kill")) 00850 return 0; 00851 00852 ierr = PetscOptionsBegin(grid.com, "", "Fixed calving front options", ""); CHKERRQ(ierr); 00853 { 00854 ierr = PISMOptionsString("-ocean_kill", "Specifies a file to get -ocean_kill thickness from", 00855 filename, flag, true); CHKERRQ(ierr); 00856 } 00857 ierr = PetscOptionsEnd(); CHKERRQ(ierr); 00858 00859 MaskQuery m(vMask); 00860 00861 IceModelVec2S thickness, *tmp; 00862 00863 if (filename.empty()) { 00864 ierr = verbPrintf(2, grid.com, 00865 "* Using ice thickness at the beginning of the run\n" 00866 " to set the fixed calving front location.\n"); CHKERRQ(ierr); 00867 tmp = &vH; 00868 } else { 00869 ierr = verbPrintf(2, grid.com, 00870 "* Setting fixed calving front location using ice thickness from '%s'.\n", 00871 filename.c_str()); CHKERRQ(ierr); 00872 00873 ierr = thickness.create(grid, "thk", false); CHKERRQ(ierr); 00874 ierr = thickness.set_attrs("temporary", "land ice thickness", 00875 "m", "land_ice_thickness"); CHKERRQ(ierr); 00876 ierr = thickness.set_attr("valid_min", 0.0); CHKERRQ(ierr); 00877 00878 ierr = thickness.regrid(filename, true); CHKERRQ(ierr); 00879 00880 tmp = &thickness; 00881 } 00882 00883 ierr = ocean_kill_mask.begin_access(); CHKERRQ(ierr); 00884 ierr = tmp->begin_access(); CHKERRQ(ierr); 00885 ierr = vMask.begin_access(); CHKERRQ(ierr); 00886 00887 for (PetscInt i = grid.xs; i < grid.xs+grid.xm; ++i) { 00888 for (PetscInt j = grid.ys; j < grid.ys+grid.ym; ++j) { 00889 if ((*tmp)(i, j) > 0 || m.grounded(i, j) ) 00890 ocean_kill_mask(i, j) = 0; 00891 else 00892 ocean_kill_mask(i, j) = 1; 00893 } 00894 } 00895 00896 ierr = vMask.end_access(); CHKERRQ(ierr); 00897 ierr = tmp->end_access(); CHKERRQ(ierr); 00898 ierr = ocean_kill_mask.end_access(); CHKERRQ(ierr); 00899 00900 return 0; 00901 }
1.7.3