PISM, A Parallel Ice Sheet Model stable 0.4.1779

src/verif/iceCompModel.cc

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