|
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 <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
1.7.5.1