00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <petsc.h>
00020 #include "pism_const.hh"
00021 #include "iceModelVec.hh"
00022 #include "columnSystem.hh"
00023
00024
00026
00042 columnSystemCtx::columnSystemCtx(PetscInt my_nmax) : nmax(my_nmax) {
00043 if (nmax < 1) {
00044 PetscPrintf(PETSC_COMM_WORLD,
00045 "columnSystem ERROR: nmax of system too small\n");
00046 PetscEnd();
00047 }
00048 if (nmax > 1000000) {
00049 PetscPrintf(PETSC_COMM_WORLD,
00050 "columnSystem ERROR: nmax of system unreasonable (> 10^6)\n");
00051 PetscEnd();
00052 }
00053 Lp = new PetscScalar[nmax-1];
00054 L = Lp-1;
00055 D = new PetscScalar[nmax];
00056 U = new PetscScalar[nmax-1];
00057 rhs = new PetscScalar[nmax];
00058 work = new PetscScalar[nmax];
00059
00060 resetColumn();
00061
00062 indicesValid = false;
00063 }
00064
00065
00066 columnSystemCtx::~columnSystemCtx() {
00067 delete [] Lp;
00068 delete [] D;
00069 delete [] U;
00070 delete [] rhs;
00071 delete [] work;
00072 }
00073
00074
00076 PetscErrorCode columnSystemCtx::resetColumn() {
00077 PetscErrorCode ierr;
00078 ierr = PetscMemzero(Lp, (nmax-1)*sizeof(PetscScalar)); CHKERRQ(ierr);
00079 ierr = PetscMemzero(U, (nmax-1)*sizeof(PetscScalar)); CHKERRQ(ierr);
00080 ierr = PetscMemzero(D, (nmax)*sizeof(PetscScalar)); CHKERRQ(ierr);
00081 ierr = PetscMemzero(rhs, (nmax)*sizeof(PetscScalar)); CHKERRQ(ierr);
00082 ierr = PetscMemzero(work, (nmax)*sizeof(PetscScalar)); CHKERRQ(ierr);
00083 return 0;
00084 }
00085
00086
00088 PetscScalar columnSystemCtx::norm1(const PetscInt n) const {
00089 if (n > nmax) {
00090 PetscPrintf(PETSC_COMM_WORLD,"PISM ERROR: n > nmax in columnSystemCtx::norm1()\n");
00091 PetscEnd();
00092 }
00093 if (n == 1) return fabs(D[0]);
00094 PetscScalar z = fabs(D[0]) + fabs(L[1]);
00095 for (PetscInt k = 1; k < n; k++) {
00096 z = PetscMax(z, fabs(U[k-1])) + fabs(D[k]) + fabs(L[k+1]);
00097 }
00098 z = PetscMax(z, fabs(U[n-2]) + fabs(D[n-1]));
00099 return z;
00100 }
00101
00102
00104
00116 PetscScalar columnSystemCtx::ddratio(const PetscInt n) const {
00117 if (n > nmax) {
00118 PetscPrintf(PETSC_COMM_WORLD,"PISM ERROR: n > nmax in columnSystemCtx::ddratio()\n");
00119 PetscEnd();
00120 }
00121 const PetscScalar scale = norm1(n);
00122
00123 if ( (fabs(D[0]) / scale) < 1.0e-12) return -1.0;
00124 PetscScalar z = fabs(U[0]) / fabs(D[0]);
00125
00126 for (PetscInt j = 1; j < n-1; j++) {
00127 if ( (fabs(D[j]) / scale) < 1.0e-12) return -1.0;
00128 const PetscScalar s = fabs(L[j]) + fabs(U[j]);
00129 z = PetscMax(z, s / fabs(D[j]) );
00130 }
00131
00132 if ( (fabs(D[n-1]) / scale) < 1.0e-12) return -1.0;
00133 z = PetscMax(z, fabs(L[n-1]) / fabs(D[n-1]) );
00134
00135 return z;
00136 }
00137
00138
00139 PetscErrorCode columnSystemCtx::setIndicesAndClearThisColumn(
00140 PetscInt my_i, PetscInt my_j, PetscInt my_ks) {
00141 if (indicesValid) { SETERRQ(3,
00142 "setIndicesAndClearThisColumn() called twice in same column"); }
00143 i = my_i;
00144 j = my_j;
00145 ks = my_ks;
00146
00147 resetColumn();
00148
00149 indicesValid = true;
00150 return 0;
00151 }
00152
00153
00155
00160 PetscErrorCode columnSystemCtx::viewColumnValues(PetscViewer viewer,
00161 PetscScalar *v, PetscInt m, const char* info) const {
00162 PetscErrorCode ierr;
00163
00164 if (v==NULL) {
00165 SETERRQ1(2,"columnSystem ERROR: can't view '%s' by v=NULL pointer ... ending ...\n", info);
00166 }
00167 if ((m<1) || (m>1000)) {
00168 SETERRQ1(3,"columnSystem ERROR: can't view '%s' because m<1 or m>1000 column values ... ending ...\n",info);
00169 }
00170
00171 PetscTruth iascii;
00172 if (!viewer) {
00173 ierr = PetscViewerASCIIGetStdout(PETSC_COMM_SELF,&viewer); CHKERRQ(ierr);
00174 }
00175 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii); CHKERRQ(ierr);
00176 if (!iascii) { SETERRQ(1,"Only ASCII viewer for ColumnSystem\n"); }
00177
00178 ierr = PetscViewerASCIIPrintf(viewer,
00179 "\n<viewing ColumnSystem column object with description '%s':\n"
00180 " k value\n",info); CHKERRQ(ierr);
00181 for (PetscInt k=0; k<m; k++) {
00182 ierr = PetscViewerASCIIPrintf(viewer,
00183 " %5d %12.5e\n",k,v[k]); CHKERRQ(ierr);
00184 }
00185 ierr = PetscViewerASCIIPrintf(viewer,
00186 "end viewing>\n"); CHKERRQ(ierr);
00187 return 0;
00188 }
00189
00190
00192
00197 PetscErrorCode columnSystemCtx::viewMatrix(PetscViewer viewer, const char* info) const {
00198 PetscErrorCode ierr;
00199 PetscTruth iascii;
00200 if (!viewer) {
00201 ierr = PetscViewerASCIIGetStdout(PETSC_COMM_SELF,&viewer); CHKERRQ(ierr);
00202 }
00203 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii); CHKERRQ(ierr);
00204 if (!iascii) { SETERRQ(1,"Only ASCII viewer for ColumnSystem\n"); }
00205
00206 if (L==NULL) {
00207 SETERRQ1(2,"columnSystem ERROR: can't matrix '%s' because L==NULL ... ending ...\n", info);
00208 }
00209 if (D==NULL) {
00210 SETERRQ1(3,"columnSystem ERROR: can't matrix '%s' because D==NULL ... ending ...\n", info);
00211 }
00212 if (U==NULL) {
00213 SETERRQ1(4,"columnSystem ERROR: can't matrix '%s' because U==NULL ... ending ...\n", info);
00214 }
00215
00216 if (nmax < 2) {
00217 ierr = PetscViewerASCIIPrintf(viewer,
00218 "\n\n<nmax >= 2 required to view ColumnSystem tridiagonal matrix '%s' ... skipping view\n",info);
00219 CHKERRQ(ierr);
00220 return 0;
00221 }
00222
00223
00224 if (nmax > 120) {
00225 ierr = PetscViewerASCIIPrintf(viewer,
00226 "\n\n<nmax > 120: matrix too big to display as full; viewing tridiagonal matrix '%s' by diagonals ...\n",info); CHKERRQ(ierr);
00227 char diag_info[PETSC_MAX_PATH_LEN];
00228 snprintf(diag_info,PETSC_MAX_PATH_LEN, "super-diagonal U for system '%s'", info);
00229 ierr = viewColumnValues(viewer,U,nmax-1,diag_info); CHKERRQ(ierr);
00230 snprintf(diag_info,PETSC_MAX_PATH_LEN, "main diagonal D for system '%s'", info);
00231 ierr = viewColumnValues(viewer,D,nmax,diag_info); CHKERRQ(ierr);
00232 snprintf(diag_info,PETSC_MAX_PATH_LEN, "sub-diagonal L for system '%s'", info);
00233 ierr = viewColumnValues(viewer,Lp,nmax-1,diag_info); CHKERRQ(ierr);
00234 } else {
00235 ierr = PetscViewerASCIIPrintf(viewer,
00236 "\n<viewing ColumnSystem tridiagonal matrix, '%s':\n",info); CHKERRQ(ierr);
00237 for (PetscInt k=0; k<nmax; k++) {
00238 if (k == 0) {
00239 ierr = PetscViewerASCIIPrintf(viewer,"%10.7f %10.7f ",D[k],U[k]); CHKERRQ(ierr);
00240 for (PetscInt j=2; j<nmax; j++) {
00241 ierr = PetscViewerASCIIPrintf(viewer,"%10.7f ",0.0); CHKERRQ(ierr);
00242 }
00243 } else if (k < nmax-1) {
00244 for (PetscInt j=0; j<k-1; j++) {
00245 ierr = PetscViewerASCIIPrintf(viewer,"%10.7f ",0.0); CHKERRQ(ierr);
00246 }
00247 ierr = PetscViewerASCIIPrintf(viewer,"%10.7f %10.7f %10.7f ",L[k],D[k],U[k]); CHKERRQ(ierr);
00248 for (PetscInt j=k+2; j<nmax; j++) {
00249 ierr = PetscViewerASCIIPrintf(viewer,"%10.7f ",0.0); CHKERRQ(ierr);
00250 }
00251 } else {
00252 for (PetscInt j=0; j<k-1; j++) {
00253 ierr = PetscViewerASCIIPrintf(viewer,"%10.7f ",0.0); CHKERRQ(ierr);
00254 }
00255 ierr = PetscViewerASCIIPrintf(viewer,"%10.7f %10.7f ",L[k],D[k]); CHKERRQ(ierr);
00256 }
00257 ierr = PetscViewerASCIIPrintf(viewer,"\n"); CHKERRQ(ierr);
00258 }
00259 }
00260
00261 ierr = PetscViewerASCIIPrintf(viewer,
00262 "end viewing tridiagonal matrix>\n"); CHKERRQ(ierr);
00263 return 0;
00264 }
00265
00266
00268
00271 PetscErrorCode columnSystemCtx::viewSystem(PetscViewer viewer, const char* info) const {
00272 PetscErrorCode ierr;
00273 ierr = viewMatrix(viewer,info); CHKERRQ(ierr);
00274 char rhs_info[PETSC_MAX_PATH_LEN];
00275 snprintf(rhs_info,PETSC_MAX_PATH_LEN, "right-hand side vector for system '%s'", info);
00276 ierr = viewColumnValues(viewer,rhs,nmax,rhs_info); CHKERRQ(ierr);
00277 return 0;
00278 }
00279
00280
00282
00292 PetscErrorCode columnSystemCtx::solveTridiagonalSystem(
00293 const PetscInt n, PetscScalar **x) {
00294 #ifdef PISM_DEBUG
00295 if (x == NULL) { SETERRQ(-999,"x is NULL in columnSystemCtx"); }
00296 if (*x == NULL) { SETERRQ(-998,"*x is NULL in columnSystemCtx"); }
00297 if (n < 1) { SETERRQ(-997,"instance size n < 1 in columnSystemCtx"); }
00298 if (n > nmax) { SETERRQ(-996,"instance size n too large in columnSystemCtx"); }
00299
00300 if (!indicesValid) { SETERRQ(-995,"column indices not valid in columnSystemCtx"); }
00301 #endif
00302 PetscScalar b;
00303 b = D[0];
00304 if (b == 0.0) { return 1; }
00305 (*x)[0] = rhs[0]/b;
00306 for (int i=1; i<n; ++i) {
00307 work[i] = U[i-1]/b;
00308 b = D[i] - L[i] * work[i];
00309 if (b == 0.0) { return i+1; }
00310 (*x)[i] = (rhs[i] - L[i] * (*x)[i-1]) / b;
00311 }
00312 for (int i=n-2; i>=0; --i) {
00313 (*x)[i] -= work[i+1] * (*x)[i+1];
00314 }
00315
00316 indicesValid = false;
00317 return 0;
00318 }
00319
00320
00321 ageSystemCtx::ageSystemCtx(PetscInt my_Mz)
00322 : columnSystemCtx(my_Mz) {
00323 initAllDone = false;
00324
00325 dx = -1.0;
00326 dy = -1.0;
00327 dtAge = -1.0;
00328 dzEQ = -1.0;
00329 u = NULL;
00330 v = NULL;
00331 w = NULL;
00332 tau3 = NULL;
00333 }
00334
00335
00336 PetscErrorCode ageSystemCtx::initAllColumns() {
00337
00338 if (dx <= 0.0) { SETERRQ(2,"un-initialized dx in ageSystemCtx"); }
00339 if (dy <= 0.0) { SETERRQ(3,"un-initialized dy in ageSystemCtx"); }
00340 if (dtAge <= 0.0) { SETERRQ(4,"un-initialized dtAge in ageSystemCtx"); }
00341 if (dzEQ <= 0.0) { SETERRQ(5,"un-initialized dzEQ in ageSystemCtx"); }
00342 if (u == NULL) { SETERRQ(6,"un-initialized pointer u in ageSystemCtx"); }
00343 if (v == NULL) { SETERRQ(7,"un-initialized pointer v in ageSystemCtx"); }
00344 if (w == NULL) { SETERRQ(8,"un-initialized pointer w in ageSystemCtx"); }
00345 if (tau3 == NULL) { SETERRQ(9,"un-initialized pointer tau3 in ageSystemCtx"); }
00346 nuEQ = dtAge / dzEQ;
00347 initAllDone = true;
00348 return 0;
00349 }
00350
00351
00352 PetscErrorCode ageSystemCtx::solveThisColumn(PetscScalar **x) {
00353 PetscErrorCode ierr;
00354 if (!initAllDone) { SETERRQ(2,
00355 "solveThisColumn() should only be called after initAllColumns() in ageSystemCtx"); }
00356
00357
00358 for (PetscInt k = 0; k < ks; k++) {
00359 planeStar ss;
00360 ierr = tau3->getPlaneStar_fine(i,j,k,&ss); CHKERRQ(ierr);
00361
00362 rhs[k] = (u[k] < 0) ? u[k] * (ss.ip1 - ss.ij) / dx
00363 : u[k] * (ss.ij - ss.im1) / dx;
00364 rhs[k] += (v[k] < 0) ? v[k] * (ss.jp1 - ss.ij) / dy
00365 : v[k] * (ss.ij - ss.jm1) / dy;
00366
00367
00368 rhs[k] = ss.ij + dtAge * (1.0 - rhs[k]);
00369
00370
00371 PetscScalar AA = nuEQ * w[k];
00372 if (k > 0) {
00373 if (AA >= 0) {
00374 L[k] = - AA;
00375 D[k] = 1.0 + AA;
00376 U[k] = 0.0;
00377 } else {
00378 L[k] = 0.0;
00379 D[k] = 1.0 - AA;
00380 U[k] = + AA;
00381 }
00382 } else {
00383
00384 if (AA > 0) {
00385
00386 D[0] = 1.0;
00387 U[0] = 0.0;
00388 rhs[0] = 0.0;
00389 } else {
00390 D[0] = 1.0 - AA;
00391 U[0] = + AA;
00392
00393 }
00394 }
00395 }
00396
00397
00398 if (ks>0) {
00399 L[ks] = 0;
00400 D[ks] = 1.0;
00401 rhs[ks] = 0.0;
00402 }
00403
00404
00405 return solveTridiagonalSystem(ks+1,x);
00406 }
00407
00408
00409 tempSystemCtx::tempSystemCtx(PetscInt my_Mz, PetscInt my_Mbz)
00410 : columnSystemCtx(my_Mz + my_Mbz - 1) {
00411 Mz = my_Mz;
00412 Mbz = my_Mbz;
00413 k0 = Mbz - 1;
00414
00415 initAllDone = false;
00416 schemeParamsValid = false;
00417 surfBCsValid = false;
00418 basalBCsValid = false;
00419
00420 dx = -1;
00421 dy = -1;
00422 dtTemp = -1;
00423 dzEQ = -1;
00424 dzbEQ = -1;
00425 ice_rho = -1;
00426 ice_c_p = -1;
00427 ice_k = -1;
00428 bed_thermal_rho = -1;
00429 bed_thermal_c_p = -1;
00430 bed_thermal_k = -1;
00431 T = NULL;
00432 Tb = NULL;
00433 u = NULL;
00434 v = NULL;
00435 w = NULL;
00436 Sigma = NULL;
00437 T3 = NULL;
00438 }
00439
00440
00441 PetscErrorCode tempSystemCtx::initAllColumns() {
00442
00443 if (dx <= 0.0) { SETERRQ(2,"un-initialized dx in tempSystemCtx"); }
00444 if (dy <= 0.0) { SETERRQ(3,"un-initialized dy in tempSystemCtx"); }
00445 if (dtTemp <= 0.0) { SETERRQ(4,"un-initialized dtTemp in tempSystemCtx"); }
00446 if (dzEQ <= 0.0) { SETERRQ(5,"un-initialized dzEQ in tempSystemCtx"); }
00447 if (dzbEQ <= 0.0) { SETERRQ(6,"un-initialized dzbEQ in tempSystemCtx"); }
00448 if (ice_rho <= 0.0) { SETERRQ(7,"un-initialized ice_rho in tempSystemCtx"); }
00449 if (ice_c_p <= 0.0) { SETERRQ(8,"un-initialized ice_c_p in tempSystemCtx"); }
00450 if (ice_k <= 0.0) { SETERRQ(9,"un-initialized ice_k in tempSystemCtx"); }
00451 if (bed_thermal_rho <= 0.0) { SETERRQ(10,"un-initialized bed_thermal_rho in tempSystemCtx"); }
00452 if (bed_thermal_c_p <= 0.0) { SETERRQ(11,"un-initialized bed_thermal_c_p in tempSystemCtx"); }
00453 if (bed_thermal_k <= 0.0) { SETERRQ(12,"un-initialized bed_thermal_k in tempSystemCtx"); }
00454 if (T == NULL) { SETERRQ(13,"un-initialized pointer T in tempSystemCtx"); }
00455 if (Tb == NULL) { SETERRQ(14,"un-initialized pointer Tb in tempSystemCtx"); }
00456 if (u == NULL) { SETERRQ(15,"un-initialized pointer u in tempSystemCtx"); }
00457 if (v == NULL) { SETERRQ(16,"un-initialized pointer v in tempSystemCtx"); }
00458 if (w == NULL) { SETERRQ(17,"un-initialized pointer w in tempSystemCtx"); }
00459 if (Sigma == NULL) { SETERRQ(18,"un-initialized pointer Sigma in tempSystemCtx"); }
00460 if (T3 == NULL) { SETERRQ(19,"un-initialized pointer T3 in tempSystemCtx"); }
00461
00462 nuEQ = dtTemp / dzEQ;
00463 rho_c_I = ice_rho * ice_c_p;
00464 rho_c_br = bed_thermal_rho * bed_thermal_c_p;
00465 rho_c_av = (dzEQ * rho_c_I + dzbEQ * rho_c_br) / (dzEQ + dzbEQ);
00466 iceK = ice_k / rho_c_I;
00467 iceR = iceK * dtTemp / PetscSqr(dzEQ);
00468 brK = bed_thermal_k / rho_c_br;
00469 brR = brK * dtTemp / PetscSqr(dzbEQ);
00470 rho_c_ratio = rho_c_I / rho_c_av;
00471 dzav = 0.5 * (dzEQ + dzbEQ);
00472 iceReff = ice_k * dtTemp / (rho_c_av * dzEQ * dzEQ);
00473 brReff = bed_thermal_k * dtTemp / (rho_c_av * dzbEQ * dzbEQ);
00474
00475 initAllDone = true;
00476 return 0;
00477 }
00478
00479
00480 PetscErrorCode tempSystemCtx::setSchemeParamsThisColumn(
00481 PismMask my_mask, bool my_isMarginal, PetscScalar my_lambda) {
00482 if (!initAllDone) { SETERRQ(2,
00483 "setSchemeParamsThisColumn() should only be called after initAllColumns() in tempSystemCtx"); }
00484 if (schemeParamsValid) { SETERRQ(3,
00485 "setSchemeParamsThisColumn() called twice (?) in tempSystemCtx"); }
00486 mask = my_mask;
00487 isMarginal = my_isMarginal;
00488 lambda = my_lambda;
00489 schemeParamsValid = true;
00490 return 0;
00491 }
00492
00493
00494 PetscErrorCode tempSystemCtx::setSurfaceBoundaryValuesThisColumn(PetscScalar my_Ts) {
00495 if (!initAllDone) { SETERRQ(2,
00496 "setSurfaceBoundaryValuesThisColumn() should only be called after initAllColumns() in tempSystemCtx"); }
00497 if (surfBCsValid) { SETERRQ(3,
00498 "setSurfaceBoundaryValuesThisColumn() called twice (?) in tempSystemCtx"); }
00499 Ts = my_Ts;
00500 surfBCsValid = true;
00501 return 0;
00502 }
00503
00504
00505 PetscErrorCode tempSystemCtx::setBasalBoundaryValuesThisColumn(
00506 PetscScalar my_Ghf, PetscScalar my_Tshelfbase, PetscScalar my_Rb) {
00507 if (!initAllDone) { SETERRQ(2,
00508 "setIndicesThisColumn() should only be called after initAllColumns() in tempSystemCtx"); }
00509 if (basalBCsValid) { SETERRQ(3,
00510 "setBasalBoundaryValuesThisColumn() called twice (?) in tempSystemCtx"); }
00511 Ghf = my_Ghf;
00512 Tshelfbase = my_Tshelfbase;
00513 Rb = my_Rb;
00514 basalBCsValid = true;
00515 return 0;
00516 }
00517
00518
00519 PetscErrorCode tempSystemCtx::solveThisColumn(PetscScalar **x) {
00520 PetscErrorCode ierr;
00521 if (!initAllDone) { SETERRQ(2,
00522 "solveThisColumn() should only be called after initAllColumns() in tempSystemCtx"); }
00523 if (!schemeParamsValid) { SETERRQ(3,
00524 "solveThisColumn() should only be called after setSchemeParamsThisColumn() in tempSystemCtx"); }
00525 if (!surfBCsValid) { SETERRQ(3,
00526 "solveThisColumn() should only be called after setSurfaceBoundaryValuesThisColumn() in tempSystemCtx"); }
00527 if (!basalBCsValid) { SETERRQ(3,
00528 "solveThisColumn() should only be called after setBasalBoundaryValuesThisColumn() in tempSystemCtx"); }
00529
00530 if (Mbz > 1) {
00531
00532
00533 D[0] = (1.0 + 2.0 * brR);
00534 U[0] = - 2.0 * brR;
00535 rhs[0] = Tb[0] + 2.0 * dtTemp * Ghf / (rho_c_br * dzbEQ);
00536
00537
00538 for (PetscInt k=1; k < k0; k++) {
00539 L[k] = -brR;
00540 D[k] = 1.0 + 2.0 * brR;
00541 U[k] = -brR;
00542 rhs[k] = Tb[k];
00543 }
00544 }
00545
00546
00547 if (ks == 0) {
00548 if (k0 > 0) { L[k0] = 0.0; }
00549 D[k0] = 1.0;
00550 U[k0] = 0.0;
00551
00552 if (mask >= MASK_FLOATING) {
00553
00554 rhs[k0] = Tshelfbase;
00555
00556 } else {
00557 rhs[k0] = Ts;
00558 }
00559 } else {
00560
00561 if (mask >= MASK_FLOATING) {
00562
00563 if (k0 > 0) { L[k0] = 0.0; }
00564 D[k0] = 1.0;
00565 U[k0] = 0.0;
00566 rhs[k0] = Tshelfbase;
00567 } else {
00568
00569 rhs[k0] = T[0] + dtTemp * (Rb / (rho_c_av * dzav));
00570 if (!isMarginal) {
00571 rhs[k0] += dtTemp * rho_c_ratio * 0.5 * (Sigma[0] / rho_c_I);
00572
00573 planeStar ss;
00574 ierr = T3->getPlaneStar(i,j,0,&ss);
00575 const PetscScalar UpTu = (u[0] < 0) ? u[0] * (ss.ip1 - ss.ij) / dx :
00576 u[0] * (ss.ij - ss.im1) / dx;
00577 const PetscScalar UpTv = (v[0] < 0) ? v[0] * (ss.jp1 - ss.ij) / dy :
00578 v[0] * (ss.ij - ss.jm1) / dy;
00579 rhs[k0] -= dtTemp * rho_c_ratio * (0.5 * (UpTu + UpTv));
00580 }
00581 const PetscScalar AA = dtTemp * rho_c_ratio * w[0] / (2.0 * dzEQ);
00582 if (Mbz > 1) {
00583
00584
00585 L[k0] = - brReff;
00586 if (w[0] >= 0.0) {
00587 D[k0] = 1.0 + iceReff + brReff;
00588 U[k0] = - iceReff;
00589 } else {
00590 D[k0] = 1.0 + iceReff + brReff - AA;
00591 U[k0] = - iceReff + AA;
00592 }
00593 } else {
00594
00595 if (w[0] >= 0.0) {
00596 D[k0] = 1.0 + 2.0 * iceR;
00597 U[k0] = - 2.0 * iceR;
00598 } else {
00599 D[k0] = 1.0 + 2.0 * iceR - AA;
00600 U[k0] = - 2.0 * iceR + AA;
00601 }
00602 rhs[k0] += 2.0 * dtTemp * Ghf / (rho_c_I * dzEQ);
00603 }
00604 }
00605 }
00606
00607
00608 for (PetscInt k = 1; k < ks; k++) {
00609 planeStar ss;
00610 ierr = T3->getPlaneStar_fine(i,j,k,&ss);
00611 const PetscScalar UpTu = (u[k] < 0) ? u[k] * (ss.ip1 - ss.ij) / dx :
00612 u[k] * (ss.ij - ss.im1) / dx;
00613 const PetscScalar UpTv = (v[k] < 0) ? v[k] * (ss.jp1 - ss.ij) / dy :
00614 v[k] * (ss.ij - ss.jm1) / dy;
00615 const PetscScalar AA = nuEQ * w[k];
00616 if (w[k] >= 0.0) {
00617 L[k0+k] = - iceR - AA * (1.0 - lambda/2.0);
00618 D[k0+k] = 1.0 + 2.0 * iceR + AA * (1.0 - lambda);
00619 U[k0+k] = - iceR + AA * (lambda/2.0);
00620 } else {
00621 L[k0+k] = - iceR - AA * (lambda/2.0);
00622 D[k0+k] = 1.0 + 2.0 * iceR - AA * (1.0 - lambda);
00623 U[k0+k] = - iceR + AA * (1.0 - lambda/2.0);
00624 }
00625 rhs[k0+k] = T[k];
00626 if (!isMarginal) {
00627 rhs[k0+k] += dtTemp * (Sigma[k] / rho_c_I - UpTu - UpTv);
00628 }
00629 }
00630
00631
00632 if (ks>0) {
00633 L[k0+ks] = 0.0;
00634 D[k0+ks] = 1.0;
00635
00636 rhs[k0+ks] = Ts;
00637 }
00638
00639
00640 schemeParamsValid = false;
00641 surfBCsValid = false;
00642 basalBCsValid = false;
00643
00644
00645 return solveTridiagonalSystem(k0+ks+1,x);
00646 }
00647