Ejemplo n.º 1
0
void
test_f (const gsl_min_fminimizer_type * T, 
        const char * description, gsl_function *f,
        double lower_bound, double middle, double upper_bound, 
        double correct_minimum)
{
  int status;
  size_t iterations = 0;
  double m, a, b;
  double x_lower, x_upper;
  gsl_min_fminimizer * s;

  x_lower = lower_bound;
  x_upper = upper_bound;

  s = gsl_min_fminimizer_alloc (T) ;
  gsl_min_fminimizer_set (s, f, middle, x_lower, x_upper) ;
  
  do 
    {
      iterations++ ;

      status = gsl_min_fminimizer_iterate (s);

      m = gsl_min_fminimizer_x_minimum(s);
      a = gsl_min_fminimizer_x_lower(s);
      b = gsl_min_fminimizer_x_upper(s);

#ifdef DEBUG
      printf("%.12f %.18f %.12f %.18f %.12f %.18f status=%d\n", 
             a, GSL_FN_EVAL(f, a), m, GSL_FN_EVAL(f, m), b, GSL_FN_EVAL(f, b), status);
#endif

      if (a > b)
        gsl_test (GSL_FAILURE, "interval is invalid (%g,%g)", a, b);

      if (m < a || m > b)
        gsl_test (GSL_FAILURE, "m lies outside interval %g (%g,%g)", m, a, b);

      if (status) break ;

      status = gsl_min_test_interval (a, b, EPSABS, EPSREL);
    }
  while (status == GSL_CONTINUE && iterations < MAX_ITERATIONS);

  gsl_test (status, "%s, %s (%g obs vs %g expected) ", 
            gsl_min_fminimizer_name(s), description, 
            gsl_min_fminimizer_x_minimum(s), correct_minimum);

  /* check the validity of the returned result */

  if (!WITHIN_TOL (m, correct_minimum, EPSREL, EPSABS))
    {
      gsl_test (GSL_FAILURE, "incorrect precision (%g obs vs %g expected)", 
                m, correct_minimum);
    }

  gsl_min_fminimizer_free (s);

}
Ejemplo n.º 2
0
const Real GreensFunction2DAbs::drawTime(const Real rnd) const
{
    THROW_UNLESS(std::invalid_argument, 0.0<=rnd && rnd <= 1.0);
    if(D == 0e0 || a == std::numeric_limits<Real>::infinity() || rnd == 1e0)
        return std::numeric_limits<Real>::infinity();
    if(a == r0 || rnd == 0e0)
        return 0e0;

    p_survival_params params = {this, rnd};

    gsl_function F = 
    {
        reinterpret_cast<double (*)(double, void*)>(&p_survival_F), &params
    };

    // this is not so accurate because
    // initial position is not the center of this system.
    const Real t_guess(a * a * 0.25 / D);
    Real value(GSL_FN_EVAL(&F, t_guess));
    Real low(t_guess);
    Real high(t_guess);

    // to determine high and low border
    if(value < 0.0)
    {
        do
        {
            high *= 1e1;
            value = GSL_FN_EVAL(&F, high);
            if(fabs(high) > t_guess * 1e6)
                throw std::invalid_argument("could not adjust higher border");
        }
        while(value <= 0e0);
    }
    else
    {
        Real value_prev = value;
        do
        {
            low *= 1e-1;
            value = GSL_FN_EVAL(&F, low);
            if(fabs(low) <= t_guess * 1e-6 || fabs(value - value_prev) < CUTOFF)
                throw std::invalid_argument("could not adjust lower border");
            value_prev = value;
        }
        while(value >= 0e0);
    }

    //find the root
    const gsl_root_fsolver_type* solverType(gsl_root_fsolver_brent);
    gsl_root_fsolver* solver(gsl_root_fsolver_alloc(solverType));

    const Real t(findRoot(F, solver, low, high, 1e-18, 1e-12,
                          "GreensFunction2DAbs::drawTime"));

    gsl_root_fsolver_free(solver);

    return t;
}
Ejemplo n.º 3
0
static double 
i_transform (double t, void *params)
{
  gsl_function *f = (gsl_function *) params;
  double x = (1 - t) / t;
  double y = GSL_FN_EVAL (f, x) + GSL_FN_EVAL (f, -x);
  return (y / t) / t;
}
Ejemplo n.º 4
0
int
gsl_diff_forward (const gsl_function * f,
                  double x, double *result, double *abserr)
{
  /* Construct a divided difference table with a fairly large step
     size to get a very rough estimate of f''.  Use this to estimate
     the step size which will minimize the error in calculating f'. */

  int i, k;
  double h = GSL_SQRT_DBL_EPSILON;
  double a[3], d[3], a2;

  /* Algorithm based on description on pg. 204 of Conte and de Boor
     (CdB) - coefficients of Newton form of polynomial of degree 2. */

  for (i = 0; i < 3; i++)
    {
      a[i] = x + i * h;
      d[i] = GSL_FN_EVAL (f, a[i]);
    }

  for (k = 1; k < 4; k++)
    {
      for (i = 0; i < 3 - k; i++)
        {
          d[i] = (d[i + 1] - d[i]) / (a[i + k] - a[i]);
        }
    }

  /* Adapt procedure described on pg. 282 of CdB to find best value of
     step size. */

  a2 = fabs (d[0] + d[1] + d[2]);

  if (a2 < 100.0 * GSL_SQRT_DBL_EPSILON)
    {
      a2 = 100.0 * GSL_SQRT_DBL_EPSILON;
    }

  h = sqrt (GSL_SQRT_DBL_EPSILON / (2.0 * a2));

  if (h > 100.0 * GSL_SQRT_DBL_EPSILON)
    {
      h = 100.0 * GSL_SQRT_DBL_EPSILON;
    }

  *result = (GSL_FN_EVAL (f, x + h) - GSL_FN_EVAL (f, x)) / h;
  *abserr = fabs (10.0 * a2 * h);

  return GSL_SUCCESS;
}
Ejemplo n.º 5
0
int UnidimensionalRootFinder(gsl_function	*F,
                             double          lower_bound,
                             double          upper_bound,
                             double          abs_error,
                             double          rel_error,
                             int             max_iterations,
                             double         *return_result)
{

    const gsl_root_fsolver_type * T	= gsl_root_fsolver_bisection;
    gsl_root_fsolver * s = gsl_root_fsolver_alloc(T);

    // Test if the limits straddle the root,
    // if they don't, we will return -1.
    if (GSL_SIGN(GSL_FN_EVAL(F, lower_bound)) == GSL_SIGN(GSL_FN_EVAL(F, upper_bound)))
        return -1;

    gsl_root_fsolver_set(s, F, lower_bound, upper_bound);

    int i = 0;
    double x_lower;
    double x_upper;
    do{
        i++;

        int status = gsl_root_fsolver_iterate(s);

        if (status != GSL_SUCCESS){
            printf("ERROR: No solution to the gap equation was found!\n");
            exit(EXIT_FAILURE);
        }

        x_lower = gsl_root_fsolver_x_lower(s);
        x_upper = gsl_root_fsolver_x_upper(s);
    } while(GSL_CONTINUE == gsl_root_test_interval(x_lower,
                                                   x_upper,
                                                   abs_error,
                                                   rel_error)
            && i <= max_iterations);

    double result = gsl_root_fsolver_root(s);

    void gsl_root_fsolver_free(gsl_root_fsolver * S);

    *return_result = result;

    return 0;
}
Ejemplo n.º 6
0
int gsl_cheb_init(gsl_cheb_series * cs, const gsl_function *func,
                  const double a, const double b)
{
  size_t k, j;

  if(a >= b) {
    GSL_ERROR_VAL("null function interval [a,b]", GSL_EDOM, 0);
  }
  cs->a = a;
  cs->b = b;
  /* cs->err = 0.0; */

  { 
    double bma = 0.5 * (cs->b - cs->a);
    double bpa = 0.5 * (cs->b + cs->a);
    double fac = 2.0/(cs->order +1.0);

    for(k = 0; k<=cs->order; k++) {
      double y = cos(M_PI * (k+0.5)/(cs->order+1));
      cs->f[k] = GSL_FN_EVAL(func, (y*bma + bpa));
    }
    
    for(j = 0; j<=cs->order; j++) {
      double sum = 0.0;
      for(k = 0; k<=cs->order; k++) 
        sum += cs->f[k]*cos(M_PI * j*(k+0.5)/(cs->order+1));
      cs->c[j] = fac * sum;
    }
    
  }
  return GSL_SUCCESS;
}
Ejemplo n.º 7
0
static double
fn_cauchy (double x, void *params)
{
  struct fn_cauchy_params *p = (struct fn_cauchy_params *) params;
  gsl_function *f = p->function;
  double c = p->singularity;
  return GSL_FN_EVAL (f, x) / (x - c);
}
Ejemplo n.º 8
0
void
test (diff_fn * diff, gsl_function * f, gsl_function * df, double x, 
      const char * desc)
{
  double result, abserr;
  double expected = GSL_FN_EVAL (df, x);
  (*diff) (f, x, &result, &abserr);
  gsl_test_abs (result, expected, abserr, desc);
  gsl_test (fabs(result-expected) >  abserr, "%s, valid error estimate", desc);
}
Ejemplo n.º 9
0
static double
fn_cos (double x, void *params)
{
  struct fn_fourier_params *p = (struct fn_fourier_params *) params;
  gsl_function *f = p->function;
  double w = p->omega;
  double wx = w * x;
  double coswx = cos(wx) ;
  return GSL_FN_EVAL (f, x) * coswx ;
}
Ejemplo n.º 10
0
static double 
il_transform (double t, void *params)
{
  struct il_params *p = (struct il_params *) params;
  double b = p->b;
  gsl_function * f = p->f;
  double x = b - (1 - t) / t;
  double y = GSL_FN_EVAL (f, x);
  return (y / t) / t;
}
Ejemplo n.º 11
0
static double 
iu_transform (double t, void *params)
{
  struct iu_params *p = (struct iu_params *) params;
  double a = p->a;
  gsl_function * f = p->f;
  double x = a + (1 - t) / t;
  double y = GSL_FN_EVAL (f, x);
  return (y / t) / t;
}
Ejemplo n.º 12
0
void 
test_dim (const size_t n, const double a, const double b,
          gsl_function * F, gsl_function * DF, gsl_function *IF)
{
  double tol = 100.0 * GSL_DBL_EPSILON;
  double x; 

  gsl_cheb_series * cs = gsl_cheb_alloc(n);
  gsl_cheb_series * csd = gsl_cheb_alloc(n);
  gsl_cheb_series * csi = gsl_cheb_alloc(n);

  gsl_cheb_init(cs, F, a, b);
  
  for(x=a; x<b; x += (b-a)/100.0) {
    double r = gsl_cheb_eval(cs, x);
    gsl_test_abs(r, GSL_FN_EVAL(F, x), tol, "gsl_cheb_eval, F(%.3g)", x);
  }

  /* Test derivative */

  gsl_cheb_calc_deriv(csd, cs);

  for(x=a; x<b; x += (b-a)/100.0) {
    double r = gsl_cheb_eval(csd, x);
    gsl_test_abs(r, GSL_FN_EVAL(DF, x), tol, "gsl_cheb_eval, deriv F(%.3g)", x);
  }
 
  /* Test integral */

  gsl_cheb_calc_integ(csi, cs);

  for(x=a; x<b; x += (b-a)/100.0) {
    double r = gsl_cheb_eval(csi, x);
    gsl_test_abs(r, GSL_FN_EVAL(IF, x), tol, "gsl_cheb_eval, integ F(%.3g)", x);
  }

  gsl_cheb_free(csi);
  gsl_cheb_free(csd);
  gsl_cheb_free(cs);
}
Ejemplo n.º 13
0
static void
central_deriv (const gsl_function * f, double x, double h,
               double *result, double *abserr_round, double *abserr_trunc)
{
  /* Compute the derivative using the 5-point rule (x-h, x-h/2, x,
     x+h/2, x+h). Note that the central point is not used.  

     Compute the error using the difference between the 5-point and
     the 3-point rule (x-h,x,x+h). Again the central point is not
     used. */

  double fm1 = GSL_FN_EVAL (f, x - h);
  double fp1 = GSL_FN_EVAL (f, x + h);

  double fmh = GSL_FN_EVAL (f, x - h / 2);
  double fph = GSL_FN_EVAL (f, x + h / 2);

  double r3 = 0.5 * (fp1 - fm1);
  double r5 = (4.0 / 3.0) * (fph - fmh) - (1.0 / 3.0) * r3;

  double e3 = (fabs (fp1) + fabs (fm1)) * GSL_DBL_EPSILON;
  double e5 = 2.0 * (fabs (fph) + fabs (fmh)) * GSL_DBL_EPSILON + e3;

  /* The next term is due to finite precision in x+h = O (eps * x) */

  double dy = GSL_MAX (fabs (r3 / h), fabs (r5 / h)) *(fabs (x) / h) * GSL_DBL_EPSILON;

  /* The truncation error in the r5 approximation itself is O(h^4).
     However, for safety, we estimate the error from r5-r3, which is
     O(h^2).  By scaling h we will minimise this estimated error, not
     the actual truncation error in r5. */

  *result = r5 / h;
  *abserr_trunc = fabs ((r5 - r3) / h); /* Estimated truncation error O(h^2) */
  *abserr_round = fabs (e5 / h) + dy;   /* Rounding error (cancellations) */
}
Ejemplo n.º 14
0
static void
forward_deriv (const gsl_function * f, double x, double h,
               double *result, double *abserr_round, double *abserr_trunc)
{
  /* Compute the derivative using the 4-point rule (x+h/4, x+h/2,
     x+3h/4, x+h).

     Compute the error using the difference between the 4-point and
     the 2-point rule (x+h/2,x+h).  */

  double f1 = GSL_FN_EVAL (f, x + h / 4.0);
  double f2 = GSL_FN_EVAL (f, x + h / 2.0);
  double f3 = GSL_FN_EVAL (f, x + (3.0 / 4.0) * h);
  double f4 = GSL_FN_EVAL (f, x + h);

  double r2 = 2.0*(f4 - f2);
  double r4 = (22.0 / 3.0) * (f4 - f3) - (62.0 / 3.0) * (f3 - f2) +
    (52.0 / 3.0) * (f2 - f1);

  /* Estimate the rounding error for r4 */

  double e4 = 2 * 20.67 * (fabs (f4) + fabs (f3) + fabs (f2) + fabs (f1)) * GSL_DBL_EPSILON;

  /* The next term is due to finite precision in x+h = O (eps * x) */

  double dy = GSL_MAX (fabs (r2 / h), fabs (r4 / h)) * fabs (x / h) * GSL_DBL_EPSILON;

  /* The truncation error in the r4 approximation itself is O(h^3).
     However, for safety, we estimate the error from r4-r2, which is
     O(h).  By scaling h we will minimise this estimated error, not
     the actual truncation error in r4. */

  *result = r4 / h;
  *abserr_trunc = fabs ((r4 - r2) / h); /* Estimated truncation error O(h) */
  *abserr_round = fabs (e4 / h) + dy;
}
Ejemplo n.º 15
0
static double
fn_qaws_R (double x, void *params)
{
  struct fn_qaws_params *p = (struct fn_qaws_params *) params;
  gsl_function *f = p->function;
  gsl_integration_qaws_table *t = p->table;

  double factor = 1.0;
  
  if (t->beta != 0.0)
    factor *= pow(p->b - x, t->beta);

  if (t->nu == 1)
    factor *= log(p->b - x);

  return factor * GSL_FN_EVAL (f, x);
}
Ejemplo n.º 16
0
void
test (deriv_fn * deriv, gsl_function * f, gsl_function * df, double x, 
      const char * desc)
{
  double result, abserr;
  double expected = GSL_FN_EVAL (df, x);
  (*deriv) (f, x, 1e-4, &result, &abserr);

  gsl_test_abs (result, expected, GSL_MIN(1e-4,fabs(expected)) + GSL_DBL_EPSILON, desc);

  if (abserr < fabs(result-expected)) 
    {
      gsl_test_factor (abserr, fabs(result-expected), 2, "%s error estimate", desc);
    }
  else if (result == expected || expected == 0.0)
    {
      gsl_test_abs (abserr, 0.0, 1e-6, "%s abserr", desc);
    }
  else
    {
      double d = fabs(result - expected);
      gsl_test_abs (abserr, fabs(result-expected), 1e6*d, "%s abserr", desc);
    }
}
Ejemplo n.º 17
0
Real GreensFunction3DRadInf::drawR(Real rnd, Real t) const
{
    const Real sigma(this->getSigma());
    const Real D(this->getD());

    if (!(rnd < 1.0 && rnd >= 0.0))
    {
        throw std::invalid_argument((boost::format("rnd < 1.0 && rnd >= 0.0 : rnd=%.16g") % rnd).str());
    }

    if (!(r0 >= sigma))
    {
        throw std::invalid_argument((boost::format("r0 >= sigma : r0=%.16g, sigma=%.16g") % r0 % sigma).str());
    }

    if (!(t >= 0.0))
    {
        throw std::invalid_argument((boost::format("t >= 0.0 : t=%.16g") % t).str());
    }


    if(t == 0.0)
    {
        return r0;
    }

    const Real psurv(p_survival(t));

    p_int_r_params params = { this, t, rnd * psurv };

    gsl_function F = 
        {
            reinterpret_cast<double (*)(double, void*)>(&p_int_r_F),
            &params 
        };


    // adjust low and high starting from r0.
    // this is necessary to avoid root finding in the long tails where
    // numerics can be unstable.

    Real low(r0);
    Real high(r0);

    const Real sqrt6Dt(sqrt(6.0 * D * t));
    if(GSL_FN_EVAL(&F, r0) < 0.0)
    {
        // low = r0
        unsigned int H(3);

        for (;;)
        {
            high = r0 + H * sqrt6Dt;

            const Real value(GSL_FN_EVAL(&F, high));
            if(value > 0.0)
            {
                break;
            }

            ++H;

            if(H > 20)
            {
                throw std::runtime_error("drawR: H > 20 while adjusting upper bound of r");
            }
        }

    }
    else
    {
        // high = r0
        unsigned int H(3);

        for (;;)
        {
            low = r0 - H * sqrt6Dt;
            if(low < sigma)
            {
                if(GSL_FN_EVAL(&F, sigma) > 0.0)
                {
                    log_.info("drawR: p_int_r(sigma) > 0.0. "
                              "returning sigma.");
                    return sigma;
                }

                low = sigma;
                break;
            }

            const Real value(GSL_FN_EVAL(&F, low));
            if(value < 0.0)
            {
                break;
            }

            ++H;
        }
    }


    // root finding by iteration.

    const gsl_root_fsolver_type* solverType(gsl_root_fsolver_brent);
    gsl_root_fsolver* solver(gsl_root_fsolver_alloc(solverType));
    gsl_root_fsolver_set(solver, &F, low, high);

    const unsigned int maxIter(100);

    unsigned int i(0);
    for (;;)
    {
        gsl_root_fsolver_iterate(solver);
        low = gsl_root_fsolver_x_lower(solver);
        high = gsl_root_fsolver_x_upper(solver);
        const int status(gsl_root_test_interval(low, high, 1e-15,
                                                  this->TOLERANCE));

        if(status == GSL_CONTINUE)
        {
            if(i >= maxIter)
            {
                gsl_root_fsolver_free(solver);
                throw std::runtime_error("drawR: failed to converge");
            }
        }
        else
        {
            break;
        }

        ++i;
    }
  
    const Real r(gsl_root_fsolver_root(solver));
    gsl_root_fsolver_free(solver);

    return r;
}
Ejemplo n.º 18
0
int
gsl_integration_cquad (const gsl_function * f, double a, double b,
		       double epsabs, double epsrel,
		       gsl_integration_cquad_workspace * ws,
		       double *result, double *abserr, size_t * nevals)
{

  /* Some constants that we will need. */
  static const int n[4] = { 4, 8, 16, 32 };
  static const int skip[4] = { 8, 4, 2, 1 };
  static const int idx[4] = { 0, 5, 14, 31 };
  static const double w = M_SQRT2 / 2;
  static const int ndiv_max = 20;

  /* Actual variables (as opposed to constants above). */
  double m, h, temp;
  double igral, err, igral_final, err_final, err_excess;
  int nivals, neval = 0;
  int i, j, d, split, t;
  int nnans, nans[32];
  gsl_integration_cquad_ival *iv, *ivl, *ivr;
  double nc, ncdiff;

  /* Check the input arguments. */
  if (f == NULL)
    GSL_ERROR ("function pointer shouldn't be NULL", GSL_EINVAL);
  if (result == NULL)
    GSL_ERROR ("result pointer shouldn't be NULL", GSL_EINVAL);
  if (ws == NULL)
    GSL_ERROR ("workspace pointer shouldn't be NULL", GSL_EINVAL);


  /* Check for unreasonable accuracy demands */
  if (epsabs < 0.0 || epsrel < 0.0)
    GSL_ERROR ("tolerances may not be negative", GSL_EBADTOL);
  if (epsabs <= 0 && epsrel < GSL_DBL_EPSILON)
    GSL_ERROR ("unreasonable accuracy requirement", GSL_EBADTOL);


  /* Create the first interval. */
  iv = &(ws->ivals[0]);
  m = (a + b) / 2;
  h = (b - a) / 2;
  nnans = 0;
  for (i = 0; i <= n[3]; i++)
    {
      iv->fx[i] = GSL_FN_EVAL (f, m + xi[i] * h);
      neval++;
      if (!finite (iv->fx[i]))
	{
	  nans[nnans++] = i;
	  iv->fx[i] = 0.0;
	}
    }
  Vinvfx (iv->fx, &(iv->c[idx[0]]), 0);
  Vinvfx (iv->fx, &(iv->c[idx[3]]), 3);
  Vinvfx (iv->fx, &(iv->c[idx[2]]), 2);
  for (i = 0; i < nnans; i++)
    iv->fx[nans[i]] = GSL_NAN;
  iv->a = a;
  iv->b = b;
  iv->depth = 3;
  iv->rdepth = 1;
  iv->ndiv = 0;
  iv->igral = 2 * h * iv->c[idx[3]] * w;
  nc = 0.0;
  for (i = n[2] + 1; i <= n[3]; i++)
    {
      temp = iv->c[idx[3] + i];
      nc += temp * temp;
    }
  ncdiff = nc;
  for (i = 0; i <= n[2]; i++)
    {
      temp = iv->c[idx[2] + i] - iv->c[idx[3] + i];
      ncdiff += temp * temp;
      nc += iv->c[idx[3] + i] * iv->c[idx[3] + i];
    }
  ncdiff = sqrt (ncdiff);
  nc = sqrt (nc);
  iv->err = ncdiff * 2 * h;
  if (ncdiff / nc > 0.1 && iv->err < 2 * h * nc)
    iv->err = 2 * h * nc;


  /* Initialize the heaps. */
  for (i = 0; i < ws->size; i++)
    ws->heap[i] = i;


  /* Initialize some global values. */
  igral = iv->igral;
  err = iv->err;
  nivals = 1;
  igral_final = 0.0;
  err_final = 0.0;
  err_excess = 0.0;


  /* Main loop. */
  while (nivals > 0 && err > 0.0 &&
	 !(err <= fabs (igral) * epsrel || err <= epsabs)
	 && !(err_final > fabs (igral) * epsrel
	      && err - err_final < fabs (igral) * epsrel)
	 && !(err_final > epsabs && err - err_final < epsabs))
    {

      /* Put our finger on the interval with the largest error. */
      iv = &(ws->ivals[ws->heap[0]]);
      m = (iv->a + iv->b) / 2;
      h = (iv->b - iv->a) / 2;

/*      printf
        ("cquad: processing ival %i (of %i) with [%e,%e] int=%e, err=%e, depth=%i\n",
         ws->heap[0], nivals, iv->a, iv->b, iv->igral, iv->err, iv->depth);
*/
      /* Should we try to increase the degree? */
      if (iv->depth < 3)
	{

	  /* Keep tabs on some variables. */
	  d = ++iv->depth;

	  /* Get the new (missing) function values */
	  for (i = skip[d]; i <= 32; i += 2 * skip[d])
	    {
	      iv->fx[i] = GSL_FN_EVAL (f, m + xi[i] * h);
	      neval++;
	    }
	  nnans = 0;
	  for (i = 0; i <= 32; i += skip[d])
	    {
	      if (!finite (iv->fx[i]))
		{
		  nans[nnans++] = i;
		  iv->fx[i] = 0.0;
		}
	    }

	  /* Compute the new coefficients. */
	  Vinvfx (iv->fx, &(iv->c[idx[d]]), d);

	  /* Downdate any NaNs. */
	  if (nnans > 0)
	    {
	      downdate (&(iv->c[idx[d]]), n[d], d, nans, nnans);
	      for (i = 0; i < nnans; i++)
		iv->fx[nans[i]] = GSL_NAN;
	    }

	  /* Compute the error estimate. */
	  nc = 0.0;
	  for (i = n[d - 1] + 1; i <= n[d]; i++)
	    {
	      temp = iv->c[idx[d] + i];
	      nc += temp * temp;
	    }
	  ncdiff = nc;
	  for (i = 0; i <= n[d - 1]; i++)
	    {
	      temp = iv->c[idx[d - 1] + i] - iv->c[idx[d] + i];
	      ncdiff += temp * temp;
	      nc += iv->c[idx[d] + i] * iv->c[idx[d] + i];
	    }
	  ncdiff = sqrt (ncdiff);
	  nc = sqrt (nc);
	  iv->err = ncdiff * 2 * h;

	  /* Compute the local integral. */
	  iv->igral = 2 * h * w * iv->c[idx[d]];

	  /* Split the interval prematurely? */
	  split = (nc > 0 && ncdiff / nc > 0.1);

	}

      /* Maximum degree reached, just split. */
      else
	{
	  split = 1;
	}


      /* Should we drop this interval? */
      if ((m + h * xi[0]) >= (m + h * xi[1])
	  || (m + h * xi[31]) >= (m + h * xi[32])
	  || iv->err < fabs (iv->igral) * GSL_DBL_EPSILON * 10)
	{

/*          printf
            ("cquad: dumping ival %i (of %i) with [%e,%e] int=%e, err=%e, depth=%i\n",
             ws->heap[0], nivals, iv->a, iv->b, iv->igral, iv->err,
             iv->depth);
*/
	  /* Keep this interval's contribution */
	  err_final += iv->err;
	  igral_final += iv->igral;

	  /* Swap with the last element on the heap */
	  t = ws->heap[nivals - 1];
	  ws->heap[nivals - 1] = ws->heap[0];
	  ws->heap[0] = t;
	  nivals--;

	  /* Fix up the heap */
	  i = 0;
	  while (2 * i + 1 < nivals)
	    {

	      /* Get the kids */
	      j = 2 * i + 1;

	      /* If the j+1st entry exists and is larger than the jth,
	         use it instead. */
	      if (j + 1 < nivals
		  && ws->ivals[ws->heap[j + 1]].err >=
		  ws->ivals[ws->heap[j]].err)
		j++;

	      /* Do we need to move the ith entry up? */
	      if (ws->ivals[ws->heap[j]].err <= ws->ivals[ws->heap[i]].err)
		break;
	      else
		{
		  t = ws->heap[j];
		  ws->heap[j] = ws->heap[i];
		  ws->heap[i] = t;
		  i = j;
		}
	    }

	}

      /* Do we need to split this interval? */
      else if (split)
	{

	  /* Some values we will need often... */
	  d = iv->depth;

	  /* Generate the interval on the left */
	  ivl = &(ws->ivals[ws->heap[nivals++]]);
	  ivl->a = iv->a;
	  ivl->b = m;
	  ivl->depth = 0;
	  ivl->rdepth = iv->rdepth + 1;
	  ivl->fx[0] = iv->fx[0];
	  ivl->fx[32] = iv->fx[16];
	  for (i = skip[0]; i < 32; i += skip[0])
	    {
	      ivl->fx[i] =
		GSL_FN_EVAL (f, (ivl->a + ivl->b) / 2 + xi[i] * h / 2);
	      neval++;
	    }
	  nnans = 0;
	  for (i = 0; i <= 32; i += skip[0])
	    {
	      if (!finite (ivl->fx[i]))
		{
		  nans[nnans++] = i;
		  ivl->fx[i] = 0.0;
		}
	    }
	  Vinvfx (ivl->fx, ivl->c, 0);
	  if (nnans > 0)
	    {
	      downdate (ivl->c, n[0], 0, nans, nnans);
	      for (i = 0; i < nnans; i++)
		ivl->fx[nans[i]] = GSL_NAN;
	    }
	  for (i = 0; i <= n[d]; i++)
	    {
	      ivl->c[idx[d] + i] = 0.0;
	      for (j = i; j <= n[d]; j++)
		ivl->c[idx[d] + i] += Tleft[i * 33 + j] * iv->c[idx[d] + j];
	    }
	  ncdiff = 0.0;
	  for (i = 0; i <= n[0]; i++)
	    {
	      temp = ivl->c[i] - ivl->c[idx[d] + i];
	      ncdiff += temp * temp;
	    }
	  for (i = n[0] + 1; i <= n[d]; i++)
	    {
	      temp = ivl->c[idx[d] + i];
	      ncdiff += temp * temp;
	    }
	  ncdiff = sqrt (ncdiff);
	  ivl->err = ncdiff * h;

	  /* Check for divergence. */
	  ivl->ndiv = iv->ndiv + (fabs (iv->c[0]) > 0
				  && ivl->c[0] / iv->c[0] > 2);
	  if (ivl->ndiv > ndiv_max && 2 * ivl->ndiv > ivl->rdepth)
	    {
              /* need copysign(INFINITY, igral) */
	      *result = (igral >= 0) ? GSL_POSINF : GSL_NEGINF;  
	      if (nevals != NULL)
		*nevals = neval;
	      return GSL_EDIVERGE;
	    }

	  /* Compute the local integral. */
	  ivl->igral = h * w * ivl->c[0];


	  /* Generate the interval on the right */
	  ivr = &(ws->ivals[ws->heap[nivals++]]);
	  ivr->a = m;
	  ivr->b = iv->b;
	  ivr->depth = 0;
	  ivr->rdepth = iv->rdepth + 1;
	  ivr->fx[0] = iv->fx[16];
	  ivr->fx[32] = iv->fx[32];
	  for (i = skip[0]; i < 32; i += skip[0])
	    {
	      ivr->fx[i] =
		GSL_FN_EVAL (f, (ivr->a + ivr->b) / 2 + xi[i] * h / 2);
	      neval++;
	    }
	  nnans = 0;
	  for (i = 0; i <= 32; i += skip[0])
	    {
	      if (!finite (ivr->fx[i]))
		{
		  nans[nnans++] = i;
		  ivr->fx[i] = 0.0;
		}
	    }
	  Vinvfx (ivr->fx, ivr->c, 0);
	  if (nnans > 0)
	    {
	      downdate (ivr->c, n[0], 0, nans, nnans);
	      for (i = 0; i < nnans; i++)
		ivr->fx[nans[i]] = GSL_NAN;
	    }
	  for (i = 0; i <= n[d]; i++)
	    {
	      ivr->c[idx[d] + i] = 0.0;
	      for (j = i; j <= n[d]; j++)
		ivr->c[idx[d] + i] += Tright[i * 33 + j] * iv->c[idx[d] + j];
	    }
	  ncdiff = 0.0;
	  for (i = 0; i <= n[0]; i++)
	    {
	      temp = ivr->c[i] - ivr->c[idx[d] + i];
	      ncdiff += temp * temp;
	    }
	  for (i = n[0] + 1; i <= n[d]; i++)
	    {
	      temp = ivr->c[idx[d] + i];
	      ncdiff += temp * temp;
	    }
	  ncdiff = sqrt (ncdiff);
	  ivr->err = ncdiff * h;

	  /* Check for divergence. */
	  ivr->ndiv = iv->ndiv + (fabs (iv->c[0]) > 0
				  && ivr->c[0] / iv->c[0] > 2);
	  if (ivr->ndiv > ndiv_max && 2 * ivr->ndiv > ivr->rdepth)
	    {
              /* need copysign(INFINITY, igral) */
	      *result = (igral >= 0) ? GSL_POSINF : GSL_NEGINF;  
	      if (nevals != NULL)
		*nevals = neval;
	      return GSL_EDIVERGE;
	    }

	  /* Compute the local integral. */
	  ivr->igral = h * w * ivr->c[0];


	  /* Fix-up the heap: we now have one interval on top
	     that we don't need any more and two new, unsorted
	     ones at the bottom. */

	  /* Flip the last interval to the top of the heap and
	     sift down. */
	  t = ws->heap[nivals - 1];
	  ws->heap[nivals - 1] = ws->heap[0];
	  ws->heap[0] = t;
	  nivals--;

	  /* Sift this interval back down the heap. */
	  i = 0;
	  while (2 * i + 1 < nivals - 1)
	    {
	      j = 2 * i + 1;
	      if (j + 1 < nivals - 1
		  && ws->ivals[ws->heap[j + 1]].err >=
		  ws->ivals[ws->heap[j]].err)
		j++;
	      if (ws->ivals[ws->heap[j]].err <= ws->ivals[ws->heap[i]].err)
		break;
	      else
		{
		  t = ws->heap[j];
		  ws->heap[j] = ws->heap[i];
		  ws->heap[i] = t;
		  i = j;
		}
	    }

	  /* Now grab the last interval and sift it up the heap. */
	  i = nivals - 1;
	  while (i > 0)
	    {
	      j = (i - 1) / 2;
	      if (ws->ivals[ws->heap[j]].err < ws->ivals[ws->heap[i]].err)
		{
		  t = ws->heap[j];
		  ws->heap[j] = ws->heap[i];
		  ws->heap[i] = t;
		  i = j;
		}
	      else
		break;
	    }


	}

      /* Otherwise, just fix-up the heap. */
      else
	{
	  i = 0;
	  while (2 * i + 1 < nivals)
	    {
	      j = 2 * i + 1;
	      if (j + 1 < nivals
		  && ws->ivals[ws->heap[j + 1]].err >=
		  ws->ivals[ws->heap[j]].err)
		j++;
	      if (ws->ivals[ws->heap[j]].err <= ws->ivals[ws->heap[i]].err)
		break;
	      else
		{
		  t = ws->heap[j];
		  ws->heap[j] = ws->heap[i];
		  ws->heap[i] = t;
		  i = j;
		}
	    }

	}

      /* If the heap is about to overflow, remove the last two
         intervals. */
      while (nivals > ws->size - 2)
	{
	  iv = &(ws->ivals[ws->heap[nivals - 1]]);

/*          printf
            ("cquad: dumping ival %i (of %i) with [%e,%e] int=%e, err=%e, depth=%i\n",
             ws->heap[0], nivals, iv->a, iv->b, iv->igral, iv->err,
             iv->depth);
*/
	  err_final += iv->err;
	  igral_final += iv->igral;
	  nivals--;
	}

      /* Collect the value of the integral and error. */
      igral = igral_final;
      err = err_final;
      for (i = 0; i < nivals; i++)
	{
	  igral += ws->ivals[ws->heap[i]].igral;
	  err += ws->ivals[ws->heap[i]].err;
	}

    }

  /* Dump the contents of the heap. */
/*  for (i = 0; i < nivals; i++)
    {
      iv = &(ws->ivals[ws->heap[i]]);
      printf
        ("cquad: ival %i (%i) with [%e,%e], int=%e, err=%e, depth=%i, rdepth=%i\n",
         i, ws->heap[i], iv->a, iv->b, iv->igral, iv->err, iv->depth,
         iv->rdepth);
    }
*/
  /* Clean up and present the results. */
  *result = igral;
  if (abserr != NULL)
    *abserr = err;
  if (nevals != NULL)
    *nevals = neval;

  /* All is well that ends well. */
  return GSL_SUCCESS;

}
Ejemplo n.º 19
0
bool three_body_system::find_characteristic_root(double &tar, vector<double> &new_orthonormal, vector<double> &h, int N){
  // find the Nth root of the characteristic function specified by new_orthonormal and h

  gsl_set_error_handler_off();

  int status;
  int iter = 0, max_iter = 100;
  const gsl_root_fsolver_type *T;
  gsl_root_fsolver *s;
  double r = 0;
  gsl_function F;

  F.function = &helper_function;
  characteristic_root_helper * params = new characteristic_root_helper(this, &new_orthonormal, &h);
  F.params = params;

  T = gsl_root_fsolver_brent;
  s = gsl_root_fsolver_alloc (T);

  double x_lo = 0.0;
  double x_hi = evals[N] - 0.00001;
  if (N > 0) x_lo = evals[N-1]*1.000000001;
  else{
    x_lo = x_hi - 1.0;
    while (true){
      double temp = GSL_FN_EVAL(&F, x_lo);
      //cout << x_lo << " " << temp << endl;
      if (temp < 0.0) break;
      x_lo -= 1.0;
      if (x_lo < x_hi - 10.0) break;

    }
    //if (evals[0] < 0.0) x_lo = evals[0] * 1.5;
    //else x_lo = min(0.0, evals[0] - 250.0);
  }


  status = gsl_root_fsolver_set (s, &F, x_lo, x_hi);
    //cout << x_lo << " " << x_hi << endl;
    //cout << GSL_FN_EVAL(&F, x_lo) << " " << GSL_FN_EVAL(&F, x_hi) << endl;
  if (status != GSL_SUCCESS){
    //cout << "Root solver failure?" << endl;
    return false;
  }

  do
    {
      iter++;
      status = gsl_root_fsolver_iterate (s);
      r = gsl_root_fsolver_root (s);
      x_lo = gsl_root_fsolver_x_lower (s);
      x_hi = gsl_root_fsolver_x_upper (s);
      status = gsl_root_test_interval (x_lo, x_hi,
                                       0, 1E-8);

    }
  while (status == GSL_CONTINUE && iter < max_iter);

  gsl_root_fsolver_free (s);

  tar = r;

  return true;
}
Ejemplo n.º 20
0
int
gsl_integration_qng (const gsl_function *f,
		     double a, double b,
		     double epsabs, double epsrel,
		     double * result, double * abserr, size_t * neval)
{
  double fv1[5], fv2[5], fv3[5], fv4[5];
  double savfun[21];  /* array of function values which have been computed */
  double res10, res21, res43, res87;	/* 10, 21, 43 and 87 point results */
  double result_kronrod, err ; 
  double resabs; /* approximation to the integral of abs(f) */
  double resasc; /* approximation to the integral of abs(f-i/(b-a)) */

  const double half_length =  0.5 * (b - a);
  const double abs_half_length = fabs (half_length);
  const double center = 0.5 * (b + a);
  const double f_center = GSL_FN_EVAL(f, center);

  int k ;

  if (epsabs <= 0 && (epsrel < 50 * GSL_DBL_EPSILON || epsrel < 0.5e-28))
    {
      * result = 0;
      * abserr = 0;
      * neval = 0;
      GSL_ERROR ("tolerance cannot be acheived with given epsabs and epsrel",
		 GSL_EBADTOL);
    };

  /* Compute the integral using the 10- and 21-point formula. */

  res10 = 0;
  res21 = w21b[5] * f_center;
  resabs = w21b[5] * fabs (f_center);

  for (k = 0; k < 5; k++)
    {
      const double abscissa = half_length * x1[k];
      const double fval1 = GSL_FN_EVAL(f, center + abscissa);
      const double fval2 = GSL_FN_EVAL(f, center - abscissa);
      const double fval = fval1 + fval2;
      res10 += w10[k] * fval;
      res21 += w21a[k] * fval;
      resabs += w21a[k] * (fabs (fval1) + fabs (fval2));
      savfun[k] = fval;
      fv1[k] = fval1;
      fv2[k] = fval2;
    }

  for (k = 0; k < 5; k++)
    {
      const double abscissa = half_length * x2[k];
      const double fval1 = GSL_FN_EVAL(f, center + abscissa);
      const double fval2 = GSL_FN_EVAL(f, center - abscissa);
      const double fval = fval1 + fval2;
      res21 += w21b[k] * fval;
      resabs += w21b[k] * (fabs (fval1) + fabs (fval2));
      savfun[k + 5] = fval;
      fv3[k] = fval1;
      fv4[k] = fval2;
    }

  resabs *= abs_half_length ;

  { 
    const double mean = 0.5 * res21;
  
    resasc = w21b[5] * fabs (f_center - mean);
    
    for (k = 0; k < 5; k++)
      {
	resasc +=
	  (w21a[k] * (fabs (fv1[k] - mean) + fabs (fv2[k] - mean))
	  + w21b[k] * (fabs (fv3[k] - mean) + fabs (fv4[k] - mean)));
      }
    resasc *= abs_half_length ;
  }

  result_kronrod = res21 * half_length;
  
  err = rescale_error ((res21 - res10) * half_length, resabs, resasc) ;

  /*   test for convergence. */

  if (err < epsabs || err < epsrel * fabs (result_kronrod))
    {
      * result = result_kronrod ;
      * abserr = err ;
      * neval = 21;
      return GSL_SUCCESS;
    }

  /* compute the integral using the 43-point formula. */

  res43 = w43b[11] * f_center;

  for (k = 0; k < 10; k++)
    {
      res43 += savfun[k] * w43a[k];
    }

  for (k = 0; k < 11; k++)
    {
      const double abscissa = half_length * x3[k];
      const double fval = (GSL_FN_EVAL(f, center + abscissa) 
			   + GSL_FN_EVAL(f, center - abscissa));
      res43 += fval * w43b[k];
      savfun[k + 10] = fval;
    }

  /*  test for convergence */

  result_kronrod = res43 * half_length;
  err = rescale_error ((res43 - res21) * half_length, resabs, resasc);

  if (err < epsabs || err < epsrel * fabs (result_kronrod))
    {
      * result = result_kronrod ;
      * abserr = err ;
      * neval = 43;
      return GSL_SUCCESS;
    }

  /* compute the integral using the 87-point formula. */

  res87 = w87b[22] * f_center;

  for (k = 0; k < 21; k++)
    {
      res87 += savfun[k] * w87a[k];
    }

  for (k = 0; k < 22; k++)
    {
      const double abscissa = half_length * x4[k];
      res87 += w87b[k] * (GSL_FN_EVAL(f, center + abscissa) 
			  + GSL_FN_EVAL(f, center - abscissa));
    }

  /*  test for convergence */

  result_kronrod = res87 * half_length ;
  
  err = rescale_error ((res87 - res43) * half_length, resabs, resasc);
  
  if (err < epsabs || err < epsrel * fabs (result_kronrod))
    {
      * result = result_kronrod ;
      * abserr = err ;
      * neval = 87;
      return GSL_SUCCESS;
    }

  /* failed to converge */

  * result = result_kronrod ;
  * abserr = err ;
  * neval = 87;

  GSL_ERROR("failed to reach tolerance with highest-order rule", GSL_ETOL) ;
}
Ejemplo n.º 21
0
// Draws the first passage time from the survival probability,
// using an assistance function drawT_f that casts the math. function
// into the form needed by the GSL root solver.
Real
GreensFunction1DRadAbs::drawTime (Real rnd) const
{
    THROW_UNLESS( std::invalid_argument, 0.0 <= rnd && rnd < 1.0 );
  
    const Real sigma(this->getsigma());
    const Real a(this->geta());
    const Real L(this->geta()-this->getsigma());
    const Real r0(this->getr0());
    const Real k(this->getk());
    const Real D(this->getD());
    const Real v(this->getv());
    const Real h((this->getk()+this->getv()/2.0)/this->getD());
    

    if ( D == 0.0 || L == INFINITY )
    {
	return INFINITY;
    }

    if ( rnd <= EPSILON || L < 0.0 || fabs(a-r0) < EPSILON*L )
    {
	return 0.0;
    }

    const Real v2D(v/2.0/D);
    const Real exp_av2D(exp(a*v2D));
    const Real exp_sigmav2D(exp(sigma*v2D));
    // exponent of the prefactor present in case of v<>0; has to be split because it has a t-dep. and t-indep. part
    const Real vexpo_t(-v*v/4.0/D);
    const Real vexpo_pref(-v*r0/2.0/D);

    // the structure to store the numbers to calculate the numbers for 1-S
    struct drawT_params parameters;
    // some temporary variables
    double root_n = 0;
    double root_n2, root_n_r0_s, root_n_L, h_root_n;
    double Xn, exponent, prefactor;


    // produce the coefficients and the terms in the exponent and put them
    // in the params structure. This is not very efficient at this point,
    // coefficients should be calculated on demand->TODO
    for (int n=0; n<MAX_TERMS; n++)
    {
	root_n = this->root_n(n+1);	// get the n-th root of tan(root*a)=root/-h (Note: root numbering starts at n=1)
	
	root_n2	    = root_n * root_n;
	root_n_r0_s = root_n * (r0-sigma);
	root_n_L    = root_n * L;
	h_root_n    = h / root_n;
	
	if(v==0)	Xn = (h*sin(root_n_r0_s) + root_n*cos(root_n_r0_s)) / (L*(root_n2+h*h)+h)
			      * ( h_root_n + sin(root_n_L) - h_root_n*cos(root_n_L) ); 
	else		Xn = (h*sin(root_n_r0_s) + root_n*cos(root_n_r0_s)) / (L*(root_n2+h*h)+h)
			      * (exp_sigmav2D*h*k/D - exp_av2D*(root_n2+h*h)*cos(root_n_L)) / (h_root_n * (root_n2 + v2D*v2D)); 
		  
	exponent = -D*root_n2 + vexpo_t;

	// store the coefficients in the structure
	parameters.Xn[n] = Xn;
	// also store the values for the exponent
	parameters.exponent[n] = exponent;
    }
    
    // the prefactor of the sum is also different in case of drift<>0 :
    if(v==0)	prefactor = 2.0;
    else	prefactor = 2.0*exp(vexpo_pref);
    parameters.prefactor  = prefactor;
    
    // store the random number for the probability
    parameters.rnd = rnd;
    // store the number of terms used
    parameters.terms = MAX_TERMS;
    parameters.tscale = this->t_scale;

    // Define the function for the rootfinder
    gsl_function F;
    F.function = &GreensFunction1DRadAbs::drawT_f;
    F.params = &parameters;


    // Find a good interval to determine the first passage time in
    // get the distance to absorbing boundary (disregard rad BC)
    const Real dist(fabs(a-r0));
    //const Real dist( std::min(r0, a-r0));	// for test purposes
    // construct a guess: MSD = sqrt (2*d*D*t)
    Real t_guess( dist * dist / ( 2.0*D ) );
    // A different guess has to be made in case of nonzero drift to account for the displacement due to it
    // TODO: This does not work properly in this case yet, but we don't know why...
    // When drifting towards the closest boundary
    //if( (r0 >= a/2.0 && v > 0.0) || (r0 <= a/2.0 && v < 0.0) )	t_guess = sqrt(D*D/(v*v*v*v)+dist*dist/(v*v)) - D/(v*v);
    // When drifting away from the closest boundary
    //if( ( r0 < a/2.0 && v > 0.0) || ( r0 > a/2.0 && v < 0.0) )	t_guess = D/(v*v) - sqrt(D*D/(v*v*v*v)-dist*dist/(v*v));
    
    Real value( GSL_FN_EVAL( &F, t_guess ) );
    Real low( t_guess );
    Real high( t_guess );


    // scale the interval around the guess such that the function straddles
    if( value < 0.0 )
    {
	// if the guess was too low
	do
	{
	    // keep increasing the upper boundary until the
	    // function straddles
	    high *= 10;
	    value = GSL_FN_EVAL( &F, high );

	    if( fabs( high ) >= t_guess * 1e6 )
	    {
		std::cerr << "GF1DRad: Couldn't adjust high. F("
		          << high << ") = " << value << std::endl;
		throw std::exception();
	    }
	}
	while ( value <= 0.0 );
    }
    else
    {
	// if the guess was too high
	// initialize with 2 so the test below survives the first
	// iteration
	Real value_prev( 2 );
	do
	{
	    if( fabs( low ) <= t_guess * 1e-6 ||
	        fabs(value-value_prev) < EPSILON*1.0 )
	    {
		std::cerr << "GF1DRad: Couldn't adjust low. F(" << low << ") = "
		          << value << " t_guess: " << t_guess << " diff: "
		          << (value - value_prev) << " value: " << value
		          << " value_prev: " << value_prev << " rnd: "
		          << rnd << std::endl;
		return low;
	    }
	    value_prev = value;
	    // keep decreasing the lower boundary until the function straddles
	    low *= 0.1;
	    // get the accompanying value
	    value = GSL_FN_EVAL( &F, low );
	}
	while ( value >= 0.0 );
    }

    // find the intersection on the y-axis between the random number and
    // the function
    
    // define a new solver type brent
    const gsl_root_fsolver_type* solverType( gsl_root_fsolver_brent );
    // make a new solver instance
    // TODO: incl typecast?
    gsl_root_fsolver* solver( gsl_root_fsolver_alloc( solverType ) );
    const Real t( findRoot( F, solver, low, high, t_scale*EPSILON, EPSILON,
                            "GreensFunction1DRadAbs::drawTime" ) );

    // return the drawn time
    return t;
}
Ejemplo n.º 22
0
void
gsl_integration_qk (const int n, 
                    const double xgk[], const double wg[], const double wgk[],
                    double fv1[], double fv2[],
                    const gsl_function * f, double a, double b,
                    double *result, double *abserr,
                    double *resabs, double *resasc)
{

  const double center = 0.5 * (a + b);
  const double half_length = 0.5 * (b - a);
  const double abs_half_length = fabs (half_length);
  const double f_center = GSL_FN_EVAL (f, center);

  double result_gauss = 0;
  double result_kronrod = f_center * wgk[n - 1];

  double result_abs = fabs (result_kronrod);
  double result_asc = 0;
  double mean = 0, err = 0;

  int j;

  if (n % 2 == 0)
    {
      result_gauss = f_center * wg[n / 2 - 1];
    }

  for (j = 0; j < (n - 1) / 2; j++)
    {
      const int jtw = j * 2 + 1;        /* j=1,2,3 jtw=2,4,6 */
      const double abscissa = half_length * xgk[jtw];
      const double fval1 = GSL_FN_EVAL (f, center - abscissa);
      const double fval2 = GSL_FN_EVAL (f, center + abscissa);
      const double fsum = fval1 + fval2;
      fv1[jtw] = fval1;
      fv2[jtw] = fval2;
      result_gauss += wg[j] * fsum;
      result_kronrod += wgk[jtw] * fsum;
      result_abs += wgk[jtw] * (fabs (fval1) + fabs (fval2));
    }

  for (j = 0; j < n / 2; j++)
    {
      int jtwm1 = j * 2;
      const double abscissa = half_length * xgk[jtwm1];
      const double fval1 = GSL_FN_EVAL (f, center - abscissa);
      const double fval2 = GSL_FN_EVAL (f, center + abscissa);
      fv1[jtwm1] = fval1;
      fv2[jtwm1] = fval2;
      result_kronrod += wgk[jtwm1] * (fval1 + fval2);
      result_abs += wgk[jtwm1] * (fabs (fval1) + fabs (fval2));
    };

  mean = result_kronrod * 0.5;

  result_asc = wgk[n - 1] * fabs (f_center - mean);

  for (j = 0; j < n - 1; j++)
    {
      result_asc += wgk[j] * (fabs (fv1[j] - mean) + fabs (fv2[j] - mean));
    }

  /* scale by the width of the integration region */

  err = (result_kronrod - result_gauss) * half_length;

  result_kronrod *= half_length;
  result_abs *= abs_half_length;
  result_asc *= abs_half_length;

  *result = result_kronrod;
  *resabs = result_abs;
  *resasc = result_asc;
  *abserr = rescale_error (err, result_abs, result_asc);

}
Ejemplo n.º 23
0
// Draws the first passage time from the propensity function.
// Uses the help routine drawT_f and structure drawT_params for some technical
// reasons related to the way to input a function and parameters required by
// the GSL library.
Real
GreensFunction1DAbsAbs::drawTime (Real rnd) const
{
    THROW_UNLESS( std::invalid_argument, 0.0 <= rnd && rnd < 1.0 );

    const Real a(this->geta());
    const Real sigma(this->getsigma());
    const Real L(this->geta() - this->getsigma());
    const Real r0(this->getr0());
    const Real D(this->getD());
    const Real v(this->getv());
    
    if (D == 0.0 )
    {
	return INFINITY;
    }
    else if ( L < 0.0 || fabs(a-r0) < EPSILON*L || fabs(r0-sigma) > (1.0 - EPSILON)*L )
    {
	// if the domain had zero size
	return 0.0;
    }

    const Real expo(-D/(L*L));
    const Real r0s_L((r0-sigma)/L);
    // some abbreviations for terms appearing in the sums with drift<>0
    const Real sigmav2D(sigma*v/2.0/D);
    const Real av2D(a*v/2.0/D);
    const Real Lv2D(L*v/2.0/D);
    // exponent of the prefactor present in case of v<>0; has to be split because it has a t-dep. and t-indep. part
    const Real vexpo_t(-v*v/4.0/D);
    const Real vexpo_pref(-v*r0/2.0/D);

    // the structure to store the numbers to calculate the numbers for 1-S
    struct drawT_params parameters;
    Real Xn, exponent, prefactor;
    
    Real nPI;
    
    // Construct the coefficients and the terms in the exponent and put them 
    // into the params structure
    int n = 0;
    // a simpler sum has to be computed for the case w/o drift, so distinguish here
    if(v==0)
    {
      do
      {
	  nPI = ((Real)(n+1))*M_PI;	// why n+1 : this loop starts at n=0 (1st index of the arrays), while the sum starts at n=1 !
	  Xn = sin(nPI*r0s_L) * (1.0 - cos(nPI)) / nPI; 
	  exponent = nPI*nPI*expo;
	  
	  // store the coefficients in the structure
	  parameters.Xn[n] = Xn;	
	  // also store the values for the exponent
	  parameters.exponent[n]=exponent;
	  n++;
      }
      // TODO: Modify this later to include a cutoff when changes are small
      while (n<MAX_TERMS);
    }
    else	// case with drift<>0
    {
     do
      {
	  nPI = ((Real)(n+1))*M_PI;	// why n+1 : this loop starts at n=0 (1st index of the arrays), while the sum starts at n=1 !
	  Xn = (exp(sigmav2D) - cos(nPI)*exp(av2D)) * nPI/(Lv2D*Lv2D+nPI*nPI) * sin(nPI*r0s_L);
	  exponent = nPI*nPI*expo + vexpo_t;
	  
	  // store the coefficients in the structure
	  parameters.Xn[n] = Xn;	
	  // also store the values for the exponent
	  parameters.exponent[n]=exponent;
	  n++;
      }
       // TODO: Modify this later to include a cutoff when changes are small
      while (n<MAX_TERMS);
    }

    // the prefactor of the sum is also different in case of drift<>0 :
    if(v==0)	prefactor = 2.0*exp(vexpo_pref);
    else	prefactor = 2.0;
    parameters.prefactor = prefactor;
    
    parameters.rnd = rnd;
    parameters.terms = MAX_TERMS;
    parameters.tscale = this->t_scale;

    gsl_function F;
    F.function = &drawT_f;
    F.params = &parameters;

    // Find a good interval to determine the first passage time in
    const Real dist( std::min(r0-sigma, a-r0) );

    // construct a guess: MSD = sqrt (2*d*D*t)
    Real t_guess( dist * dist / ( 2.0 * D ) );
    // A different guess has to be made in case of nonzero drift to account for the displacement due to it
    // When drifting towards the closest boundary...
    if( ( r0-sigma >= L/2.0 && v > 0.0 ) || ( r0-sigma <= L/2.0 && v < 0.0 ) )	t_guess = sqrt(D*D/(v*v*v*v)+dist*dist/(v*v)) - D/(v*v);
    // When drifting away from the closest boundary...
    if( ( r0-sigma  < L/2.0 && v > 0.0 ) || ( r0-sigma  > L/2.0 && v < 0.0 ) )	t_guess = D/(v*v) - sqrt(D*D/(v*v*v*v)-dist*dist/(v*v));
    
    
    Real value( GSL_FN_EVAL( &F, t_guess ) );
    Real low( t_guess );
    Real high( t_guess );

    if( value < 0.0 )
    {
	// scale the interval around the guess such that the function 
	// straddles if the guess was too low
	do
	{
	    // keep increasing the upper boundary until the 
	    // function straddles
	    high *= 10.0;
	    value = GSL_FN_EVAL( &F, high );

	    if( fabs( high ) >= t_guess * 1e6 )
	    {
		std::cerr << "Couldn't adjust high. F(" << high << ") = "
		          << value << std::endl;
		throw std::exception();
	    }
	}
	while ( value <= 0.0 );
    }
    else
    {
	// if the guess was too high initialize with 2 so the test 
	// below survives the first iteration
	Real value_prev( 2.0 );
	do
	{
	    if( fabs( low ) <= t_guess * 1.0e-6 ||
	        fabs(value-value_prev) < EPSILON*this->t_scale )
	    {
		std::cerr << "Couldn't adjust low. F(" << low << ") = "
		          << value << " t_guess: " << t_guess << " diff: "
		          << (value - value_prev) << " value: " << value
		          << " value_prev: " << value_prev << " t_scale: "
		          << this->t_scale << std::endl;
		return low;
	    }

	    value_prev = value;
	    // keep decreasing the lower boundary until the 
	    // function straddles
	    low *= 0.1;
	    // get the accompanying value
	    value = GSL_FN_EVAL( &F, low );

	}
	while ( value >= 0.0 );
    }

    // find the intersection on the y-axis between the random number and 
    // the function
    // define a new solver type brent
    const gsl_root_fsolver_type* solverType( gsl_root_fsolver_brent );
    // make a new solver instance
    // TODO: incl typecast?
    gsl_root_fsolver* solver( gsl_root_fsolver_alloc( solverType ) );
    const Real t( findRoot( F, solver, low, high, EPSILON*t_scale, EPSILON,
                            "GreensFunction1DAbsAbs::drawTime" ) );

    // return the drawn time
    return t;
}
Ejemplo n.º 24
0
void
gsl_integration_qcheb (gsl_function * f, double a, double b, double *cheb12, double *cheb24)
{
  size_t i;
  double fval[25], v[12];

  /* These are the values of cos(pi*k/24) for k=1..11 needed for the
     Chebyshev expansion of f(x) */
  
  const double x[11] = { 0.9914448613738104,     
			 0.9659258262890683,
			 0.9238795325112868,     
			 0.8660254037844386,
			 0.7933533402912352,     
			 0.7071067811865475,
			 0.6087614290087206,     
			 0.5000000000000000,
			 0.3826834323650898,     
			 0.2588190451025208,
			 0.1305261922200516 };
  
  const double center = 0.5 * (b + a);
  const double half_length =  0.5 * (b - a);
  
  fval[0] = 0.5 * GSL_FN_EVAL (f, center + half_length);
  fval[12] = GSL_FN_EVAL (f, center);
  fval[24] = 0.5 * GSL_FN_EVAL (f, center - half_length);

  for (i = 1; i < 12; i++)
    {
      const size_t j = 24 - i;
      const double u = half_length * x[i-1];
      fval[i] = GSL_FN_EVAL(f, center + u);
      fval[j] = GSL_FN_EVAL(f, center - u);
    }

  for (i = 0; i < 12; i++)
    {
      const size_t j = 24 - i;
      v[i] = fval[i] - fval[j];
      fval[i] = fval[i] + fval[j];
    }

  {
    const double alam1 = v[0] - v[8];
    const double alam2 = x[5] * (v[2] - v[6] - v[10]);

    cheb12[3] = alam1 + alam2;
    cheb12[9] = alam1 - alam2;
  }

  {
    const double alam1 = v[1] - v[7] - v[9];
    const double alam2 = v[3] - v[5] - v[11];
    {
      const double alam = x[2] * alam1 + x[8] * alam2;

      cheb24[3] = cheb12[3] + alam;
      cheb24[21] = cheb12[3] - alam;
    }

    {
      const double alam = x[8] * alam1 - x[2] * alam2;
      cheb24[9] = cheb12[9] + alam;
      cheb24[15] = cheb12[9] - alam;
    }
  }

  {
    const double part1 = x[3] * v[4];
    const double part2 = x[7] * v[8];
    const double part3 = x[5] * v[6];
    
    {
      const double alam1 = v[0] + part1 + part2;
      const double alam2 = x[1] * v[2] + part3 + x[9] * v[10];
      
      cheb12[1] = alam1 + alam2;
      cheb12[11] = alam1 - alam2;
    }
    
    {
      const double alam1 = v[0] - part1 + part2;
      const double alam2 = x[9] * v[2] - part3 + x[1] * v[10];
      cheb12[5] = alam1 + alam2;
      cheb12[7] = alam1 - alam2;
    }
  }

  {
    const double alam = (x[0] * v[1] + x[2] * v[3] + x[4] * v[5]
		+ x[6] * v[7] + x[8] * v[9] + x[10] * v[11]);
    cheb24[1] = cheb12[1] + alam;
    cheb24[23] = cheb12[1] - alam;
  }

  {
    const double alam = (x[10] * v[1] - x[8] * v[3] + x[6] * v[5] 
		- x[4] * v[7] + x[2] * v[9] - x[0] * v[11]);
    cheb24[11] = cheb12[11] + alam;
    cheb24[13] = cheb12[11] - alam;
  }

  {
    const double alam = (x[4] * v[1] - x[8] * v[3] - x[0] * v[5] 
		- x[10] * v[7] + x[2] * v[9] + x[6] * v[11]);
    cheb24[5] = cheb12[5] + alam;
    cheb24[19] = cheb12[5] - alam;
  }

  {
    const double alam = (x[6] * v[1] - x[2] * v[3] - x[10] * v[5] 
		+ x[0] * v[7] - x[8] * v[9] - x[4] * v[11]);
    cheb24[7] = cheb12[7] + alam;
    cheb24[17] = cheb12[7] - alam;
  }

  for (i = 0; i < 6; i++)
    {
      const size_t j = 12 - i;
      v[i] = fval[i] - fval[j];
      fval[i] = fval[i] + fval[j];
    }

  {
    const double alam1 = v[0] + x[7] * v[4];
    const double alam2 = x[3] * v[2];

    cheb12[2] = alam1 + alam2;
    cheb12[10] = alam1 - alam2;
  }

  cheb12[6] = v[0] - v[4];

  {
    const double alam = x[1] * v[1] + x[5] * v[3] + x[9] * v[5];
    cheb24[2] = cheb12[2] + alam;
    cheb24[22] = cheb12[2] - alam;
  }

  {
    const double alam = x[5] * (v[1] - v[3] - v[5]);
    cheb24[6] = cheb12[6] + alam;
    cheb24[18] = cheb12[6] - alam;
  }

  {
    const double alam = x[9] * v[1] - x[5] * v[3] + x[1] * v[5];
    cheb24[10] = cheb12[10] + alam;
    cheb24[14] = cheb12[10] - alam;
  }

  for (i = 0; i < 3; i++)
    {
      const size_t j = 6 - i;
      v[i] = fval[i] - fval[j];
      fval[i] = fval[i] + fval[j];
    }

  cheb12[4] = v[0] + x[7] * v[2];
  cheb12[8] = fval[0] - x[7] * fval[2];

  {
    const double alam = x[3] * v[1];
    cheb24[4] = cheb12[4] + alam;
    cheb24[20] = cheb12[4] - alam;
  }

  {
    const double alam = x[7] * fval[1] - fval[3];
    cheb24[8] = cheb12[8] + alam;
    cheb24[16] = cheb12[8] - alam;
  }

  cheb12[0] = fval[0] + fval[2];

  {
    const double alam = fval[1] + fval[3];
    cheb24[0] = cheb12[0] + alam;
    cheb24[24] = cheb12[0] - alam;
  }

  cheb12[12] = v[0] - v[2];
  cheb24[12] = cheb12[12];

  for (i = 1; i < 12; i++)
    {
      cheb12[i] *= 1.0 / 6.0;
    }

  cheb12[0] *= 1.0 / 12.0;
  cheb12[12] *= 1.0 / 12.0;

  for (i = 1; i < 24; i++)
    {
      cheb24[i] *= 1.0 / 12.0;
    }

  cheb24[0] *= 1.0 / 24.0;
  cheb24[24] *= 1.0 / 24.0;
}
const Real 
GreensFunction2DAbsSym::drawTime( const Real rnd ) const
{
  
    THROW_UNLESS( std::invalid_argument, rnd < 1.0 && rnd >= 0.0 );

    const Real a( geta() );

    if( getD() == 0.0 || a == std::numeric_limits<Real>::infinity() )
    {
            return std::numeric_limits<Real>::infinity();
    }
    if( a == 0.0 )
    {
            return 0.0;
    }

    p_survival_params params = { this, rnd };

    gsl_function F = 
    {
            reinterpret_cast<double (*)(double, void*)>( &p_survival_F ), &params 
    };

    //for (Real t=0.0001; t<=1; t+=0.0001)
    //{	std::cout << t << " " << GSL_FN_EVAL( &F, t) << std::endl;
    //}

    // Find a good interval to determine the first passage time in
    const Real t_guess( a * a / ( 4. * D ) );   // construct a guess: msd = sqrt (2*d*D*t)
    Real value( GSL_FN_EVAL( &F, t_guess ) );
    Real low( t_guess );
    Real high( t_guess );

    // scale the interval around the guess such that the function straddles
    if( value < 0.0 )               // if the guess was too low
    {
            do
            {       high *= 10;     // keep increasing the upper boundary until the function straddles
                    value = GSL_FN_EVAL( &F, high );

                    if( fabs( high ) >= t_guess * 1e6 )
                    {
//                            log_.warn("Couldn't adjust high. F(%.16g) = %.16g", high, value);
                            throw std::exception();
                    }
            }
            while ( value <= 0.0 );
    }
    else                            // if the guess was too high
    {
            Real value_prev( value );
            do
            {       low *= .1;      // keep decreasing the lower boundary until the function straddles
                    value = GSL_FN_EVAL( &F, low );     // get the accompanying value

                    if( fabs( low ) <= t_guess * 1e-6 || fabs( value - value_prev ) < CUTOFF )
                    {
//                            log_.warn("Couldn't adjust high. F(%.16g) = %.16g", low, value);
                            return low;
                    }
                    value_prev = value;
            }
            while ( value >= 0.0 );
    }

    // find the root
    const gsl_root_fsolver_type* solverType( gsl_root_fsolver_brent );  // a new solver type brent
    gsl_root_fsolver* solver( gsl_root_fsolver_alloc( solverType ) );   // make a new solver instance
    const Real t( findRoot( F, solver, low, high, 1e-18, 1e-12,
                        "GreensFunction2DAbsSym::drawTime" ) );
    gsl_root_fsolver_free( solver );

    return t;
}
Ejemplo n.º 26
0
Real GreensFunction3DAbsSym::drawTime(Real rnd) const
{
    const Real D(getD());

    if (rnd >= 1.0 || rnd < 0.0)
    {
        throw std::invalid_argument((boost::format("0.0 <= %.16g < 1.0") % rnd).str());
    }

    const Real a(geta());

    if (D == 0.0 || a == INFINITY)
    {
        return INFINITY;
    }

    if (a == 0.0)
    {
        return 0.0;
    }

    p_survival_params params = { this, rnd };

    gsl_function F = 
        {
            reinterpret_cast<double (*)(double, void*)>( &p_survival_F ),
            &params 
        };

    const Real t_guess(a * a / (6. * D));

    Real low(t_guess);
    Real high(t_guess);

    const Real value(GSL_FN_EVAL(&F, t_guess));

    if (value < 0.0)
    {
        high *= 10;

        for (;;)
        {
            const Real high_value(GSL_FN_EVAL(&F, high));
            
            if (high_value >= 0.0)
            {
                break;
            }

            if (fabs(high) >= t_guess * 1e6)
            {
                throw std::runtime_error(
                    (boost::format("couldn't adjust high. F(%.16g) = %.16g; %s") %
                       high % GSL_FN_EVAL(&F, high) %
                       boost::lexical_cast<std::string>(*this)).str());
            }
            high *= 10;
        }
    }
    else
    {
        Real low_value_prev(value);
        low *= .1;

        for (;;)
        {
            const Real low_value(GSL_FN_EVAL(&F, low));
            
            if (low_value <= 0.0)
            {
                break;
            }
            
            if (fabs(low) <= t_guess * 1e-6 ||
                fabs(low_value - low_value_prev) < CUTOFF)
            {
                log_.info("couldn't adjust high. F(%.16g) = %.16g; %s",
                          low, GSL_FN_EVAL(&F, low),
                          boost::lexical_cast<std::string>(*this).c_str());
                log_.info("returning low (%.16g)", low);
                return low;
            }
            low_value_prev = low_value;
            low *= .1;
        }
    }


    const gsl_root_fsolver_type* solverType(gsl_root_fsolver_brent);
    gsl_root_fsolver* solver(gsl_root_fsolver_alloc(solverType));

    const Real t(findRoot(F, solver, low, high, 1e-18, 1e-12,
                            "GreensFunction3DAbsSym::drawTime"));

    gsl_root_fsolver_free(solver);

    return t;
}
Ejemplo n.º 27
0
Real GreensFunction3DSym::drawR(Real rnd, Real t) const
{
    // input parameter range checks.
    if ( !(rnd <= 1.0 && rnd >= 0.0 ) )
    {
        throw std::invalid_argument( ( boost::format( "GreensFunction3DSym: rnd <= 1.0 && rnd >= 0.0 : rnd=%.16g" ) % rnd ).str() );
    }

    if ( !(t >= 0.0 ) )
    {
        throw std::invalid_argument( ( boost::format( "GreensFunction3DSym: t >= 0.0 : t=%.16g" ) % t ).str() );
    }


    // t == 0 or D == 0 means no move.
    if( t == 0.0 || getD() == 0.0 )
    {
        return 0.0;
    }

    ip_r_params params = { this, t, rnd };

    gsl_function F = 
        {
            reinterpret_cast<double (*)(double, void*)>( &ip_r_F ),
            &params 
        };

    Real max_r( 4.0 * sqrt( 6.0 * getD() * t ) );

    while( GSL_FN_EVAL( &F, max_r ) < 0.0 )
    {
        max_r *= 10;
    }

    const gsl_root_fsolver_type* solverType( gsl_root_fsolver_brent );
    gsl_root_fsolver* solver( gsl_root_fsolver_alloc( solverType ) );
    gsl_root_fsolver_set( solver, &F, 0.0, max_r );

    const unsigned int maxIter( 100 );

    unsigned int i( 0 );
    while( true )
    {
        gsl_root_fsolver_iterate( solver );
        const Real low( gsl_root_fsolver_x_lower( solver ) );
        const Real high( gsl_root_fsolver_x_upper( solver ) );
        const int status( gsl_root_test_interval( low, high, 1e-15, 
                                                  this->TOLERANCE ) );

        if( status == GSL_CONTINUE )
        {
            if( i >= maxIter )
            {
                gsl_root_fsolver_free( solver );
                throw std::runtime_error("GreensFunction3DSym: drawR: failed to converge");
            }
        }
        else
        {
            break;
        }

        ++i;
    }
  
    //printf("%d\n", i );

    const Real r( gsl_root_fsolver_root( solver ) );
    gsl_root_fsolver_free( solver );
    
    return r;
}
Ejemplo n.º 28
0
int
test (const char * name, gsl_function * f, double x[], int N, char *fmt)
{
  int i;
  double res, err, sum = 0, sumerr = 0;

  printf ("void test_auto_%s (void);\n\n", name);

  printf ("void\ntest_auto_%s (void)\n{\n", name);

  /* gsl_set_error_handler_off(); */

  w = gsl_integration_workspace_alloc (1000);

  for (i = 0; i < N; i++)
    {
      res = 0;
      err = 0;

      if (x[0] < -1000)
        {
          if (x[i] < 0)
            {
              res = integrate_lower (f, x[i]);
            }
          else
            {
              res = 1 - integrate_upper (f, x[i]);
            }
          sum = res;
        }
      else
        {
          if (i == 0)
            sum += 0;
          else
            sum += integrate(f, x[i-1], x[i]);
        }
      
      if (res < 0) 
        continue;

      printf (fmt, "_P", x[i], sum);

      if (inverse && (sum != 0 && sum != 1) && (x[i] == 0 || sum * 1e-4 < GSL_FN_EVAL(f,x[i]) * fabs(x[i])))
        printf (fmt, "_Pinv", sum, x[i]);
    }

  printf("\n");

  sum=0;
  sumerr=0;

  for (i = N-1; i >= 0; i--)
    {
      res = 0;
      err = 0;

      if (x[N-1] > 1000)
        {
          if (x[i] > 0)
            {
              res = integrate_upper (f, x[i]);
            }
          else
            {
              res = 1-integrate_lower (f, x[i]);
            }

          sum = res;
        }
      else 
        {
          if (i == N-1)
            sum += 0;
          else
            sum += integrate(f, x[i], x[i+1]);
        }

      printf (fmt, "_Q", x[i], sum);

      if (inverse && (sum != 0 && sum != 1) && (x[i] == 0 || sum * 1e-4 < GSL_FN_EVAL(f,x[i]) * fabs(x[i])))
        printf (fmt, "_Qinv", sum, x[i]);
    }
  
  printf ("}\n\n");

  gsl_integration_workspace_free (w);

}
Ejemplo n.º 29
0
// Draws the first passage time from the propendity function
const Real FirstPassageGreensFunction1DRad::drawTime (const Real rnd) const
{
    const Real L(this->getL());
    const Real k(this->getk());
    const Real D(this->getD());
    const Real r0(this->getr0());

    THROW_UNLESS( std::invalid_argument, 0.0 <= rnd && rnd < 1.0 );

    if ( D == 0.0 || L == INFINITY )
    {
        return INFINITY;
    }

    if ( rnd <= EPSILON || L < 0.0 || fabs(r0 - L) < EPSILON*L )
    {
        return 0.0;
    }


    const Real h(k/D);

    // the structure to store the numbers to calculate the numbers for 1-S
    struct drawT_params parameters;
    double An = 0;
    double tmp0, tmp1, tmp2, tmp3;
    double Xn, exponent;


    // produce the coefficients and the terms in the exponent and put them
    // in the params structure. This is not very efficient at this point,
    // coefficients should be calculated on demand->TODO
    for (int n=0; n<MAX_TERMEN; n++)
    {
        An = a_n (n+1); // get the n-th root of tan(alfa*L)=alfa/-k
        tmp0 = An * An; // An^2
        tmp1 = An * r0; // An * z'
        tmp2 = An * L;	// An * L
        tmp3 = h / An;	// h / An
        Xn = (An*cos(tmp1) + h*sin(tmp1)) *
             (sin(tmp2)-tmp3*cos(tmp2)+tmp3) / (L*(tmp0+h*h)+h);
        exponent = -D*tmp0;

        // store the coefficients in the structure
        parameters.Xn[n] = Xn;
        // also store the values for the exponent
        parameters.exponent[n]=exponent;

    }
    // store the random number for the probability
    parameters.rnd = rnd;
    // store the number of terms used
    parameters.terms = MAX_TERMEN;
    parameters.tscale = this->t_scale;

    // Define the function for the rootfinder
    gsl_function F;
    F.function = &FirstPassageGreensFunction1DRad::drawT_f;
    F.params = &parameters;


    // Find a good interval to determine the first passage time in
    // get the distance to absorbing boundary (disregard rad BC)
    const Real dist(L-r0);
    // construct a guess: msd = sqrt (2*d*D*t)
    const Real t_guess( dist * dist / ( 2. * D ) );
    Real value( GSL_FN_EVAL( &F, t_guess ) );
    Real low( t_guess );
    Real high( t_guess );


    // scale the interval around the guess such that the function straddles
    if( value < 0.0 )
    {
        // if the guess was too low
        do
        {
            // keep increasing the upper boundary until the
            // function straddles
            high *= 10;
            value = GSL_FN_EVAL( &F, high );

            if( fabs( high ) >= t_guess * 1e6 )
            {
                std::cerr << "GF1DRad: Couldn't adjust high. F("
                          << high << ") = " << value << std::endl;
                throw std::exception();
            }
        }
        while ( value <= 0.0 );
    }
    else
    {
        // if the guess was too high
        // initialize with 2 so the test below survives the first
        // iteration
        Real value_prev( 2 );
        do
        {
            if( fabs( low ) <= t_guess * 1e-6 ||
                    fabs(value-value_prev) < EPSILON*1.0 )
            {
                std::cerr << "GF1DRad: Couldn't adjust low. F(" << low << ") = "
                          << value << " t_guess: " << t_guess << " diff: "
                          << (value - value_prev) << " value: " << value
                          << " value_prev: " << value_prev << " rnd: "
                          << rnd << std::endl;
                return low;
            }
            value_prev = value;
            // keep decreasing the lower boundary until the function straddles
            low *= .1;
            // get the accompanying value
            value = GSL_FN_EVAL( &F, low );
        }
        while ( value >= 0.0 );
    }


    // find the intersection on the y-axis between the random number and
    // the function
    // define a new solver type brent
    const gsl_root_fsolver_type* solverType( gsl_root_fsolver_brent );
    // make a new solver instance
    // incl typecast?
    gsl_root_fsolver* solver( gsl_root_fsolver_alloc( solverType ) );
    const Real t( findRoot( F, solver, low, high, t_scale*EPSILON, EPSILON,
                            "FirstPassageGreensFunction1DRad::drawTime" ) );

    // return the drawn time
    return t;
}