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 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540
|
/*******************************************************************************
* Instrument: DISCO beam-line at SOLEIL
*
* %Identification
* Written by: Stephane Bac, Emmanuel Farhi, Antoine Padovani
* Date: 01/08/2022
* Origin: SOLEIL
* Version: 0.2
* %INSTRUMENT_SITE: SOLEIL
*
* DISCO beam-line at SOLEIL, imaging branch
*
* %Description
* DISCO beamline description here: https://hal.archives-ouvertes.fr/hal-01479318/document
* You may scan the grating monochromator with e.g.:
* mxrun -n 1e5 SOLEIL_DISCO.instr -N84 x_screw=20,103 scan=1
*
* %Example: grazing_angle_one=22.5 -n 1e5 Detector: second_HFP_I=2.08292e+11
*
* %Parameters
* grazing_angle_one: [deg] Mirrors M1/M2 rotation angle
* HFP_shift: [m] z translation from the HFP position (horizontal focal point detector)
* VFP_shift: [m] z translation from the VFP position (vertical focal point detector)
* second_HFP_shift: [m] z translation second HFP position
* x_screw: [mm] length of the screw
* scan: [] if there is an x_screw scan [1], calculate the Wavelength(Angstroms) as a function of x_screw(mm)
*
* %Link
* https://www.synchrotron-soleil.fr/en/beamlines/disco
*
* %End
*******************************************************************************/
//Work in progress.
//M3 should probably deviate the rays in the other direction, not very important (qualitatively), but something to change later on if so.
//Check that M53 and M54 should face each other in that fashion. Not sure.
//Add trapezoidal diaphragm.
//webgl viewer works but takes a bit of time to load.
DEFINE INSTRUMENT SOLEIL_DISCO(grazing_angle_one=22.5, HFP_shift=0, VFP_shift=0, second_HFP_shift=0, x_screw=50, scan=0)
DECLARE
%{
char filename[255];
double E0;
double dE;
double grazing_angle_reflect_grating;
//For more information on the following see the Czerny_turner instrument
//At a later date, the Czerny-turner used in this instrument should be changed to the one used on DISCO(blazed grating, toroidal mirrors ...)
double number_lines_per_mm;
double grazing_angle_order_grating;
double order;
double period;
double x_screw;
double theta_calculated;
double w_monitor_value;
double x_screw_var;
double w_monitor_error;
double number_events_w_monitor;
%}
INITIALIZE
%{
//Our source ranges from 1.2 to 6.2 eV (imaging branch, other branches to come at a later date)
E0 = 0.0037;
dE = 0.0025;
//For more information on the following see the Czerny_turner instrument
number_lines_per_mm = 1200;
theta_calculated = RAD2DEG*asin(x_screw/164.61);
order=1;
if (theta_calculated<9){
order=-1;
}
period = 1/(1e3*number_lines_per_mm);
%}
TRACE
COMPONENT Origin = Progress_bar()
AT (0, 0, 0) ABSOLUTE
/* -------------------------------------------------- Source */
COMPONENT Source = Bending_magnet(
E0=E0, dE = dE,
Ee = 2.75, Ie = 0.5, B = 1.72, sigex=45.5e-6, sigey=18.4e-6
)
AT (0, 0, 0) RELATIVE Origin
//____________________________________________________________ ??? 4.13? m : Diaphragm ==> trapezoidal?
//At 4.13 ma trapezoidal diaphragm reshapes thebeam and represents the optical aper-ture with maximum tolerances accom-modating beam position shifts while maintaining a constantbeam shape (dimensions: length 165.8 mm; inner and outerheight of the trapeze shape with respect to the storage ring:45.1 and 38.2 mm, respectively)
//____________________________________________________________ 4.975 m : Cold finger ==> cylindrical sample along x
//glidcop material,
//to set the tooth-like cold fingerfront-edge facing the beam.
/*COMPONENT placeholder_ColdFinger = Arm()
AT (0,0,4.975) RELATIVE Source*/
COMPONENT ColdFinger = Mask(xwidth=0.3, yheight=7.5e-3,mask="coldfinger.mask") //need to input the proper shape in the mask file
AT (0,0,4.975) RELATIVE Source
/*EXTEND
%{
if (SCATTERED) ABSORB;
%}*/
//____________________________________________________________ 5.800 m : M1 cylindrical convex mirror (vertical deviation) / beam goes up / 22.5° / Si / r = -75 m
COMPONENT M1_location = Arm()
AT (0,0,5.800) RELATIVE Source
COMPONENT M1_rotated = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (0,0,90) RELATIVE PREVIOUS
COMPONENT M1_x = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (90, 0, 0) RELATIVE PREVIOUS
// Mirror_curved is initially in the YZ plane
COMPONENT M1 = Mirror_curved(
coating="Si_disco.dat", radius=-75, length=0.26, width=0.19)//radius=-0.1 to see the curve for testing purposes. length and width reversed.
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (0, 0, -grazing_angle_one) RELATIVE PREVIOUS
EXTEND
%{
if (!SCATTERED) ABSORB;
%}
COMPONENT M1_takeoff = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (0, 0, -grazing_angle_one) RELATIVE PREVIOUS
COMPONENT M1_x_takeoff = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (-90, 0, 0) RELATIVE PREVIOUS
//____________________________________________________________ 6.000 m : M2 toroidal mirror (vertical deviation) : beam is sent back horizontally / 22.5° / Si / R = 21.04 m, r = 2.56 m
COMPONENT M2_location = Arm()
AT (0,0,0.2) RELATIVE M1_x_takeoff
COMPONENT M2_rotated_x = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (-90,0,0) RELATIVE M1
COMPONENT M2_rotated = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (0,0,-90) RELATIVE PREVIOUS
COMPONENT M2_other_side = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (0,0,180) RELATIVE PREVIOUS
COMPONENT M2 = Mirror_toroid_pothole(
xwidth = 0.26,
zdepth = 0.19,
radius = 2.56,
radius_o = 21.04,
coating="Si_disco.dat")
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (0, 0, 0) RELATIVE PREVIOUS
EXTEND
%{
if (!SCATTERED) ABSORB;
%}
COMPONENT M2_other_side_back = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (0,0,-180) RELATIVE PREVIOUS
COMPONENT M2_takeoff = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (grazing_angle_one, 0, 0) RELATIVE PREVIOUS
//____________________________________________________________ 14.000 m : HFP : Horizontal Focal Point ==> PSD
COMPONENT HFP_location = Arm()
AT (0,0,8) RELATIVE M2_takeoff
COMPONENT HFP = PSD_monitor(
nx=100, ny=100, filename="HFP_image.dat",xwidth=0.08,yheight=0.04)
AT (0,0, HFP_shift) RELATIVE PREVIOUS //HFP_shift should be less than 2.6m
//____________________________________________________________ 16.600 M3 elliptic cylindrical mirror (horizontal deviation) / 22.5 ° / Si / R = 9.93 m
//use a cylindrical mirror for now because I do not know what elliptic cylindrical means
COMPONENT M3_arm = Arm()
AT (0,0,2.6) RELATIVE HFP_location
ROTATED (0, 0, 0) RELATIVE HFP_location
// Mirror_curved is initially in YZ plane
COMPONENT M3 = Mirror_curved(
coating="Si_disco.dat", radius=9.93, length=240e-3, width=30e-3)
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (0, grazing_angle_one, 0) RELATIVE PREVIOUS
EXTEND
%{
if (!SCATTERED) ABSORB;
%}
COMPONENT M3_takeoff = Arm()
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED (0, grazing_angle_one, 0) RELATIVE PREVIOUS
COMPONENT M3_yz = Arm()
AT (0,0,0) RELATIVE PREVIOUS //to do like before
ROTATED (0, 0, 90) RELATIVE PREVIOUS
//____________________________________________________________ 16.800 M4 plane mirror (horizontal deviation) / 22.5° / Si
COMPONENT M4_yz = Arm()
AT (0,0,0.2) RELATIVE PREVIOUS
COMPONENT M4 = Mirror(
xwidth=30e-3,
zdepth=240e-3,
coating="Si_disco.dat")
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED ( -grazing_angle_one, 0, 0) RELATIVE PREVIOUS
EXTEND
%{
if (!SCATTERED) ABSORB;
%}
COMPONENT M4_takeoff = Arm()
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED ( -grazing_angle_one, 0, 0) RELATIVE PREVIOUS
//rotate 90 back so our repere is normal again
COMPONENT M4_arm_back = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (0, 0, -90) RELATIVE PREVIOUS
//____________________________________________________________ 18.470 m : VFP : Vertical Focal Point
COMPONENT VFP_location = Arm()
AT (0,0,1.67) RELATIVE M4_arm_back
COMPONENT VFP = PSD_monitor(
nx=100, ny=100, filename="VFP_image.dat",xwidth=0.02,yheight=0.04)
AT (0,0,VFP_shift) RELATIVE PREVIOUS //VFP_shift should be less than 1.48m
//____________________________________________________________ 19.950 m : M51 Convex spherical mirror (horizontal deviation) / 22.5° Si / R = -35 //Aluminium or Si?
COMPONENT M51_position = Arm()
AT (0, 0, 1.48) RELATIVE VFP_location
COMPONENT M51_rotation = Arm()
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED (0, 0, -90) RELATIVE PREVIOUS
COMPONENT M51 = Mirror_elliptic(
length=40e-3,
width=20e-3,
x_a=35, //0.04 for testing purposes
y_b=35,
z_c=35,
coating="Si_disco.dat")
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED (grazing_angle_one, 0, 0) RELATIVE PREVIOUS
EXTEND
%{
if (!SCATTERED) ABSORB;
%}
COMPONENT arm = Arm()
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED (grazing_angle_one, 0, 0) RELATIVE PREVIOUS
//rotate 90 back so our frame is normal again
COMPONENT M51_arm_back = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (0, 0, 90) RELATIVE PREVIOUS
//____________________________________________________________ 20.750 m : M52 cylindrical mirror (horizontal deviation) / 20.65° / AlMgF2 / r = 2 m
COMPONENT M52_position = Arm()
AT (0,0,0.8) RELATIVE PREVIOUS
COMPONENT M52_x = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (90, 0, 0) RELATIVE PREVIOUS
COMPONENT M52 = Mirror_curved(
radius=2, //0.04 for testing purposes
length=20e-3,//length and width reversed
width=40e-3,
coating="AlMgF2_disco.dat") // used the density of MgF2
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED (0, 0, -20.65) RELATIVE PREVIOUS
EXTEND
%{
if (!SCATTERED) ABSORB;
%}
COMPONENT M52_takeoff = Arm()
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED ( 0, 0, -20.65) RELATIVE PREVIOUS
COMPONENT M52_x_takeoff = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (-90, 0, 0) RELATIVE PREVIOUS
//____________________________________________________________ 25.71 m : HFP : Horizontal Focal Point ==> PSD
COMPONENT second_HFP_location = Arm()
AT (0,0,4.96) RELATIVE M52_x_takeoff
COMPONENT second_HFP = PSD_monitor(
nx=100, ny=100, filename="second_HFP_image.dat",xwidth=0.8,yheight=0.08)
AT (0,0, second_HFP_shift) RELATIVE PREVIOUS
//____________________________________________________________ 44.500 m : M53 toroidal mirror (horizontal deviation) / 22.5° / AlMgF2 / R = 4.75 m, r = 0.714 m
COMPONENT M53_location = Arm()
AT (0,0,23.75) RELATIVE M52_x_takeoff
COMPONENT M53_rotated = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (0,0,90) RELATIVE PREVIOUS
COMPONENT M53 = Mirror_toroid_pothole(
xwidth = 50e-3,
zdepth = 130e-3,
radius = 0.714,
radius_o=4.75,
coating="AlMgF2_disco.dat")
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (-grazing_angle_one, 0, 0) RELATIVE PREVIOUS
EXTEND
%{
if (!SCATTERED) ABSORB;
%}
COMPONENT M53_takeoff = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (-grazing_angle_one, 0, 0) RELATIVE PREVIOUS
//____________________________________________________________ 44.750 m : M54 toroidal mirror (horizontal deviation) / 22.5° / AlMgF2 / R = 7.80 m, r = 1.12 m
COMPONENT M54_location = Arm()
AT (0,0,0.25) RELATIVE PREVIOUS
COMPONENT M54_rotated = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (0,0,180) RELATIVE PREVIOUS
COMPONENT M54 = Mirror_toroid_pothole(
xwidth = 50e-3,
zdepth = 110e-3,
radius = 1.12,
radius_o=7.8,
coating="AlMgF2_disco.dat")
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (-grazing_angle_one, 0, 0) RELATIVE PREVIOUS
EXTEND
%{
if (!SCATTERED) ABSORB;
%}
COMPONENT M54_takeoff = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (-grazing_angle_one, 0, 0) RELATIVE PREVIOUS
COMPONENT Mtoroids_arm_back = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (0, 0, -180-90) RELATIVE PREVIOUS
//____________________________________________________________ 45.050 m : CX3, Czerny-turner monochromator
COMPONENT M1_position = Arm()
AT (0, 0, 0.3) RELATIVE PREVIOUS
COMPONENT M1_rotation = Arm()
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED (0, 0, 90) RELATIVE PREVIOUS
COMPONENT mirror_m1 = Mirror_elliptic(
length=150e-3,
width=150e-3,
x_a=1.025,
y_b=1.025,
z_c=1.025)
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED (-(90-4.5), 0, 0) RELATIVE PREVIOUS
EXTEND
%{
if (!SCATTERED) ABSORB;
%}
COMPONENT armm = Arm()
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED (-(90-4.5), 0, 0) RELATIVE PREVIOUS
//rotate 90 back so our frame is normal again
COMPONENT M1_arm_back = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (0, 0, -90) RELATIVE PREVIOUS
COMPONENT Grating_position = Arm()
AT (0, 0, 834.35e-3) RELATIVE PREVIOUS
COMPONENT Grating_rotation = Arm()
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED (-90, 0, 0) RELATIVE PREVIOUS
COMPONENT Grating_rotation_lines_grating = Arm()
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED (0, -90, 0) RELATIVE PREVIOUS
COMPONENT Grating_rotation_nine_degrees = Arm()
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED (-9, 0, 0) RELATIVE PREVIOUS
//COMPONENT reflective_grating = Grating_reflect(
SPLIT 100 COMPONENT reflective_grating = Grating_reflect(//SPLIT 100 can be taken off
d_phi=1,order=order,
rho_l=number_lines_per_mm,
zdepth=102e-3,xwidth=102e-3)
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED (theta_calculated, 0, 0) RELATIVE PREVIOUS //theta_calculated will change, angle between the bisector of phi and the grating's norm
COMPONENT Grating_rotation_lines_grating_back = Arm()
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED (0, 90, 0) RELATIVE PREVIOUS
//rotate 90 back so our frame is normal again
COMPONENT Grating_arm_back = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (90, 0, 0) RELATIVE PREVIOUS
COMPONENT Grating_arm_back_2 = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (0, 180, 0) RELATIVE PREVIOUS
COMPONENT Grating_arm_back_3 = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (0, -theta_calculated-9, 0) RELATIVE PREVIOUS
COMPONENT M22_location = Arm()
AT (0,0,749.1e-3) RELATIVE PREVIOUS
COMPONENT M22_rotated = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (0,0,90) RELATIVE PREVIOUS
COMPONENT mirror_m2 = Mirror_elliptic(
length=150e-3,
width=150e-3,
x_a=0.925,
y_b=0.925,
z_c=0.925)
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED (-(90-5), 0, 0) RELATIVE PREVIOUS
EXTEND
%{
if (!SCATTERED) ABSORB;
%}
COMPONENT arm2 = Arm()
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED (-(90-5), 0, 0) RELATIVE PREVIOUS
//rotate 90 back so our frame is normal again
COMPONENT M44_arm_back = Arm()
AT (0,0,0) RELATIVE PREVIOUS
ROTATED (0, 0, -90) RELATIVE PREVIOUS
COMPONENT arm3 = Arm()
AT (0, 0, 760.33e-3) RELATIVE PREVIOUS
ROTATED (0, 0, 0) RELATIVE PREVIOUS
COMPONENT psd_before_slit = PSD_monitor(
nx=100, ny=100, filename="psd_before_slit.dat",xwidth=130e-3,yheight=130e-3)
AT (0,0,0) RELATIVE PREVIOUS
COMPONENT slit = Slit(
//xwidth=13.5e-4,
xwidth=13.5e-6,
yheight=0.01)
AT (0, 0, 0) RELATIVE PREVIOUS
COMPONENT psd_monitor = PSD_monitor(
filename="psd",
xwidth=0.002,
yheight=0.02,
nx=100,
ny=100,
restore_xray = 1
)
AT (0, 0, 10e-3) RELATIVE PREVIOUS
COMPONENT psd_giant_after_grating = PSD_monitor(xwidth=2e-3, yheight=1e-2, filename="psd_giant_after_grating",nx=2001,ny=1)
AT(0,0,0) RELATIVE PREVIOUS
COMPONENT e_monitor = Monitor_nD(
xwidth=2e-3, yheight=1e-2, options="energy bins=500 limits=[0 0.007], x bins=500", filename="e_monitor",restore_xray = 1)
AT (0,0,0) RELATIVE PREVIOUS
COMPONENT w_monitor = Monitor_nD(
xwidth=2e-3, yheight=1e-2, options="wavelength bins=500 limits=[1980 11000], x bins=500", filename="w_monitor",restore_xray = 1)
AT (0,0,0) RELATIVE PREVIOUS
FINALLY
%{
// If there is a scan, calculate the Wavelength(Angstroms) as a function of x_screw(mm).
if(scan>=1){
#ifdef USE_MPI
//MPI_MASTER is equivalent to if(mpi_node_root>=mpi_node_rank){ //statement }
//If DETECTOR_OUT_0D is inside of MPI_MASTER the program hangs forever.
//If outside it seems to work. Weird.
MPI_MASTER(
#endif
MCDETECTOR w_monitor_var = COMP_GETPAR(w_monitor,detector); // We have to think in terms of wavelength, the sine drive mechanism was built to linearize the wavelength.
w_monitor_value = w_monitor_var.centerX;
x_screw_var = x_screw;
w_monitor_error = 0; //Forgot how to get rid of the error bar.
//For the error we could have dlambda = lambda*2*period*cos(phi)/L*dx_screw/x_screw, but we need to have dx_screw. Does it make sense for dx_screw to exist in an exact simulation?
number_events_w_monitor = w_monitor_var.events;
#ifdef USE_MPI
);
//MPI_Barrier(MPI_COMM_WORLD);
#endif
//Adding a legend to the graph would be good, need to find out how to do that at a later date. todo
// This set of defines is to avoid getting a '.' in the component name
Rotation Rot;
rot_set_rotation(Rot,0,0,0);
mcdetector_out_0D("Wavelength(Ang) as a function of x_screw(mm)", number_events_w_monitor, w_monitor_value, w_monitor_error, "Wavelength", coords_set(0,0,0),Rot);
}
%}
END
|