|
PISM, A Parallel Ice Sheet Model stable 0.4.1779
|
00001 // Copyright (C) 2004-2011 Jed Brown, 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 #include <cmath> 00020 #include <cstring> 00021 #include <petscda.h> 00022 00023 #include <vector> // STL vector container; sortable; used in test L 00024 #include <algorithm> // required by sort(...) in test L 00025 00026 #include "tests/exactTestsABCDE.h" 00027 #include "tests/exactTestsFG.h" 00028 #include "tests/exactTestH.h" 00029 #include "tests/exactTestL.h" 00030 00031 #include "iceCompModel.hh" 00032 #include "SIA_Sliding.hh" 00033 #include "SIAFD.hh" 00034 00035 const PetscScalar IceCompModel::ablationRateOutside = 0.02; // m/a 00036 00037 IceCompModel::IceCompModel(IceGrid &g, NCConfigVariable &conf, NCConfigVariable &conf_overrides, int mytest) 00038 : IceModel(g, conf, conf_overrides), tgaIce(NULL) { 00039 00040 // note lots of defaults are set by the IceModel constructor 00041 00042 // defaults for IceCompModel: 00043 testname = mytest; 00044 exactOnly = PETSC_FALSE; 00045 bedrock_is_ice_forK = PETSC_FALSE; 00046 00047 // Override some defaults from parent class 00048 config.set("enhancement_factor", 1.0); 00049 config.set("bed_smoother_range", 0.0); // none use bed smoothing & bed roughness 00050 // parameterization 00051 00052 // set values of flags in run() 00053 config.set_flag("do_mass_conserve", true); 00054 config.set_flag("use_ssa_velocity", false); 00055 config.set_flag("include_bmr_in_continuity", false); 00056 config.set_flag("use_ssa_when_grounded", false); 00057 } 00058 00059 PetscErrorCode IceCompModel::createVecs() { 00060 PetscErrorCode ierr; 00061 00062 ierr = IceModel::createVecs(); CHKERRQ(ierr); 00063 00064 ierr = vHexactL.create(grid, "HexactL", true, 2); CHKERRQ(ierr); 00065 00066 ierr = SigmaComp3.create(grid,"SigmaComp", false); CHKERRQ(ierr); 00067 ierr = SigmaComp3.set_attrs("internal","rate of compensatory strain heating in ice", 00068 "W m-3", ""); CHKERRQ(ierr); 00069 00070 // this ensures that these variables are saved to an output file and are read 00071 // back in if -i option is used (they are "model_state", in a sense, since 00072 // PSDummy is used): 00073 ierr = artm.set_attr("pism_intent", "model_state"); CHKERRQ(ierr); 00074 ierr = acab.set_attr("pism_intent", "model_state"); CHKERRQ(ierr); 00075 00076 if (testname == 'V') { 00077 ierr = bc_mask.create(grid, "bc_mask", false); CHKERRQ(ierr); 00078 ierr = bc_mask.set_attrs("model_state", "SSA Dirichlet BC locations", "", ""); CHKERRQ(ierr); 00079 bc_mask.time_independent = true; 00080 ierr = variables.add(bc_mask); CHKERRQ(ierr); 00081 00082 ierr = bc_vel.create(grid, "_bc", false); CHKERRQ(ierr); 00083 ierr = bc_vel.set_attrs("model_state", "X-component of the SSA Dirichlet BC", "m s-1", "", 0); CHKERRQ(ierr); 00084 ierr = bc_vel.set_attrs("model_state", "Y-component of the SSA Dirichlet BC", "m s-1", "", 1); CHKERRQ(ierr); 00085 bc_vel.time_independent = true; 00086 ierr = bc_vel.set_glaciological_units("m year-1"); CHKERRQ(ierr); 00087 bc_vel.write_in_glaciological_units = true; 00088 ierr = variables.add(bc_vel); CHKERRQ(ierr); 00089 } 00090 00091 return 0; 00092 } 00093 00094 PetscErrorCode IceCompModel::set_grid_defaults() { 00095 PetscErrorCode ierr; 00096 00097 // This sets the defaults for each test; command-line options can override this. 00098 00099 // equal spacing is the default for all the tests except K 00100 grid.ice_vertical_spacing = EQUAL; 00101 00102 switch (testname) { 00103 case 'A': 00104 case 'E': 00105 // use 1600km by 1600km by 4000m rectangular domain 00106 grid.Lx = grid.Ly = 800e3; 00107 grid.Lz = 4000; 00108 break; 00109 case 'B': 00110 case 'H': 00111 // use 2400km by 2400km by 4000m rectangular domain 00112 grid.Lx = grid.Ly = 1200e3; 00113 grid.Lz = 4000; 00114 break; 00115 case 'C': 00116 case 'D': 00117 // use 2000km by 2000km by 4000m rectangular domain 00118 grid.Lx = grid.Ly = 1000e3; 00119 grid.Lz = 4000; 00120 break; 00121 case 'F': 00122 case 'G': 00123 case 'L': 00124 // use 1800km by 1800km by 4000m rectangular domain 00125 grid.Lx = grid.Ly = 900e3; 00126 grid.Lz = 4000; 00127 break; 00128 case 'K': 00129 case 'O': 00130 // use 2000km by 2000km by 4000m rectangular domain, but make truely periodic 00131 config.set("grid_Mbz", 2); 00132 config.set("grid_Lbz", 1000); 00133 grid.Lx = grid.Ly = 1000e3; 00134 grid.Lz = 4000; 00135 grid.periodicity = XY_PERIODIC; 00136 grid.ice_vertical_spacing = QUADRATIC; 00137 break; 00138 case 'V': 00139 grid.My = 3; // it's a flow-line setup 00140 grid.Lx = 500e3; // 500 km long 00141 grid.periodicity = Y_PERIODIC; 00142 break; 00143 default: 00144 ierr = PetscPrintf(grid.com, "IceCompModel ERROR : desired test not implemented\n"); 00145 CHKERRQ(ierr); 00146 PISMEnd(); 00147 } 00148 00149 return 0; 00150 } 00151 00152 PetscErrorCode IceCompModel::setFromOptions() { 00153 PetscErrorCode ierr; 00154 00155 ierr = verbPrintf(2, grid.com, "starting Test %c ...\n", testname); CHKERRQ(ierr); 00156 00157 /* This switch turns off actual numerical evolution and simply reports the 00158 exact solution. */ 00159 bool flag; 00160 ierr = PISMOptionsIsSet("-eo", flag); CHKERRQ(ierr); 00161 if (flag) { 00162 exactOnly = PETSC_TRUE; 00163 ierr = verbPrintf(1,grid.com, "!!EXACT SOLUTION ONLY, NO NUMERICAL SOLUTION!!\n"); 00164 CHKERRQ(ierr); 00165 } 00166 00167 // These ifs are here (and not in the constructor or later) because 00168 // testname actually comes from a command-line *and* because command-line 00169 // options should be able to override parameter values set here. 00170 00171 if (testname == 'H') { 00172 config.set_string("bed_deformation_model", "iso"); 00173 } else 00174 config.set_string("bed_deformation_model", "none"); 00175 00176 if ((testname == 'F') || (testname == 'G') || (testname == 'K') || (testname == 'O')) { 00177 config.set_flag("do_energy", true); 00178 // essentially turn off run-time reporting of extremely low computed 00179 // temperatures; *they will be reported as errors* anyway 00180 config.set("global_min_allowed_temp", 0.0); 00181 config.set("max_low_temp_count", 1000000); 00182 } else 00183 config.set_flag("do_energy", false); 00184 00185 config.set_flag("is_dry_simulation", true); 00186 config.set_flag("ocean_kill", false); 00187 00188 // special considerations for K and O wrt thermal bedrock and pressure-melting 00189 if ((testname == 'K') || (testname == 'O')) { 00190 allowAboveMelting = PETSC_FALSE; // test K 00191 } else { 00192 // note temps are generally allowed to go above pressure melting in verify 00193 allowAboveMelting = PETSC_TRUE; // tests other than K 00194 } 00195 00196 if (testname == 'V') { 00197 00198 // no sub-shelf melting 00199 config.set_flag("include_bmr_in_continuity", false); 00200 00201 // this test is isothermal 00202 config.set_flag("do_energy", false); 00203 00204 // do use the SIA stress balance 00205 config.set_flag("do_sia", false); 00206 00207 // do use the SSA solver 00208 config.set_flag("use_ssa_velocity", true); 00209 00210 // compute surface gradient inward 00211 config.set_flag("compute_surf_grad_inward_ssa", true); 00212 00213 // this certainly is not a "dry silumation" 00214 config.set_flag("is_dry_simulation", false); 00215 00216 // use CustomGlenIce, which allows easy setting of ice hardness 00217 ierr = iceFactory.setType(ICE_CUSTOM); CHKERRQ(ierr); 00218 } else { 00219 // Set the default for IceCompModel: 00220 ierr = iceFactory.setType(ICE_ARR); CHKERRQ(ierr); 00221 } 00222 00223 config.set_flag("do_cold_ice_methods", true); 00224 00225 ierr = IceModel::setFromOptions();CHKERRQ(ierr); 00226 00227 return 0; 00228 } 00229 00230 PetscErrorCode IceCompModel::allocate_enthalpy_converter() { 00231 00232 if (EC != NULL) 00233 return 0; 00234 00235 // allocate the "special" enthalpy converter; 00236 EC = new ICMEnthalpyConverter(config); 00237 00238 return 0; 00239 } 00240 00241 PetscErrorCode IceCompModel::allocate_bedrock_thermal_unit() { 00242 PetscErrorCode ierr; 00243 00244 if (btu != NULL) 00245 return 0; 00246 00247 // this switch changes Test K to make material properties for bedrock the same as for ice 00248 bool biiSet; 00249 ierr = PISMOptionsIsSet("-bedrock_is_ice", biiSet); CHKERRQ(ierr); 00250 if (biiSet == PETSC_TRUE) { 00251 if (testname == 'K') { 00252 ierr = verbPrintf(1,grid.com, 00253 "setting material properties of bedrock to those of ice in Test K\n"); CHKERRQ(ierr); 00254 config.set("bedrock_thermal_density", ice->rho); 00255 config.set("bedrock_thermal_conductivity", ice->k); 00256 config.set("bedrock_thermal_specific_heat_capacity", ice->c_p); 00257 bedrock_is_ice_forK = PETSC_TRUE; 00258 } else { 00259 ierr = verbPrintf(1,grid.com, 00260 "IceCompModel WARNING: option -bedrock_is_ice ignored; only applies to Test K\n"); 00261 CHKERRQ(ierr); 00262 } 00263 } 00264 00265 if (testname != 'K' && testname != 'V') { 00266 // now make bedrock have same material properties as ice 00267 // (note Mbz=1 also, by default, but want ice/rock interface to see 00268 // pure ice from the point of view of applying geothermal boundary 00269 // condition, especially in tests F and G) 00270 config.set("bedrock_thermal_density", ice->rho); 00271 config.set("bedrock_thermal_conductivity", ice->k); 00272 config.set("bedrock_thermal_specific_heat_capacity", ice->c_p); 00273 } 00274 00275 btu = new BTU_Verification(grid, config, testname, bedrock_is_ice_forK); 00276 00277 return 0; 00278 } 00279 00280 PetscErrorCode IceCompModel::allocate_flowlaw() { 00281 PetscErrorCode ierr; 00282 00283 ierr = IceModel::allocate_flowlaw(); CHKERRQ(ierr); 00284 00285 if (testname != 'V') { 00286 // check on whether the options (already checked) chose the right IceFlowLaw for verification; 00287 // need to have a tempFromSoftness() procedure as well as the need for the right 00288 // flow law to have the errors make sense 00289 tgaIce = dynamic_cast<ThermoGlenArrIce*>(ice); 00290 if (!tgaIce) SETERRQ(1,"IceCompModel requires ThermoGlenArrIce or a derived class"); 00291 if (IceFlowLawIsPatersonBuddCold(ice, config) == PETSC_FALSE) { 00292 ierr = verbPrintf(1, grid.com, 00293 "WARNING: user set -gk; default flow law should be -ice_type arr for IceCompModel\n"); 00294 CHKERRQ(ierr); 00295 } 00296 } 00297 00298 if (testname == 'V') { 00299 CustomGlenIce *ice_custom = dynamic_cast<CustomGlenIce*>(ice); 00300 if (ice_custom == NULL) SETERRQ(1, "test V requires using CustomGlenIce"); 00301 00302 ice_custom->setHardness(1.9e8); 00303 } 00304 00305 return 0; 00306 } 00307 00308 PetscErrorCode IceCompModel::allocate_stressbalance() { 00309 PetscErrorCode ierr; 00310 00311 if (stress_balance != NULL) 00312 return 0; 00313 00314 if (testname == 'E') { 00315 ShallowStressBalance *ssb = new SIA_Sliding(grid, *basal, *ice, *EC, config); 00316 SIAFD *sia = new SIAFD(grid, *ice, *EC, config); 00317 00318 stress_balance = new PISMStressBalance(grid, ssb, sia, NULL, config); 00319 ierr = stress_balance->init(variables); CHKERRQ(ierr); 00320 } else { 00321 ierr = IceModel::allocate_stressbalance(); CHKERRQ(ierr); 00322 } 00323 00324 return 0; 00325 } 00326 00327 PetscErrorCode IceCompModel::allocate_bed_deformation() { 00328 PetscErrorCode ierr; 00329 00330 ierr = IceModel::allocate_bed_deformation(); CHKERRQ(ierr); 00331 00332 f = ice->rho / config.get("lithosphere_density"); // for simple isostasy 00333 00334 string bed_def_model = config.get_string("bed_deformation_model"); 00335 00336 if ( (testname == 'H') && bed_def_model != "iso" ) { 00337 ierr = verbPrintf(1,grid.com, 00338 "IceCompModel WARNING: Test H should be run with option\n" 00339 " '-bed_def iso' for the reported errors to be correct.\n"); CHKERRQ(ierr); 00340 } 00341 00342 return 0; 00343 } 00344 00345 PetscErrorCode IceCompModel::set_vars_from_options() { 00346 PetscErrorCode ierr; 00347 00348 // -boot_file command-line option is not allowed here. 00349 ierr = stop_if_set(grid.com, "-boot_file"); CHKERRQ(ierr); 00350 00351 ierr = SigmaComp3.set(0.0); CHKERRQ(ierr); 00352 00353 ierr = verbPrintf(3,grid.com, "initializing Test %c from formulas ...\n",testname); CHKERRQ(ierr); 00354 00355 // all have no uplift 00356 ierr = vuplift.set(0.0); CHKERRQ(ierr); 00357 00358 ierr = vbmr.set(0.0); CHKERRQ(ierr); // this is the correct initialization for 00359 // Test O (and every other Test; they 00360 // all generate zero basal melt rate) 00361 ierr = vHmelt.set(0.0); CHKERRQ(ierr); // ditto 00362 00363 // Test-specific initialization: 00364 switch (testname) { 00365 case 'A': 00366 case 'B': 00367 case 'C': 00368 case 'D': 00369 case 'E': 00370 case 'H': 00371 ierr = initTestABCDEH(); CHKERRQ(ierr); 00372 break; 00373 case 'F': 00374 case 'G': 00375 ierr = initTestFG(); CHKERRQ(ierr); // see iCMthermo.cc 00376 break; 00377 case 'K': 00378 case 'O': 00379 ierr = initTestsKO(); CHKERRQ(ierr); // see iCMthermo.cc 00380 break; 00381 case 'L': 00382 ierr = initTestL(); CHKERRQ(ierr); 00383 break; 00384 case 'V': 00385 ierr = test_V_init(); CHKERRQ(ierr); 00386 break; 00387 default: SETERRQ(1,"Desired test not implemented by IceCompModel.\n"); 00388 } 00389 00390 ierr = compute_enthalpy_cold(T3, Enth3); CHKERRQ(ierr); 00391 00392 return 0; 00393 } 00394 00395 PetscErrorCode IceCompModel::initTestABCDEH() { 00396 PetscErrorCode ierr; 00397 PetscScalar A0, T0, **H, **accum, dummy1, dummy2, dummy3; 00398 00399 // compute T so that A0 = A(T) = Acold exp(-Qcold/(R T)) (i.e. for ThermoGlenArrIce); 00400 // set all temps to this constant 00401 A0 = 1.0e-16/secpera; // = 3.17e-24 1/(Pa^3 s); (EISMINT value) flow law parameter 00402 T0 = tgaIce->tempFromSoftness(A0); 00403 ierr = artm.set(T0); CHKERRQ(ierr); 00404 ierr = T3.set(T0); CHKERRQ(ierr); 00405 ierr = vGhf.set(Ggeo); CHKERRQ(ierr); 00406 00407 ierr = vMask.set(MASK_GROUNDED); CHKERRQ(ierr); 00408 00409 ierr = acab.get_array(accum); CHKERRQ(ierr); 00410 ierr = vH.get_array(H); CHKERRQ(ierr); 00411 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00412 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00413 PetscScalar xx = grid.x[i], yy = grid.y[j], 00414 r = grid.radius(i,j); 00415 switch (testname) { 00416 case 'A': 00417 exactA(r,&H[i][j],&accum[i][j]); 00418 break; 00419 case 'B': 00420 exactB(grid.year*secpera,r,&H[i][j],&accum[i][j]); 00421 break; 00422 case 'C': 00423 exactC(grid.year*secpera,r,&H[i][j],&accum[i][j]); 00424 break; 00425 case 'D': 00426 exactD(grid.year*secpera,r,&H[i][j],&accum[i][j]); 00427 break; 00428 case 'E': 00429 exactE(xx,yy,&H[i][j],&accum[i][j],&dummy1,&dummy2,&dummy3); 00430 break; 00431 case 'H': 00432 exactH(f,grid.year*secpera,r,&H[i][j],&accum[i][j]); 00433 break; 00434 default: SETERRQ(1,"test must be A, B, C, D, E, or H"); 00435 } 00436 } 00437 } 00438 ierr = acab.end_access(); CHKERRQ(ierr); 00439 ierr = vH.end_access(); CHKERRQ(ierr); 00440 00441 ierr = vH.beginGhostComm(); CHKERRQ(ierr); 00442 ierr = vH.endGhostComm(); CHKERRQ(ierr); 00443 00444 if (testname == 'H') { 00445 ierr = vH.copy_to(vh); CHKERRQ(ierr); 00446 ierr = vh.scale(1-f); CHKERRQ(ierr); 00447 ierr = vH.copy_to(vbed); CHKERRQ(ierr); 00448 ierr = vbed.scale(-f); CHKERRQ(ierr); 00449 } else { // flat bed case otherwise 00450 ierr = vH.copy_to(vh); CHKERRQ(ierr); 00451 ierr = vbed.set(0.0); CHKERRQ(ierr); 00452 } 00453 00454 return 0; 00455 } 00456 00457 00459 class rgrid { 00460 public: 00461 double r; 00462 int i,j; 00463 }; 00464 00465 00467 struct rgridReverseSort { 00468 bool operator()(rgrid a, rgrid b) { return (a.r > b.r); } 00469 }; 00470 00471 00472 PetscErrorCode IceCompModel::initTestL() { 00473 PetscErrorCode ierr; 00474 PetscScalar A0, T0, **H, **accum, **bed; 00475 00476 if (testname != 'L') { SETERRQ(1,"test must be 'L'"); } 00477 00478 // compute T so that A0 = A(T) = Acold exp(-Qcold/(R T)) (i.e. for ThermoGlenArrIce); 00479 // set all temps to this constant 00480 A0 = 1.0e-16/secpera; // = 3.17e-24 1/(Pa^3 s); (EISMINT value) flow law parameter 00481 T0 = tgaIce->tempFromSoftness(A0); 00482 ierr = artm.set(T0); CHKERRQ(ierr); 00483 ierr = T3.set(T0); CHKERRQ(ierr); 00484 ierr = vGhf.set(Ggeo); CHKERRQ(ierr); 00485 00486 // setup to evaluate test L; requires solving an ODE numerically using sorted list 00487 // of radii, sorted in decreasing radius order 00488 const int MM = grid.xm * grid.ym; 00489 00490 std::vector<rgrid> rrv(MM); // destructor at end of scope 00491 for (PetscInt i = 0; i < grid.xm; i++) { 00492 for (PetscInt j = 0; j < grid.ym; j++) { 00493 const PetscInt k = i * grid.ym + j; 00494 rrv[k].i = i + grid.xs; rrv[k].j = j + grid.ys; 00495 rrv[k].r = grid.radius(i,j); 00496 } 00497 } 00498 std::sort(rrv.begin(), rrv.end(), rgridReverseSort()); // so rrv[k].r > rrv[k+1].r 00499 00500 // get soln to test L at these radii; solves ODE only once (on each processor) 00501 double *rr, *HH, *bb, *aa; 00502 rr = new double[MM]; 00503 for (PetscInt k = 0; k < MM; k++) 00504 rr[k] = rrv[k].r; 00505 HH = new double[MM]; bb = new double[MM]; aa = new double[MM]; 00506 ierr = exactL_list(rr, MM, HH, bb, aa); 00507 switch (ierr) { 00508 case TESTL_NOT_DONE: 00509 verbPrintf(1,grid.com, 00510 "\n\nTest L ERROR: exactL_list() returns 'NOT_DONE' ...\n\n\n",ierr); 00511 break; 00512 case TESTL_NOT_DECREASING: 00513 verbPrintf(1,grid.com, 00514 "\n\nTest L ERROR: exactL_list() returns 'NOT_DECREASING' ...\n\n\n",ierr); 00515 break; 00516 case TESTL_INVALID_METHOD: 00517 verbPrintf(1,grid.com, 00518 "\n\nTest L ERROR: exactL_list() returns 'INVALID_METHOD' ...\n\n\n",ierr); 00519 break; 00520 case TESTL_NO_LIST: 00521 verbPrintf(1,grid.com, 00522 "\n\nTest L ERROR: exactL_list() returns 'NO_LIST' ...\n\n\n",ierr); 00523 break; 00524 default: 00525 break; 00526 } 00527 CHKERRQ(ierr); 00528 delete [] rr; 00529 00530 ierr = acab.get_array(accum); CHKERRQ(ierr); 00531 ierr = vH.get_array(H); CHKERRQ(ierr); 00532 ierr = vbed.get_array(bed); CHKERRQ(ierr); 00533 for (PetscInt k = 0; k < MM; k++) { 00534 H [rrv[k].i][rrv[k].j] = HH[k]; 00535 bed [rrv[k].i][rrv[k].j] = bb[k]; 00536 accum[rrv[k].i][rrv[k].j] = aa[k]; 00537 } 00538 ierr = acab.end_access(); CHKERRQ(ierr); 00539 ierr = vH.end_access(); CHKERRQ(ierr); 00540 ierr = vbed.end_access(); CHKERRQ(ierr); 00541 delete [] HH; delete [] bb; delete [] aa; 00542 00543 ierr = vH.beginGhostComm(); CHKERRQ(ierr); 00544 ierr = vH.endGhostComm(); CHKERRQ(ierr); 00545 ierr = vbed.beginGhostComm(); CHKERRQ(ierr); 00546 ierr = vbed.endGhostComm(); CHKERRQ(ierr); 00547 00548 // store copy of vH for "-eo" runs and for evaluating geometry errors 00549 ierr = vH.copy_to(vHexactL); CHKERRQ(ierr); 00550 00551 // set surface to H+b 00552 ierr = vH.add(1.0, vbed, vh); CHKERRQ(ierr); 00553 ierr = vh.beginGhostComm(); CHKERRQ(ierr); 00554 ierr = vh.endGhostComm(); CHKERRQ(ierr); 00555 return 0; 00556 } 00557 00558 00559 PetscErrorCode IceCompModel::getCompSourcesTestCDH() { 00560 PetscErrorCode ierr; 00561 PetscScalar **accum, dummy; 00562 00563 // before flow step, set accumulation from exact values; 00564 ierr = acab.get_array(accum); CHKERRQ(ierr); 00565 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00566 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00567 PetscScalar r = grid.radius(i,j); 00568 switch (testname) { 00569 case 'C': 00570 exactC(grid.year*secpera,r,&dummy,&accum[i][j]); 00571 break; 00572 case 'D': 00573 exactD(grid.year*secpera,r,&dummy,&accum[i][j]); 00574 break; 00575 case 'H': 00576 exactH(f,grid.year*secpera,r,&dummy,&accum[i][j]); 00577 break; 00578 default: SETERRQ(1,"testname must be C, D, or H"); 00579 } 00580 } 00581 } 00582 ierr = acab.end_access(); CHKERRQ(ierr); 00583 return 0; 00584 } 00585 00587 PetscErrorCode IceCompModel::reset_thickness_tests_AE() { 00588 PetscErrorCode ierr; 00589 const PetscScalar LforAE = 750e3; // m 00590 00591 ierr = vH.begin_access(); CHKERRQ(ierr); 00592 for (PetscInt i = grid.xs; i < grid.xs+grid.xm; ++i) { 00593 for (PetscInt j = grid.ys; j < grid.ys+grid.ym; ++j) { 00594 if (grid.radius(i, j) > LforAE) 00595 vH(i, j) = 0; 00596 } 00597 } 00598 ierr = vH.end_access(); CHKERRQ(ierr); 00599 00600 ierr = vH.beginGhostComm(); CHKERRQ(ierr); 00601 ierr = vH.endGhostComm(); CHKERRQ(ierr); 00602 return 0; 00603 } 00604 00605 00606 00607 PetscErrorCode IceCompModel::fillSolnTestABCDH() { 00608 PetscErrorCode ierr; 00609 PetscScalar **H, **accum; 00610 00611 ierr = acab.get_array(accum); CHKERRQ(ierr); 00612 ierr = vH.get_array(H); CHKERRQ(ierr); 00613 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00614 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00615 PetscScalar r = grid.radius(i,j); 00616 switch (testname) { 00617 case 'A': 00618 exactA(r,&H[i][j],&accum[i][j]); 00619 break; 00620 case 'B': 00621 exactB(grid.year*secpera,r,&H[i][j],&accum[i][j]); 00622 break; 00623 case 'C': 00624 exactC(grid.year*secpera,r,&H[i][j],&accum[i][j]); 00625 break; 00626 case 'D': 00627 exactD(grid.year*secpera,r,&H[i][j],&accum[i][j]); 00628 break; 00629 case 'H': 00630 exactH(f,grid.year*secpera,r,&H[i][j],&accum[i][j]); 00631 break; 00632 default: SETERRQ(1,"test must be A, B, C, D, or H"); 00633 } 00634 } 00635 } 00636 00637 ierr = acab.end_access(); CHKERRQ(ierr); 00638 ierr = vH.end_access(); CHKERRQ(ierr); 00639 00640 ierr = vH.beginGhostComm(); CHKERRQ(ierr); 00641 ierr = vH.endGhostComm(); CHKERRQ(ierr); 00642 00643 if (testname == 'H') { 00644 ierr = vH.copy_to(vh); CHKERRQ(ierr); 00645 ierr = vh.scale(1-f); CHKERRQ(ierr); 00646 ierr = vH.copy_to(vbed); CHKERRQ(ierr); 00647 ierr = vbed.scale(-f); CHKERRQ(ierr); 00648 ierr = vbed.beginGhostComm(); CHKERRQ(ierr); 00649 ierr = vbed.endGhostComm(); CHKERRQ(ierr); 00650 } else { 00651 ierr = vH.copy_to(vh); CHKERRQ(ierr); 00652 } 00653 ierr = vh.beginGhostComm(); CHKERRQ(ierr); 00654 ierr = vh.endGhostComm(); CHKERRQ(ierr); 00655 return 0; 00656 } 00657 00658 00659 PetscErrorCode IceCompModel::fillSolnTestE() { 00660 PetscErrorCode ierr; 00661 PetscScalar **H, **accum, dummy; 00662 PISMVector2 **bvel; 00663 IceModelVec2V *vel_adv; 00664 ierr = stress_balance->get_advective_2d_velocity(vel_adv); CHKERRQ(ierr); 00665 00666 ierr = acab.get_array(accum); CHKERRQ(ierr); 00667 ierr = vH.get_array(H); CHKERRQ(ierr); 00668 ierr = vel_adv->get_array(bvel); CHKERRQ(ierr); 00669 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00670 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00671 PetscScalar xx = grid.x[i], yy = grid.y[j]; 00672 exactE(xx,yy,&H[i][j],&accum[i][j],&dummy,&bvel[i][j].u,&bvel[i][j].v); 00673 } 00674 } 00675 ierr = acab.end_access(); CHKERRQ(ierr); 00676 ierr = vH.end_access(); CHKERRQ(ierr); 00677 ierr = vel_adv->end_access(); CHKERRQ(ierr); 00678 00679 ierr = vH.beginGhostComm(); CHKERRQ(ierr); 00680 ierr = vH.endGhostComm(); CHKERRQ(ierr); 00681 ierr = vH.copy_to(vh); CHKERRQ(ierr); 00682 00683 return 0; 00684 } 00685 00686 00687 PetscErrorCode IceCompModel::fillSolnTestL() { 00688 PetscErrorCode ierr; 00689 00690 ierr = vHexactL.beginGhostComm(); CHKERRQ(ierr); 00691 ierr = vHexactL.endGhostComm(); CHKERRQ(ierr); 00692 ierr = vH.copy_from(vHexactL); 00693 00694 ierr = vbed.add(1.0, vH, vh); CHKERRQ(ierr); // h = H + bed = 1 * H + bed 00695 ierr = vh.beginGhostComm(); CHKERRQ(ierr); 00696 ierr = vh.endGhostComm(); CHKERRQ(ierr); 00697 00698 // note bed was filled at initialization and hasn't changed 00699 return 0; 00700 } 00701 00702 00703 PetscErrorCode IceCompModel::computeGeometryErrors( 00704 PetscScalar &gvolexact, PetscScalar &gareaexact, PetscScalar &gdomeHexact, 00705 PetscScalar &volerr, PetscScalar &areaerr, 00706 PetscScalar &gmaxHerr, PetscScalar &gavHerr, PetscScalar &gmaxetaerr, 00707 PetscScalar ¢erHerr) { 00708 // compute errors in thickness, eta=thickness^{(2n+2)/n}, volume, area 00709 00710 PetscErrorCode ierr; 00711 PetscScalar **H, **HexactL; 00712 PetscScalar Hexact, vol, area, domeH, volexact, areaexact, domeHexact; 00713 PetscScalar Herr, avHerr, etaerr; 00714 00715 PetscScalar dummy, z, dummy1, dummy2, dummy3, dummy4, dummy5; 00716 00717 ierr = vH.get_array(H); CHKERRQ(ierr); 00718 if (testname == 'L') { 00719 ierr = vHexactL.get_array(HexactL); CHKERRQ(ierr); 00720 } 00721 00722 vol = 0; area = 0; domeH = 0; 00723 volexact = 0; areaexact = 0; domeHexact = 0; 00724 Herr = 0; avHerr=0; etaerr = 0; 00725 00726 double 00727 seawater_density = config.get("sea_water_density"), 00728 B0 = ice->hardnessParameter_from_enth(0, 0), // enthalpy and pressure do not matter here 00729 C = pow(ice->rho * standard_gravity * (1.0 - ice->rho/seawater_density) / (4 * B0), 3), 00730 H0 = 600.0, v0 = convert(300.0, "m/year", "m/second"), 00731 Q0 = H0 * v0; 00732 00733 // area of grid square in square km: 00734 const PetscScalar a = grid.dx * grid.dy * 1e-3 * 1e-3; 00735 const PetscScalar m = (2.0 * ice->exponent() + 2.0) / ice->exponent(); 00736 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00737 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00738 if (H[i][j] > 0) { 00739 area += a; 00740 vol += a * H[i][j] * 1e-3; 00741 } 00742 PetscScalar xx = grid.x[i], yy = grid.y[j], 00743 r = grid.radius(i,j); 00744 switch (testname) { 00745 case 'A': 00746 exactA(r,&Hexact,&dummy); 00747 break; 00748 case 'B': 00749 exactB(grid.year*secpera,r,&Hexact,&dummy); 00750 break; 00751 case 'C': 00752 exactC(grid.year*secpera,r,&Hexact,&dummy); 00753 break; 00754 case 'D': 00755 exactD(grid.year*secpera,r,&Hexact,&dummy); 00756 break; 00757 case 'E': 00758 exactE(xx,yy,&Hexact,&dummy,&dummy1,&dummy2,&dummy3); 00759 break; 00760 case 'F': 00761 if (r > LforFG - 1.0) { // outside of sheet 00762 Hexact=0.0; 00763 } else { 00764 r=PetscMax(r,1.0); 00765 z=0.0; 00766 bothexact(0.0,r,&z,1,0.0, 00767 &Hexact,&dummy,&dummy5,&dummy1,&dummy2,&dummy3,&dummy4); 00768 } 00769 break; 00770 case 'G': 00771 if (r > LforFG -1.0) { // outside of sheet 00772 Hexact=0.0; 00773 } else { 00774 r=PetscMax(r,1.0); 00775 z=0.0; 00776 bothexact(grid.year*secpera,r,&z,1,ApforG, 00777 &Hexact,&dummy,&dummy5,&dummy1,&dummy2,&dummy3,&dummy4); 00778 } 00779 break; 00780 case 'H': 00781 exactH(f,grid.year*secpera,r,&Hexact,&dummy); 00782 break; 00783 case 'K': 00784 case 'O': 00785 Hexact = 3000.0; 00786 break; 00787 case 'L': 00788 Hexact = HexactL[i][j]; 00789 break; 00790 case 'V': 00791 { 00792 Hexact = pow(4 * C / Q0 * xx + 1/pow(H0, 4), -0.25); 00793 } 00794 break; 00795 default: SETERRQ(1,"test must be A, B, C, D, E, F, G, H, K, L, or O"); 00796 } 00797 00798 if (Hexact > 0) { 00799 areaexact += a; 00800 volexact += a * Hexact * 1e-3; 00801 } 00802 if (i == (grid.Mx - 1)/2 && j == (grid.My - 1)/2) { 00803 domeH = H[i][j]; 00804 domeHexact = Hexact; 00805 } 00806 // compute maximum errors 00807 Herr = PetscMax(Herr,PetscAbsReal(H[i][j] - Hexact)); 00808 etaerr = PetscMax(etaerr,PetscAbsReal(pow(H[i][j],m) - pow(Hexact,m))); 00809 // add to sums for average errors 00810 avHerr += PetscAbsReal(H[i][j] - Hexact); 00811 } 00812 } 00813 00814 ierr = vH.end_access(); CHKERRQ(ierr); 00815 if (testname == 'L') { 00816 ierr = vHexactL.end_access(); CHKERRQ(ierr); 00817 } 00818 00819 // globalize (find errors over all processors) 00820 PetscScalar gvol, garea, gdomeH; 00821 ierr = PetscGlobalSum(&volexact, &gvolexact, grid.com); CHKERRQ(ierr); 00822 ierr = PetscGlobalMax(&domeHexact, &gdomeHexact, grid.com); CHKERRQ(ierr); 00823 ierr = PetscGlobalSum(&areaexact, &gareaexact, grid.com); CHKERRQ(ierr); 00824 00825 ierr = PetscGlobalSum(&vol, &gvol, grid.com); CHKERRQ(ierr); 00826 ierr = PetscGlobalSum(&area, &garea, grid.com); CHKERRQ(ierr); 00827 volerr = PetscAbsReal(gvol - gvolexact); 00828 areaerr = PetscAbsReal(garea - gareaexact); 00829 00830 ierr = PetscGlobalMax(&Herr, &gmaxHerr, grid.com); CHKERRQ(ierr); 00831 ierr = PetscGlobalSum(&avHerr, &gavHerr, grid.com); CHKERRQ(ierr); 00832 gavHerr = gavHerr/(grid.Mx*grid.My); 00833 ierr = PetscGlobalMax(&etaerr, &gmaxetaerr, grid.com); CHKERRQ(ierr); 00834 00835 ierr = PetscGlobalMax(&domeH, &gdomeH, grid.com); CHKERRQ(ierr); 00836 centerHerr = PetscAbsReal(gdomeH - gdomeHexact); 00837 00838 return 0; 00839 } 00840 00841 00842 PetscErrorCode IceCompModel::computeBasalVelocityErrors( 00843 PetscScalar &exactmaxspeed, 00844 PetscScalar &gmaxvecerr, PetscScalar &gavvecerr, 00845 PetscScalar &gmaxuberr, PetscScalar &gmaxvberr) { 00846 00847 PetscErrorCode ierr; 00848 PetscScalar **H; 00849 PetscScalar maxvecerr, avvecerr, maxuberr, maxvberr; 00850 PetscScalar ubexact,vbexact, dummy1,dummy2,dummy3; 00851 PISMVector2 **bvel; 00852 00853 if (testname != 'E') 00854 SETERRQ(1,"basal velocity errors only computable for test E\n"); 00855 00856 IceModelVec2V *vel_adv; 00857 ierr = stress_balance->get_advective_2d_velocity(vel_adv); CHKERRQ(ierr); 00858 00859 ierr = vel_adv->get_array(bvel); CHKERRQ(ierr); 00860 ierr = vH.get_array(H); CHKERRQ(ierr); 00861 maxvecerr = 0.0; avvecerr = 0.0; maxuberr = 0.0; maxvberr = 0.0; 00862 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; i++) { 00863 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; j++) { 00864 if (H[i][j] > 0.0) { 00865 PetscScalar xx = grid.x[i], yy = grid.y[j]; 00866 exactE(xx,yy,&dummy1,&dummy2,&dummy3,&ubexact,&vbexact); 00867 // compute maximum errors 00868 const PetscScalar uberr = PetscAbsReal(bvel[i][j].u - ubexact); 00869 const PetscScalar vberr = PetscAbsReal(bvel[i][j].v - vbexact); 00870 maxuberr = PetscMax(maxuberr,uberr); 00871 maxvberr = PetscMax(maxvberr,vberr); 00872 const PetscScalar vecerr = sqrt(uberr*uberr + vberr*vberr); 00873 maxvecerr = PetscMax(maxvecerr,vecerr); 00874 avvecerr += vecerr; 00875 } 00876 } 00877 } 00878 ierr = vH.end_access(); CHKERRQ(ierr); 00879 ierr = vel_adv->end_access(); CHKERRQ(ierr); 00880 00881 ierr = PetscGlobalMax(&maxuberr, &gmaxuberr, grid.com); CHKERRQ(ierr); 00882 ierr = PetscGlobalMax(&maxvberr, &gmaxvberr, grid.com); CHKERRQ(ierr); 00883 00884 ierr = PetscGlobalMax(&maxvecerr, &gmaxvecerr, grid.com); CHKERRQ(ierr); 00885 ierr = PetscGlobalSum(&avvecerr, &gavvecerr, grid.com); CHKERRQ(ierr); 00886 gavvecerr = gavvecerr/(grid.Mx*grid.My); 00887 00888 const PetscScalar xpeak = 450e3 * cos(25.0*(pi/180.0)), 00889 ypeak = 450e3 * sin(25.0*(pi/180.0)); 00890 exactE(xpeak,ypeak,&dummy1,&dummy2,&dummy3,&ubexact,&vbexact); 00891 exactmaxspeed = sqrt(ubexact*ubexact + vbexact*vbexact); 00892 return 0; 00893 } 00894 00895 00896 PetscErrorCode IceCompModel::additionalAtStartTimestep() { 00897 PetscErrorCode ierr; 00898 00899 ierr = verbPrintf(5,grid.com, 00900 "additionalAtStartTimestep() in IceCompModel entered with test %c", 00901 testname); CHKERRQ(ierr); 00902 00903 if (exactOnly == PETSC_TRUE) 00904 dt_force = config.get("maximum_time_step_years") * secpera; 00905 00906 // these have no changing boundary conditions or comp sources: 00907 if (strchr("AEBKLO",testname) != NULL) 00908 return 0; 00909 00910 switch (testname) { 00911 case 'C': 00912 case 'D': 00913 case 'H': 00914 ierr = getCompSourcesTestCDH(); 00915 break; 00916 case 'F': 00917 case 'G': 00918 ierr = getCompSourcesTestFG(); // see iCMthermo.cc 00919 break; 00920 case 'V': 00921 ierr = test_V_set_thickness_bc(); CHKERRQ(ierr); 00922 break; 00923 default: SETERRQ(1,"only tests CDHFG have comp source update at start time step\n"); 00924 } 00925 00926 return 0; 00927 } 00928 00929 00930 PetscErrorCode IceCompModel::additionalAtEndTimestep() { 00931 PetscErrorCode ierr; 00932 00933 ierr = verbPrintf(5,grid.com, 00934 "additionalAtEndTimestep() in IceCompModel entered with test %c",testname); 00935 CHKERRQ(ierr); 00936 00937 00938 if (testname == 'A' || testname == 'E') { 00939 ierr = reset_thickness_tests_AE(); CHKERRQ(ierr); 00940 } 00941 00942 // do nothing at the end of the time step unless the user has asked for the 00943 // exact solution to overwrite the numerical solution 00944 if (exactOnly == PETSC_FALSE) 00945 return 0; 00946 00947 // because user wants exact solution, fill gridded values from exact formulas; 00948 // important notes: 00949 // (1) the numerical computation *has* already occurred, in run(), 00950 // and we just overwrite it with the exact solution here 00951 // (2) certain diagnostic quantities like dHdt are computed numerically, 00952 // and not overwritten here; while cbar,csurf,cflx,wsurf are diagnostic 00953 // quantities recomputed at the end of the run for writing into 00954 // NetCDF, in particular dHdt is not recomputed before being written 00955 // into the output file, so it is actually numerical 00956 switch (testname) { 00957 case 'A': 00958 case 'B': 00959 case 'C': 00960 case 'D': 00961 case 'H': 00962 ierr = fillSolnTestABCDH(); CHKERRQ(ierr); 00963 break; 00964 case 'E': 00965 ierr = fillSolnTestE(); CHKERRQ(ierr); 00966 break; 00967 case 'F': 00968 case 'G': 00969 ierr = fillSolnTestFG(); CHKERRQ(ierr); // see iCMthermo.cc 00970 break; 00971 case 'K': 00972 ierr = fillTemperatureSolnTestsKO(); CHKERRQ(ierr); // see iCMthermo.cc 00973 break; 00974 case 'O': 00975 ierr = fillTemperatureSolnTestsKO(); CHKERRQ(ierr); // see iCMthermo.cc 00976 ierr = fillBasalMeltRateSolnTestO(); CHKERRQ(ierr); // see iCMthermo.cc 00977 break; 00978 case 'L': 00979 ierr = fillSolnTestL(); CHKERRQ(ierr); 00980 break; 00981 default: SETERRQ(1,"unknown testname in IceCompModel"); 00982 } 00983 00984 return 0; 00985 } 00986 00987 00988 PetscErrorCode IceCompModel::summary(bool /* tempAndAge */) { 00989 // we always show a summary at every step 00990 return IceModel::summary(true); 00991 } 00992 00993 00994 PetscErrorCode IceCompModel::reportErrors() { 00995 // geometry errors to report (for all tests except K and O): 00996 // -- max thickness error 00997 // -- average (at each grid point on whole grid) thickness error 00998 // -- max (thickness)^(2n+2)/n error 00999 // -- volume error 01000 // -- area error 01001 // and temperature errors (for tests F & G & K & O): 01002 // -- max T error over 3D domain of ice 01003 // -- av T error over 3D domain of ice 01004 // and basal temperature errors (for tests F & G): 01005 // -- max basal temp error 01006 // -- average (at each grid point on whole grid) basal temp error 01007 // and bedrock temperature errors (for tests K & O): 01008 // -- max Tb error over 3D domain of bedrock 01009 // -- av Tb error over 3D domain of bedrock 01010 // and strain-heating (Sigma) errors (for tests F & G): 01011 // -- max Sigma error over 3D domain of ice (in 10^-3 K a^-1) 01012 // -- av Sigma error over 3D domain of ice (in 10^-3 K a^-1) 01013 // and basal melt rate error (for test O): 01014 // -- max bmelt error over base of ice 01015 // and surface velocity errors (for tests F & G): 01016 // -- max |<us,vs> - <usex,vsex>| error 01017 // -- av |<us,vs> - <usex,vsex>| error 01018 // -- max ws error 01019 // -- av ws error 01020 // and basal sliding errors (for test E): 01021 // -- max ub error 01022 // -- max vb error 01023 // -- max |<ub,vb> - <ubexact,vbexact>| error 01024 // -- av |<ub,vb> - <ubexact,vbexact>| error 01025 01026 PetscErrorCode ierr; 01027 ierr = verbPrintf(1,grid.com, 01028 "NUMERICAL ERRORS evaluated at final time (relative to exact solution):\n"); 01029 CHKERRQ(ierr); 01030 01031 unsigned int start; 01032 char filename[TEMPORARY_STRING_LENGTH]; 01033 PetscTruth netcdf_report; 01034 NCTimeseries err; 01035 ierr = PetscOptionsGetString(PETSC_NULL, "-report_file", filename, 01036 TEMPORARY_STRING_LENGTH, &netcdf_report); CHKERRQ(ierr); 01037 01038 if (netcdf_report) { 01039 ierr = verbPrintf(2,grid.com, "Also writing errors to '%s'...\n", filename); 01040 CHKERRQ(ierr); 01041 01042 // Find the number of records in this file: 01043 NCTool nc(grid.com, grid.rank); 01044 // append = true; check_dims = false 01045 ierr = nc.open_for_writing(filename); CHKERRQ(ierr); 01046 ierr = nc.get_dim_length("N", &start); CHKERRQ(ierr); 01047 ierr = nc.close(); CHKERRQ(ierr); 01048 01049 ierr = global_attributes.write(filename); CHKERRQ(ierr); 01050 01051 // Write the dimension variable: 01052 err.init("N", "N", grid.com, grid.rank); 01053 ierr = err.write(filename, (size_t)start, (double)(start + 1), NC_INT); CHKERRQ(ierr); 01054 01055 // Always write grid parameters: 01056 err.short_name = "dx"; 01057 ierr = err.set_units("meters"); CHKERRQ(ierr); 01058 ierr = err.write(filename, (size_t)start, grid.dx); CHKERRQ(ierr); 01059 err.short_name = "dy"; 01060 ierr = err.write(filename, (size_t)start, grid.dy); CHKERRQ(ierr); 01061 err.short_name = "dz"; 01062 ierr = err.write(filename, (size_t)start, grid.dzMAX); CHKERRQ(ierr); 01063 01064 // Always write the test name: 01065 err.reset(); 01066 err.short_name = "test"; 01067 ierr = err.write(filename, (size_t)start, (double)testname, NC_BYTE); CHKERRQ(ierr); 01068 } 01069 01070 // geometry (thickness, vol) errors if appropriate; reported in m except for relmaxETA 01071 if ((testname != 'K') && (testname != 'O')) { 01072 PetscScalar volexact, areaexact, domeHexact, volerr, areaerr, maxHerr, avHerr, 01073 maxetaerr, centerHerr; 01074 ierr = computeGeometryErrors(volexact,areaexact,domeHexact, 01075 volerr,areaerr,maxHerr,avHerr,maxetaerr,centerHerr); 01076 CHKERRQ(ierr); 01077 ierr = verbPrintf(1,grid.com, 01078 "geometry : prcntVOL maxH avH relmaxETA\n"); 01079 CHKERRQ(ierr); // no longer reporting centerHerr 01080 const PetscScalar m = (2.0 * ice->exponent() + 2.0) / ice->exponent(); 01081 ierr = verbPrintf(1,grid.com, " %12.6f%12.6f%12.6f%12.6f\n", 01082 100*volerr/volexact, maxHerr, avHerr, 01083 maxetaerr/pow(domeHexact,m)); CHKERRQ(ierr); 01084 01085 if (netcdf_report) { 01086 err.reset(); 01087 err.short_name = "relative_volume"; 01088 ierr = err.set_units("percent"); CHKERRQ(ierr); 01089 err.set_string("long_name", "relative ice volume error"); 01090 ierr = err.write(filename, (size_t)start, 100*volerr/volexact); CHKERRQ(ierr); 01091 01092 err.short_name = "relative_max_eta"; 01093 ierr = err.set_units("1"); CHKERRQ(ierr); 01094 err.set_string("long_name", "relative $\\eta$ error"); 01095 ierr = err.write(filename, (size_t)start, maxetaerr/pow(domeHexact,m)); CHKERRQ(ierr); 01096 01097 err.short_name = "maximum_thickness"; 01098 ierr = err.set_units("meters"); CHKERRQ(ierr); 01099 err.set_string("long_name", "maximum ice thickness error"); 01100 ierr = err.write(filename, (size_t)start, maxHerr); CHKERRQ(ierr); 01101 01102 err.short_name = "average_thickness"; 01103 ierr = err.set_units("meters"); CHKERRQ(ierr); 01104 err.set_string("long_name", "average ice thickness error"); 01105 ierr = err.write(filename, (size_t)start, avHerr); CHKERRQ(ierr); 01106 } 01107 } 01108 01109 // temperature errors for F and G 01110 if ((testname == 'F') || (testname == 'G')) { 01111 PetscScalar maxTerr, avTerr, basemaxTerr, baseavTerr, basecenterTerr; 01112 ierr = computeTemperatureErrors(maxTerr, avTerr); CHKERRQ(ierr); 01113 ierr = computeBasalTemperatureErrors(basemaxTerr, baseavTerr, basecenterTerr); 01114 CHKERRQ(ierr); 01115 ierr = verbPrintf(1,grid.com, 01116 "temp : maxT avT basemaxT baseavT\n"); 01117 CHKERRQ(ierr); // no longer reporting basecenterT 01118 ierr = verbPrintf(1,grid.com, " %12.6f%12.6f%12.6f%12.6f\n", 01119 maxTerr, avTerr, basemaxTerr, baseavTerr); CHKERRQ(ierr); 01120 01121 if (netcdf_report) { 01122 err.reset(); 01123 err.short_name = "maximum_temperature"; 01124 ierr = err.set_units("Kelvin"); CHKERRQ(ierr); 01125 err.set_string("long_name", "maximum ice temperature error"); 01126 ierr = err.write(filename, (size_t)start, maxTerr); CHKERRQ(ierr); 01127 01128 err.short_name = "average_temperature"; 01129 err.set_string("long_name", "average ice temperature error"); 01130 ierr = err.write(filename, (size_t)start, avTerr); CHKERRQ(ierr); 01131 01132 err.short_name = "maximum_basal_temperature"; 01133 err.set_string("long_name", "maximum basal temperature error"); 01134 ierr = err.write(filename, (size_t)start, basemaxTerr); CHKERRQ(ierr); 01135 err.short_name = "average_basal_temperature"; 01136 err.set_string("long_name", "average basal temperature error"); 01137 ierr = err.write(filename, (size_t)start, baseavTerr); CHKERRQ(ierr); 01138 } 01139 01140 } else if ((testname == 'K') || (testname == 'O')) { 01141 PetscScalar maxTerr, avTerr, maxTberr, avTberr; 01142 ierr = computeIceBedrockTemperatureErrors(maxTerr, avTerr, maxTberr, avTberr); 01143 CHKERRQ(ierr); 01144 ierr = verbPrintf(1,grid.com, 01145 "temp : maxT avT maxTb avTb\n"); CHKERRQ(ierr); 01146 ierr = verbPrintf(1,grid.com, " %12.6f%12.6f%12.6f%12.6f\n", 01147 maxTerr, avTerr, maxTberr, avTberr); CHKERRQ(ierr); 01148 01149 if (netcdf_report) { 01150 err.reset(); 01151 err.short_name = "maximum_temperature"; 01152 ierr = err.set_units("Kelvin"); CHKERRQ(ierr); 01153 err.set_string("long_name", "maximum ice temperature error"); 01154 ierr = err.write(filename, (size_t)start, maxTerr); CHKERRQ(ierr); 01155 01156 err.short_name = "average_temperature"; 01157 err.set_string("long_name", "average ice temperature error"); 01158 ierr = err.write(filename, (size_t)start, avTerr); CHKERRQ(ierr); 01159 01160 err.short_name = "maximum_bedrock_temperature"; 01161 err.set_string("long_name", "maximum bedrock temperature error"); 01162 ierr = err.write(filename, (size_t)start, maxTberr); CHKERRQ(ierr); 01163 01164 err.short_name = "average_bedrock_temperature"; 01165 err.set_string("long_name", "average bedrock temperature error"); 01166 ierr = err.write(filename, (size_t)start, avTberr); CHKERRQ(ierr); 01167 } 01168 } 01169 01170 // Sigma errors if appropriate; reported in 10^6 J/(s m^3) 01171 if ((testname == 'F') || (testname == 'G')) { 01172 PetscScalar maxSigerr, avSigerr; 01173 ierr = computeSigmaErrors(maxSigerr, avSigerr); CHKERRQ(ierr); 01174 ierr = verbPrintf(1,grid.com, 01175 "Sigma : maxSig avSig\n"); CHKERRQ(ierr); 01176 ierr = verbPrintf(1,grid.com, " %12.6f%12.6f\n", 01177 maxSigerr*1.0e6, avSigerr*1.0e6); CHKERRQ(ierr); 01178 01179 if (netcdf_report) { 01180 err.reset(); 01181 err.short_name = "maximum_sigma"; 01182 ierr = err.set_units("J s-1 m-3"); CHKERRQ(ierr); 01183 ierr = err.set_glaciological_units("1e6 J s-1 m-3"); CHKERRQ(ierr); 01184 err.set_string("long_name", "maximum strain heating error"); 01185 ierr = err.write(filename, (size_t)start, maxSigerr); CHKERRQ(ierr); 01186 01187 err.short_name = "average_sigma"; 01188 err.set_string("long_name", "average strain heating error"); 01189 ierr = err.write(filename, (size_t)start, avSigerr); CHKERRQ(ierr); 01190 } 01191 } 01192 01193 // surface velocity errors if exact values are available; reported in m/a 01194 if ((testname == 'F') || (testname == 'G')) { 01195 PetscScalar maxUerr, avUerr, maxWerr, avWerr; 01196 ierr = computeSurfaceVelocityErrors(maxUerr, avUerr, maxWerr, avWerr); CHKERRQ(ierr); 01197 ierr = verbPrintf(1,grid.com, 01198 "surf vels : maxUvec avUvec maxW avW\n"); CHKERRQ(ierr); 01199 ierr = verbPrintf(1,grid.com, " %12.6f%12.6f%12.6f%12.6f\n", 01200 maxUerr*secpera, avUerr*secpera, maxWerr*secpera, avWerr*secpera); CHKERRQ(ierr); 01201 01202 if (netcdf_report) { 01203 err.reset(); 01204 err.short_name = "maximum_surface_velocity"; 01205 err.set_string("long_name", "maximum ice surface horizontal velocity error"); 01206 ierr = err.set_units("m/s"); CHKERRQ(ierr); 01207 ierr = err.set_glaciological_units("meters/year"); CHKERRQ(ierr); 01208 ierr = err.write(filename, (size_t)start, maxUerr); CHKERRQ(ierr); 01209 01210 err.short_name = "average_surface_velocity"; 01211 err.set_string("long_name", "average ice surface horizontal velocity error"); 01212 ierr = err.write(filename, (size_t)start, avUerr); CHKERRQ(ierr); 01213 01214 err.short_name = "maximum_surface_w"; 01215 err.set_string("long_name", "maximum ice surface vertical velocity error"); 01216 ierr = err.write(filename, (size_t)start, maxWerr); CHKERRQ(ierr); 01217 01218 err.short_name = "average_surface_w"; 01219 err.set_string("long_name", "average ice surface vertical velocity error"); 01220 ierr = err.write(filename, (size_t)start, avWerr); CHKERRQ(ierr); 01221 } 01222 } 01223 01224 // basal velocity errors if appropriate; reported in m/a except prcntavvec 01225 if (testname == 'E') { 01226 PetscScalar exactmaxspeed, maxvecerr, avvecerr, maxuberr, maxvberr; 01227 ierr = computeBasalVelocityErrors(exactmaxspeed, 01228 maxvecerr,avvecerr,maxuberr,maxvberr); CHKERRQ(ierr); 01229 ierr = verbPrintf(1,grid.com, 01230 "base vels : maxvector avvector prcntavvec maxub maxvb\n"); 01231 CHKERRQ(ierr); 01232 ierr = verbPrintf(1,grid.com, " %11.4f%11.5f%12.5f%10.4f%10.4f\n", 01233 maxvecerr*secpera, avvecerr*secpera, 01234 (avvecerr/exactmaxspeed)*100.0, 01235 maxuberr*secpera, maxvberr*secpera); CHKERRQ(ierr); 01236 01237 if (netcdf_report) { 01238 err.reset(); 01239 err.short_name = "maximum_basal_velocity"; 01240 ierr = err.set_units("m/s"); CHKERRQ(ierr); 01241 ierr = err.set_glaciological_units("meters/year"); CHKERRQ(ierr); 01242 ierr = err.write(filename, (size_t)start, maxvecerr); CHKERRQ(ierr); 01243 01244 err.short_name = "average_basal_velocity"; 01245 ierr = err.write(filename, (size_t)start, avvecerr); CHKERRQ(ierr); 01246 err.short_name = "maximum_basal_u"; 01247 ierr = err.write(filename, (size_t)start, maxuberr); CHKERRQ(ierr); 01248 err.short_name = "maximum_basal_v"; 01249 ierr = err.write(filename, (size_t)start, maxvberr); CHKERRQ(ierr); 01250 01251 err.reset(); 01252 err.short_name = "relative_basal_velocity"; 01253 ierr = err.set_units("percent"); CHKERRQ(ierr); 01254 ierr = err.write(filename, (size_t)start, (avvecerr/exactmaxspeed)*100); CHKERRQ(ierr); 01255 } 01256 } 01257 01258 // basal melt rate errors if appropriate; reported in m/a 01259 if (testname == 'O') { 01260 PetscScalar maxbmelterr, minbmelterr; 01261 ierr = computeBasalMeltRateErrors(maxbmelterr, minbmelterr); CHKERRQ(ierr); 01262 if (maxbmelterr != minbmelterr) { 01263 ierr = verbPrintf(1,grid.com, 01264 "IceCompModel WARNING: unexpected Test O situation: max and min of bmelt error\n" 01265 " are different: maxbmelterr = %f, minbmelterr = %f\n", 01266 maxbmelterr * secpera, minbmelterr * secpera); CHKERRQ(ierr); 01267 } 01268 ierr = verbPrintf(1,grid.com, 01269 "basal melt: max\n"); CHKERRQ(ierr); 01270 ierr = verbPrintf(1,grid.com, " %11.5f\n", maxbmelterr*secpera); CHKERRQ(ierr); 01271 01272 if (netcdf_report) { 01273 err.reset(); 01274 err.short_name = "maximum_basal_melt_rate"; 01275 ierr = err.set_units("m/s"); CHKERRQ(ierr); 01276 ierr = err.set_glaciological_units("meters/year"); CHKERRQ(ierr); 01277 ierr = err.write(filename, (size_t)start, maxbmelterr); CHKERRQ(ierr); 01278 } 01279 } 01280 01281 ierr = verbPrintf(1,grid.com, "NUM ERRORS DONE\n"); CHKERRQ(ierr); 01282 return 0; 01283 } 01284 01286 /* 01287 Try 01288 01289 pismv -test V -y 1000 -part_grid -ssa_method fd_pik -o fig4-blue.nc 01290 pismv -test V -y 1000 -part_grid -ssa_method fd -o fig4-green.nc 01291 01292 to try to reproduce Figure 4. 01293 01294 Try 01295 01296 pismv -test V -y 3000 -ssa_method fd_pik -o fig5.nc -calving_at_thickness 250 -part_grid 01297 01298 with -Mx 51, -Mx 101, -Mx 201 for figure 5, 01299 01300 pismv -test V -y 300 -ssa_method fd -o fig6-ab.nc 01301 01302 for 6a and 6b, 01303 01304 pismv -test V -y 300 -ssa_method fd_pik -part_grid -o fig6-cd.nc 01305 01306 for 6c and 6d, 01307 01308 pismv -test V -y 300 -ssa_method fd_pik -part_grid -part_redist -o fig6-ef.nc 01309 01310 for 6e and 6f. 01311 01312 */ 01313 PetscErrorCode IceCompModel::test_V_init() { 01314 PetscErrorCode ierr; 01315 01316 // initialize temperature; the value used does not matter 01317 ierr = artm.set(273.15); CHKERRQ(ierr); 01318 01319 // initialize mass balance: 01320 ierr = acab.set(0.0); CHKERRQ(ierr); 01321 01322 // initialize the bed topography 01323 ierr = vbed.set(-1000); CHKERRQ(ierr); 01324 01325 // set SSA boundary conditions: 01326 PetscReal upstream_velocity = convert(300.0, "m/year", "m/second"); 01327 01328 ierr = bc_mask.begin_access(); CHKERRQ(ierr); 01329 ierr = bc_vel.begin_access(); CHKERRQ(ierr); 01330 for (PetscInt i = grid.xs; i < grid.xs+grid.xm; ++i) { 01331 for (PetscInt j = grid.ys; j < grid.ys+grid.ym; ++j) { 01332 if (i <= 2) { 01333 bc_mask(i,j) = 1; 01334 bc_vel(i,j).u = upstream_velocity; 01335 bc_vel(i,j).v = 0; 01336 } else { 01337 bc_mask(i,j) = 0; 01338 bc_vel(i,j).u = 0; 01339 bc_vel(i,j).v = 0; 01340 } 01341 } 01342 } 01343 ierr = bc_vel.end_access(); CHKERRQ(ierr); 01344 ierr = bc_mask.end_access(); CHKERRQ(ierr); 01345 01346 ShallowStressBalance *ssa = stress_balance->get_stressbalance(); CHKERRQ(ierr); 01347 ierr = ssa->set_boundary_conditions(bc_mask, bc_vel); CHKERRQ(ierr); 01348 01349 return 0; 01350 } 01351 01353 PetscErrorCode IceCompModel::test_V_set_thickness_bc() { 01354 PetscErrorCode ierr; 01355 PetscReal upstream_thk = 600.0; 01356 01357 ierr = vH.begin_access(); CHKERRQ(ierr); 01358 for (PetscInt i = grid.xs; i < grid.xs+grid.xm; ++i) { 01359 for (PetscInt j = grid.ys; j < grid.ys+grid.ym; ++j) { 01360 if (i <= 2) { 01361 vH(i,j) = upstream_thk; 01362 } 01363 } 01364 } 01365 ierr = vH.end_access(); CHKERRQ(ierr); 01366 01367 ierr = vH.beginGhostComm(); CHKERRQ(ierr); 01368 ierr = vH.endGhostComm(); CHKERRQ(ierr); 01369 return 0; 01370 }
1.7.3