Loading [MathJax]/extensions/tex2jax.js
PISM, A Parallel Ice Sheet Model 2.2.2-d6b3a29ca committed by Constantine Khrulev on 2025-03-28
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
exactTestL.cc
Go to the documentation of this file.
1/* Copyright (C) 2016, 2017, 2022, 2023 PISM Authors
2 *
3 * This file is part of PISM.
4 *
5 * PISM is free software; you can redistribute it and/or modify it under the
6 * terms of the GNU General Public License as published by the Free Software
7 * Foundation; either version 3 of the License, or (at your option) any later
8 * version.
9 *
10 * PISM is distributed in the hope that it will be useful, but WITHOUT ANY
11 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 * details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with PISM; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include "pism/verification/tests/exactTestL.hh"
21
22#include <cstdlib>
23#include <cmath>
24#include <gsl/gsl_errno.h>
25#include <gsl/gsl_matrix.h>
26#include <gsl/gsl_math.h> /* M_PI */
27
28#include <gsl/gsl_version.h>
29#if (defined GSL_MAJOR_VERSION) && (defined GSL_MINOR_VERSION) && \
30 ((GSL_MAJOR_VERSION >= 1 && GSL_MINOR_VERSION >= 15) || (GSL_MAJOR_VERSION >= 2))
31#define PISM_USE_ODEIV2 1
32#include <gsl/gsl_odeiv2.h>
33#endif
34
35#include "pism/util/error_handling.hh"
37
38static const double SperA = 31556926.0; /* seconds per year; 365.2422 days */
39
40static const double L = 750.0e3; /* m; i.e. 750 km */
41static const double b0 = 500.0; /* m */
42static const double z0 = 1.2;
43static const double g = 9.81;
44static const double rho = 910.0;
45static const double n = 3.0; /* Glen power */
46
47int funcL(double r, const double u[], double f[], void *params) {
48 /*
49 RHS for differential equation:
50 du 5/8 / a_0 r (L^2 - r^2) \ 1/3
51 -- = - (8/3) b'(r) u - |---------------------|
52 dr \ 2 L^2 \tilde\Gamma /
53 */
54
55 const double Lsqr = L * L;
56 const double a0 = 0.3 / SperA; /* m/s; i.e. 0.3 m/a */
57 const double A = 1.0e-16 / SperA; /* = 3.17e-24 1/(Pa^3 s); EISMINT I flow law */
58 const double Gamma = 2 * pow(rho * g,n) * A / (n+2);
59 const double tilGamma = Gamma * pow(n,n) / (pow(2.0 * n + 2.0, n));
60 const double C = a0 / (2.0 * Lsqr * tilGamma);
61
62 if (params == NULL) {} /* quash warning "unused parameters" */
63
64 if ((r >= 0.0) && (r <= L)) {
65 const double freq = z0 * M_PI / L;
66 const double bprime = b0 * freq * sin(freq * r);
67 f[0] = - (8.0/3.0) * bprime * pow(u[0], 5.0/8.0)
68 - pow(C * r * (Lsqr - r * r), 1.0/3.0);
69 } else {
70 f[0] = 0.0; /* no changes outside of defined interval */
71 }
72 return GSL_SUCCESS;
73}
74
75/* exit status could be one of these; returned zero indicates success */
76#define TESTL_NOT_DONE 8966
77#define TESTL_NOT_DECREASING 8967
78#define TESTL_INVALID_METHOD 8968
79#define TESTL_NO_LIST 8969
80
81#ifdef PISM_USE_ODEIV2
82
83/* combination EPS_ABS = 1e-12, EPS_REL=0.0, method = 1 = RK Cash-Karp
84 is believed to be predictable and accurate */
85int getU(const double *r, int N, double *u,
86 const double EPS_ABS, const double EPS_REL, const int ode_method) {
87 /* solves ODE for u(r)=H(r)^{8/3}, 0 <= r <= L, for test L
88 r and u must be allocated vectors of length N; r[] must be decreasing */
89 int k, count;
90 int status = TESTL_NOT_DONE;
91 double rr, hstart;
92 const gsl_odeiv2_step_type* Tpossible[4];
93 const gsl_odeiv2_step_type *T;
94 gsl_odeiv2_system sys = {funcL, NULL, 1, NULL}; /* Jac-free method and no params */
95 gsl_odeiv2_driver *d;
96
97 /* setup for GSL ODE solver; these choices don't need Jacobian */
98 Tpossible[0] = gsl_odeiv2_step_rk8pd;
99 Tpossible[1] = gsl_odeiv2_step_rk2;
100 Tpossible[2] = gsl_odeiv2_step_rkf45;
101 Tpossible[3] = gsl_odeiv2_step_rkck;
102 if ((ode_method > 0) && (ode_method < 5))
103 T = Tpossible[ode_method-1];
104 else {
106 }
107
108 /* check first: we have a list, and r is decreasing */
109 if (N < 1) return TESTL_NO_LIST;
110 for (k = 1; k<N; k++) { if (r[k] > r[k-1]) return TESTL_NOT_DECREASING; }
111
112 /* outside of ice cap, u = 0 */
113 k = 0;
114 while (r[k] >= L) {
115 u[k] = 0.0;
116 k++;
117 if (k == N) return GSL_SUCCESS;
118 }
119
120 /* initialize GSL ODE solver */
121 hstart = -10000.0;
122 d = gsl_odeiv2_driver_alloc_y_new(&sys, T, hstart, EPS_ABS, EPS_REL);
123
124 /* initial conditions: (r,u) = (L,0); r decreases from L */
125 rr = L;
126 for (count = k; count < N; count++) {
127 /* except at start, use value at end of last interval as initial guess */
128 u[count] = (count == 0) ? 0.0 : u[count-1];
129 while (rr > r[count]) {
130 status = gsl_odeiv2_driver_apply(d, &rr, r[count], &(u[count]));
131 if (status != GSL_SUCCESS){
132 break;
133 }
134 }
135 }
136
137 gsl_odeiv2_driver_free(d);
138 return status;
139}
140
141#else /* old GSL (< 1.15) */
142int getU(const double *r, int N, double *u,
143 const double EPS_ABS, const double EPS_REL, const int ode_method) {
144 (void) r;
145 (void) N;
146 (void) u;
147 (void) EPS_ABS;
148 (void) EPS_REL;
149 (void) ode_method;
150 throw RuntimeError(PISM_ERROR_LOCATION, "Test L requires GSL version 1.15 or later.");
151 return 0;
152}
153#endif
154
155int exactL_list(const double *r, int N, double *H, double *b, double *a) {
156 /* N values r[0] > r[1] > ... > r[N-1] (decreasing)
157 assumes r, H, b, a are allocated length N arrays */
158
159 const double Lsqr = L * L;
160 const double a0 = 0.3 / SperA; /* m/s; i.e. 0.3 m/a */
161 int stat, i;
162
163 std::vector<double> u(N);
164
165 /* combination EPS_ABS = 1e-12, EPS_REL=0.0, method = 1 = RK Cash-Karp
166 believed to be predictable and accurate */
167 stat = getU(r,N,u.data(),1.0e-12,0.0,1);
168 if (stat != GSL_SUCCESS) {
169 return stat;
170 }
171
172 for (i = 0; i < N; i++) {
173 H[i] = pow(u[i],3.0/8.0);
174 b[i] = - b0 * cos(z0 * M_PI * r[i] / L);
175 a[i] = a0 * (1.0 - (2.0 * r[i] * r[i] / Lsqr));
176 }
177
178 return 0;
179}
180
182 : H(size), a(size), b(size) {
183}
184
185ExactLParameters exactL(const std::vector<double> &r) {
186 ExactLParameters result(r.size());
187
188 int error_code = exactL_list(&r[0], r.size(), &result.H[0], &result.b[0], &result.a[0]);
189
190 switch (error_code) {
191 case TESTL_NOT_DONE:
192 throw RuntimeError::formatted(PISM_ERROR_LOCATION, "Test L ERROR: exactL_list() returns 'NOT_DONE' (%d) ...",
193 error_code);
194 break;
196 throw RuntimeError::formatted(PISM_ERROR_LOCATION, "Test L ERROR: exactL_list() returns 'NOT_DECREASING' (%d) ...",
197 error_code);
198 break;
200 throw RuntimeError::formatted(PISM_ERROR_LOCATION, "Test L ERROR: exactL_list() returns 'INVALID_METHOD' (%d) ...",
201 error_code);
202 break;
203 case TESTL_NO_LIST:
204 throw RuntimeError::formatted(PISM_ERROR_LOCATION, "Test L ERROR: exactL_list() returns 'NO_LIST' (%d) ...",
205 error_code);
206 break;
207 default:
208 break;
209 }
210
211 return result;
212}
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
#define PISM_ERROR_LOCATION
static const double L
Definition exactTestL.cc:40
#define TESTL_NOT_DECREASING
Definition exactTestL.cc:77
int funcL(double r, const double u[], double f[], void *params)
Definition exactTestL.cc:47
#define TESTL_NO_LIST
Definition exactTestL.cc:79
#define TESTL_NOT_DONE
Definition exactTestL.cc:76
int exactL_list(const double *r, int N, double *H, double *b, double *a)
static const double g
Definition exactTestL.cc:43
static const double SperA
Definition exactTestL.cc:38
static const double b0
Definition exactTestL.cc:41
int getU(const double *r, int N, double *u, const double EPS_ABS, const double EPS_REL, const int ode_method)
static const double z0
Definition exactTestL.cc:42
ExactLParameters exactL(const std::vector< double > &r)
static const double rho
Definition exactTestL.cc:44
#define TESTL_INVALID_METHOD
Definition exactTestL.cc:78
static const double n
Definition exactTestL.cc:45
std::vector< double > b
Definition exactTestL.hh:39
std::vector< double > H
Definition exactTestL.hh:39
std::vector< double > a
Definition exactTestL.hh:39
ExactLParameters(size_t n)
int count
Definition test_cube.c:16