PISM, A Parallel Ice Sheet Model  stable v0.5
src/verif/iCMthermo.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 <petscdmda.h>
00021 #include "tests/exactTestsFG.h" 
00022 #include "tests/exactTestK.h" 
00023 #include "tests/exactTestO.h" 
00024 #include "iceCompModel.hh"
00025 #include "PISMStressBalance.hh"
00026 #include "PISMTime.hh"
00027 #include "IceGrid.hh"
00028 #include "pism_options.hh"
00029 
00030 // boundary conditions for tests F, G (same as EISMINT II Experiment F)
00031 const PetscScalar IceCompModel::Ggeo = 0.042;
00032 const PetscScalar IceCompModel::ST = 1.67e-5;
00033 const PetscScalar IceCompModel::Tmin = 223.15;  // K
00034 const PetscScalar IceCompModel::LforFG = 750000; // m
00035 const PetscScalar IceCompModel::ApforG = 200; // m
00036 
00037 
00039 PetscErrorCode IceCompModel::temperatureStep(
00040        PetscScalar* vertSacrCount, PetscScalar* bulgeCount) {
00041   PetscErrorCode  ierr;
00042 
00043   if ((testname == 'F') || (testname == 'G')) {
00044     IceModelVec3 *Sigma3;
00045     ierr = stress_balance->get_volumetric_strain_heating(Sigma3); CHKERRQ(ierr);
00046 
00047     ierr = Sigma3->add(1.0, SigmaComp3); CHKERRQ(ierr); // Sigma = Sigma + Sigma_c
00048     ierr = IceModel::temperatureStep(vertSacrCount,bulgeCount); CHKERRQ(ierr);
00049     ierr = Sigma3->add(-1.0, SigmaComp3); CHKERRQ(ierr); // Sigma = Sigma - Sigma_c
00050   } else {
00051     ierr = IceModel::temperatureStep(vertSacrCount,bulgeCount); CHKERRQ(ierr);
00052   }
00053   return 0;
00054 }
00055 
00056 
00057 PetscErrorCode IceCompModel::initTestFG() {
00058   PetscErrorCode  ierr;
00059   PetscInt        Mz=grid.Mz;
00060   PetscScalar     **H, **accum, **Ts;
00061   PetscScalar     *dummy1, *dummy2, *dummy3, *dummy4;
00062 
00063   dummy1=new PetscScalar[Mz];  dummy2=new PetscScalar[Mz];
00064   dummy3=new PetscScalar[Mz];  dummy4=new PetscScalar[Mz];
00065 
00066   ierr = vbed.set(0); CHKERRQ(ierr);
00067   ierr = vGhf.set(Ggeo); CHKERRQ(ierr);
00068 
00069   PetscScalar *T;
00070   T = new PetscScalar[grid.Mz];
00071 
00072   ierr = acab.get_array(accum); CHKERRQ(ierr);
00073   ierr = artm.get_array(Ts); CHKERRQ(ierr);
00074 
00075   ierr = vH.get_array(H); CHKERRQ(ierr);
00076   ierr = T3.begin_access(); CHKERRQ(ierr);
00077 
00078   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00079     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00080       PetscScalar r = grid.radius(i,j);
00081       Ts[i][j] = Tmin + ST * r;
00082       if (r > LforFG - 1.0) { // if (essentially) outside of sheet
00083         H[i][j] = 0.0;
00084         accum[i][j] = -ablationRateOutside/secpera;
00085         for (PetscInt k = 0; k < Mz; k++)
00086           T[k]=Ts[i][j];
00087       } else {
00088         r = PetscMax(r,1.0); // avoid singularity at origin
00089         if (testname == 'F') {
00090           bothexact(0.0,r,&grid.zlevels[0],Mz,0.0,
00091                      &H[i][j],&accum[i][j],T,dummy1,dummy2,dummy3,dummy4);
00092         } else {
00093           bothexact(grid.time->current(),r,&grid.zlevels[0],Mz,ApforG,
00094                      &H[i][j],&accum[i][j],T,dummy1,dummy2,dummy3,dummy4);
00095         }
00096       }
00097       ierr = T3.setInternalColumn(i,j,T); CHKERRQ(ierr);
00098 
00099     }
00100   }
00101 
00102   ierr =     vH.end_access(); CHKERRQ(ierr);
00103   ierr =     T3.end_access(); CHKERRQ(ierr);
00104 
00105   ierr = acab.end_access(); CHKERRQ(ierr);
00106   ierr = artm.end_access(); CHKERRQ(ierr);
00107 
00108   ierr = vH.beginGhostComm(); CHKERRQ(ierr);
00109   ierr = vH.endGhostComm(); CHKERRQ(ierr);
00110   
00111   ierr = T3.beginGhostComm(); CHKERRQ(ierr);
00112   ierr = T3.endGhostComm(); CHKERRQ(ierr);
00113 
00114   ierr = vH.copy_to(vh); CHKERRQ(ierr);
00115 
00116   delete [] dummy1;  delete [] dummy2;  delete [] dummy3;  delete [] dummy4;
00117   delete [] T;
00118   
00119   return 0;
00120 }
00121 
00122 
00123 PetscErrorCode IceCompModel::getCompSourcesTestFG() {
00124   PetscErrorCode  ierr;
00125   PetscInt        Mz=grid.Mz;
00126   PetscScalar     **accum;
00127   PetscScalar     dummy0;
00128   PetscScalar     *dummy1, *dummy2, *dummy3, *dummy4;
00129 
00130   dummy1=new PetscScalar[Mz];  dummy2=new PetscScalar[Mz];
00131   dummy3=new PetscScalar[Mz];  dummy4=new PetscScalar[Mz];
00132 
00133   PetscScalar *SigmaC;
00134   SigmaC = new PetscScalar[Mz];
00135 
00136   const PetscScalar
00137     ice_rho   = config.get("ice_density"),
00138     ice_c     = config.get("ice_specific_heat_capacity");
00139 
00140   // before temperature and flow step, set Sigma_c and accumulation from exact values
00141   ierr = acab.get_array(accum); CHKERRQ(ierr);
00142   ierr = SigmaComp3.begin_access(); CHKERRQ(ierr);
00143   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00144     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00145       PetscScalar r = grid.radius(i,j);
00146       if (r > LforFG - 1.0) {  // outside of sheet
00147         accum[i][j] = -ablationRateOutside/secpera;
00148         ierr = SigmaComp3.setColumn(i,j,0.0); CHKERRQ(ierr);
00149       } else {
00150         r = PetscMax(r,1.0); // avoid singularity at origin
00151         if (testname == 'F') {
00152           bothexact(0.0,r,&grid.zlevels[0],Mz,0.0,
00153                     &dummy0,&accum[i][j],dummy1,dummy2,dummy3,dummy4,SigmaC);
00154         } else {
00155           bothexact(grid.time->current(),r,&grid.zlevels[0],Mz,ApforG,
00156                     &dummy0,&accum[i][j],dummy1,dummy2,dummy3,dummy4,SigmaC);
00157         }
00158         for (PetscInt k=0;  k<Mz;  k++) // scale Sigma to J/(s m^3)
00159           SigmaC[k] = SigmaC[k] * ice_rho * ice_c;
00160         ierr = SigmaComp3.setInternalColumn(i,j,SigmaC); CHKERRQ(ierr);
00161       }
00162     }
00163   }
00164   ierr = acab.end_access(); CHKERRQ(ierr);
00165   ierr = SigmaComp3.end_access(); CHKERRQ(ierr);
00166 
00167   delete [] dummy1;  delete [] dummy2;  delete [] dummy3;  delete [] dummy4;
00168   delete [] SigmaC;
00169 
00170   return 0;
00171 }
00172 
00173 
00174 PetscErrorCode IceCompModel::fillSolnTestFG() {
00175   // fills Vecs vH, vh, vAccum, T3, u3, v3, w3, Sigma3, vSigmaComp
00176   PetscErrorCode  ierr;
00177   PetscInt        Mz=grid.Mz;
00178   PetscScalar     **H, **accum;
00179   PetscScalar     Ts, *Uradial;
00180 
00181   IceModelVec3 *u3, *v3, *w3, *Sigma3;
00182   ierr = stress_balance->get_3d_velocity(u3, v3, w3); CHKERRQ(ierr);
00183   ierr = stress_balance->get_volumetric_strain_heating(Sigma3); CHKERRQ(ierr);
00184 
00185   Uradial = new PetscScalar[Mz];
00186 
00187   PetscScalar *T, *u, *v, *w, *Sigma, *SigmaC;
00188   T = new PetscScalar[grid.Mz];
00189   u = new PetscScalar[grid.Mz];
00190   v = new PetscScalar[grid.Mz];
00191   w = new PetscScalar[grid.Mz];
00192   Sigma = new PetscScalar[grid.Mz];
00193   SigmaC = new PetscScalar[grid.Mz];
00194 
00195   const PetscScalar
00196     ice_rho   = config.get("ice_density"),
00197     ice_c     = config.get("ice_specific_heat_capacity");
00198 
00199   ierr = vH.get_array(H); CHKERRQ(ierr);
00200   ierr = acab.get_array(accum); CHKERRQ(ierr);
00201   
00202   ierr = T3.begin_access(); CHKERRQ(ierr);
00203 
00204   ierr = u3->begin_access(); CHKERRQ(ierr);
00205   ierr = v3->begin_access(); CHKERRQ(ierr);
00206   ierr = w3->begin_access(); CHKERRQ(ierr);
00207   ierr = Sigma3->begin_access(); CHKERRQ(ierr);
00208   ierr = SigmaComp3.begin_access(); CHKERRQ(ierr);
00209 
00210   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00211     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00212       PetscScalar xx = grid.x[i], yy = grid.y[j], r = grid.radius(i,j);
00213       if (r > LforFG - 1.0) {  // outside of sheet
00214         accum[i][j] = -ablationRateOutside/secpera;
00215         H[i][j] = 0.0;
00216         Ts = Tmin + ST * r;
00217         ierr = T3.setColumn(i,j,Ts); CHKERRQ(ierr);
00218         ierr = u3->setColumn(i,j,0.0); CHKERRQ(ierr);
00219         ierr = v3->setColumn(i,j,0.0); CHKERRQ(ierr);
00220         ierr = w3->setColumn(i,j,0.0); CHKERRQ(ierr);
00221         ierr = Sigma3->setColumn(i,j,0.0); CHKERRQ(ierr);
00222         ierr = SigmaComp3.setColumn(i,j,0.0); CHKERRQ(ierr);
00223       } else {  // inside the sheet
00224         r = PetscMax(r,1.0); // avoid singularity at origin
00225         if (testname == 'F') {
00226           bothexact(0.0,r,&grid.zlevels[0],Mz,0.0,
00227                     &H[i][j],&accum[i][j],T,Uradial,w, Sigma,SigmaC);
00228         } else {
00229           bothexact(grid.time->current(),r,&grid.zlevels[0],Mz,ApforG,
00230                     &H[i][j],&accum[i][j],T,Uradial,w, Sigma,SigmaC);
00231         }
00232         for (PetscInt k = 0; k < Mz; k++) {
00233           u[k] = Uradial[k]*(xx/r);
00234           v[k] = Uradial[k]*(yy/r);
00235           Sigma[k] = Sigma[k] * ice_rho * ice_c; // scale Sigma to J/(s m^3)
00236           SigmaC[k] = SigmaC[k] * ice_rho * ice_c; // scale SigmaC to J/(s m^3)
00237         }
00238         ierr = T3.setInternalColumn(i,j,T); CHKERRQ(ierr);
00239         ierr = u3->setInternalColumn(i,j,u); CHKERRQ(ierr);
00240         ierr = v3->setInternalColumn(i,j,v); CHKERRQ(ierr);
00241         ierr = w3->setInternalColumn(i,j,w); CHKERRQ(ierr);
00242         ierr = Sigma3->setInternalColumn(i,j,Sigma); CHKERRQ(ierr);
00243         ierr = SigmaComp3.setInternalColumn(i,j,SigmaC); CHKERRQ(ierr);
00244       }      
00245     }
00246   }
00247 
00248   ierr = T3.end_access(); CHKERRQ(ierr);
00249   ierr = u3->end_access(); CHKERRQ(ierr);
00250   ierr = v3->end_access(); CHKERRQ(ierr);
00251   ierr = w3->end_access(); CHKERRQ(ierr);
00252   ierr = Sigma3->end_access(); CHKERRQ(ierr);
00253   ierr = SigmaComp3.end_access(); CHKERRQ(ierr);
00254   
00255   ierr = vH.end_access(); CHKERRQ(ierr);
00256   ierr = acab.end_access(); CHKERRQ(ierr);
00257 
00258   delete [] Uradial;
00259 
00260   delete [] T;  delete [] u;  delete [] v;  delete [] w;
00261   delete [] Sigma;  delete [] SigmaC;
00262 
00263   ierr = vH.beginGhostComm(); CHKERRQ(ierr);
00264   ierr = vH.endGhostComm(); CHKERRQ(ierr);
00265   ierr = vH.copy_to(vh); CHKERRQ(ierr);
00266 
00267   ierr = T3.beginGhostComm(); CHKERRQ(ierr);
00268   ierr = u3->beginGhostComm(); CHKERRQ(ierr);
00269   ierr = v3->beginGhostComm(); CHKERRQ(ierr);
00270 
00271   ierr = T3.endGhostComm(); CHKERRQ(ierr);
00272   ierr = u3->endGhostComm(); CHKERRQ(ierr);
00273   ierr = v3->endGhostComm(); CHKERRQ(ierr);
00274 
00275   return 0;
00276 }
00277 
00278 PetscErrorCode IceCompModel::computeTemperatureErrors(
00279                                   PetscScalar &gmaxTerr, PetscScalar &gavTerr) {
00280 
00281   PetscErrorCode ierr;
00282   PetscScalar    maxTerr = 0.0, avTerr = 0.0, avcount = 0.0;
00283   PetscScalar    **H;
00284   const PetscInt Mz = grid.Mz;
00285   
00286   PetscScalar   *dummy1, *dummy2, *dummy3, *dummy4, *Tex;
00287   PetscScalar   junk0, junk1;
00288   
00289   Tex = new PetscScalar[Mz];
00290   dummy1 = new PetscScalar[Mz];  dummy2 = new PetscScalar[Mz];
00291   dummy3 = new PetscScalar[Mz];  dummy4 = new PetscScalar[Mz];
00292 
00293   PetscScalar *T;
00294 
00295   ierr = vH.get_array(H); CHKERRQ(ierr);
00296   ierr = T3.begin_access(); CHKERRQ(ierr);
00297   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; i++) {
00298     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; j++) {
00299       PetscScalar r = grid.radius(i,j);
00300       ierr = T3.getInternalColumn(i,j,&T); CHKERRQ(ierr);
00301       if ((r >= 1.0) && (r <= LforFG - 1.0)) {  // only evaluate error if inside sheet 
00302                                                 // and not at central singularity
00303         switch (testname) {
00304           case 'F':
00305             bothexact(0.0,r,&grid.zlevels[0],Mz,0.0,
00306                       &junk0,&junk1,Tex,dummy1,dummy2,dummy3,dummy4);
00307             break;
00308           case 'G':
00309             bothexact(grid.time->current(),r,&grid.zlevels[0],Mz,ApforG,
00310                       &junk0,&junk1,Tex,dummy1,dummy2,dummy3,dummy4);
00311             break;
00312           default:  SETERRQ(grid.com, 1,"temperature errors only computable for tests F and G\n");
00313         }
00314         const PetscInt ks = grid.kBelowHeight(H[i][j]);
00315         for (PetscInt k = 0; k < ks; k++) {  // only eval error if below num surface
00316           const PetscScalar Terr = PetscAbs(T[k] - Tex[k]);
00317           maxTerr = PetscMax(maxTerr,Terr);
00318           avcount += 1.0;
00319           avTerr += Terr;
00320         }
00321       }
00322     }
00323   }
00324   ierr = vH.end_access(); CHKERRQ(ierr);
00325   ierr = T3.end_access(); CHKERRQ(ierr);
00326 
00327   delete [] Tex;
00328   delete [] dummy1;  delete [] dummy2;  delete [] dummy3;  delete [] dummy4;
00329   
00330   ierr = PISMGlobalMax(&maxTerr, &gmaxTerr, grid.com); CHKERRQ(ierr);
00331   ierr = PISMGlobalSum(&avTerr, &gavTerr, grid.com); CHKERRQ(ierr);
00332   PetscScalar  gavcount;
00333   ierr = PISMGlobalSum(&avcount, &gavcount, grid.com); CHKERRQ(ierr);
00334   gavTerr = gavTerr/PetscMax(gavcount,1.0);  // avoid div by zero
00335   return 0;
00336 }
00337 
00338 
00339 PetscErrorCode IceCompModel::computeIceBedrockTemperatureErrors(
00340                                 PetscScalar &gmaxTerr, PetscScalar &gavTerr,
00341                                 PetscScalar &gmaxTberr, PetscScalar &gavTberr) {
00342   PetscErrorCode ierr;
00343 
00344   if ((testname != 'K') && (testname != 'O'))
00345     SETERRQ(grid.com, 1,"ice and bedrock temperature errors only computable for tests K and O\n");
00346 
00347   PetscScalar    maxTerr = 0.0, avTerr = 0.0, avcount = 0.0;
00348   PetscScalar    maxTberr = 0.0, avTberr = 0.0, avbcount = 0.0;
00349   const PetscInt    Mz = grid.Mz;
00350  
00351   PetscScalar    *Tex, *Tbex, *T, *Tb;
00352   PetscScalar    FF;
00353   Tex = new PetscScalar[Mz];  
00354 
00355   IceModelVec3BTU *bedrock_temp;
00356 
00357   BTU_Verification *my_btu = dynamic_cast<BTU_Verification*>(btu);
00358   if (my_btu == NULL) SETERRQ(grid.com, 1, "my_btu == NULL");
00359   ierr = my_btu->get_temp(bedrock_temp); CHKERRQ(ierr);
00360 
00361   vector<double> zblevels = bedrock_temp->get_levels();
00362   int Mbz = (int)zblevels.size();
00363   Tbex = new PetscScalar[Mbz];
00364 
00365   switch (testname) {
00366     case 'K':
00367       for (PetscInt k = 0; k < Mz; k++) {
00368         ierr = exactK(grid.time->current(), grid.zlevels[k], &Tex[k], &FF,
00369                       (bedrock_is_ice_forK==PETSC_TRUE)); CHKERRQ(ierr);
00370       }
00371       for (PetscInt k = 0; k < Mbz; k++) {
00372         ierr = exactK(grid.time->current(), zblevels[k], &Tbex[k], &FF,
00373                       (bedrock_is_ice_forK==PETSC_TRUE)); CHKERRQ(ierr);
00374       }
00375       break;
00376     case 'O':
00377       PetscScalar dum1, dum2, dum3, dum4;
00378       for (PetscInt k = 0; k < Mz; k++) {
00379         ierr = exactO(grid.zlevels[k], &Tex[k], &dum1, &dum2, &dum3, &dum4);
00380              CHKERRQ(ierr);
00381       }
00382       for (PetscInt k = 0; k < Mbz; k++) {
00383         ierr = exactO(zblevels[k], &Tbex[k], &dum1, &dum2, &dum3, &dum4);
00384              CHKERRQ(ierr);
00385       }
00386       break;
00387     default: SETERRQ(grid.com, 2,"again: ice and bedrock temperature errors only for tests K and O\n");
00388   }
00389     
00390   ierr = T3.begin_access(); CHKERRQ(ierr);
00391   ierr = bedrock_temp->begin_access(); CHKERRQ(ierr);
00392   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; i++) {
00393     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; j++) {
00394       ierr = bedrock_temp->getInternalColumn(i,j,&Tb); CHKERRQ(ierr);
00395       for (PetscInt kb = 0; kb < Mbz; kb++) { 
00396         const PetscScalar Tberr = PetscAbs(Tb[kb] - Tbex[kb]);
00397         maxTberr = PetscMax(maxTberr,Tberr);
00398         avbcount += 1.0;
00399         avTberr += Tberr;
00400       }
00401       ierr = T3.getInternalColumn(i,j,&T); CHKERRQ(ierr);
00402       for (PetscInt k = 0; k < Mz; k++) { 
00403         const PetscScalar Terr = PetscAbs(T[k] - Tex[k]);
00404         maxTerr = PetscMax(maxTerr,Terr);
00405         avcount += 1.0;
00406         avTerr += Terr;
00407       }
00408     }
00409   }
00410   ierr = T3.end_access(); CHKERRQ(ierr);
00411   ierr = bedrock_temp->end_access(); CHKERRQ(ierr);
00412 
00413   delete [] Tex;  delete [] Tbex;
00414   
00415   ierr = PISMGlobalMax(&maxTerr, &gmaxTerr, grid.com); CHKERRQ(ierr);
00416   ierr = PISMGlobalSum(&avTerr, &gavTerr, grid.com); CHKERRQ(ierr);
00417   PetscScalar  gavcount;
00418   ierr = PISMGlobalSum(&avcount, &gavcount, grid.com); CHKERRQ(ierr);
00419   gavTerr = gavTerr/PetscMax(gavcount,1.0);  // avoid div by zero
00420 
00421   ierr = PISMGlobalMax(&maxTberr, &gmaxTberr, grid.com); CHKERRQ(ierr);
00422   ierr = PISMGlobalSum(&avTberr, &gavTberr, grid.com); CHKERRQ(ierr);
00423   PetscScalar  gavbcount;
00424   ierr = PISMGlobalSum(&avbcount, &gavbcount, grid.com); CHKERRQ(ierr);
00425   gavTberr = gavTberr/PetscMax(gavbcount,1.0);  // avoid div by zero
00426   return 0;
00427 }
00428 
00429 
00430 PetscErrorCode IceCompModel::computeBasalTemperatureErrors(
00431       PetscScalar &gmaxTerr, PetscScalar &gavTerr, PetscScalar &centerTerr) {
00432 
00433   PetscErrorCode  ierr;
00434   PetscScalar     domeT, domeTexact, Terr, avTerr;
00435 
00436   PetscScalar     dummy, z, Texact, dummy1, dummy2, dummy3, dummy4, dummy5;
00437 
00438   ierr = T3.begin_access(); CHKERRQ(ierr);
00439 
00440   domeT=0; domeTexact = 0; Terr=0; avTerr=0;
00441 
00442   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00443     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00444       PetscScalar r = grid.radius(i,j);
00445       switch (testname) {
00446         case 'F':
00447           if (r > LforFG - 1.0) {  // outside of sheet
00448             Texact=Tmin + ST * r;  // = Ts
00449           } else {
00450             r=PetscMax(r,1.0);
00451             z=0.0;
00452             bothexact(0.0,r,&z,1,0.0,
00453                       &dummy5,&dummy,&Texact,&dummy1,&dummy2,&dummy3,&dummy4);
00454           }
00455           break;
00456         case 'G':
00457           if (r > LforFG -1.0) {  // outside of sheet
00458             Texact=Tmin + ST * r;  // = Ts
00459           } else {
00460             r=PetscMax(r,1.0);
00461             z=0.0;
00462             bothexact(grid.time->current(),r,&z,1,ApforG,
00463                       &dummy5,&dummy,&Texact,&dummy1,&dummy2,&dummy3,&dummy4);
00464           }
00465           break;
00466         default:  SETERRQ(grid.com, 1,"temperature errors only computable for tests F and G\n");
00467       }
00468 
00469       const PetscScalar Tbase = T3.getValZ(i,j,0.0);
00470       if (i == (grid.Mx - 1)/2 && j == (grid.My - 1)/2) {
00471         domeT = Tbase;
00472         domeTexact = Texact;
00473       }
00474       // compute maximum errors
00475       Terr = PetscMax(Terr,PetscAbsReal(Tbase - Texact));
00476       // add to sums for average errors
00477       avTerr += PetscAbs(Tbase - Texact);
00478     }
00479   }
00480   ierr = T3.end_access(); CHKERRQ(ierr);
00481   
00482   PetscScalar gdomeT, gdomeTexact;
00483 
00484   ierr = PISMGlobalMax(&Terr, &gmaxTerr, grid.com); CHKERRQ(ierr);
00485   ierr = PISMGlobalSum(&avTerr, &gavTerr, grid.com); CHKERRQ(ierr);
00486   gavTerr = gavTerr/(grid.Mx*grid.My);
00487   ierr = PISMGlobalMax(&domeT, &gdomeT, grid.com); CHKERRQ(ierr);
00488   ierr = PISMGlobalMax(&domeTexact, &gdomeTexact, grid.com); CHKERRQ(ierr);  
00489   centerTerr = PetscAbsReal(gdomeT - gdomeTexact);
00490   
00491   return 0;
00492 }
00493 
00494 
00495 PetscErrorCode IceCompModel::computeSigmaErrors(
00496                       PetscScalar &gmaxSigmaerr, PetscScalar &gavSigmaerr) {
00497 
00498   PetscErrorCode ierr;
00499   PetscScalar    maxSigerr = 0.0, avSigerr = 0.0, avcount = 0.0;
00500   PetscScalar    **H;
00501   const PetscInt Mz = grid.Mz;
00502   
00503   PetscScalar   *dummy1, *dummy2, *dummy3, *dummy4, *Sigex;
00504   PetscScalar   junk0, junk1;
00505   
00506   Sigex = new PetscScalar[Mz];
00507   dummy1 = new PetscScalar[Mz];  dummy2 = new PetscScalar[Mz];
00508   dummy3 = new PetscScalar[Mz];  dummy4 = new PetscScalar[Mz];
00509 
00510   const PetscScalar
00511     ice_rho   = config.get("ice_density"),
00512     ice_c     = config.get("ice_specific_heat_capacity");
00513 
00514   PetscScalar *Sig;
00515   IceModelVec3 *Sigma3;
00516   ierr = stress_balance->get_volumetric_strain_heating(Sigma3); CHKERRQ(ierr);
00517 
00518   ierr = vH.get_array(H); CHKERRQ(ierr);
00519   ierr = Sigma3->begin_access(); CHKERRQ(ierr);
00520   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; i++) {
00521     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; j++) {
00522       PetscScalar r = grid.radius(i,j);
00523       if ((r >= 1.0) && (r <= LforFG - 1.0)) {  // only evaluate error if inside sheet 
00524                                                 // and not at central singularity
00525         switch (testname) {
00526           case 'F':
00527             bothexact(0.0,r,&grid.zlevels[0],Mz,0.0,
00528                       &junk0,&junk1,dummy1,dummy2,dummy3,Sigex,dummy4);
00529             break;
00530           case 'G':
00531             bothexact(grid.time->current(),r,&grid.zlevels[0],Mz,ApforG,
00532                       &junk0,&junk1,dummy1,dummy2,dummy3,Sigex,dummy4);
00533             break;
00534           default:
00535             SETERRQ(grid.com, 1,"strain-heating (Sigma) errors only computable for tests F and G\n");
00536         }
00537         for (PetscInt k = 0; k < Mz; k++)
00538           Sigex[k] = Sigex[k] * ice_rho * ice_c; // scale exact Sigma to J/(s m^3)
00539         const PetscInt ks = grid.kBelowHeight(H[i][j]);
00540         ierr = Sigma3->getInternalColumn(i,j,&Sig); CHKERRQ(ierr);
00541         for (PetscInt k = 0; k < ks; k++) {  // only eval error if below num surface
00542           const PetscScalar Sigerr = PetscAbs(Sig[k] - Sigex[k]);
00543           maxSigerr = PetscMax(maxSigerr,Sigerr);
00544           avcount += 1.0;
00545           avSigerr += Sigerr;
00546         }
00547       }
00548     }
00549   }
00550   ierr =     vH.end_access(); CHKERRQ(ierr);
00551   ierr = Sigma3->end_access(); CHKERRQ(ierr);
00552 
00553   delete [] Sigex;
00554   delete [] dummy1;  delete [] dummy2;  delete [] dummy3;  delete [] dummy4;
00555   
00556   ierr = PISMGlobalMax(&maxSigerr, &gmaxSigmaerr, grid.com); CHKERRQ(ierr);
00557   ierr = PISMGlobalSum(&avSigerr, &gavSigmaerr, grid.com); CHKERRQ(ierr);
00558   PetscScalar  gavcount;
00559   ierr = PISMGlobalSum(&avcount, &gavcount, grid.com); CHKERRQ(ierr);
00560   gavSigmaerr = gavSigmaerr/PetscMax(gavcount,1.0);  // avoid div by zero
00561   return 0;
00562 }
00563 
00564 
00565 PetscErrorCode IceCompModel::computeSurfaceVelocityErrors(
00566         PetscScalar &gmaxUerr, PetscScalar &gavUerr,
00567         PetscScalar &gmaxWerr, PetscScalar &gavWerr) {
00568 
00569   PetscErrorCode ierr;
00570   PetscScalar    maxUerr = 0.0, maxWerr = 0.0, avUerr = 0.0, avWerr = 0.0;
00571   PetscScalar    **H;
00572 
00573   IceModelVec3 *u3, *v3, *w3;
00574   ierr = stress_balance->get_3d_velocity(u3, v3, w3); CHKERRQ(ierr);
00575 
00576   ierr = vH.get_array(H); CHKERRQ(ierr);
00577   ierr = u3->begin_access(); CHKERRQ(ierr);
00578   ierr = v3->begin_access(); CHKERRQ(ierr);
00579   ierr = w3->begin_access(); CHKERRQ(ierr);
00580   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; i++) {
00581     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; j++) {
00582       PetscScalar xx = grid.x[i], yy = grid.y[j], r = grid.radius(i,j);
00583       if ((r >= 1.0) && (r <= LforFG - 1.0)) {  // only evaluate error if inside sheet 
00584                                                 // and not at central singularity
00585         PetscScalar radialUex,wex;
00586         PetscScalar dummy0,dummy1,dummy2,dummy3,dummy4;
00587         switch (testname) {
00588           case 'F':
00589             bothexact(0.0,r,&(H[i][j]),1,0.0,
00590                       &dummy0,&dummy1,&dummy2,&radialUex,&wex,&dummy3,&dummy4);
00591             break;
00592           case 'G':
00593             bothexact(grid.time->current(),r,&(H[i][j]),1,ApforG,
00594                       &dummy0,&dummy1,&dummy2,&radialUex,&wex,&dummy3,&dummy4);
00595             break;
00596           default:  SETERRQ(grid.com, 1,"surface velocity errors only computed for tests F and G\n");
00597         }
00598         const PetscScalar uex = (xx/r) * radialUex;
00599         const PetscScalar vex = (yy/r) * radialUex;
00600         // note that because getValZ does linear interpolation and H[i][j] is not exactly at
00601         // a grid point, this causes nonzero errors even with option -eo
00602         const PetscScalar Uerr = sqrt(PetscSqr(u3->getValZ(i,j,H[i][j]) - uex)
00603                                       + PetscSqr(v3->getValZ(i,j,H[i][j]) - vex));
00604         maxUerr = PetscMax(maxUerr,Uerr);
00605         avUerr += Uerr;
00606         const PetscScalar Werr = PetscAbs(w3->getValZ(i,j,H[i][j]) - wex);
00607         maxWerr = PetscMax(maxWerr,Werr);
00608         avWerr += Werr;
00609       }
00610     }
00611   }
00612   ierr = vH.end_access(); CHKERRQ(ierr);
00613   ierr = u3->end_access(); CHKERRQ(ierr);
00614   ierr = v3->end_access(); CHKERRQ(ierr);
00615   ierr = w3->end_access(); CHKERRQ(ierr);
00616 
00617   ierr = PISMGlobalMax(&maxUerr, &gmaxUerr, grid.com); CHKERRQ(ierr);
00618   ierr = PISMGlobalMax(&maxWerr, &gmaxWerr, grid.com); CHKERRQ(ierr);
00619   ierr = PISMGlobalSum(&avUerr, &gavUerr, grid.com); CHKERRQ(ierr);
00620   gavUerr = gavUerr/(grid.Mx*grid.My);
00621   ierr = PISMGlobalSum(&avWerr, &gavWerr, grid.com); CHKERRQ(ierr);
00622   gavWerr = gavWerr/(grid.Mx*grid.My);
00623   return 0;
00624 }
00625 
00626 
00627 PetscErrorCode IceCompModel::computeBasalMeltRateErrors(
00628                    PetscScalar &gmaxbmelterr, PetscScalar &gminbmelterr) {
00629   PetscErrorCode ierr;
00630   PetscScalar    maxbmelterr = -9.99e40, minbmelterr = 9.99e40, err;
00631   PetscScalar    bmelt,dum1,dum2,dum3,dum4;
00632 
00633   if (testname != 'O')
00634     SETERRQ(grid.com, 1,"basal melt rate errors are only computable for test O\n");
00635 
00636   // we just need one constant from exact solution:
00637   ierr = exactO(0.0, &dum1, &dum2, &dum3, &dum4, &bmelt); CHKERRQ(ierr);
00638 
00639   ierr = vbmr.begin_access(); CHKERRQ(ierr);
00640   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; i++) {
00641     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; j++) {
00642       err = PetscAbs(vbmr(i,j) - bmelt);
00643       maxbmelterr = PetscMax(maxbmelterr, err);
00644       minbmelterr = PetscMin(minbmelterr, err);
00645     }
00646   }
00647   ierr = vbmr.end_access(); CHKERRQ(ierr);
00648 
00649   ierr = PISMGlobalMax(&maxbmelterr, &gmaxbmelterr, grid.com); CHKERRQ(ierr);
00650   ierr = PISMGlobalMin(&minbmelterr, &gminbmelterr, grid.com); CHKERRQ(ierr);
00651   return 0;
00652 }
00653 
00654 
00655 PetscErrorCode IceCompModel::fillTemperatureSolnTestsKO() {
00656   PetscErrorCode    ierr;
00657   const PetscInt    Mz = grid.Mz;
00658 
00659   PetscScalar       *Tcol;
00660   PetscScalar       dum1, dum2, dum3, dum4;
00661   PetscScalar    FF;
00662   Tcol = new PetscScalar[Mz];
00663 
00664   // evaluate exact solution in a column; all columns are the same
00665   switch (testname) {
00666     case 'K':
00667       for (PetscInt k=0; k<Mz; k++) {
00668         ierr = exactK(grid.time->current(), grid.zlevels[k], &Tcol[k], &FF,
00669                       (bedrock_is_ice_forK==PETSC_TRUE)); CHKERRQ(ierr);
00670       }
00671       break;
00672     case 'O':
00673       for (PetscInt k=0; k<Mz; k++) {
00674         ierr = exactO(grid.zlevels[k], &Tcol[k], &dum1, &dum2, &dum3, &dum4); CHKERRQ(ierr);
00675       }
00676       break;
00677     default:  SETERRQ(grid.com, 2,"only fills temperature solutions for tests K and O\n");
00678   }
00679 
00680   // copy column values into 3D arrays
00681   ierr = T3.begin_access(); CHKERRQ(ierr);
00682   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00683     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00684       ierr = T3.setInternalColumn(i,j,Tcol); CHKERRQ(ierr);
00685     }
00686   }
00687   ierr = T3.end_access(); CHKERRQ(ierr);
00688 
00689   delete [] Tcol;
00690 
00691   // communicate T
00692   ierr = T3.beginGhostComm(); CHKERRQ(ierr);
00693   ierr = T3.endGhostComm(); CHKERRQ(ierr);
00694   return 0;
00695 }
00696 
00697 
00698 PetscErrorCode IceCompModel::fillBasalMeltRateSolnTestO() {
00699   PetscErrorCode    ierr;
00700   PetscScalar       bmelt, dum1, dum2, dum3, dum4;
00701   if (testname != 'O') { SETERRQ(grid.com, 1,"only fills basal melt rate soln for test O\n"); }
00702 
00703   // we just need one constant from exact solution:
00704   ierr = exactO(0.0, &dum1, &dum2, &dum3, &dum4, &bmelt); CHKERRQ(ierr);
00705 
00706   ierr = vbmr.set(bmelt); CHKERRQ(ierr);
00707   return 0;
00708 }
00709 
00710 
00711 PetscErrorCode IceCompModel::initTestsKO() {
00712   PetscErrorCode    ierr;
00713 
00714   if (testname == 'K') {
00715     bool Mbz_set;
00716     int Mbz;
00717     ierr = PISMOptionsInt("-Mbz", "Number of levels in the bedrock thermal model",
00718                           Mbz, Mbz_set); CHKERRQ(ierr);
00719     if (Mbz_set && Mbz < 2) {
00720       PetscPrintf(grid.com, "PISM ERROR: pismv test K requires a bedrock thermal layer 1000m deep.\n");
00721       PISMEnd();
00722     }
00723   }
00724 
00725   ierr = acab.set(0.0); CHKERRQ(ierr);
00726   ierr = artm.set(223.15); CHKERRQ(ierr);
00727 
00728   ierr = vbed.set(0.0); CHKERRQ(ierr);
00729   ierr = vGhf.set(0.042); CHKERRQ(ierr);
00730   ierr = vH.set(3000.0); CHKERRQ(ierr);
00731   ierr = vbwat.set(0.0); CHKERRQ(ierr);
00732   ierr = vH.copy_to(vh); CHKERRQ(ierr);
00733 
00734   ierr = fillTemperatureSolnTestsKO(); CHKERRQ(ierr);
00735   return 0;
00736 }
00737 
00738 PetscErrorCode BTU_Verification::get_temp(IceModelVec3BTU* &result) {
00739   result = &temp;
00740   return 0;
00741 }
00742 
00743 PetscErrorCode BTU_Verification::bootstrap() {
00744   PetscErrorCode ierr;
00745 
00746   if (Mbz < 2) return 0;
00747 
00748   vector<double> Tbcol(Mbz),
00749     zlevels = temp.get_levels();
00750   PetscScalar       dum1, dum2, dum3, dum4;
00751   PetscScalar    FF;
00752 
00753   // evaluate exact solution in a column; all columns are the same
00754   switch (testname) {
00755     case 'K':
00756       for (PetscInt k=0; k<Mbz; k++) {
00757         if (exactK(grid.time->current(), zlevels[k], &Tbcol[k], &FF,
00758                    (bedrock_is_ice==PETSC_TRUE)))
00759           SETERRQ1(grid.com, 1,"exactK() reports that level %9.7f is below B0 = -1000.0 m\n",
00760                    zlevels[k]);
00761       }
00762       break;
00763     case 'O':
00764       for (PetscInt k=0; k<Mbz; k++) {
00765         ierr = exactO(zlevels[k], &Tbcol[k], &dum1, &dum2, &dum3, &dum4); CHKERRQ(ierr);
00766       }
00767       break;
00768     default:
00769       {
00770         ierr = PISMBedThermalUnit::bootstrap(); CHKERRQ(ierr);
00771       }
00772   }
00773 
00774   // copy column values into 3D arrays
00775   ierr = temp.begin_access(); CHKERRQ(ierr);
00776   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00777     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00778       ierr = temp.setInternalColumn(i,j,&Tbcol[0]); CHKERRQ(ierr);
00779     }
00780   }
00781   ierr = temp.end_access(); CHKERRQ(ierr);
00782 
00783   return 0;
00784 }
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines