/*******************************************************************************
*
* McXtrace, x-ray tracing package
*         Copyright, All rights reserved
*         DTU Physics, Kgs. Lyngby, Denmark
*         Synchrotron SOLEIL, Saint-Aubin, France
*
* Component: Lens_simple
*
* %Identification
* Written by: Erik Knudsen
* Date: June 16, 2009
* Origin: Risoe
*
* Simple refractive x-ray lens
* 
* %Description
* Models a stack of N refractive lenses, with a radius of curvature, r, at the apex.
* The model is a thin-lens approximation where photons are refracted in a the XY plane
* at Z=0. Absorption is generally disregarded may be handled through the use of the optional
* transmission parameter T, where 0<=T<=1.
* Thus, the lens has the focal length of f=R/(2*N*&delta) where the x-ray refractive
* index is written: n = 1 - &delta + i &beta.
*
* Example: Lens_simple(xwidth=1e-5, yheight=1e-5, material_datafile="Be.txt",N=100,r=0.3e-3)
*
* %Parameters
* INPUT PARAMETERS
*
* xwidth:  [m] Width of lens aperture.
* yheight: [m] Height of lens aperture.
* radius:  [m] Radius of lens aperture (overrides xwidth & yheight).
* f:       [m] Focal length - overrides the material_datafile - and diregards chromatic aberration.
* material_datafile: [ ] File where the material parameters for the lens may be found. Format is similar to what may be found off the NIST website.
* N:       [ ] The number of successive lenses in the stack.
* r:       [m] The radius of curvature of the lens.
* Optional parameters:
* T:       [0-1] Transmission efficiency of the lens.
* verbose: [ ] Extra information for debugging. 
*
* %Link
* material datafile obtained from http://physics.nist.gov/cgi-bin/ffast/ffast.pl
*
* %End
*******************************************************************************/
DEFINE COMPONENT Lens_simple
DEFINITION PARAMETERS ()
SETTING PARAMETERS (xwidth=0,yheight=0,radius=1e-3, T=1 ,r=3e-4, int N=1, int verbose=0, f=0, string material_datafile="Be.txt")
OUTPUT PARAMETERS ()
/* X-ray parameters: (x,y,z,kx,ky,kz,phi,t,Ex,Ey,Ez,p) */ 

SHARE
%{
  %include "read_table-lib"
%}

DECLARE
%{
  int Z;
  double Ar;
  double rho;
  t_Table matT;
%}

INITIALIZE
%{
  int status=0;
 
  if(!radius && !(xwidth && yheight) ){
    fprintf(stderr,"%s: Lens has zero effective area\n",NAME_CURRENT_COMP);
    exit(-1);
  }
  
  if(r<=0){
      fprintf(stderr,"Error (%s): No meaningful radius of curvature found r=%g.\n",NAME_CURRENT_COMP,r);
      exit(-1);
  }

  if (!f && material_datafile && strlen(material_datafile)){
      if ( (status=Table_Read(&(matT),material_datafile,0))==-1){
          fprintf(stderr,"Error: Could not parse file \"%s\" in COMP %s\n",material_datafile,NAME_CURRENT_COMP);
          exit(-1);
      }
      char **header_parsed;
      header_parsed=Table_ParseHeader(matT.header,"Z","A[r]","rho");
      if (!Ar) Ar=strtod(header_parsed[1],NULL);
      if (!Z) Z=strtol(header_parsed[0],NULL,10);
      if (!rho) rho=strtod(header_parsed[2],NULL);
  }

  if (T==0){
    fprintf(stderr,"Warning (%s): Transmission is set to 0 and no material set. All X-rays will be absorbed by lens\n.",NAME_CURRENT_COMP);
  }
%}

TRACE
%{
  double sx,sy,sz,s;  
  double s2x,s2y,s2z,s2;  
  double F,k,e,theta,alpha,delta;
  double f1,rhoel;

  PROP_Z0;
  if (radius && x*x+y*y<radius*radius){
      SCATTER;
  }else if (xwidth && (x >-xwidth*0.5 && x<xwidth*0.5 && y>-yheight*0.5 && y<yheight*0.5)){
      SCATTER;
  }else{
      ABSORB;
  }

  /*change direction towards focal point*/
  if(!f){
    /*Focal length given by lambda and delta*/
    k=sqrt(scalar_prod(kx,ky,kz,kx,ky,kz));
    e=K2E*k;
    f1=Table_Value(matT,e,1);

    /*Calculation of Refractive Index */
    rhoel= f1*NA*(rho*1e-24)/Ar; /*Material's Number Density of Electrons [e/A^3] incl f' scattering length correction*/
    delta= 2.0*M_PI*RE*rhoel/(k*k);
    F=r/2/delta/N;
  }else{
    /*focal length is a scalar*/
    F=f;
  }

  /*Only focusing in the y-direction for now.*/


  /*auxiliary vector s*/
  sx=0;sy=-y;sz=F;
  s=sqrt(scalar_prod(sx,sy,sz,sx,sy,sz));
  theta=acos(scalar_prod(sx,sy,sz,0,0,1)/s);
  if (y<0)theta=-theta; /*if y is negative rotation should be ccw*/
  /*apply the rotation around the x-axis to focus in y*/
  Rotation R;
  R[0][0]=1; R[0][1]=0;R[0][2]=0;
  R[1][0]=0; R[1][1]=cos(theta); R[1][2]=-sin(theta);
  R[2][0]=0; R[2][1]=sin(theta); R[2][2]=cos(theta);
  /*reuse the vector s as temp storage*/
  sx=kx;
  sy=ky*R[1][1]+kz*R[1][2];
  sz=ky*R[2][1]+kz*R[2][2];
  
  /*rotate around a vector parallel to x.*/
  rotate(s2x,s2y,s2z, kx,ky,kz, theta, 1, 0, 0);

  kx=s2x;ky=s2y;kz=s2z;

  /*set the phase shift*/
  phi+=k*1e10*((x*x+y*y)/2*F); /*k in AA⁻1 but x,y and f are in m. conversion factor.*/
  
  p *= T;
%}

FINALLY
%{
  Table_Free(&(matT));
%}


MCDISPLAY
%{
  double delta;
  int NN=8;
  int i;
  
  rectangle("xy",0,0,0,xwidth,yheight);
  if (yheight<xwidth){
    delta=yheight/NN;
  } else {
    delta=xwidth/NN;
  }
  for (i=1;i<=NN;i++){
    circle("xy",0,0,0,sqrt(delta*i));
  }
%}

END
