/*******************************************************************************
*
* McXtrace, X-ray tracing package
*         Copyright, All rights reserved
*         DTU Physics, Kgs. Lyngby, Denmark
*         Synchrotron SOLEIL, Saint-Aubin, France
*
* Component: Saxs_spheres
*
* %Identification
* Written by: E. B. Knudsen, P. Willendrup, K. Lefmann, L. Arleth
* Date: 28.10.2010
* Origin: DTU Fysik
* Release: McXtrace 1.1
*
* Sample for Small Angle X-ray Scattering - hard spheres in thin solution, mono disperse.
*
* %Description
* Sample for use in a SAXS instrument, models hard, monodisperse spheres in thin solution.
*   The shape of the sample may be a filled box with dimensions 
*   xwidth, yheight, zdepth, a cylinder with dimensions radius and yheight,
*   a filled sphere with radius R.
*
* Example: Saxs_spheres(R = 20, Phi = 1e-3, Delta_rho = 0.6, sigma_abs = 50, xwidth=0.01, yheight=0.01, zdepth=0.005)
*
* %Parameters
*
* INPUT PARAMETERS
*
* R:        [AA] Radius of scattering hard spheres 
* Phi:      [1] Particle volume fraction
* Delta_rho: [fm/AA^3] Excess scattering length density 
* radius:   [m] Outer radius of sample in (x,z) plane for cylinder/sphere
* xwidth:   [m] horiz. dimension of sample, as a width
* yheight:  [m] vert . dimension of sample, as a height for cylinder/box
* zdepth:   [m] depth of sample
* target_index: [1] Relative index of component to focus at, e.g. next is +1
* focus_xw: [m] horiz. dimension of a rectangular area
* focus_yh: [m] vert.  dimension of a rectangular area
* focus_aw: [deg] horiz. angular dimension of a rectangular area
* focus_ah: [deg] vert.  angular dimension of a rectangular area
* focus_r:  [m] Detector (disk-shaped) radius
*
* Optional parameters:
* target_x: [m]
* target_y: [m] position of target to focus at 
* target_z: [m]
* sphere_mtrl: [] Material datafile from which to find absorption. If none is given absorption is neglected. 
* mu_c: [5] Column of the datafile which contains absorption coefficients.
*
* %End
*******************************************************************************/

DEFINE COMPONENT Saxs_spheres
DEFINITION PARAMETERS ()
SETTING PARAMETERS (string sphere_mtrl="", R=100, Phi=1e-3, Delta_rho=0.6, 
xwidth=0, yheight=0, zdepth=0, radius=0,
target_x = 0, target_y = 0, target_z = 6, int target_index=0, 
focus_xw=0, focus_yh=0, focus_aw=0, focus_ah=0, focus_r=0, mu_c=0)
OUTPUT PARAMETERS ()
/* X-ray parameters: (x,y,z,kx,ky,kz,phi,t,Ex,Ey,Ez,p) */ 
DECLARE
%{
  double my_s_pre;
  int shape;
  int Z;
  double At;
  double rho;
  t_Table T;
  int mu_ci;/*which column holds absorption mus*/
  int abs_data;
%}
INITIALIZE
%{
  shape=-1; /* -1:no shape, 0:cyl, 1:box, 2:sphere  */
  if (xwidth && yheight && zdepth)  shape=1; /* box */
  else if (radius > 0 && yheight)   shape=0; /* cylinder */
  else if (radius > 0 && !yheight)  shape=2; /* sphere */

  if (shape < 0) 
    exit(fprintf(stderr,"Saxs_spheres: %s: sample has invalid dimensions.\n"
                        "ERROR     Please check parameter values.\n", NAME_CURRENT_COMP));
  
  /* now compute target coords if a component index is supplied */
  if (!target_index && !target_x && !target_y && !target_z) target_index=1;
  if (target_index)
  {
    Coords ToTarget;
    ToTarget = coords_sub(POS_A_COMP_INDEX(INDEX_CURRENT_COMP+target_index),POS_A_CURRENT_COMP);
    ToTarget = rot_apply(ROT_A_CURRENT_COMP, ToTarget);
    coords_get(ToTarget, &target_x, &target_y, &target_z);
  }

  if (!(target_x || target_y || target_z)) {
    printf("Saxs_spheres: %s: The target is not defined. Using direct beam (Z-axis).\n",
      NAME_CURRENT_COMP);
    target_z=1;
  }
  /*check for existance of a sphere material datafile. If none is given absorption will be neglected.*/
  if (sphere_mtrl && strlen(sphere_mtrl) && strcmp(sphere_mtrl,"NULL")){  
    int status;
    if ( sphere_mtrl && (status=Table_Read(&(T),sphere_mtrl,0))==-1){
      fprintf(stderr,"Error(%s): Could not parse file \"%s\"\n",NAME_CURRENT_COMP,sphere_mtrl);
      exit(-1);
    }
    char **header_parsed;
    header_parsed=Table_ParseHeader(T.header,"Z","A[r]","rho","Z/A","sigma[a]",NULL);
    if(header_parsed[2]){rho=strtod(header_parsed[2],NULL);}
    if(header_parsed[0]){Z=strtod(header_parsed[0],NULL);}
    if(header_parsed[1]){At=strtod(header_parsed[1],NULL);}
    /*which columns holds the mus*/
    if (mu_c){
      mu_ci=mu_c;
    }else{
      /*not given so take a guess*/
      mu_ci=5;
      if (T.columns==3) mu_ci=1;
    }
    abs_data=1;
  }else{
    abs_data=0;
  }
  my_s_pre = Phi * 4*PI*R*R*R/3 * Delta_rho*Delta_rho;

%}
TRACE
%{
  double l0, l1, v, l_full, l, l_1, dt, dl, d_phi, theta, my_a_v;
  double aim_x=0, aim_y=0, aim_z=1, axis_x, axis_y, axis_z;
  double arg, tmp_vx, tmp_vy, tmp_vz, vout_x, vout_y, vout_z;
  double f, solid_angle, kx_i, ky_i, kz_i, k, q, qx, qy, qz;
  char   intersect=0;

  /* Intersection particle trajectory / sample (sample surface) */
  if (shape == 0)
    intersect = cylinder_intersect(&l0, &l1, x, y, z, kx, ky, kz, radius, yheight);
  else if (shape == 1)
    intersect = box_intersect(&l0, &l1, x, y, z, kx, ky, kz, xwidth, yheight, zdepth);
  else if (shape == 2)
    intersect = sphere_intersect(&l0, &l1, x, y, z, kx, ky, kz, radius);
  if(intersect)
  {
    if(l0 < 0){
      fprintf(stderr,"photon already inside sample %s - absorbing\n",NAME_CURRENT_COMP);
      ABSORB;
    }
    /* Xray enters at l=l0. */
    k = sqrt(kx*kx + ky*ky + kz*kz);
    l_full = (l1 - l0);             /* Length of full path through sample */
    dl = rand01()*(l1 - l0) + l0; /* Time of scattering */
    PROP_DL(dl);                  /* Point of scattering */
    l = (dl-l0);                /* Penetration in sample */

    kx_i=kx;
    ky_i=ky;
    kz_i=kz;
    if ((target_x || target_y || target_z)) {
      aim_x = target_x-x;       /* Vector pointing at target (anal./det.) */
      aim_y = target_y-y;
      aim_z = target_z-z;
    }
    if(focus_aw && focus_ah) {
      randvec_target_rect_angular(&kx, &ky, &kz, &solid_angle,
        aim_x, aim_y, aim_z, focus_aw, focus_ah, ROT_A_CURRENT_COMP);
    } else if(focus_xw && focus_yh) {
      randvec_target_rect(&kx, &ky, &kz, &solid_angle,
        aim_x, aim_y, aim_z, focus_xw, focus_yh, ROT_A_CURRENT_COMP);
    } else {
      randvec_target_circle(&kx, &ky, &kz, &solid_angle, aim_x, aim_y, aim_z, focus_r);
    }
    NORM(kx, ky, kz);
    kx *= k;
    ky *= k;
    kz *= k;
    qx = (kx_i-kx);
    qy = (ky_i-ky);
    qz = (kz_i-kz);
    q = sqrt(qx*qx+qy*qy+qz*qz);

    f = 3 * (sin(q*R) - q*R*cos(q*R))/(q*R*q*R*q*R);

    /*calculate absorption*/
    if(abs_data){
      my_a_v=Table_Value(T,k*K2E,mu_ci);
    }else{
      my_a_v=0;
    }
    p *= l_full*solid_angle/(4*PI)*my_s_pre*f*f*exp(-my_a_v*(l+l1));
    SCATTER;
  }
%}

MCDISPLAY
%{
  
  if (shape == 0) {	/* cylinder */
    circle("xz", 0,  yheight/2.0, 0, radius);
    circle("xz", 0, -yheight/2.0, 0, radius);
    line(-radius, -yheight/2.0, 0, -radius, +yheight/2.0, 0);
    line(+radius, -yheight/2.0, 0, +radius, +yheight/2.0, 0);
    line(0, -yheight/2.0, -radius, 0, +yheight/2.0, -radius);
    line(0, -yheight/2.0, +radius, 0, +yheight/2.0, +radius);
  }
  else if (shape == 1) { 	/* box */
    box(0,0,0,xwidth,yheight,zdepth);
  }
  else if (shape == 2) {	/* sphere */
    circle("xy", 0,  0.0, 0, radius);
    circle("xz", 0,  0.0, 0, radius);
    circle("yz", 0,  0.0, 0, radius);        
  }
%}
END
