/************************************************************************
* 
* McXtrace, X-ray tracing package
*         Copyright, All rights reserved
*         DTU Physics, Kgs. Lyngby, Denmark
*         Synchrotron SOLEIL, Saint-Aubin, France
*
*
* Component: Source_genesis
*
* %Identification
* Written by: Erik B Knudsen
* Date: Aug. 10th, 2014
* Origin: Risoe
* Release: McXtrace 1.2
*
* Interface source for importing GENESIS 1.3 generated X-ray pulses into McXtrace
* 
* %Description
* This source model reads the dumped radiation field output from GENESIS 1.3 and samples it to be used
* in McXtrace.
* 
* Example: Source_pt(dist=1,focus_xw=0.1,focus_yh=0.1, lamda=0.231, dlambda=0.002)
*
* %Parameters
* focus_xw: [m]     Width of target.
* focus_yh: [m]     Height of target.
* E0:       [keV]   Mean energy of xrays.
* dE:       [kev]   Half-width (or std. dev.) of emitted energy spectrum.
* fname:    [string] Filename of main output file of GENESIS 1.3.
* meshsize: [m]     Spacing between mesh points (equal in x and y).
* gridpoints:[int]  Number of mesh points along 1 axis.
* s0:       [m]     Back end of pulse time sampling windows scaled by c^-1. 
* s1:       [m]     Front end of pulse time sampling window scaled by c^-1.
* focus_a:  [rad]   Mean divergence angle.
* nslices:  [int]   Number of slices simulated
* flux:     [1]     Flux-multiplier
* dist:     [m]     Distance to target along z axis.
*
* %End
***********************************************************************/

DEFINE COMPONENT Source_genesis13

SETTING PARAMETERS (int gridpoints=101, string fname="template.out",focus_xw=0,focus_yh=0,dist=1,E0=0, dE=0, 
    meshsize=1e-5, int nslices=102, s0=-2e-3,s1=2e-3,flux=1.0, focus_a=0.1)

/* X-ray parameters: (x,y,z,kx,ky,kz,phi,t,Ex,Ey,Ez,p) */ 

SHARE
%{
  %include "read_table-lib"
#include <complex.h>
%}


DECLARE
%{
  double e;
  double pmul;
  double pint;
  t_Table T;
  double complex **dfl;
%}

INITIALIZE
%{

  /*open the main output file and parse for parameters*/
  /*skip this for now*/

  char dflfn[512];
  FILE *dflfp;
  int k,l,m;
  double *r;
  double *i;

  r=malloc(gridpoints*sizeof(double));
  i=malloc(gridpoints*sizeof(double));

  strncpy(dflfn,fname,502);
  strncat(dflfn,".dfl",4);
  /*allocate storage for the input array*/
  if( (dfl=calloc(nslices,sizeof(double complex *)))==NULL){
    fprintf(stderr,"Error(%s): allocation failed for slice array. Aborting.\n",NAME_CURRENT_COMP);
    exit(-1);
  }
  if( (dflfp=Open_File(dflfn,"r",NULL))==NULL){
    fprintf(stderr,"Error(%s): cannot open file %s for reading- Aborting.\n",NAME_CURRENT_COMP,dflfn);
    exit(-1);
  }

  for (k=0;k<nslices;k++){
    /*printf("alloc'ing for slice %d...",k);*/
    if( (dfl[k]=calloc(gridpoints*gridpoints,sizeof(double complex)))==NULL) { 
      fprintf(stderr,"Error(%s): allocation failed for slice %d. Aborting.\n",NAME_CURRENT_COMP,k);
      exit(-1);
    }
    /*printf("done\n");*/
    /*so read the data*/
    /*printf("reading for slice %d...",k);*/
    for (l=0;l<gridpoints;l++){
      int s=0;
      for (m=0;m<gridpoints;m++){
        s+=fread(r+m,sizeof(double),1,dflfp);
        s+=fread(i+m,sizeof(double),1,dflfp);
      }
      if(s!=2*gridpoints){
        fprintf(stderr,"Error(%s): input data not read cleanly (slice %d, row %d)\n",NAME_CURRENT_COMP,k,l);
      }
      for (m=0;m<gridpoints;m++){
        dfl[k][l*gridpoints+m]=r[m]+I*i[m];
      }
    }
    /*printf("done\n");*/
  }
  free(r);
  free(i);
  pmul=flux/(double)mcget_ncount();
%}

TRACE
%{
  double xwidth,yheight,k;
  double theta_x,theta_y;
  double alpha,beta;
  double complex cp,cp2,t0,t1;
  int ix,iy,is;
  double ds,s,deltas;

  xwidth=(gridpoints-1)*meshsize;
  yheight=(gridpoints-1)*meshsize;
  /*sample x and y from gridsize*/
  x=(rand01()-0.5)*xwidth;
  y=(rand01()-0.5)*yheight;
  ix=(int)((x+0.5*xwidth)/meshsize);
  if(ix==gridpoints) ix--;
  iy=(int)((y+0.5*yheight)/meshsize);
  if(iy==gridpoints) iy--;

  /*sample s inbetween s and s0 and s1*/
  s=rand01()*(s1-s0);
  
  deltas=(s1-s0)/(nslices-1);
  /*which slice is closest*/
  is=(int)(s/deltas+0.5);
  if(is==nslices) is--;
  t=(s+s0)/M_C;


  alpha=( (x+0.5*xwidth - ix*meshsize) /meshsize );
  beta= ( (y+0.5*yheight - iy*meshsize) /meshsize );

  t0=(1-alpha)*dfl[is][iy*gridpoints+ix] + alpha*dfl[is][iy*gridpoints+ix+1];
  t1=(1-alpha)*dfl[is][(iy+1)*gridpoints+ix] + alpha*dfl[is][(iy+1)*gridpoints+ix+1];
  
  cp = (1-beta)*t0+beta*t1;
  /*cp now contains the complex radiation field at x,y*/

  p=pmul*cabs(cp);
  phi=carg(cp);

  theta_x=(randnorm())*focus_a;
  theta_y=(randnorm())*focus_a;
  
  /*draw random coordinates in the acceptance window*/
  kx=tan(theta_x);
  ky=tan(theta_y);
  kz=1;
  NORM(kx,ky,kz);

  k=E0*E2K;
  kx*=k;
  ky*=k;
  kz*=k;

  /*set polarization vector*/
  Ex=0;Ey=0;Ez=0;

%}

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

MCDISPLAY
%{
  double radius=0.05;
  
  circle("xy",0,0,0,radius);
  circle("xz",0,0,0,radius);
  circle("yz",0,0,0,radius);
%}

END
