1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
|
/*******************************************************************************
*
* McXtrace, X-ray tracing package
* Copyright, All rights reserved
* DTU Physics, Kgs. Lyngby, Denmark
* Synchrotron SOLEIL, Saint-Aubin, France
*
* Component: Abs_objects
*
* %Identification
* Written by: Erik Knudsen
* Date: Jan 24, 2011
* Version: $Revision$
* Origin: DTU Physics
* Release: McXtrace 1.1
*
* Blocks of attenuating material in off format
*
* %Description
*
* This component is a model of 1 or more off-shaped blocks attenuating the x-ray beam.
* Which shapes are present and their relative positions are described in a file of the follwing format:
* #objects
* Material-filename OFF-filename x y z xwidth yheight zdepth
* ...
*
* An example is;
* 2
* Be.txt cube.off 0 0.01 0 0 0 0
* Rh.txt chess.off 0 -0.01 0 0 0 0
*
* A xwidth etc of zero means use whatever dimensions are in the off/ply file.
* If xwidth (or yheight or zdepth) is nonzero, the component scales the object
* to fill that dimension. The xyz coordinates indicate the object shift.
*
* Example: Abs_objects(objects="input_abs_objects_template.dat")
*
* %Parameters
* INPUT PARAMETERS
* objects: [str] Input file where the off-shapes are defined.
* refraction: [str] Flag to enable refraction at interfaces.
*
* %End
*******************************************************************************/
DEFINE COMPONENT Abs_objects
SETTING PARAMETERS (int refraction=1, string objects="input_abs_objects_template.dat")
/* X-ray parameters: (x,y,z,kx,ky,kz,phi,t,Ex,Ey,Ez,p) */
SHARE
%{
#ifndef MX_ABS_OBJECTS_MAX_INTERSECTS
#define MX_ABS_OBJECTS_MAX_INTERSECTS 256
#endif
%include "read_table-lib"
%include "interoff-lib"
struct _abs_object_data_struct {
int mu_c;
double Z,Ar, rho;
double delta_prefactor,betafact;
double xx,obj_xwidth,yy,obj_yheight,zz,obj_zdepth;
};
#pragma acc routine
int abs_object_refract(double *kx, double *ky, double *kz, double nx, double ny, double nz, double delta0, double delta1){
const double n2=scalar_prod(nx,ny,nz, nx,ny,nz);
const double k=sqrt(scalar_prod(*kx,*ky,*kz, *kx,*ky,*kz));
const double nr=(1.0-delta0)/(1.0-delta1);
double kxi=*kx;
double kyi=*ky;
double kzi=*kz;
double s;
NORM(kxi,kyi,kzi);
if(n2!=1){
NORM(nx,ny,nz);
}
s=scalar_prod(nx,ny,nz,kxi,kyi,kzi);
if(s>0){
/*n points in the direction of k - i.e. into material 1, so use -n instead*/
double sinth2=nr*nr*(1.0-(s)*(s));
*kx=nr* (kxi) - (nr*(-s)+sqrt(1.0-sinth2))*(-nx);
*ky=nr* (kyi) - (nr*(-s)+sqrt(1.0-sinth2))*(-ny);
*kz=nr* (kzi) - (nr*(-s)+sqrt(1.0-sinth2))*(-nz);
} else {
/*n points oppsite to k - i.e. out of material 1, into mat. 0*/
double sinth2=nr*nr*(1.0-s*s);
*kx=nr* (kxi) - (nr*s+sqrt(1.0-sinth2))*nx;
*ky=nr* (kyi) - (nr*s+sqrt(1.0-sinth2))*ny;
*kz=nr* (kzi) - (nr*s+sqrt(1.0-sinth2))*nz;
}
*kx *=k;
*ky *=k;
*kz *=k;
return 1;
}
%}
DECLARE
%{
int mu_c[128];
double Z[128];
double Ar[128];
double rho[128];
double delta_prefactor[128];
double betafact[128];
double xx[128];
double obj_xwidth[128];
double yy[128];
double obj_yheight[128];
double zz[128];
double obj_zdepth[128];
int objectsc;
struct _abs_object_data_struct prms[128];
t_Table mat_table[128];
off_struct offdata[128];
%}
INITIALIZE
%{
FILE *fp=Open_File(objects,"r",NULL);
if (fp == NULL) {
fprintf(stderr,"Error: %s: Could not open file \"%s\".\n", NAME_CURRENT_COMP, objects);
exit(-1);
}
char line[512];
fgets(line,512,fp);
objectsc=atoi(line);
int i;
for (i=0;i<objectsc;i++){
fgets(line,512,fp);
char off_fn[512],mat_fn[512];
float xx1,yy1,zz1,xwidth,yheight,zdepth;
int status;
//sscanf(line,"%s %s \n", mat_fn,off_fn);
status=sscanf(line,"%s %s %g %g %g %g %g %g\n",
mat_fn,off_fn, &xx1,&yy1,&zz1,&xwidth,&yheight,&zdepth);
if (status < 8) {
fprintf(stderr,"Error: %s: Invalid line %i in file \"%s\".\n",
NAME_CURRENT_COMP, i+1, objects);
exit(-1);
}
xx[i]=xx1; yy[i]=yy1; zz[i]=zz1;
obj_xwidth[i]=xwidth; obj_yheight[i]=yheight; obj_zdepth[i]=zdepth;
if ( (status=Table_Read(&(mat_table[i]),mat_fn,0))==-1){
fprintf(stderr,"Error: %s: Could not parse file \"%s\".\n",
NAME_CURRENT_COMP, mat_fn);
exit(-1);
}
char **header_parsed;
header_parsed=Table_ParseHeader(mat_table[i].header,"Z","A[r]","rho","Z/A","sigma[a]",NULL);
if (header_parsed[0]){Z[i]=strtod(header_parsed[0],NULL);}
if (header_parsed[1]){Ar[i]=strtod(header_parsed[1],NULL);}
if (header_parsed[2]){rho[i]=strtod(header_parsed[2],NULL);}
else{fprintf(stderr,"Warning: %s: %s not found in header of %s, set to 1.\n",
NAME_CURRENT_COMP,"rho",mat_fn);rho[i]=1;}
/*which columns holds the mus*/
mu_c[i]=5;
if (mat_table[i].columns==3) {
/*format for compound material (XCOM) is assumed. For now set delta_prefactor=0 => delta=0 (no refraction).*/
mu_c[i]=1;
delta_prefactor[i]=0;
}else{
delta_prefactor[i]= NA*(rho[i]*1e-24)/Ar[i] * 2.0*M_PI*RE;
}
/*read in the off/ply data from file. The literal 1 is to not center the object in local (0,0,0)*/
if (!off_init(off_fn, obj_xwidth[i], obj_yheight[i], obj_zdepth[i], 1, &(offdata[i]))) {
fprintf(stderr,"Error: %s: Could not parse file \"%s\".\n",
NAME_CURRENT_COMP, off_fn);
exit(-1);
}
printf("%s: Volume[%d], material='%s' geometry='%s'\n",
NAME_CURRENT_COMP, i+1,mat_fn,off_fn);
}
fclose(fp);
%}
TRACE
%{
double alpha,e,k,kx_vac,ky_vac,kz_vac,mu,mu0,delta,beta,f;
double l0,l1,nx,ny,nz;
Coords c0,c1;
int i=1,j,m,status=0,exit=0;
int intersect=0,entry_exit=0;
double lmin;
int idx;
struct intersection_data_struct {
double l0,dl;
double mu0,beta,delta;
double _kx,_ky,_kz;
int idx;
int entry_exit;
} intersections[MX_ABS_OBJECTS_MAX_INTERSECTS],intersection_tmp;
k=sqrt(kx*kx+ky*ky+kz*kz);
e=k*K2E;
kx_vac=kx;
ky_vac=ky;
kz_vac=kz;
for (i=0;i<MX_ABS_OBJECTS_MAX_INTERSECTS;i++){
intersections[i].dl=0;
}
int intersectionc=0;
for (i=0;i<objectsc;i++){
l0=0;
l1=0;
status = off_x_intersect(&l0, &l1, &c0,&c1, x-xx[i], y-yy[i], z-zz[i], kx, ky, kz, offdata[i] );
if (status>1){/*ignore singlet intersections*/
if (l0<0 && l1 >0){
/*we're already inside some thing. Set l0 to 0;*/
l0=0;
}
if (l0>=0) {
int j=0;
intersectionc++;
if(intersectionc>=MX_ABS_OBJECTS_MAX_INTERSECTS){
fprintf(stderr, "Warning: %s: Intersection storage overrun. Rest of scene will be ignored. Please examine results carefully and/or recompile with \"-DMX_ABS_OBJECTS_MAX_INTERSECTS=N\" where N>256",NAME_CURRENT_COMP);
break;
}
/*a dl of 0 marks an unused slot*/
while ( intersections[j].dl!=0 && (intersections[j].l0<l0 || (intersections[j].l0==l0 && intersections[j].dl<(l1-l0)) ) ) {
j++;
}
int m=objectsc*2;//MX_ABS_OBJECTS_MAX_INTERSECTS-1;
while (m>j){
if(intersections[m-1].dl!=0){
intersections[m]=intersections[m-1];
}
m--;
}
intersections[j].l0=l0;
intersections[j].dl=l1-l0;
intersections[j].idx=i;
/*precompute some material constants*/
double f;
f=Table_Value(mat_table[i],e,1);
intersections[j].delta = f/(k*k) * delta_prefactor[i];
intersections[j].mu0=Table_Value(mat_table[i],e,mu_c[i])*rho[i]*1e2;
intersections[j].beta = mu0/(2*k);
/*change k we're now inside some material*/
intersections[j]._kx=kx_vac*(1.0-intersections[j].delta);
intersections[j]._ky=ky_vac*(1.0-intersections[j].delta);
intersections[j]._kz=kz_vac*(1.0-intersections[j].delta);
}
}
}
/*now we can loop through the intersection times and do propagation accordingly*/
double lsum=0;
for (j=0;j<intersectionc;j++){
/*set k*/
/*if l0-lsum>0 propagate to the first intersection in vacuum. I.e. prop. to object entry.*/
double dl=intersections[j].l0-lsum;
if (dl>0){
PROP_DL(dl);
lsum+=dl;
SCATTER;
}
//kx=intersections[j].kx;
//ky=intersections[j].ky;
//kz=intersections[j].kz;
dl=intersections[j].dl;
p*=exp(-intersections[j].mu0*dl);
PROP_DL(dl);
lsum+=dl;
SCATTER;/*we set scatterpoints at entry and exit*/
//kx=kx_vac;
//ky=ky_vac;
//kz=kz_vac;
/*we may reenter this object at a later stage so check for intersection again*/
l0=-1;l1=-1;status=0;
i=intersections[j].idx;
status = off_x_intersect(&l0, &l1, &c0, &c1, x-xx[i], y-yy[i], z-zz[i], kx, ky, kz, offdata[i] );
if (status>1 && l0>FLT_EPSILON && l1>FLT_EPSILON){/*ignore singlet intersections*/
/*we do in fact hit the object again*/
intersection_tmp=intersections[j];/*store the computed material values for later*/
intersection_tmp.dl=l1-l0;
if (l0<0 && l1 >0){
/*already inside something. Set l0 to 0;*/
l0=0;
}
if (l0>=0) {
l0=l0+lsum;/*correct for the fact that we have travelled in the component already*/
int m=j;/*start at the present object and go on to sort in this intersection*/
/*a dl of 0 marks an unused slot*/
while ( intersections[m+1].dl!=0 && (intersections[m+1].l0<l0 || (intersections[m+1].l0==l0 && intersections[m+1].dl<(l1-l0)) ) ) {
intersections[m]=intersections[m+1];
m++;
}
intersections[m]=intersection_tmp;/*reinsert values but override new intersection lengths*/
intersections[m].l0=l0;
}
/*we have added another intersection so don't progress j*/
j--;
}
}
%}
FINALLY
%{
int i;
for (i=0;i<objectsc;i++){
Table_Free(&(mat_table[i]));
}
%}
MCDISPLAY
%{
int i;
for (i=0;i<objectsc;i++){
off_display(offdata[i]);
}
%}
END
|