PISM, A Parallel Ice Sheet Model stable 0.4.1779

src/verif/tests/exactTestK.c

Go to the documentation of this file.
00001 /*
00002    Copyright (C) 2007, 2011 Ed Bueler
00003   
00004    This file is part of PISM.
00005   
00006    PISM is free software; you can redistribute it and/or modify it under the
00007    terms of the GNU General Public License as published by the Free Software
00008    Foundation; either version 2 of the License, or (at your option) any later
00009    version.
00010   
00011    PISM is distributed in the hope that it will be useful, but WITHOUT ANY
00012    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00013    FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
00014    details.
00015   
00016    You should have received a copy of the GNU General Public License
00017    along with PISM; if not, write to the Free Software
00018    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00019 */
00020 
00021 #include <stdio.h>
00022 #include <math.h>
00023 #include <gsl/gsl_errno.h>
00024 #include <gsl/gsl_math.h>
00025 #include <gsl/gsl_roots.h>
00026 #include "exactTestK.h"
00027 
00028 #define pi             3.1415926535897931
00029 #define SperA          31556926.0   /* seconds per year; 365.2422 days */
00030 
00031 #define c_p_ICE        2009.0       /* J/(kg K)  specific heat capacity of ice */
00032 #define rho_ICE        910.0        /* kg/(m^3)  density of ice */
00033 #define k_ICE          2.10         /* J/(m K s) = W/(m K)  thermal conductivity of ice */
00034 #define c_p_BRdefault  1000.0       /* J/(kg K)  specific heat capacity of bedrock */
00035 #define rho_BRdefault  3300.0       /* kg/(m^3)  density of bedrock */
00036 #define k_BRdefault    3.0          /* J/(m K s) = W/(m K)  thermal conductivity of bedrock */
00037 
00038 #define H0             3000.0       /* m */
00039 #define B0             1000.0       /* m */
00040 #define Ts             223.15       /* K */
00041 #define G              0.042        /* W/(m^2) */
00042 #define phi            0.0125       /* K/m */
00043 
00044 #define Nsum           30           /* number of terms in eigenfunction expansion; the exact
00045                                        solution is deliberately chosen to have finite expansion */
00046 
00047 
00048 int exactK(const double t, const double z, double *TT, double *FF, const int bedrockIsIce_p) {
00049   int k;
00050   int belowB0;
00051   double ZZ, alpha, lambda, beta, my_gamma, XkSQR, Xk,
00052          theta, dthetakdz, P, dPdz,
00053          Ck, I1, I2, aH, bB, mI, mR;
00054   double c_p_BR, rho_BR, k_BR;
00055   /* following constants were produced by calling print_alpha_k(30) (below) */
00056   double alf[Nsum] = {3.350087528822397e-04, 1.114576827617396e-03, 1.953590840303518e-03,
00057                       2.684088585781064e-03, 3.371114869333445e-03, 4.189442265117592e-03,
00058                       5.008367405382524e-03, 5.696044031764593e-03, 6.425563506942886e-03,
00059                       7.264372872913219e-03, 8.044853066396166e-03, 8.714877612414516e-03,
00060                       9.493529164160654e-03, 1.033273985210279e-02, 1.106421822502108e-02,
00061                       1.175060460132703e-02, 1.256832682090360e-02, 1.338784224692084e-02,
00062                       1.407617951778051e-02, 1.480472324161026e-02, 1.564331999062109e-02,
00063                       1.642470780103220e-02, 1.709475346624607e-02, 1.787248418996684e-02,
00064                       1.871188358061674e-02, 1.944434477688470e-02, 2.013010181370026e-02,
00065                       2.094721145334310e-02, 2.176730968036079e-02, 2.245631776169424e-02};
00066 
00067   if (bedrockIsIce_p) {
00068     c_p_BR = c_p_ICE;
00069     rho_BR = rho_ICE;
00070     k_BR = k_ICE;
00071     for (k = 0; k < Nsum; k++) { /* overwrite alpha_k with ice-meets-ice values; see preprint */
00072       alf[k] = (2.0 * k + 1.0) * pi / (2.0 * (H0 + B0));
00073     }
00074   } else {
00075     c_p_BR = c_p_BRdefault;
00076     rho_BR = rho_BRdefault;
00077     k_BR = k_BRdefault;
00078   }
00079   if (z > H0) {
00080     *TT = Ts;
00081     return 0;
00082   }
00083   belowB0 = (z < -B0);
00084 
00085   ZZ = sqrt((rho_BR * c_p_BR * k_ICE) / (rho_ICE * c_p_ICE * k_BR));
00086   mI = (G / k_ICE) - phi;     mR = (G / k_BR) - phi;
00087   /* DEBUG: printf("ZZ = %10e, mI = %10e, mR = %10e\n", ZZ,mI,mR); */
00088   *TT = 0.0;
00089   *FF = 0.0;
00090   for (k = Nsum-1; k >= 0; k--) {
00091     /* constants only having to do with eigenfunctions; theta = theta_k(z) is the
00092        normalized eigenfunction */ 
00093     alpha = alf[k];
00094     beta = ZZ * alpha;
00095     my_gamma = sin(alpha * H0) / cos(beta * B0);
00096     XkSQR = (rho_BR * c_p_BR * my_gamma * my_gamma * B0 + rho_ICE * c_p_ICE * H0) / 2.0;
00097     Xk = sqrt(XkSQR);
00098     /* theta = ( (z > 0) ? sin(alpha * (H0 - z)) : my_gamma * cos(beta * (B0 + z)) ) / Xk; */
00099     theta = (z > 0) ? sin(alpha * (H0 - z))
00100                     : my_gamma * cos(beta * (B0 + z)); 
00101     theta /= Xk;
00102     dthetakdz = (z > 0) ? - alpha * cos(alpha * (H0 - z)) 
00103                         : - beta * my_gamma * sin(beta * (B0 + z));
00104     dthetakdz /= Xk;
00105     lambda = (k_ICE * alpha * alpha) / (rho_ICE * c_p_ICE);
00106     /* DEBUG: printf("k = %3d:  alpha = %10e, Xk = %10e, theta = %10e, dthetakdz = %10e, lambda = %10e,\n",
00107            k,alpha,Xk,theta,dthetakdz,lambda); */
00108     /* constants involved in computing the expansion coefficients */
00109     aH = alpha * H0;            bB = beta * B0;
00110     I1 = - mI * (sin(aH) - aH * cos(aH)) / (alpha * alpha);
00111     I2 = mR * (cos(bB) - 1.0 + bB * sin(bB)) / (beta * beta)
00112          - (B0 * mR + H0 * mI) * sin(bB) / beta;
00113     Ck = (rho_ICE * c_p_ICE * I1 + rho_BR * c_p_BR * my_gamma * I2) / Xk;
00114     /* add the term to the expansion */
00115     *TT += Ck * exp(- lambda * t) * theta;
00116     *FF += - ((z > 0) ? k_ICE : k_BR) * Ck * exp(- lambda * t) * dthetakdz;
00117     /* DEBUG: printf("          I1 = %10e, I2 = %10e, Ck = %10e, term = %10f\n",
00118            I1,I2,Ck, Ck * exp(- lambda * t) * theta ); */
00119   }
00120   /* P = (z >= 0) ? (z / k_ICE) - (H0 / k_ICE) : (z / k_BR) - (H0 / k_ICE); */
00121   P = (z / ((z > 0) ? k_ICE : k_BR)) - (H0 / k_ICE);
00122   dPdz = 1.0 / ((z > 0) ? k_ICE : k_BR);
00123   *TT += Ts - G * P;
00124   *FF += ((z > 0) ? k_ICE : k_BR) * G * dPdz;
00125 
00126   return belowB0;
00127 
00128 }
00129 
00130 
00131 #define COMPUTE_ALPHA 0
00132 #if COMPUTE_ALPHA
00133 
00134 #define ALPHA_RELTOL   1.0e-14
00135 #define ITER_MAXED_OUT 999
00136 
00137 /* parameters needed for root problem: */
00138 struct coscross_params {
00139   double Afrac, HZBsum, HZBdiff;
00140 };
00141 
00142 /* the root problem is to make this function zero: */
00143 double coscross(double alpha, void *params) {
00144   struct coscross_params *p = (struct coscross_params *) params;
00145   return cos(p->HZBsum * alpha) - p->Afrac * cos(p->HZBdiff * alpha);
00146 }
00147 
00148 /* compute the first N roots alpha_k of the equation
00149      ((A-1)/(A+1)) cos((H - Z B) alpha) = cos((H + Z B) alpha)
00150 where H and B are heights and A, Z are defined in terms of material 
00151 constants */
00152 int print_alpha_k(const int N) {
00153   int status, iter, k, max_iter = 200;
00154   double Z, A;
00155   double alpha, alpha_lo, alpha_hi, temp_lo;
00156   const gsl_root_fsolver_type *solvT;
00157   gsl_root_fsolver *solv;
00158   gsl_function F;
00159   struct coscross_params params;
00160   
00161   Z = sqrt((rho_BR * c_p_BR * k_ICE) / (rho_ICE * c_p_ICE * k_BR));
00162   A = (k_BR / k_ICE) * Z;
00163   params.Afrac   = (A - 1.0) / (A + 1.0);     
00164   params.HZBsum  = H0 + Z * B0;
00165   params.HZBdiff = H0 - Z * B0;
00166      
00167   F.function = &coscross;
00168   F.params = &params;
00169   solvT = gsl_root_fsolver_brent;  /* faster than bisection but still bracketing */
00170   solv = gsl_root_fsolver_alloc(solvT);
00171 
00172   for (k = 0; k < N; k++) {
00173     /* these numbers bracket exactly one solution */
00174     alpha_lo = (double(k) * pi) / params.HZBsum;
00175     alpha_hi = (double(k + 1) * pi) / params.HZBsum;
00176     gsl_root_fsolver_set(solv, &F, alpha_lo, alpha_hi);
00177      
00178     iter = 0;
00179     do {
00180       iter++;
00181       status = gsl_root_fsolver_iterate(solv);
00182       alpha = gsl_root_fsolver_root(solv);
00183       alpha_lo = gsl_root_fsolver_x_lower(solv);
00184       alpha_hi = gsl_root_fsolver_x_upper(solv);
00185       temp_lo = (alpha_lo > 0) ? alpha_lo : (alpha_hi/2.0);
00186       status = gsl_root_test_interval(temp_lo, alpha_hi, 0, ALPHA_RELTOL);
00187     } while ((status == GSL_CONTINUE) && (iter < max_iter));
00188     if (iter >= max_iter) {
00189       printf("!!!ERROR: root finding iteration reached maximum iterations; QUITING!\n");
00190       return ITER_MAXED_OUT;
00191     }
00192     printf("%19.15e,\n",alpha);
00193     /* DEBUG: printf("%19.15e  (in orig bracket [%19.15e,%19.15e])\n",alpha,
00194               (double(k) * pi) / params.HZBsum, (double(k+1) * pi) / params.HZBsum); */
00195   }
00196   
00197   gsl_root_fsolver_free(solv);
00198   return status;
00199 }
00200 #endif /* COMPUTE_ALPHA */
00201 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines