PISM, A Parallel Ice Sheet Model stable 0.4.1779

src/earth/PBLingleClark.cc

Go to the documentation of this file.
00001 // Copyright (C) 2010, 2011 Constantine Khroulev
00002 //
00003 // This file is part of PISM.
00004 //
00005 // PISM is free software; you can redistribute it and/or modify it under the
00006 // terms of the GNU General Public License as published by the Free Software
00007 // Foundation; either version 2 of the License, or (at your option) any later
00008 // version.
00009 //
00010 // PISM is distributed in the hope that it will be useful, but WITHOUT ANY
00011 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00012 // FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
00013 // details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with PISM; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018 
00019 #if (PISM_HAVE_FFTW==1)
00020 
00021 #include "PISMBedDef.hh"
00022 #include "PISMIO.hh"
00023 
00024 PBLingleClark::PBLingleClark(IceGrid &g, const NCConfigVariable &conf)
00025   : PISMBedDef(g, conf) {
00026   PetscErrorCode ierr;
00027 
00028   ierr = allocate();
00029   if (ierr != 0) {
00030     PetscPrintf(grid.com, "PBLingleClark::PBLingleClark(...): allocate() failed\n");
00031     PISMEnd();
00032   }
00033   
00034 }
00035 
00036 PBLingleClark::~PBLingleClark() {
00037   PetscErrorCode ierr;
00038 
00039   ierr = deallocate();
00040   if (ierr != 0) {
00041     PetscPrintf(grid.com, "PBLingleClark::~PBLingleClark(...): deallocate() failed\n");
00042     PISMEnd();
00043   }
00044 
00045 }
00046 
00047 /* the following is from the PETSc FAQ page:
00048 
00049 How do I collect all the values from a parallel PETSc vector into a vector 
00050 on the zeroth processor?
00051 
00052     * Create the scatter context that will do the communication
00053           o VecScatterCreateToZero(v,&ctx,&w);
00054     * Actually do the communication; this can be done repeatedly as needed
00055           o VecScatterBegin(ctx,v,w,INSERT_VALUES,SCATTER_FORWARD);
00056           o VecScatterEnd(ctx,v,w,INSERT_VALUES,SCATTER_FORWARD);
00057     * Remember to free the scatter context when no longer needed
00058           o VecScatterDestroy(ctx);
00059 
00060 Note that this simply concatenates in the parallel ordering of the vector.
00061 If you are using a vector from DACreateGlobalVector() you likely want to 
00062 first call DAGlobalToNaturalBegin/End() to scatter the original vector into 
00063 the natural ordering in a new global vector before calling 
00064 VecScatterBegin/End() to scatter the natural vector onto process 0.
00065 */
00066 
00067 PetscErrorCode PBLingleClark::transfer_to_proc0(IceModelVec2S *source, Vec result) {
00068   PetscErrorCode ierr;
00069 
00070   ierr = source->copy_to(g2);
00071 
00072   ierr = DAGlobalToNaturalBegin(grid.da2, g2, INSERT_VALUES, g2natural); CHKERRQ(ierr);
00073   ierr =   DAGlobalToNaturalEnd(grid.da2, g2, INSERT_VALUES, g2natural); CHKERRQ(ierr);
00074 
00075   ierr = VecScatterBegin(scatter, g2natural, result, INSERT_VALUES, SCATTER_FORWARD); CHKERRQ(ierr);
00076   ierr =   VecScatterEnd(scatter, g2natural, result, INSERT_VALUES, SCATTER_FORWARD); CHKERRQ(ierr);
00077 
00078   return 0;
00079 }
00080 
00081 PetscErrorCode PBLingleClark::transfer_from_proc0(Vec source, IceModelVec2S *result) {
00082   PetscErrorCode ierr;
00083 
00084   ierr = VecScatterBegin(scatter, source, g2natural, INSERT_VALUES, SCATTER_REVERSE); CHKERRQ(ierr);
00085   ierr =   VecScatterEnd(scatter, source, g2natural, INSERT_VALUES, SCATTER_REVERSE); CHKERRQ(ierr);
00086 
00087   ierr = DANaturalToGlobalBegin(grid.da2, g2natural, INSERT_VALUES, g2); CHKERRQ(ierr);
00088   ierr =   DANaturalToGlobalEnd(grid.da2, g2natural, INSERT_VALUES, g2); CHKERRQ(ierr);
00089 
00090   ierr = result->copy_from(g2); CHKERRQ(ierr);
00091 
00092   return 0;
00093 }
00094 
00095 PetscErrorCode PBLingleClark::allocate() {
00096   PetscErrorCode ierr;
00097 
00098   ierr = DACreateGlobalVector(grid.da2, &g2); CHKERRQ(ierr);
00099 
00100   // note we want a global Vec but reordered in the natural ordering so when it is
00101   // scattered to proc zero it is not all messed up; see above
00102   ierr = DACreateNaturalVector(grid.da2, &g2natural); CHKERRQ(ierr);
00103   // next get context *and* allocate samplep0 (on proc zero only, naturally)
00104   ierr = VecScatterCreateToZero(g2natural, &scatter, &Hp0); CHKERRQ(ierr);
00105 
00106   ierr = VecDuplicate(Hp0,&bedp0); CHKERRQ(ierr);
00107   ierr = VecDuplicate(Hp0,&Hstartp0); CHKERRQ(ierr);
00108   ierr = VecDuplicate(Hp0,&bedstartp0); CHKERRQ(ierr);
00109   ierr = VecDuplicate(Hp0,&upliftp0); CHKERRQ(ierr);
00110 
00111   if (grid.rank == 0) {
00112     ierr = bdLC.settings(config,
00113                          PETSC_FALSE, // turn off elastic model for now
00114                          grid.Mx, grid.My, grid.dx, grid.dy,
00115                          //                       2,                 // use Z = 2 for now
00116                          4,                 // use Z = 4 for now; to reduce global drift?
00117                          config.get("ice_density"),
00118                          &Hstartp0, &bedstartp0, &upliftp0, &Hp0, &bedp0);
00119     CHKERRQ(ierr);
00120 
00121     ierr = bdLC.alloc(); CHKERRQ(ierr);
00122   }
00123 
00124   return 0;
00125 }
00126 
00127 PetscErrorCode PBLingleClark::deallocate() {
00128   PetscErrorCode ierr;
00129 
00130   ierr = VecDestroy(g2); CHKERRQ(ierr);
00131   ierr = VecDestroy(g2natural); CHKERRQ(ierr);
00132   ierr = VecScatterDestroy(scatter); CHKERRQ(ierr);
00133 
00134   ierr = VecDestroy(Hp0); CHKERRQ(ierr);
00135   ierr = VecDestroy(bedp0); CHKERRQ(ierr);
00136   ierr = VecDestroy(Hstartp0); CHKERRQ(ierr);
00137   ierr = VecDestroy(bedstartp0); CHKERRQ(ierr);
00138   ierr = VecDestroy(upliftp0); CHKERRQ(ierr);
00139 
00140   return 0;
00141 }
00142 
00144 PetscErrorCode PBLingleClark::init(PISMVars &vars) {
00145   PetscErrorCode ierr;
00146 
00147   ierr = PISMBedDef::init(vars); CHKERRQ(ierr);
00148 
00149   ierr = verbPrintf(2, grid.com,
00150                     "* Initializing the Lingle-Clark bed deformation model...\n"); CHKERRQ(ierr);
00151 
00152   ierr = correct_topg(); CHKERRQ(ierr);
00153 
00154   ierr = transfer_to_proc0(thk,    Hstartp0); CHKERRQ(ierr);
00155   ierr = transfer_to_proc0(topg,   bedstartp0); CHKERRQ(ierr);
00156   ierr = transfer_to_proc0(uplift, upliftp0); CHKERRQ(ierr);
00157 
00158   if (grid.rank == 0) {
00159     ierr = bdLC.uplift_init(); CHKERRQ(ierr);
00160   }
00161 
00162   return 0;
00163 }
00164 
00165 PetscErrorCode PBLingleClark::correct_topg() {
00166   PetscErrorCode ierr;
00167   bool use_special_regrid_semantics, regrid_file_set, boot_file_set,
00168     topg_exists, topg_initial_exists, regrid_vars_set;
00169   string boot_filename, regrid_filename;
00170   PISMIO nc(&grid);
00171 
00172   ierr = PISMOptionsIsSet("-regrid_bed_special",
00173                           "Correct topg when switching to a different grid",
00174                           use_special_regrid_semantics); CHKERRQ(ierr);
00175 
00176   // Stop if topg correction was not requiested.
00177   if (!use_special_regrid_semantics) return 0;
00178 
00179   ierr = PISMOptionsString("-regrid_file", "Specifies the name of a file to regrid from",
00180                            regrid_filename, regrid_file_set); CHKERRQ(ierr);
00181 
00182   ierr = PISMOptionsString("-boot_file", "Specifies the name of the file to bootstrap from",
00183                            boot_filename, boot_file_set); CHKERRQ(ierr);
00184 
00185   // Stop if it was requested, but we're not bootstrapping *and* regridding.
00186   if (! (regrid_file_set && boot_file_set) ) return 0;
00187 
00188   ierr = nc.open_for_reading(regrid_filename.c_str()); CHKERRQ(ierr);
00189 
00190   ierr = nc.find_variable("topg_initial", NULL, topg_initial_exists); CHKERRQ(ierr);
00191   ierr = nc.find_variable("topg", NULL, topg_exists); CHKERRQ(ierr);
00192   ierr = nc.close(); CHKERRQ(ierr);
00193 
00194   // Stop if the regridding file does not have both topg and topg_initial.
00195   if ( !(topg_initial_exists && topg_exists) ) {
00196     return 0;
00197   }
00198 
00199   // Stop if the user asked to regrid topg (in this case no correction is necessary).
00200   vector<string> regrid_vars;
00201   ierr = PISMOptionsStringArray("-regrid_vars", "Specifies regridding variables", "",
00202                                 regrid_vars, regrid_vars_set); CHKERRQ(ierr);
00203 
00204   if (regrid_vars_set) {
00205     for (unsigned int i = 0; i < regrid_vars.size(); ++i) {
00206       if (regrid_vars[i] == "topg") {
00207         ierr = verbPrintf(2, grid.com,
00208                           "  Bed elevation correction requested, but -regrid_vars contains topg...\n"); CHKERRQ(ierr); 
00209         return 0;
00210       }
00211     }
00212   }
00213 
00214   ierr = verbPrintf(2, grid.com,
00215                     "  Correcting topg from the bootstrapping file '%s' by adding the effect\n"
00216                     "  of the bed deformation from '%s'...\n",
00217                     boot_filename.c_str(), regrid_filename.c_str()); CHKERRQ(ierr); 
00218   
00219   IceModelVec2S topg_tmp;       // will be de-allocated at 'return 0' below.
00220   int WIDE_STENCIL = grid.max_stencil_width;
00221   ierr = topg_tmp.create(grid, "topg", true, WIDE_STENCIL); CHKERRQ(ierr);
00222   ierr = topg_tmp.set_attrs("model_state", "bedrock surface elevation (at the end of the previous run)",
00223                             "m", "bedrock_altitude"); CHKERRQ(ierr);
00224 
00225   // Get topg and topg_initial from the regridding file.
00226   ierr = topg_initial.regrid(regrid_filename.c_str(), true); CHKERRQ(ierr);
00227   ierr =     topg_tmp.regrid(regrid_filename.c_str(), true); CHKERRQ(ierr);
00228 
00229   // After bootstrapping, topg contains the bed elevation field from
00230   // -boot_file.
00231 
00232   ierr = topg_tmp.add(-1.0, topg_initial); CHKERRQ(ierr); 
00233   // Now topg_tmp contains the change in bed elevation computed during the run
00234   // that produced -regrid_file.
00235 
00236   // Apply this change to topg from -boot_file:
00237   ierr = topg->add(1.0, topg_tmp); CHKERRQ(ierr);
00238 
00239   // Store the corrected topg as the new "topg_initial".
00240   ierr = topg->copy_to(topg_initial); CHKERRQ(ierr);
00241 
00242   return 0;
00243 }
00244 
00245 
00247 PetscErrorCode PBLingleClark::update(PetscReal t_years, PetscReal dt_years) {
00248   PetscErrorCode ierr;
00249 
00250   if ((fabs(t_years - t)   < 1e-12) &&
00251       (fabs(dt_years - dt) < 1e-12))
00252     return 0;
00253 
00254   t  = t_years;
00255   dt = dt_years;
00256 
00257   // Check if it's time to update:
00258   PetscScalar dt_beddef = t_years - t_beddef_last;
00259   if (dt_beddef < config.get("bed_def_interval_years"))
00260     return 0;
00261 
00262   t_beddef_last = t_years;
00263 
00264   ierr = transfer_to_proc0(thk,  Hp0);   CHKERRQ(ierr);
00265   ierr = transfer_to_proc0(topg, bedp0); CHKERRQ(ierr);
00266 
00267   if (grid.rank == 0) {  // only processor zero does the step
00268     ierr = bdLC.step(dt_beddef, t_years - grid.start_year); CHKERRQ(ierr);
00269   }
00270 
00271   ierr = transfer_from_proc0(bedp0, topg); CHKERRQ(ierr);
00272 
00274   ierr = compute_uplift(dt_beddef); CHKERRQ(ierr);
00275   ierr = topg->copy_to(topg_last); CHKERRQ(ierr);
00276 
00277   return 0;
00278 }
00279 
00280 #else // PISM_HAVE_FFTW
00281 #error "PISM build system error: Lingle and Clark bed deformation model requires FFTW3."
00282 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines