PISM, A Parallel Ice Sheet Model stable 0.4.1779

src/base/iMinit.cc

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