PISM, A Parallel Ice Sheet Model  stable v0.5
src/base/energy/tempSystem.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 <petsc.h>
00020 #include "pism_const.hh"
00021 #include "iceModelVec.hh"
00022 #include "tempSystem.hh"
00023 #include "Mask.hh"
00024 
00025 tempSystemCtx::tempSystemCtx(PetscInt my_Mz, string my_prefix)
00026       : columnSystemCtx(my_Mz, my_prefix) {
00027   Mz = my_Mz;
00028   // set flags to indicate nothing yet set
00029   initAllDone = false;
00030   schemeParamsValid = false;
00031   surfBCsValid = false;
00032   basalBCsValid = false;
00033   // set values so we can check if init was called on all
00034   dx = -1;
00035   dy = -1;
00036   dtTemp = -1;
00037   dzEQ = -1;
00038   ice_rho = -1;
00039   ice_c_p = -1;
00040   ice_k = -1;
00041   T = NULL;
00042   u = NULL;
00043   v = NULL;
00044   w = NULL;
00045   Sigma = NULL;
00046   T3 = NULL;
00047 }
00048 
00049 
00050 PetscErrorCode tempSystemCtx::initAllColumns() {
00051   // check whether each parameter & pointer got set
00052   if (dx <= 0.0) { SETERRQ(PETSC_COMM_SELF, 2,"un-initialized dx in tempSystemCtx"); }
00053   if (dy <= 0.0) { SETERRQ(PETSC_COMM_SELF, 3,"un-initialized dy in tempSystemCtx"); }
00054   if (dtTemp <= 0.0) { SETERRQ(PETSC_COMM_SELF, 4,"un-initialized dtTemp in tempSystemCtx"); }
00055   if (dzEQ <= 0.0) { SETERRQ(PETSC_COMM_SELF, 5,"un-initialized dzEQ in tempSystemCtx"); }
00056   if (ice_rho <= 0.0) { SETERRQ(PETSC_COMM_SELF, 7,"un-initialized ice_rho in tempSystemCtx"); }
00057   if (ice_c_p <= 0.0) { SETERRQ(PETSC_COMM_SELF, 8,"un-initialized ice_c_p in tempSystemCtx"); }
00058   if (ice_k <= 0.0) { SETERRQ(PETSC_COMM_SELF, 9,"un-initialized ice_k in tempSystemCtx"); }
00059   if (T == NULL) { SETERRQ(PETSC_COMM_SELF, 13,"un-initialized pointer T in tempSystemCtx"); }
00060   if (u == NULL) { SETERRQ(PETSC_COMM_SELF, 15,"un-initialized pointer u in tempSystemCtx"); }
00061   if (v == NULL) { SETERRQ(PETSC_COMM_SELF, 16,"un-initialized pointer v in tempSystemCtx"); }
00062   if (w == NULL) { SETERRQ(PETSC_COMM_SELF, 17,"un-initialized pointer w in tempSystemCtx"); }
00063   if (Sigma == NULL) { SETERRQ(PETSC_COMM_SELF, 18,"un-initialized pointer Sigma in tempSystemCtx"); }
00064   if (T3 == NULL) { SETERRQ(PETSC_COMM_SELF, 19,"un-initialized pointer T3 in tempSystemCtx"); }
00065   // set derived constants
00066   nuEQ = dtTemp / dzEQ;
00067   rho_c_I = ice_rho * ice_c_p;
00068   iceK = ice_k / rho_c_I;
00069   iceR = iceK * dtTemp / PetscSqr(dzEQ);
00070   // done
00071   initAllDone = true;
00072   return 0;
00073 }
00074 
00075 
00076 PetscErrorCode tempSystemCtx::setSchemeParamsThisColumn(
00077                      PismMask my_mask, bool my_isMarginal, PetscScalar my_lambda) {
00078   if (!initAllDone) {  SETERRQ(PETSC_COMM_SELF, 2,
00079      "setSchemeParamsThisColumn() should only be called after initAllColumns() in tempSystemCtx"); }
00080   if (schemeParamsValid) {  SETERRQ(PETSC_COMM_SELF, 3,
00081      "setSchemeParamsThisColumn() called twice (?) in tempSystemCtx"); }
00082   mask = my_mask;
00083   isMarginal = my_isMarginal;
00084   lambda = my_lambda;
00085   schemeParamsValid = true;
00086   return 0;
00087 }
00088 
00089 
00090 PetscErrorCode tempSystemCtx::setSurfaceBoundaryValuesThisColumn(PetscScalar my_Ts) {
00091   if (!initAllDone) {  SETERRQ(PETSC_COMM_SELF, 2,
00092      "setSurfaceBoundaryValuesThisColumn() should only be called after initAllColumns() in tempSystemCtx"); }
00093   if (surfBCsValid) {  SETERRQ(PETSC_COMM_SELF, 3,
00094      "setSurfaceBoundaryValuesThisColumn() called twice (?) in tempSystemCtx"); }
00095   Ts = my_Ts;
00096   surfBCsValid = true;
00097   return 0;
00098 }
00099 
00100 
00101 PetscErrorCode tempSystemCtx::setBasalBoundaryValuesThisColumn(
00102                      PetscScalar my_G0, PetscScalar my_Tshelfbase, PetscScalar my_Rb) {
00103   if (!initAllDone) {  SETERRQ(PETSC_COMM_SELF, 2,
00104      "setIndicesThisColumn() should only be called after initAllColumns() in tempSystemCtx"); }
00105   if (basalBCsValid) {  SETERRQ(PETSC_COMM_SELF, 3,
00106      "setBasalBoundaryValuesThisColumn() called twice (?) in tempSystemCtx"); }
00107   G0 = my_G0;
00108   Tshelfbase = my_Tshelfbase;
00109   Rb = my_Rb;
00110   basalBCsValid = true;
00111   return 0;
00112 }
00113 
00114 
00115 PetscErrorCode tempSystemCtx::solveThisColumn(PetscScalar **x, PetscErrorCode &pivoterrorindex) {
00116 
00117   if (!initAllDone) {  SETERRQ(PETSC_COMM_SELF, 2,
00118      "solveThisColumn() should only be called after initAllColumns() in tempSystemCtx"); }
00119   if (!schemeParamsValid) {  SETERRQ(PETSC_COMM_SELF, 3,
00120      "solveThisColumn() should only be called after setSchemeParamsThisColumn() in tempSystemCtx"); }
00121   if (!surfBCsValid) {  SETERRQ(PETSC_COMM_SELF, 3,
00122      "solveThisColumn() should only be called after setSurfaceBoundaryValuesThisColumn() in tempSystemCtx"); }
00123   if (!basalBCsValid) {  SETERRQ(PETSC_COMM_SELF, 3,
00124      "solveThisColumn() should only be called after setBasalBoundaryValuesThisColumn() in tempSystemCtx"); }
00125 
00126   Mask M;
00127 
00128   // bottom of ice; k=0 eqn
00129   if (ks == 0) { // no ice; set T[0] to surface temp if grounded
00130     // note L[0] not allocated 
00131     D[0] = 1.0;
00132     U[0] = 0.0;
00133     // if floating and no ice then worry only about bedrock temps
00134     if (M.ocean(mask)) {
00135       // essentially no ice but floating ... ask PISMOceanCoupler
00136       rhs[0] = Tshelfbase;
00137     } else { // top of bedrock sees atmosphere
00138       rhs[0] = Ts; 
00139     }
00140   } else { // ks > 0; there is ice
00141     // for w, always difference *up* from base, but make it implicit
00142     if (M.ocean(mask)) {
00143       // just apply Dirichlet condition to base of column of ice in an ice shelf
00144       // note L[0] not allocated 
00145       D[0] = 1.0;
00146       U[0] = 0.0;
00147       rhs[0] = Tshelfbase; // set by PISMOceanCoupler
00148     } else { 
00149       // there is *grounded* ice; from FV across interface
00150       rhs[0] = T[0] + dtTemp * (Rb / (rho_c_I * dzEQ));
00151       if (!isMarginal) {
00152         rhs[0] += dtTemp * 0.5 * Sigma[0]/ rho_c_I;
00153         planeStar<PetscScalar> ss;
00154         T3->getPlaneStar(i,j,0,&ss);
00155         const PetscScalar UpTu = (u[0] < 0) ? u[0] * (ss.e -  ss.ij) / dx :
00156                                               u[0] * (ss.ij  - ss.w) / dx;
00157         const PetscScalar UpTv = (v[0] < 0) ? v[0] * (ss.n -  ss.ij) / dy :
00158                                               v[0] * (ss.ij  - ss.s) / dy;
00159         rhs[0] -= dtTemp  * (0.5 * (UpTu + UpTv));
00160       }
00161       // vertical upwinding
00162       // L[0] = 0.0;  (is not an allocated location!) 
00163       D[0] = 1.0 + 2.0 * iceR;
00164       U[0] = - 2.0 * iceR;
00165       if (w[0] < 0.0) { // velocity downward: add velocity contribution
00166         const PetscScalar AA = dtTemp * w[0] / (2.0 * dzEQ);
00167         D[0] -= AA;
00168         U[0] += AA;
00169       }
00170       // apply geothermal flux G0 here
00171       rhs[0] += 2.0 * dtTemp * G0 / (rho_c_I * dzEQ);
00172     }
00173   }
00174 
00175   // generic ice segment; build 1:ks-1 eqns
00176   for (PetscInt k = 1; k < ks; k++) {
00177     planeStar<PetscScalar> ss;
00178     T3->getPlaneStar_fine(i,j,k,&ss);
00179     const PetscScalar UpTu = (u[k] < 0) ? u[k] * (ss.e -  ss.ij) / dx :
00180                                           u[k] * (ss.ij  - ss.w) / dx;
00181     const PetscScalar UpTv = (v[k] < 0) ? v[k] * (ss.n -  ss.ij) / dy :
00182                                           v[k] * (ss.ij  - ss.s) / dy;
00183     const PetscScalar AA = nuEQ * w[k];      
00184     if (w[k] >= 0.0) {  // velocity upward
00185       L[k] = - iceR - AA * (1.0 - lambda/2.0);
00186       D[k] = 1.0 + 2.0 * iceR + AA * (1.0 - lambda);
00187       U[k] = - iceR + AA * (lambda/2.0);
00188     } else {  // velocity downward
00189       L[k] = - iceR - AA * (lambda/2.0);
00190       D[k] = 1.0 + 2.0 * iceR - AA * (1.0 - lambda);
00191       U[k] = - iceR + AA * (1.0 - lambda/2.0);
00192     }
00193     rhs[k] = T[k];
00194     if (!isMarginal) {
00195       rhs[k] += dtTemp * (Sigma[k] / rho_c_I - UpTu - UpTv);
00196     }
00197   }
00198       
00199   // surface b.c.
00200   if (ks>0) {
00201     L[ks] = 0.0;
00202     D[ks] = 1.0;
00203     // ignore U[ks]
00204     rhs[ks] = Ts;
00205   }
00206 
00207   // mark column as done
00208   schemeParamsValid = false;
00209   surfBCsValid = false;
00210   basalBCsValid = false;
00211 
00212   // solve it; note melting not addressed yet
00213   pivoterrorindex = solveTridiagonalSystem(ks+1,x);
00214   return 0;
00215 }
00216 
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines