|
PISM, A Parallel Ice Sheet Model stable 0.4.1779
|
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
1.7.3