|
PISM, A Parallel Ice Sheet Model
stable v0.5
|
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 ¢erTerr) { 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 }
1.7.5.1