PISM, A Parallel Ice Sheet Model stable 0.4.1779

src/verif/tests/exactTestsFG.c

Go to the documentation of this file.
00001 /*
00002    Copyright (C) 2004-2008 Ed Bueler and Jed Brown
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 <stdlib.h>
00023 #include <math.h>
00024 #include "exactTestsFG.h"
00025 
00026 static double p3(double x) {
00027   /* p_3=x^3-3*x^2+6*x-6, using Horner's */
00028   return -6.0 + x*(6.0 + x*(-3.0 + x));
00029 }
00030 
00031 static double p4(double x) {
00032   /* p_4=x^4-4*x^3+12*x^2-24*x+24, using Horner's */
00033   return 24.0 + x*(-24.0 + x*(12.0 + x*(-4.0 + x)));
00034 }
00035 
00036 int bothexact(double t, double r, double *z, int Mz, double Cp,
00037               double *Hreturn, double *M, double *TT,
00038               double *Ureturn, double *wreturn, 
00039               double *Sigreturn, double *Sigc) {
00040 
00041   const double pi = 3.14159265358979;
00042   const double SperA = 31556926.0;  /* seconds per year; 365.2422 days */
00043 
00044   /* parameters describing extent of sheet: */
00045   const double H0=3000.0;    /* m */
00046   const double L=750000.0;   /* m */
00047   /* period of perturbation; inactive in Test F: */
00048   const double Tp=2000.0*SperA;  /* s */
00049 
00050   /* fundamental physical constants */
00051   const double g=9.81;       /* m/s^2; accel of gravity */
00052   const double Rgas=8.314;   /* J/(mol K) */
00053   /* ice properties; parameters which appear in constitutive relation: */
00054   const double rho=910.0;    /* kg/m^3; density */
00055   const double k=2.1;        /* J/m K s; thermal conductivity */
00056   const double cpheat=2009.0;/* J/kg K; specific heat capacity */
00057   const double n=3.0;        /* Glen exponent */
00058   /* next two are EISMINT II values; Paterson-Budd for T<263 */
00059   const double A=3.615E-13;  /* Pa^-3 s^-1 */
00060   const double Q=6.0E4;      /* J/mol */
00061   /* EISMINT II temperature boundary condition (Experiment F): */
00062   const double Ggeo=0.042;   /* J/m^2 s; geo. heat flux */
00063   const double ST=1.67E-5;   /* K m^-1 */
00064   const double Tmin=223.15;  /* K */
00065   const double Kcond=k/(rho*cpheat);  /* constant in temp eqn */
00066 
00067   /* declare all temporary quantities; computed in blocks below */
00068   double power, Hconst, s, lamhat, f, goft, Ts, nusqrt, nu;
00069   double lamhatr, fr, Hr, mu, surfArr, Uconst, omega;
00070   double Sigmu, lamhatrr, frr, Hrr, Tsr, nur, mur, phi, gam;
00071   double I4H, divQ, Ht, nut;
00072   double I4,dTt,Tr,Tz,Tzz;
00073   double H, *U, *w, *Sig; /* compute with these; return copies */
00074   int i;
00075   double *I3;
00076 
00077   I3 = (double *) malloc((size_t)Mz * sizeof(double)); /* need temporary arrays */
00078   U = (double *) malloc((size_t)Mz * sizeof(double));
00079   w = (double *) malloc((size_t)Mz * sizeof(double));
00080   Sig = (double *) malloc((size_t)Mz * sizeof(double));
00081   if ((I3 == NULL) || (U == NULL) || (w == NULL) || (Sig == NULL)) { 
00082     fprintf(stderr, "\nERROR bothexact(): couldn't allocate memory!\n\n");
00083     return -9999;
00084   }
00085   
00086   if ( (r<=0) || (r>=L) ) {
00087     fprintf(stderr, "\nERROR bothexact(): code and derivation assume 0<r<L  !\n\n");
00088     return 1;
00089   }
00090 
00091   /* compute H from analytical steady state Hs (Test D) plus perturbation */
00092   power = n/(2*n+2);
00093   Hconst = H0/pow(1-1/n,power);
00094   s = r/L;
00095   lamhat = (1+1/n)*s - (1/n) + pow(1-s,1+1/n) - pow(s,1+1/n);
00096   if ((r>0.3*L) && (r<0.9*L))
00097     f = pow( cos(pi*(r-0.6*L)/(0.6*L)) ,2.0);
00098   else
00099     f = 0.0;
00100   goft = Cp*sin(2.0*pi*t/Tp);
00101   H = Hconst*pow(lamhat,power) + goft*f;
00102 
00103   /* compute TT = temperature */
00104   Ts = Tmin+ST*r;
00105   nusqrt = sqrt( 1 + (4.0*H*Ggeo)/(k*Ts) );
00106   nu = ( k*Ts/(2.0*Ggeo) )*( 1 + nusqrt );
00107   for (i=0; i<Mz; i++) {
00108     if (z[i] < H) {
00109       TT[i] = Ts * (nu+H) / (nu+z[i]);
00110     } else { /* surface value above ice surface; matches numerical way */
00111       TT[i] = Ts;
00112     }
00113     /* old way: extend formula above surface: TT[i] = Ts * (nu+H) / (nu+z[i]); */
00114   }
00115 
00116   /* compute surface slope and horizontal velocity */
00117   lamhatr = ((1+1/n)/L)*( 1 - pow(1-s,1/n) - pow(s,1/n) );
00118   if ( (r>0.3*L) && (r<0.9*L) )
00119     fr = -(pi/(0.6*L)) * sin(2.0*pi*(r-0.6*L)/(0.6*L));
00120   else
00121     fr = 0.0;
00122   Hr = Hconst * power * pow(lamhat,power-1) * lamhatr + goft*fr;   /* chain rule */
00123   if ( Hr>0 ) {
00124     fprintf(stderr, "\nERROR bothexact(): assumes H_r negative for all 0<r<L !\n\n");
00125     return 2;
00126   }
00127   mu = Q/(Rgas*Ts*(nu+H));
00128   surfArr = exp(-Q/(Rgas*Ts));
00129   Uconst = 2.0 * pow(rho*g,n) * A;
00130   omega = Uconst * pow(-Hr,n) * surfArr * pow(mu,-n-1);
00131   for (i=0; i<Mz; i++) {
00132     if (z[i] < H) {
00133       I3[i] = p3(mu*H) * exp(mu*H) - p3(mu*(H-z[i])) * exp(mu*(H-z[i]));
00134       U[i] = omega * I3[i];
00135     } else { /* surface value above ice surface; matches numerical way */
00136       I3[i] = p3(mu*H) * exp(mu*H) - p3(0.0);  /* z[i] = H case in above */
00137       U[i] = omega * I3[i];
00138     }
00139   }
00140 
00141   /* compute strain heating */
00142   for (i=0; i<Mz; i++) {
00143     if (z[i] < H) {
00144       Sigmu = -(Q*(nu+z[i])) / (Rgas*Ts*(nu+H));
00145       Sig[i] = (Uconst*g/cpheat) * exp(Sigmu) * pow( fabs(Hr)*( H -z[i]) ,n+1);
00146     } else {
00147       Sig[i] = 0.0;
00148     }
00149   }
00150 
00151   /* compute vertical velocity */
00152   lamhatrr = ((1+1/n) / (n*L*L)) * ( pow(1-s,(1/n)-1) - pow(s,(1/n)-1) );
00153   if ( (r>0.3*L) && (r<0.9*L) )
00154     frr = -(2.0*pi*pi/(0.36*L*L)) * cos(2.0*pi*(r-0.6*L)/(0.6*L));
00155   else
00156     frr = 0.0;
00157   Hrr = Hconst*power*(power-1)*pow(lamhat,power-2.0) * pow(lamhatr,2.0)  +
00158     Hconst*power*pow(lamhat,power-1)*lamhatrr + goft*frr;
00159   Tsr = ST;
00160   nur = (k*Tsr/(2.0*Ggeo)) * (1 + nusqrt) +
00161     (1/Ts) * (Hr*Ts-H*Tsr) / nusqrt;
00162   mur = ( -Q/(Rgas*Ts*Ts*pow(nu+H,2.0)) ) * ( Tsr*(nu+H)+Ts*(nur+Hr) );
00163   phi = 1/r + n*Hrr/Hr + Q*Tsr/(Rgas*Ts*Ts) - (n+1)*mur/mu;   /* division by r */
00164   gam = pow(mu,n) * exp(mu*H) * (mur*H+mu*Hr) * pow(H,n);
00165   for (i=0; i<Mz; i++) {
00166     I4 = p4(mu*H) * exp(mu*H) - p4(mu*(H-z[i])) * exp(mu*(H-z[i]));
00167     w[i] = omega * ((mur/mu - phi)*I4/mu + (phi*(H-z[i])+Hr)*I3[i] - gam*z[i]);
00168   }
00169 
00170   /* compute compensatory accumulation M */
00171   I4H = p4(mu*H) * exp(mu*H) - 24.0;
00172   divQ = - omega * (mur/mu - phi) * I4H / mu + omega * gam * H;
00173   Ht = (Cp*2.0*pi/Tp) * cos(2.0*pi*t/Tp) * f;
00174   *M = Ht + divQ;
00175 
00176   /* compute compensatory heating */
00177   nut = Ht/nusqrt;
00178   for (i=0; i<Mz; i++) {
00179     if (z[i] < H) {
00180       dTt = Ts * ((nut+Ht)*(nu+z[i])-(nu+H)*nut) * pow(nu+z[i],-2.0);
00181       Tr = Tsr*(nu+H)/(nu+z[i])
00182         + Ts * ((nur+Hr)*(nu+z[i])-(nu+H)*nur) * pow(nu+z[i],-2.0);
00183       Tz = -Ts * (nu+H) * pow(nu+z[i],-2.0);
00184       Tzz = 2.0 * Ts * (nu+H) * pow(nu+z[i],-3.0);
00185       Sigc[i] = dTt + U[i]*Tr + w[i]*Tz - Kcond*Tzz - Sig[i];
00186     } else {
00187       Sigc[i] = 0.0;
00188     }
00189   }
00190 
00191   /* return duplicate copies to avoid conflicts */
00192   *Hreturn = H;
00193   for (i=0; i<Mz; i++) {
00194     Ureturn[i] = U[i];
00195     wreturn[i] = w[i];
00196     Sigreturn[i] = Sig[i];
00197   }
00198 
00199   free(I3); free(U); free(w); free(Sig);
00200   return 0;
00201 }
00202 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines