Exemple #1
0
/* \fcnfh
   Computes optical depth at a given impact parameter, note that b needs
   to be given in units of 'rad' and the result needs to be multiplied by
   the units 'rad' to be real.
   There is no ray bending, refr=constant.
   It can take nrad values of 1 or bigger. However, if 2 is given then
   'ex' and 'rad' need to have a referenceable element at position
   -1; i.e. rad[-1] and ex[-1] need to exist.

   @returns $\frac{tau}{units_{rad}}$ returns optical depth divided by units
                                      of 'rad'
*/
static  PREC_RES
totaltau1(PREC_RES b,		/* impact parameter */
	  PREC_RES *rad,	/* Equispaced radius array */
	  PREC_RES refr,	/* refractivity index */
	  PREC_RES *ex,		/* extinction[rad] */
	  long nrad)		/* number of radii elements */
{
  int rs;
  int i;
  PREC_RES res;
  PREC_RES x3[3],r3[3];

  //Look for closest approach radius
  PREC_RES r0=b/refr;

  //get bin value 'rs' such that r0 is between rad[rs] inclusive
  //and rad[rs+1] exclusive.
  //If we are looking at the outmost layer, then return
  if((rs=binsearch(rad,0,nrad-1,r0))==-5)
    return 0;
  //If some other error occurred
  else if(rs<0)
    transiterror(TERR_CRITICAL,
		 "Closest approach value(%g) is outside sampled radius\n"
		 "range(%g - %g)\n"
		 ,r0,rad[0],rad[nrad-1]);
  //advance the extinction and radius arrays such that the zeroeth
  //element now is the closest sample to the minimum approach from below
  //it.
  rad+=rs;
  ex+=rs;
  nrad-=rs;

  //By parabolic fitting, interpolate the value of extinction at the
  //radius of minimum approach and store it in the sample that
  //corresponded to the closest from below. Store such value and radius,
  //which are to be replaced before returning (\lin{tmpex})
  const PREC_RES tmpex=*ex;
  const PREC_RES tmprad=*rad;
  if(nrad==2) *ex=interp_parab(rad-1,ex-1,r0);
  else *ex=interp_parab(rad,ex,r0);
  *rad=r0;
  if(nrad==2){
    x3[0]=ex[0];
    x3[2]=ex[1];
    x3[1]=(ex[1]+ex[0])/2.0;
    r3[0]=rad[0];
    r3[2]=rad[1];
    r3[1]=(rad[0]+rad[1])/2.0;
    *rad=tmprad;
    *ex=tmpex;
    rad=r3;
    ex=x3;
    nrad++;
  }
  const PREC_RES dr=rad[1]-rad[0];

  //Now convert to s spacing, i.e. distance along the path. Radius needs
  //to be equispaced.
  PREC_RES s[nrad];
  const PREC_RES Dr=rad[2]-rad[1];
  const PREC_RES cte=dr*(dr + 2*r0);
  s[0]=0;

  for(i=1 ; i<nrad ; i++)
    s[i]=sqrt(cte + (i-1)*Dr*(2.0*(r0+dr) + (i-1)*Dr) );

  //Integrate!\par
  //Use spline if GSL is available along with at least 3 points
#ifdef _USE_GSL
  gsl_interp_accel *acc = gsl_interp_accel_alloc ();
  gsl_interp *spl=gsl_interp_alloc(gsl_interp_cspline,nrad);
  gsl_interp_init(spl,s,ex,nrad);
  res=gsl_interp_eval_integ(spl,s,ex,0,s[nrad-1],acc);
  gsl_interp_free(spl);
  gsl_interp_accel_free (acc);
#else
#error non equispaced integration is not implemented without GSL
#endif /* _USE_GSL */

  //replace original value of extinction
  //\linelabel{tmpex}
  *ex=tmpex;
  *rad=tmprad;

  //return
  return 2*(res);
}
Exemple #2
0
/* DEF */
static PREC_RES
eclipsetau(struct transit *tr,
           PREC_RES height,    /* Altitude down to where calculate tau      */
           PREC_RES *ex){      /* Extinction per layer [rad]                */
  /* Incident angle:                                                        */
  //PREC_RES angle = tr->angles[tr->angleIndex];
  //PREC_RES angle_rad = angle * DEGREES;   
  /* Layers radius array:                                                   */
  prop_samp *rads = &tr->rads;  /* Radius sampling                           */
  PREC_RES *rad  = rads->v;     /* Radius array                              */
  /* Get the index rs, of the sampled radius immediately below or equal
     to height (i.e. rad[rs] <= height < rad[rs+1]):                        */
  int rs = binsearchapprox(rad, height, 0, tr->rads.n-1);

  /* Returns 0 if this is the top layer (no distance travelled):            */
  if (rs == tr->rads.n-1)
    return 0.0;

  /* Move pointers to the location of height:                               */
  rad += rs;
  ex  += rs;

  /* Number of layers beween height and the top layer:                      */
  int nrad = tr->rads.n - rs;

  PREC_RES res;          /* Optical depth divided by units of radius        */
  PREC_RES x3[3], r3[3]; /* Interpolation variables                         */

  /* Conversion to radian:                                                  */
  //PREC_RES angle_rad = angle * DEGREES;   

  /* Distance along the path:                                               */
  PREC_RES s[nrad];

  /* Providing three necessary points for spline integration:               */
  const PREC_RES tmpex  = *ex;
  const PREC_RES tmprad = *rad;

  if(nrad==2) *ex = interp_parab(rad-1, ex-1, rad[0]);
  else        *ex = interp_parab(rad,   ex,   rad[0]);

  if(nrad==2){
    x3[0] = ex[0];
    x3[2] = ex[1];
    x3[1] = (ex[1]+ex[0])/2.0;
    r3[0] = rad[0];
    r3[2] = rad[1];
    r3[1] = (rad[0]+rad[1])/2.0;
    *rad = tmprad;
    *ex  = tmpex;
    rad  = r3;
    ex   = x3;
    nrad++;
  }

  /* Distance along the path:                                               */
  s[0] = 0.0;
  for(int i=1; i < nrad; i++){
    s[i] = s[i-1] + (rad[i] - rad[i-1]); // /cos(angle_rad);
  }

  /* Integrate extinction along the path:                                   */
  /* Use spline if GSL is available along with at least 3 points:           */
//#ifdef _USE_GSL
//  gsl_interp_accel *acc = gsl_interp_accel_alloc();
//  gsl_interp *spl = gsl_interp_alloc(gsl_interp_cspline, nrad);
//  gsl_interp_init(spl, s, ex, nrad);
//  res = gsl_interp_eval_integ(spl, s, ex, 0, s[nrad-1], acc);
//  gsl_interp_free(spl);
//  gsl_interp_accel_free(acc);
//#else
//#error non equispaced integration is not implemented without GSL
//#endif /* _USE_GSL */

  /* Safety mode: GSL is acting up sometimes                                */
  res = integ_trapz(s, ex, nrad);

  /* Optical depth divided by units of radius:                              */
  return res;
}