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
|
/*******************************************************************************
*
* McXtrace, x-ray tracing package
* Copyright, All rights reserved
* DTU Physics, Kgs. Lyngby, Denmark
* Synchrotron SOLEIL, Saint-Aubin, France
*
* Component: Mirror_toroid_pothole
*
* %Identification
*
* Written by: Erik B Knudsen
* Date: Jul 2016
* Version: 1.0
* Origin: DTU Physics
* Modified by: Padovani Antoine, 5th August 2022.
*
* Toroidal shape mirror (in XZ)
*
* %Description
* This is an implementation of a toroidal mirror which may be curved in two dimensions.
* To avoid solving quartic equations, the intersection is computed as a combination of
* two intersections. First, the ray is intersected with a cylinder to catch (almost) the small
* radius curvature. Secondly, the ray is the intersected with an ellipsoid, with the curvatures
* matching that of the torus.
*
* The first incarnation (Mirror_toroid.comp) the mirror curves outwards (a bump), but this incarnation (Mirror_toroid_pothole) curves inwards (a pothole).
*
* Example: Mirror_toroid_pothole( radius=0.1, radius_o=1000, xwidth=5e-2, zdepth=2e-1,R0=1, coating="")
*
* %Parameters
* R0: [1] Reflectivity of mirror.
* xwidth: [m] Width of mirror.
* zdepth: [m] Length of mirror.
* coating: [str] Datafile containing either mirror material constants or reflectivity numbers.
* radius: [m] Curvature radius
* radius_o:[m] Curvature radius, outwards
*
* %End
*******************************************************************************/
DEFINE COMPONENT Mirror_toroid_pothole
SETTING PARAMETERS (zdepth=0.1, xwidth=0.01, radius, radius_o,R0=0,string coating="")
SHARE
%{
#include <complex.h>
%include "read_table-lib"
%include "reflectivity-lib"
struct potholestruct {
double e_min,e_max,e_step,theta_min,theta_max,theta_step;
int use_reflec_table;
};
%}
DECLARE
%{
struct potholestruct prms;
t_Table reflec_table;
t_Reflec re;
%}
INITIALIZE
%{
if (coating && strlen(coating)){
char **header_parsed;
t_Table *tp=&reflec_table;
/* read 1st block data from file into tp */
if (Table_Read(tp, coating, 1) <= 0)
{
exit(fprintf(stderr,"Error: %s: cannot read file %s\n",NAME_CURRENT_COMP, coating));
}
header_parsed = Table_ParseHeader(tp->header,
"e_min=","e_max=","e_step=","theta_min=","theta_max=","theta_step=",NULL);
if (header_parsed[0] && header_parsed[1] && header_parsed[2] &&
header_parsed[3] && header_parsed[4] && header_parsed[5])
{
prms.e_min=strtod(header_parsed[0],NULL);
prms.e_max=strtod(header_parsed[1],NULL);
prms.e_step=strtod(header_parsed[2],NULL);
prms.theta_min=strtod(header_parsed[3],NULL);
prms.theta_max=strtod(header_parsed[4],NULL);
prms.theta_step=strtod(header_parsed[5],NULL);
} else {
exit(fprintf(stderr,"Error: %s: wrong/missing header line(s) in file %s\n", NAME_CURRENT_COMP, coating));
}
if (((tp->rows-2)*prms.e_step) > (prms.e_max-prms.e_min))
{
exit(fprintf(stderr,"Error: %s: e_step does not match e_min and e_max in file %s (<)\n",NAME_CURRENT_COMP, coating));
}
if ((prms.e_max-prms.e_min) > ((tp->rows)*prms.e_step))
{
exit(fprintf(stderr,"Error: %s: e_step does not match e_min and e_max in file %s (>)\n",NAME_CURRENT_COMP, coating));
}
if (((tp->columns-2)*prms.theta_step) > (prms.theta_max-prms.theta_min))
{
exit(fprintf(stderr,"Error: %s: theta_step does not match theta_min and theta_max in file %s (<)\n",NAME_CURRENT_COMP,coating));
}
if ((prms.theta_max-prms.theta_min) > ((tp->columns)*prms.theta_step))
{
exit(fprintf(stderr,"Error: %s: theta_step does not match theta_min and theta_max in file %s (>)\n",NAME_CURRENT_COMP,coating));
}
prms.use_reflec_table=1;
}else{
prms.use_reflec_table=0;
}
%}
TRACE
%{
int status;
double l0,l1,l2,l3,tx,ty,tz;
do {
/*TODO check the permutation of coordinates and the actual position of the cylinder.*/
status= cylinder_intersect(&l0,&l1,x,z,y-radius,kx,kz,ky, radius, zdepth);
if (!status) break; /* no interaction with the cylinder*/
//if(status & (02|04)) break; /*we exit the top/bottom of the cylinder*/
if(status & (24)) break;
//if(status & (8|16)) break; /*we exit the top/bottom of the cylinder*/
/*if the first intersection is behind the particle - this means the ray is on the wrong side of the mirror*/
if(l1<0) break;
do {
/*this to do a test propagation*/
double op[12];
op[0]=x; op[1]=y; op[2]=z; op[3]=kx; op[4]=ky; op[5]=kz; op[6]=phi; op[7]=t; op[8]=Ex; op[9]=Ey; op[10]=Ez; op[12]=p;
mcPROP_DL(l1);
(tx)=x;(ty)=y; (tz)=z;
x=op[0]; y=op[1]; z=op[2]; kx=op[3]; ky=op[4]; kz=op[5]; phi=op[6]; t=op[7]; Ex=op[8]; Ey=op[9]; Ez=op[10]; p=op[12];
}while(0);
/*check mirror limits of intersectio point.*/
if(tz<-zdepth/2.0 || tz>zdepth/2.0) break;
/*check if the width is OK*/
double xmax=acos(xwidth/(2.0*radius))*radius;
if(tx<-xmax || tx>xmax) break;
status=ellipsoid_intersect(&l2,&l3,x,y-radius,z,kx,ky,kz,radius,radius,radius_o+radius,NULL);
if (!status) break;
if(l3<0) break; /*This shouldn't be possible*/
/*the mirror is indeed hit*/
PROP_DL(l3);
SCATTER;
double nx,ny,nz;
nx=2*x/(radius*radius);
ny=2*(y-radius)/(radius*radius);/*ellipsoid is displaced to put Origin on the surface*/
nz=2*z/((radius+radius_o)*(radius+radius_o));
NORM(nx,ny,nz);
/*By definition the normal vector points out from the ellipsoid*/
double s=scalar_prod(kx,ky,kz,nx,ny,nz);
double k=sqrt(scalar_prod(kx,ky,kz,kx,ky,kz));
kx=kx-2*s*nx;
ky=ky-2*s*ny;
kz=kz-2*s*nz;
/*find energy, and glancing angle*/
if (prms.use_reflec_table){
/*the get ref. by call to Table_value2d*/
double R;
double theta=RAD2DEG*(acos(s/k)-M_PI_2);
double e=K2E*k;
R=Table_Value2d(reflec_table,fabs((e-prms.e_min)/prms.e_step), fabs(((theta-prms.theta_min)/prms.theta_step)));
p*=R;
/*update phase - as an approximation turn by 180 deg.*/
phi+=M_PI;
}else{
p*=R0;
}
}while(0);
%}
MCDISPLAY
%{
//See parametric equation used for the 3D view here: https://en.wikipedia.org/wiki/Torus#Geometry or here:https://web.maths.unsw.edu.au/~rsw/Torus/index.php
//Because the code above doesn't actually reproduce a torus exactly but uses a cylinder and an ellipsoid to construct the toroidal mirror (to avoid solving quartic equations),
//there's a slight mismatch between the 3D view (exact torus) and the actual toroidal mirror coded above.
double x0,y0,z0,x1,y1,z1,theta,phi,phi_total,theta_total,theta_beginning,phi_beginning,theta_end,phi_end;
//int N=50; too many points, makes the 3D matlab viewer bug
int N=10;
phi_total = RAD2DEG*(zdepth/(radius+radius_o));//degrees
theta_total = RAD2DEG*(xwidth/radius);
//fix theta=0 and phi=180 degrees respectively
theta=0;
phi=180;
//then start at the beginning of the theta or phi range in order to map the flat surface (xwidth, zdepth) on the torus.
theta_beginning=theta-(theta_total/2);
phi_beginning=phi-(phi_total/2);
theta_end = theta+(theta_total/2);
phi_end = phi+(phi_total/2);
theta = theta_beginning;
phi = phi_beginning;
while (theta<=theta_end){
phi=180-(phi_total/2);
x0=radius*sin(DEG2RAD*theta);
y0=(radius_o+radius*cos(DEG2RAD*theta))*cos(DEG2RAD*phi)+(radius_o+radius);
z0=(radius_o+radius*cos(DEG2RAD*theta))*sin(DEG2RAD*phi);
while (phi<=phi_end){
x1=radius*sin(DEG2RAD*theta);
y1=(radius_o+radius*cos(DEG2RAD*theta))*cos(DEG2RAD*phi)+(radius_o+radius);
z1=(radius_o+radius*cos(DEG2RAD*theta))*sin(DEG2RAD*phi);
line(x0,y0,z0,x1,y1,z1);
x0=x1;
y0=y1;
z0=z1;
phi+=phi_total/N;
}
theta+=theta_total/N;
}
theta = theta_beginning;
phi = phi_beginning;
while (phi<=phi_end){
theta=-(theta_total/2);
x0=radius*sin(DEG2RAD*theta);
y0=(radius_o+radius*cos(DEG2RAD*theta))*cos(DEG2RAD*phi)+(radius_o+radius);
z0=(radius_o+radius*cos(DEG2RAD*theta))*sin(DEG2RAD*phi);
while (theta<=theta_end){
x1=radius*sin(DEG2RAD*theta);
y1=(radius_o+radius*cos(DEG2RAD*theta))*cos(DEG2RAD*phi)+(radius_o+radius);
z1=(radius_o+radius*cos(DEG2RAD*theta))*sin(DEG2RAD*phi);
line(x0,y0,z0,x1,y1,z1);
x0=x1;
y0=y1;
z0=z1;
theta+=theta_total/N;
}
phi+=phi_total/N;
}
%}
END
|