21 #include "pism/verification/tests/exactTestP.hh"
22 #include <gsl/gsl_errno.h>
26 #include <gsl/gsl_version.h>
27 #if (defined GSL_MAJOR_VERSION) && (defined GSL_MINOR_VERSION) && \
28 ((GSL_MAJOR_VERSION >= 1 && GSL_MINOR_VERSION >= 15) || (GSL_MAJOR_VERSION >= 2))
29 #define PISM_USE_ODEIV2 1
30 #include <gsl/gsl_odeiv2.h>
35 static const double SperA = 31556926.0;
36 static const double g = 9.81;
37 static const double rhoi = 910.0;
38 static const double rhow = 1000.0;
41 static const double Aglen = 3.1689e-24;
42 static const double k = (0.01 / (
rhow *
g));
43 static const double Wr = 1.0;
44 static const double c1 = 0.500;
45 static const double c2 = 0.040;
49 static const double h0 = 500.0;
51 static const double R1 = 5000.0;
53 int getsb(
double r,
double *sb,
double *dsbdr) {
60 *sb = CC * pow(r -
R1, (5.0 / 3.0));
61 *dsbdr = (5.0 / 3.0) * CC * pow(r -
R1, (2.0 / 3.0));
74 double sbcube = sb * sb * sb;
75 double Pocube = Po * Po * Po;
77 return (sbcube / (sbcube + Pocube)) *
Wr;
81 int funcP(
double r,
const double W[],
double f[],
void *params) {
90 double sb, dsb, dPo, tmp1, omega0, numer, denom;
105 omega0 =
m0 / (2.0 *
rhow *
k);
107 tmp1 = pow(W[0], 4.0 / 3.0) * pow(
Wr - W[0], 2.0 / 3.0);
108 numer = dsb * W[0] * (
Wr - W[0]);
109 numer = numer - (omega0 * r / W[0] + dPo) * tmp1;
110 denom = (1.0 / 3.0) * sb *
Wr +
rhow *
g * tmp1;
111 f[0] = numer / denom;
122 return (pow(sbL, 3.0) / (pow(sbL, 3.0) + pow(PoL, 3.0))) *
Wr;
126 double psteady(
double W,
double magvb,
double Po) {
127 double sbcube, frac, P;
128 sbcube =
c1 * fabs(magvb) / (
c2 *
Aglen);
129 frac = (W <
Wr) ? (
Wr - W) / W : 0.0;
130 P = Po - pow(sbcube * frac, 1.0 / 3.0);
137 #ifdef PISM_USE_ODEIV2
145 int getW(
const double *r,
int N,
double *W,
double EPS_ABS,
double EPS_REL,
int ode_method) {
149 const gsl_odeiv2_step_type *Tpossible[4];
150 const gsl_odeiv2_step_type *T;
151 gsl_odeiv2_system sys = {
funcP, NULL, 1, NULL };
152 gsl_odeiv2_driver *d;
155 Tpossible[0] = gsl_odeiv2_step_rk8pd;
156 Tpossible[1] = gsl_odeiv2_step_rk2;
157 Tpossible[2] = gsl_odeiv2_step_rkf45;
158 Tpossible[3] = gsl_odeiv2_step_rkck;
159 if ((ode_method > 0) && (ode_method < 5)) {
160 T = Tpossible[ode_method - 1];
166 d = gsl_odeiv2_driver_alloc_y_new(&sys, T, hstart, EPS_ABS, EPS_REL);
173 while (rr > r[
count]) {
174 status = gsl_odeiv2_driver_apply(d, &rr, r[
count], &(W[
count]));
175 if (status != GSL_SUCCESS) {
187 gsl_odeiv2_driver_free(d);
192 int getW(
const double *r,
int N,
double *W,
193 double EPS_ABS,
double EPS_REL,
int ode_method) {
199 for (
int j = 0; j < N; ++j) {
206 int exactP_list(
const double *r,
int N,
double *h,
double *magvb,
double *Wcrit,
double *W,
double *P,
207 double EPS_ABS,
double EPS_REL,
int ode_method) {
215 for (i = 0; i < N; i++) {
216 if ((i > 0) && (r[i] > r[i - 1])) {
234 for (i = M; i < N; i++) {
246 status =
getW(&(r[M]), N - M, &(W[M]), EPS_ABS, EPS_REL, ode_method);
249 for (i = M; i < N; i++) {
254 for (i = M; i < N; i++) {
261 double EPS_ABS,
double EPS_REL,
int ode_method) {
267 (result.
magvb).data(),
268 (result.
Wcrit).data(),
271 EPS_ABS, EPS_REL, ode_method);
287 result.
error_message =
"error: invalid choice for ODE method";
293 result.
error_message =
"error: no list of r values at input to exactP_list()";
296 result.
error_message =
"error: input list of r values to exactP_list() is not decreasing";
#define TESTP_LIST_NOT_DECREASING
#define TESTP_INVALID_METHOD
#define TESTP_W_EXCEEDS_WR
#define TESTP_W_BELOW_WCRIT
int getsb(double r, double *sb, double *dsbdr)
double initialconditionW()
int funcP(double r, const double W[], double f[], void *params)
static const double SperA
double criticalW(double r)
static const double Aglen
TestPParameters exactP(const std::vector< double > &r, double EPS_ABS, double EPS_REL, int ode_method)
int exactP_list(const double *r, int N, double *h, double *magvb, double *Wcrit, double *W, double *P, double EPS_ABS, double EPS_REL, int ode_method)
int getW(const double *r, int N, double *W, double EPS_ABS, double EPS_REL, int ode_method)
double psteady(double W, double magvb, double Po)
std::vector< double > Wcrit
std::vector< double > magvb
std::string error_message