/************************************************************************
* 
* 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 Simplex generated X-ray pulses into McXtrace
* 
* %Description
* This source model reads the dumped radiation field output from Simplex and samples it to be used
* in McXtrace.
* 
* %Parameters
* focus_xw:   [m]   Width of target.
* focus_yh:   [m]   Height of target.
* dist:       [m]   Distance to target along z axis.
* E0:         [keV] Mean energy of xrays.
* dE:         [keV] Energy half spread of x-rays.
* 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:    [1]   Number of slices simulated.
* flux:       [1]   Flux-multiplier.
*
* %Link
* Tanaka, Journal of Synchrotron Radiation 22, 1319 (2015) http://journals.iucr.org/s/issues/2015/05/00/gb5029/
* http://radiant.harima.riken.go.jp/simplex/
* 
* %End
*****************************************************************************/

DEFINE COMPONENT Source_simplex
DEFINITION PARAMETERS ()
SETTING PARAMETERS (int gridpoints=101, string fname="template.fld",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)
OUTPUT PARAMETERS (prms)
/* X-ray parameters: (x,y,z,kx,ky,kz,phi,t,Ex,Ey,Ez,p) */ 

SHARE
%{
  %include "read_table-lib"
  #include <complex.h>
  struct Ssimplex_struct {
    double l0,dl;
    double s0,s1;
    double pmul,pint;
    t_Table T;
    double complex **dfl;
  };
%}


DECLARE
%{
  double e;
  struct Ssimplex_struct prms;
%}

INITIALIZE
%{

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

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

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

  strncpy(dflfn,fname,502);
  strncat(dflfn,".fld",4);
  /*allocate storage for the input array*/
  if( (prms.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( (prms.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(float),1,dflfp);
        s+=fread(i+m,sizeof(float),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++){
        prms.dfl[k][l*gridpoints+m]=r[m]+I*i[m];
      }
    }
    /*printf("done\n");*/
  }
  free(r);
  free(i);
  prms.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)*prms.dfl[is][iy*gridpoints+ix] + alpha*prms.dfl[is][iy*gridpoints+ix+1];
  t1=(1-alpha)*prms.dfl[is][(iy+1)*gridpoints+ix] + alpha*prms.dfl[is][(iy+1)*gridpoints+ix+1];
  
  cp = (1-beta)*t0+beta*t1;
  /*cp now contains the complex radiation field at x,y*/

  p=prms.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(&(prms.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
