Hex  1.0
Hydrogen-electron collision solver
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ode.h
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
2  * *
3  * / / / / __ \ \ / / *
4  * / /__ / / / _ \ \ \/ / *
5  * / ___ / | |/_/ / /\ \ *
6  * / / / / \_\ / / \ \ *
7  * *
8  * Jakub Benda (c) 2014 *
9  * Charles University in Prague *
10  * *
11 \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12 
13 #ifndef HEX_ODE
14 #define HEX_ODE
15 
16 #include <gsl/gsl_odeiv2.h>
17 
18 #define DIVERGENCE_THRESHOLD 100
19 
20 #define ABORT_ON_OVERFLOW 0
21 #define RETURN_ON_OVERFLOW 1
22 #define NORMALIZE_ON_OVERFLOW 2
23 
24 #include "misc.h"
25 
49 int solve2 (
50  double xg[], int N, double h, double yg[][2],
51  int (*derivs) (double, const double [2], double [2], void*),
52  void * data, int flag
53 ) {
54  // initialize auxiliary variables
55  size_t ntrial = 100000000; // 10⁷
56  double x0 = xg[0], x1 = xg[N - 2];
57  double x = x0, xnext;
58  int status = GSL_SUCCESS, first_status = GSL_SUCCESS;
59  size_t nsteps = 0;
60  xg[0] = x0;
61 
62  // setup the stepper
63  const gsl_odeiv2_step_type * step_type = gsl_odeiv2_step_rkck;
64  gsl_odeiv2_step * step = gsl_odeiv2_step_alloc(step_type, 2);
65  gsl_odeiv2_control * control = gsl_odeiv2_control_y_new(1e-6, 0.0);
66  gsl_odeiv2_evolve * evolve = gsl_odeiv2_evolve_alloc(2);
67 
68  // setup the system
69  gsl_odeiv2_system sys;
70  sys.function = derivs;
71  sys.jacobian = nullptr;
72  sys.dimension = 2;
73  sys.params = data;
74 
75  // for all steps
76  for(int i = 1; i < N - 1 and status == GSL_SUCCESS; i++)
77  {
78  xnext = x0 + (x1 - x0) * ((double)i)/((double)(N - 2));
79  double (& y_row) [2] = yg[i];
80  y_row[0] = yg[i-1][0];
81  y_row[1] = yg[i-1][1];
82 
83  // Step until we reach the next grid point
84  bool done = false;
85  while (not done and status == GSL_SUCCESS)
86  {
87  status = gsl_odeiv2_evolve_apply (
88  evolve,
89  control,
90  step,
91  &sys,
92  &x, xnext,
93  &h,
94  y_row
95  );
96 
97  // check finiteness
98  if (not std::isfinite(y_row[0]))
99  throw exception("[solve2] Infinite result (%g) for i = %d", y_row[0], i);
100 
101  // advance number of steps
102  nsteps++;
103  if (status != GSL_SUCCESS and first_status != GSL_SUCCESS)
104  first_status = status;
105  if (nsteps > ntrial)
106  std::cerr << "[solve2] Too many steps required (ntrial=" << ntrial << ", x=" << x << ").";
107 
108  // avoid overflow (normalize)
109  if (fabs(y_row[0]) > DIVERGENCE_THRESHOLD)
110  {
111  if (flag == NORMALIZE_ON_OVERFLOW)
112  {
113  double inverse_norm = 1./fabs(y_row[0]);
114  for (int j = 0; j <= i; j++)
115  {
116  yg[j][0] *= inverse_norm;
117  yg[j][1] *= inverse_norm;
118  }
119  }
120  if (flag == RETURN_ON_OVERFLOW)
121  {
122  return i - 1;
123  }
124  if (flag == ABORT_ON_OVERFLOW)
125  {
126  throw exception ("[solve2] Overflow error.");
127  }
128  }
129 
130  // decide if we have reached the grid point
131  if (x1 > x0)
132  {
133  if (x >= xnext)
134  done = true;
135  }
136  else
137  {
138  if (x <= xnext)
139  done = true;
140  }
141 
142  }
143  }
144 
145  gsl_odeiv2_evolve_free(evolve);
146  gsl_odeiv2_control_free(control);
147  gsl_odeiv2_step_free(step);
148 
149  return N;
150 }
151 
152 #endif
DistortingPotential exception
#define ABORT_ON_OVERFLOW
Definition: ode.h:20
#define NORMALIZE_ON_OVERFLOW
Definition: ode.h:22
const double e
Definition: special.h:44
int solve2(double xg[], int N, double h, double yg[][2], int(*derivs)(double, const double[2], double[2], void *), void *data, int flag)
Second-order differential equation solver.
Definition: ode.h:49
#define RETURN_ON_OVERFLOW
Definition: ode.h:21
int derivs(double x, const double y[2], double dydx[2], void *data)
Definition: wave_distort.cpp:67
#define DIVERGENCE_THRESHOLD
Definition: ode.h:18