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 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632
|
/*******************************************************************************
*
* McStas, neutron ray-tracing package
* Copyright (C) 1997-2008, All rights reserved
* Risoe National Laboratory, Roskilde, Denmark
* Institut Laue Langevin, Grenoble, France
*
* Component: Source_gen
*
* %I
* Written by: Emmanuel Farhi, Kim Lefmann
* Date: Aug 27, 2001
* Origin: ILL/Risoe
* Modified by: EF, Aug 27, 2001 ; can use Energy/wavelength and I1
* Modified by: EF, Sep 18, 2001 ; corrected illumination bug. Add options
* Modified by: EF, Oct 30, 2001 ; minor changes. mccompcurname replaced
*
* Circular/squared neutron source with flat or Maxwellian energy/wavelength
* spectrum
*
* %D
* This routine is a neutron source (rectangular or circular), which aims at
* a square target centered at the beam (in order to improve MC-acceptance
* rate). The angular divergence is then given by the dimensions of the
* target. However, it may be directly set using the 'focus-aw' and 'focus_ah'
* parameters.
*
* The neutron energy/wavelength is distributed uniformly in wavelength between
* Emin=E0-dE and Emax=E0+dE or Lmin=lambda0-dlambda and Lmax=lambda0+dlambda.
* The I1 may be either arbitrary (I1=0), or specified in neutrons per steradian
* per square cm per Angstrom per s. A Maxwellian spectra may be selected if you
* give the source temperatures (up to 3).
*
* Finally, a file with the flux as a
* function of the wavelength [lambda(AA) flux(n/s/cm^2/st/AA)] may be used
* with the 'flux_file' parameter. Format is 2 columns free text.
*
* Additional distributions for the horizontal and vertical phase spaces
* distributions (position-divergence) may be specified with the
* 'xdiv_file' and 'ydiv_file' parameters. Format is free text, requiring
* a comment line '# xylimits: pos_min pos_max div_min div_max' to set
* the axis of the distribution matrix. All these files may be generated using
* standard monitors (better in McStas/PGPLOT format), e.g.:
* Monitor_nD(options="auto lambda per cm2")
* Monitor_nD(options="x hdiv, all auto")
* Monitor_nD(options="y vdiv, all auto")
*
* The source shape is defined by its radius, or can alternatively be squared
* if you specify non-zero yheight and xwidth parameters.
* The beam is divergence uniform,.
* The source may have a thickness, which will broaden the default zero time
* distribution.
*
* Usage example:
* Source_gen(radius=0.1,lambda0=2.36,dlambda=0.16,T1=20,I1=1e13,focus_xw=0.01,focus_yh=0.01)
* Source_gen(yheight=0.1,xwidth=0.1,Emin=1,Emax=3,I1=1e13,verbose=1,focus_xw=0.01,focus_yh=0.01)
* EXTEND
* %{
* t = rand0max(1e-3); // set time from 0 to 1 ms for TOF instruments.
* %}
*
* <b>Some neutron facility parameters:</b>
* PSI cold source T1=296.2,I1=8.5E11, T2=40.68,I2=5.2E11
* ILL VCS cold source T1=216.8,I1=1.24e+13,T2=33.9,I2=1.02e+13
* (H1, 58 MW) T3=16.7 ,I3=3.0423e+12
* ILL HCS cold source T1=413.5,I1=10.22e12,T2=145.8,I2=3.44e13
* (H5, 58 MW) T3=40.1 ,I3=2.78e13
* ILL Thermal tube T1=683.7,I1=0.5874e+13,T2=257.7,I2=2.5099e+13
* (H12, 58 MW) T3=16.7 ,I3=1.0343e+12
* ILL Hot source T1=1695, I1=1.74e13,T2=708, I2=3.9e12 (58MW)
* HZB cold source T1=43.7 ,I1=1.4e12, T2=137.2,I2=2.08e12,radius=.155 (10MW)
* HZB bi-spectral T1=43.7, I1=1.4e12, T2=137.2,I2=2.08e12,T3=293.0,I3=1.77e12
* HZB thermal tube T1=293.0,I1=2.64e12 (10MW)
* FRM2 cold,20MW T1=35.0, I1=9.38e12,T2=547.5,I2=2.23e12,T3=195.4,I3=1.26e13
* FRM2 thermal,20MW T1=285.6,I1=3.06e13,T2=300.0,I2=1.68e12,T3=429.9,I3=6.77e12
* LLB cold,14MW T1=220, I1=2.09e12,T2=60, I2=3.83e12,T3=20, I3=1.04e12
* TRIGA thermal 1MW T1=300, I1=3.5e11 (scale by thermal power in MW)
*
* %VALIDATION
* Feb 2005: output cross-checked for 3 Maxwellians against VITESS source
* I(lambda), I(hor_div), I(vert_div) identical in shape and absolute values
* Validated by: K. Lieutenant
*
* %P
* radius: [m] Radius of circle in (x,y,0) plane where neutrons are generated. You may also use 'yheight' and 'xwidth' for a square source
* target_index: [1] relative index of component to focus at, e.g. next is +1 this is used to compute 'dist' automatically.
* focus_xw: [m] Width of target.
* focus_yh: [m] Height of target.
*
* Energy or wavelength range must be defined by giving min and max value or
* average and spread:
* Emin: [meV] Minimum energy of neutrons
* Emax: [meV] Maximum energy of neutrons
* E0: [meV] Mean energy of neutrons.
* dE: [meV] Energy spread of neutrons, half width.
* Lmin: [AA] Minimum wavelength of neutrons
* Lmax: [AA] Maximum wavelength of neutrons
* lambda0: [AA] Mean wavelength of neutrons.
* dlambda: [AA] Wavelength spread of neutrons,half width
*
* Optional parameters:
* dist: [m] Distance to target along z axis.
* yheight: [m] Source y-height, then does not use radius parameter
* xwidth: [m] Source x-width, then does not use radius parameter
* zdepth: [m] Source z-zdepth, not anymore flat
* focus_aw: [deg] maximal (uniform) horz. width divergence
* focus_ah: [deg] maximal (uniform) vert. height divergence
* T1: [K] Temperature of the Maxwellian source, 0=none
* I1: [1/(cm**2*sr)] Source flux per solid angle, area and Angstrom if I1=0, the source emits 1 in 4*PI whole space.
* T2: [K] Second Maxwellian source Temperature, 0=none
* I2: [1/(cm**2*sr)] Second Maxwellian Source flux
* T3: [K] Third Maxwellian source Temperature, 0=none
* I3: [1/(cm**2*sr)] Third Maxwellian Source flux
* flux_file: [str] Name of a two columns [lambda flux] text file that contains the wavelength distribution of the flux in <b>either</b> [1/(s*cm**2*st)] <b>or</b> [1/(s*cm**2*st*AA)] (see flux_file_perAA flag) Comments (#) and further columns are ignored. Format is compatible with McStas/PGPLOT wavelength monitor files. When specified, temperature and intensity values are ignored.
* flux_file_perAA: [1] When true (1), indicates that flux file data is already per Aangstroem. If false, file data is per wavelength bin.
* flux_file_log: [1] When true, will transform the flux table in log scale to improve the sampling.
* xdiv_file: [str] Name of the x-horiz. divergence distribution file, given as a free format text matrix, preceeded with a line '# xylimits: xmin xmax xdiv_min xdiv_max'
* ydiv_file: [str] Name of the y-vert. divergence distribution file, given as a free format text matrix, preceeded with a line '# xylimits: ymin ymax ydiv_min ydiv_max'
* verbose: [0/1] display info about the source. -1 unactivate source.
*
* %L
* P. Ageron, Nucl. Inst. Meth. A 284 (1989) 197
* %E
******************************************************************************/
DEFINE COMPONENT Source_gen
SETTING PARAMETERS (string flux_file="NULL", string xdiv_file="NULL", string ydiv_file="NULL",
radius=0.0, dist=0, focus_xw=0.045, focus_yh=0.12, focus_aw=0, focus_ah=0,
E0=0, dE=0, lambda0=0, dlambda=0, I1=1,
yheight=0.1, xwidth=0.1, verbose=0, T1=0,
flux_file_perAA=0, flux_file_log=0,
Lmin=0,Lmax=0,Emin=0,Emax=0,T2=0,I2=0,T3=0,I3=0,zdepth=0, int target_index=+1)
/* Neutron parameters: (x,y,z,vx,vy,vz,t,sx,sy,sz,p) */
SHARE
%{
%include "read_table-lib"
#ifndef SOURCE_GEN_DEF
#define SOURCE_GEN_DEF
/*******************************************************************************
* str_dup_numeric: replaces non 'valid name' chars with spaces
*******************************************************************************/
char *str_dup_numeric(char *orig)
{
long i;
if (!orig || !strlen(orig)) return(NULL);
for (i=0; i < strlen(orig); i++)
{
if ( (orig[i] > 122)
|| (orig[i] < 32)
|| (strchr("!\"#$%&'()*,:;<=>?@[\\]^`/ ", orig[i]) != NULL) )
{
orig[i] = ' ';
}
}
orig[i] = '\0';
/* now skip spaces */
for (i=0; i < strlen(orig); i++) {
if (*orig == ' ') orig++;
else break;
}
return(orig);
} /* str_dup_numeric */
/* A normalised Maxwellian distribution : Integral over all l = 1 */
#pragma acc routine seq
double SG_Maxwell(double l, double temp)
{
double a=949.0/temp;
return 2*a*a*exp(-a/(l*l))/(l*l*l*l*l);
}
#endif
%}
DECLARE
%{
double p_in;
double lambda1; /* first Maxwellian source */
double lambda2; /* second Maxwellian source */
double lambda3; /* third Maxwellian source */
t_Table pTable;
t_Table pTable_x;
t_Table pTable_y;
double pTable_xmin;
double pTable_xmax;
double pTable_xsum;
double pTable_ymin;
double pTable_ymax;
double pTable_ysum;
double pTable_dxmin;
double pTable_dxmax;
double pTable_dymin;
double pTable_dymax;
%}
INITIALIZE
%{
pTable_xsum=0;
pTable_ysum=0;
double source_area, k;
if (target_index && !dist)
{
Coords ToTarget;
double tx,ty,tz;
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, &tx, &ty, &tz);
dist=sqrt(tx*tx+ty*ty+tz*tz);
}
/* spectrum characteristics */
if (flux_file && strlen(flux_file) && strcmp(flux_file,"NULL") && strcmp(flux_file,"0")) {
if (Table_Read(&pTable, flux_file, 1) <= 0) /* read 1st block data from file into pTable */
exit(fprintf(stderr, "Source_gen: %s: can not read flux file %s\n", NAME_CURRENT_COMP, flux_file));
/* put table in Log scale */
int i;
if (pTable.columns < 2) exit(fprintf(stderr, "Source_gen: %s: Flux file %s should contain at least 2 columns [wavelength in Angs,flux].\n", NAME_CURRENT_COMP, flux_file));
double table_lmin=FLT_MAX, table_lmax=-FLT_MAX;
double tmin=FLT_MAX, tmax=-FLT_MAX;
for (i=0; i<pTable.rows; i++) {
double val = Table_Index(pTable, i,1);
val = Table_Index(pTable, i,0); /* lambda */
if (val > tmax) tmax=val;
if (val < tmin) tmin=val;
}
for (i=0; i<pTable.rows; i++) {
double val = Table_Index(pTable, i,1);
if (val < 0) fprintf(stderr, "Source_gen: %s: File %s has negative flux at row %i.\n", NAME_CURRENT_COMP, flux_file, i+1);
if (flux_file_log)
val = log(val > 0 ? val : tmin/10);
Table_SetElement(&pTable, i, 1, val);
val = Table_Index(pTable, i,0); /* lambda */
if (val > table_lmax) table_lmax=val;
if (val < table_lmin) table_lmin=val;
}
if (!Lmin && !Lmax && !lambda0 && !dlambda && !E0 && !dE && !Emin && !Emax) {
Lmin = table_lmin; Lmax = table_lmax;
}
if (Lmax > table_lmax) {
if (verbose) fprintf(stderr, "Source_gen: %s: Maximum wavelength %g is beyond table range upper limit %g. Constraining.\n", NAME_CURRENT_COMP, Lmax, table_lmax);
Lmax = table_lmax;
}
if (Lmin < table_lmin) {
if (verbose) fprintf(stderr, "Source_gen: %s: Minimum wavelength %g is below table range lower limit %g. Constraining.\n", NAME_CURRENT_COMP, Lmin, table_lmin);
Lmin = table_lmin;
}
} /* end flux file */
else
{
k = 1.38066e-23; /* k_B */
if (T1 > 0)
{
lambda1 = 1.0e10*sqrt(HBAR*HBAR*4.0*PI*PI/2.0/MNEUTRON/k/T1);
}
else
{ lambda1 = lambda0; }
if (T2 > 0)
{
lambda2 = 1.0e10*sqrt(HBAR*HBAR*4.0*PI*PI/2.0/MNEUTRON/k/T2);
}
else
{ lambda2 = lambda0; }
if (T3 > 0)
{
lambda3 = 1.0e10*sqrt(HBAR*HBAR*4.0*PI*PI/2.0/MNEUTRON/k/T3);
}
else
{ lambda3 = lambda0; }
}
/* now read position-divergence files, if any */
if (xdiv_file && strlen(xdiv_file) && strcmp(xdiv_file,"NULL") && strcmp(xdiv_file,"0")) {
int i,j;
if (Table_Read(&pTable_x, xdiv_file, 1) <= 0) /* read 1st block data from file into pTable */
exit(fprintf(stderr, "Source_gen: %s: can not read XDiv file %s\n", NAME_CURRENT_COMP, xdiv_file));
pTable_xsum = 0;
for (i=0; i<pTable_x.rows; i++)
for (j=0; j<pTable_x.columns; j++)
pTable_xsum += Table_Index(pTable_x, i,j);
/* now extract limits */
char **parsing;
char xylimits[1024];
strcpy(xylimits, "");
parsing = Table_ParseHeader(pTable_x.header,
"xlimits", "xylimits",
NULL);
if (parsing) {
if (parsing[0]) strcpy(xylimits, str_dup_numeric(parsing[0]));
if (parsing[1] && !strlen(xylimits))
strcpy(xylimits, str_dup_numeric(parsing[1]));
for (i=0; i<=1; i++) {
if (parsing[i]) free(parsing[i]);
}
free(parsing);
}
i = sscanf(xylimits, "%lg %lg %lg %lg",
&(pTable_xmin), &(pTable_xmax),
&(pTable_dxmin), &(pTable_dxmax));
if (i != 2 && i != 4 && verbose)
fprintf(stderr, "Source_gen: %s: invalid xylimits '%s' from file %s. extracted %i values\n",
NAME_CURRENT_COMP, xylimits, xdiv_file, i);
if (!xwidth) xwidth=pTable_xmax-pTable_xmin;
if (!focus_xw && !dist) focus_xw=fabs(pTable_dxmax-pTable_dxmin);
} /* end xdiv file */
if (ydiv_file && strlen(ydiv_file) && strcmp(ydiv_file,"NULL") && strcmp(ydiv_file,"0")) {
int i,j;
if (Table_Read(&pTable_y, ydiv_file, 1) <= 0) /* read 1st block data from file into pTable */
exit(fprintf(stderr, "Source_gen: %s: can not read YDiv file %s\n", NAME_CURRENT_COMP, ydiv_file));
pTable_ysum = 0;
for (i=0; i<pTable_y.rows; i++)
for (j=0; j<pTable_y.columns; j++)
pTable_ysum += Table_Index(pTable_y, i,j);
/* now extract limits */
char **parsing;
char xylimits[1024];
strcpy(xylimits, "");
parsing = Table_ParseHeader(pTable_y.header,
"xlimits", "xylimits",
NULL);
if (parsing) {
if (parsing[0]) strcpy(xylimits,str_dup_numeric(parsing[0]));
if (parsing[1] && !strlen(xylimits))
strcpy(xylimits,str_dup_numeric(parsing[1]));
for (i=0; i<=1; i++) {
if (parsing[i]) free(parsing[i]);
}
free(parsing);
}
i = sscanf(xylimits, "%lg %lg %lg %lg",
&(pTable_ymin), &(pTable_ymax),
&(pTable_dymin), &(pTable_dymax));
if (i != 2 && i != 4 && verbose)
fprintf(stderr, "Source_gen: %s: invalid xylimits '%s' from file %s. extracted %i values\n",
NAME_CURRENT_COMP, xylimits, ydiv_file, i);
if (!yheight) yheight=pTable_ymax-pTable_ymin;
if (!focus_yh && !dist) focus_yh=fabs(pTable_dymax-pTable_dymin);
} /* end ydiv file */
/* tests for parameter values */
if (Emin < 0 || Emax < 0 || Lmin < 0 || Lmax < 0 || E0 < 0 || dE < 0 || lambda0 < 0 || dlambda < 0)
{
fprintf(stderr,"Source_gen: %s: Error: Negative average\n"
" or range values for wavelength or energy encountered\n",
NAME_CURRENT_COMP);
exit(-1);
}
if ((Emin == 0 && Emax > 0) || (dE > 0 && dE >= E0))
{
fprintf(stderr,"Source_gen: %s: Error: minimal energy cannot be less or equal zero\n",
NAME_CURRENT_COMP);
exit(-1);
}
if ((Emax >= Emin) && (Emin > 0))
{ E0 = (Emax+Emin)/2;
dE = (Emax-Emin)/2;
}
if ((E0 > dE) && (dE >= 0))
{
Lmin = sqrt(81.81/(E0+dE)); /* Angstroem */
Lmax = sqrt(81.81/(E0-dE));
}
if (Lmax > 0)
{ lambda0 = (Lmax+Lmin)/2;
dlambda = (Lmax-Lmin)/2;
}
if (lambda0 <= 0 || (lambda0 < dlambda) || (dlambda < 0))
{ fprintf(stderr,"Source_gen: %s: Error: Wavelength range %.3f +/- %.3f AA calculated \n",
NAME_CURRENT_COMP, lambda0, dlambda);
fprintf(stderr,"- whole wavelength range must be >= 0 \n");
fprintf(stderr,"- range must be > 0; otherwise intensity gets zero, use other sources in this case \n\n");
exit(-1);
}
radius = fabs(radius); xwidth=fabs(xwidth); yheight=fabs(yheight); I1=fabs(I1);
lambda0=fabs(lambda0); dlambda=fabs(dlambda);
focus_xw = fabs(focus_xw); focus_yh=fabs(focus_yh); dist=fabs(dist);
if ((!focus_ah && !focus_aw) && (!focus_xw && !focus_yh))
{
fprintf(stderr,"Source_gen: %s: Error: No focusing information.\n"
" Specify focus_xw, focus_yh or focus_aw, focus_ah\n",
NAME_CURRENT_COMP);
exit(-1);
}
Lmin = lambda0 - dlambda; /* Angstroem */
Lmax = lambda0 + dlambda;
/* compute initial weight factor p_in to get [n/s] */
if ((I1 > 0 && T1 >= 0)
|| (flux_file && strlen(flux_file) && strcmp(flux_file,"NULL") && strcmp(flux_file,"0")))
{ /* the I1,2,3 are usually in [n/s/cm2/st/AA] */
if (radius)
source_area = radius*radius*PI*1e4; /* circular cm^2 */
else
source_area = yheight*xwidth*1e4; /* square cm^2 */
p_in = source_area; /* cm2 */
p_in *= (Lmax-Lmin); /* AA. 1 bin=AA/n */
if (flux_file && strlen(flux_file) && strcmp(flux_file,"NULL") && strcmp(flux_file,"0")
&& !flux_file_perAA) p_in *= pTable.rows/(Lmax-Lmin);
}
else
p_in = 1.0/4/PI; /* Small angle approx. */
p_in /= mcget_ncount();
if (!T1 && I1) p_in *= I1;
if (radius == 0 && yheight == 0 && xwidth == 0)
{
fprintf(stderr,"Source_gen: %s: Error: Please specify source geometry (radius, yheight, xwidth)\n",
NAME_CURRENT_COMP);
exit(-1);
}
if (focus_xw*focus_yh == 0)
{
fprintf(stderr,"Source_gen: %s: Error: Please specify source target (focus_xw, focus_yh)\n",
NAME_CURRENT_COMP);
exit(-1);
}
MPI_MASTER(
if (verbose)
{
printf("Source_gen: component %s ", NAME_CURRENT_COMP);
if ((yheight == 0) || (xwidth == 0))
printf("(disk, radius=%g)", radius);
else
printf("(square %g x %g)",xwidth,yheight);
if (dist) printf("\n focusing distance dist=%g area=%g x %g\n", dist, focus_xw, focus_yh);
printf(" spectra ");
printf("%.3f to %.3f AA (%.3f to %.3f meV)", Lmin, Lmax, 81.81/Lmax/Lmax, 81.81/Lmin/Lmin);
printf("\n");
if (flux_file && strlen(flux_file) && strcmp(flux_file,"NULL") && strcmp(flux_file,"0"))
{ printf(" File %s for flux distribution used. Flux is dPhi/dlambda in [n/s/AA]. \n", flux_file);
Table_Info(pTable);
}
else if (T1>=0 && I1)
{ if (T1 != 0)
printf(" T1=%.1f K (%.3f AA)", T1, lambda1);
if (T2*I2 != 0)
printf(", T2=%.1f K (%.3f AA)", T2, lambda2);
if (T3*I3 != 0)
printf(", T3=%.1f K (%.3f AA)", T3, lambda3);
if (T1) printf("\n");
printf(" Flux is dPhi/dlambda in [n/s/cm2].\n");
}
else
{ printf(" Flux is Phi in [n/s].\n");
}
if (xdiv_file && strlen(xdiv_file) && strcmp(xdiv_file,"NULL") && strcmp(xdiv_file,"0"))
printf(" File %s x=[%g:%g] [m] xdiv=[%g:%g] [deg] used as horizontal phase space distribution.\n", xdiv_file, pTable_xmin, pTable_xmax, pTable_dxmin, pTable_dxmax);
if (ydiv_file && strlen(ydiv_file) && strcmp(ydiv_file,"NULL") && strcmp(ydiv_file,"0"))
printf(" File %s y=[%g:%g] [m] ydiv=[%g:%g] [deg] used as vertical phase space distribution.\n", ydiv_file, pTable_ymin, pTable_ymax, pTable_dymin, pTable_dymax);
}
else
if (verbose == -1)
printf("Source_gen: component %s unactivated", NAME_CURRENT_COMP);
);
%}
TRACE
%{
double dx=0,dy=0,xf,yf,rf,pdir,chi,v,r, lambda;
double Maxwell;
if (verbose >= 0)
{
z=0;
if (radius)
{
chi=2*PI*rand01(); /* Choose point on source */
r=sqrt(rand01())*radius; /* with uniform distribution. */
x=r*cos(chi);
y=r*sin(chi);
}
else
{
x = xwidth*randpm1()/2; /* select point on source (uniform) */
y = yheight*randpm1()/2;
}
if (zdepth != 0)
z = zdepth*randpm1()/2;
/* Assume linear wavelength distribution */
lambda = lambda0+dlambda*randpm1();
if (lambda <= 0) ABSORB;
v = K2V*(2*PI/lambda);
if (!focus_ah && !focus_aw) {
randvec_target_rect_real(&xf, &yf, &rf, &pdir,
0, 0, dist, focus_xw, focus_yh, ROT_A_CURRENT_COMP, x, y, z, 2);
dx = xf-x;
dy = yf-y;
rf = sqrt(dx*dx+dy*dy+dist*dist);
vz=v*dist/rf;
vy=v*dy/rf;
vx=v*dx/rf;
} else {
randvec_target_rect_angular(&vx, &vy, &vz, &pdir,
0, 0, 1, focus_aw*DEG2RAD, focus_ah*DEG2RAD, ROT_A_CURRENT_COMP);
dx = vx; dy = vy; /* from unit vector */
vx *= v; vy *= v; vz *= v;
}
p = p_in*pdir;
/* spectral dependency from files or Maxwellians */
if (flux_file && strlen(flux_file) && strcmp(flux_file,"NULL") && strcmp(flux_file,"0"))
{
double binwidth=Table_Value(pTable, lambda, 1);
if (flux_file_log) binwidth=exp(binwidth);
p *= binwidth;
}
else
if (T1 > 0 && I1 > 0)
{
Maxwell = I1 * SG_Maxwell(lambda, T1);; /* 1/AA */
if ((T2 > 0) && (I2 > 0))
{
Maxwell += I2 * SG_Maxwell(lambda, T2);
}
if ((T3 > 0) && (I3 > 0))
{
Maxwell += I3 * SG_Maxwell(lambda, T3);;
}
p *= Maxwell;
}
/* optional x-xdiv and y-ydiv weightening: position=along columns, div=along rows */
if (xdiv_file && strlen(xdiv_file)
&& strcmp(xdiv_file,"NULL") && strcmp(xdiv_file,"0") && pTable_xsum > 0) {
double i,j;
j = (x- pTable_xmin) /(pTable_xmax -pTable_xmin) *pTable_x.columns;
i = (atan2(dx,rf)*RAD2DEG-pTable_dxmin)/(pTable_dxmax-pTable_dxmin)*pTable_x.rows;
r = Table_Value2d(pTable_x, i,j); /* row, column */
p *= r/pTable_xsum;
}
if (ydiv_file && strlen(ydiv_file)
&& strcmp(ydiv_file,"NULL") && strcmp(ydiv_file,"0") && pTable_ysum > 0) {
double i,j;
j = (y- pTable_ymin) /(pTable_ymax -pTable_ymin) *pTable_y.columns;
i = (atan2(dy,rf)*RAD2DEG- pTable_dymin)/(pTable_dymax-pTable_dymin)*pTable_y.rows;
r = Table_Value2d(pTable_y, i,j);
p *= r/pTable_ysum;
}
SCATTER;
}
%}
FINALLY
%{
Table_Free(&pTable);
Table_Free(&pTable_x);
Table_Free(&pTable_y);
%}
MCDISPLAY
%{
double xmin;
double xmax;
double ymin;
double ymax;
if (radius)
{
circle("xy",0,0,0,radius);
if (zdepth) {
circle("xy",0,0,-zdepth/2,radius);
circle("xy",0,0, zdepth/2,radius);
}
}
else
{
xmin = -xwidth/2; xmax = xwidth/2;
ymin = -yheight/2; ymax = yheight/2;
multiline(5, (double)xmin, (double)ymin, 0.0,
(double)xmax, (double)ymin, 0.0,
(double)xmax, (double)ymax, 0.0,
(double)xmin, (double)ymax, 0.0,
(double)xmin, (double)ymin, 0.0);
if (zdepth) {
multiline(5, (double)xmin, (double)ymin, -zdepth/2,
(double)xmax, (double)ymin, -zdepth/2,
(double)xmax, (double)ymax, -zdepth/2,
(double)xmin, (double)ymax, -zdepth/2,
(double)xmin, (double)ymin, -zdepth/2);
multiline(5, (double)xmin, (double)ymin, zdepth/2,
(double)xmax, (double)ymin, zdepth/2,
(double)xmax, (double)ymax, zdepth/2,
(double)xmin, (double)ymax, zdepth/2,
(double)xmin, (double)ymin, zdepth/2);
}
}
if (dist) {
if (focus_aw) focus_xw=dist*tan(focus_aw*DEG2RAD);
if (focus_ah) focus_yh=dist*tan(focus_ah*DEG2RAD);
dashed_line(0,0,0, -focus_xw/2,-focus_yh/2,dist, 4);
dashed_line(0,0,0, focus_xw/2,-focus_yh/2,dist, 4);
dashed_line(0,0,0, focus_xw/2, focus_yh/2,dist, 4);
dashed_line(0,0,0, -focus_xw/2, focus_yh/2,dist, 4);
}
%}
END
|