/******************************************************************************* * * McStas, neutron ray-tracing package * Copyright 1997-2003, All rights reserved * Risoe National Laboratory, Roskilde, Denmark * Institut Laue Langevin, Grenoble, France * * Component: Guide_curved * * %I * Written by: Ross Stewart * Date: November 18 2003 * * Non-focusing curved neutron guide. * * %D * Models a rectangular curved guide tube with entrance centered on the Z axis. * The entrance lies in the X-Y plane. Unlike Bender.comp, draws a true depiction * of the guide, and trajectories. Guide is not focusing * * Example: Guide(w1=0.1, h1=0.1, l=2.0, R0=0.99, Qc=0.021, * alpha=6.07, m=2, W=0.003, r=2700) * * %BUGS * This component does not work with gravitation on. Use component Guide_gravity then. * * %P * INPUT PARAMETERS: * * w: [m] Width at the guide entry * h: [m] Height at the guide entry * l: [m] length of guide * R0: [1] Low-angle reflectivity * Qc: [AA-1] Critical scattering vector * alpha: [AA] Slope of reflectivity * m: [1] m-value of material. Zero means completely absorbing. * W: [AA-1] Width of supermirror cut-off * r: [m] Radius of curvature of the guide * * %L * Bender * * %E *******************************************************************************/ DEFINE COMPONENT Guide_curved DEFINITION PARAMETERS () SETTING PARAMETERS (w, h, l, R0=0.99, Qc=0.0219, alpha=6.07, m=2, W=0.003, r=2700) STATE PARAMETERS (x,y,z,vx,vy,vz,t,s1,s2,p) INITIALIZE %{ if (mcgravitation) fprintf(stderr,"WARNING: Guide_curved: %s: " "This component produces wrong results with gravitation !\n" "Use Guide_gravity.\n", NAME_CURRENT_COMP); %} TRACE %{ double t11, t12, t21, t22, theta, alpha, endtime, phi; double time, time1, time2, q, R; int ii, i_bounce; double whalf = 0.5*w, hhalf = 0.5*h; /* half width and height of guide */ double z_off = r*sin(l/r); /* z-component of total guide length */ double R1 = r - whalf; /* radius of curvature of inside mirror */ double R2 = r + whalf; /* radius of curvature of outside mirror */ double vel = sqrt(vx*vx + vy*vy + vz*vz); /* neutron velocity */ double vel_xz = sqrt(vx*vx + vz*vz); /* in plane velocity */ double K = V2K*vel; /* neutron wavevector */ double lambda = 2.0*PI/K; /* neutron wavelength */ /* Propagate neutron to guide entrance. */ PROP_Z0; if(x <= -whalf || x >= whalf || y <= -hhalf || y >= hhalf) ABSORB; for(;;) { /* Find itersection points of neutron with inside and outside guide walls */ ii = cylinder_intersect(&t11, &t12 ,x - r, y, z, vx, vy, vz, R1, h); ii = cylinder_intersect(&t21, &t22 ,x - r, y, z, vx, vy, vz, R2, h); /* Choose appropriate reflection time */ time1 = (t11 < 1e-7) ? t12 : t11; time2 = (t21 < 1e-7) ? t22 : t21; time = (time1 < 1e-7 || time2 < time1) ? time2 : time1; /* Has neutron left the guide? */ endtime = (z_off - z)/vz; if (time > endtime || time <= 1e-7) break; PROP_DT(time); /* Find reflection surface */ R = (time == time1) ? R1 : R2; i_bounce = (fabs(y - hhalf) < 1e-7 || fabs(y + hhalf) < 1e-7) ? 2 : 1; switch(i_bounce) { case 1: /* Inside or Outside wall */ phi = atan(vx/vz); /* angle of neutron trajectory */ alpha = asin(z/R); /* angle of guide wall */ theta = fabs(phi - alpha); /* angle of reflection */ vz = vel_xz*cos(2.0*alpha - phi); vx = vel_xz*sin(2.0*alpha - phi); break; case 2: /* Top or Bottom wall */ theta = fabs(atan(vy/vz)); vy = -vy; break; } /* Now compute reflectivity. */ if (m == 0) ABSORB; q = 4.0*PI*sin(theta)/lambda; if(q > Qc) { double arg = (q - m*Qc)/W; if (arg < 10) p *= .5*(1 - tanh(arg))*(1 - alpha*(q - Qc)); else ABSORB; /* Cutoff ~ 1E-10 */ } p *= R0; SCATTER; } %} MCDISPLAY %{ double x1, x2, z1, z2; double xplot1[100], xplot2[100], zplot1[100], zplot2[100]; int n = 100; int j = 1; double R1 = (r - 0.5*w); /* radius of inside arc */ double R2 = (r + 0.5*w); /* radius of outside arc */ magnify("xy"); for(;;) { if(j == n + 1) break; z1 = ((double)j - 1.0)*(R1*l/r)/(double)(n - 1); z2 = ((double)j - 1.0)*(R2*l/r)/(double)(n - 1); x1 = r - sqrt(R1*R1 - z1*z1); x2 = r - sqrt(R2*R2 - z2*z2); xplot1[j] = x1; xplot2[j] = x2; zplot1[j] = z1; zplot2[j] = z2; j++; } j = 1; line(xplot1[j], 0.5*h,zplot1[j],xplot2[j], 0.5*h,zplot2[j]); line(xplot1[j], 0.5*h,zplot1[j],xplot1[j],-0.5*h,zplot1[j]); line(xplot2[j],-0.5*h,zplot2[j],xplot2[j], 0.5*h,zplot2[j]); line(xplot1[j],-0.5*h,zplot1[j],xplot2[j],-0.5*h,zplot2[j]); for(;;) { if(j == n) break; line(xplot1[j], 0.5*h, zplot1[j], xplot1[j+1], 0.5*h, zplot1[j+1]); line(xplot2[j], 0.5*h, zplot2[j], xplot2[j+1], 0.5*h, zplot2[j+1]); line(xplot1[j], -0.5*h, zplot1[j], xplot1[j+1], -0.5*h, zplot1[j+1]); line(xplot2[j], -0.5*h, zplot2[j], xplot2[j+1], -0.5*h, zplot2[j+1]); j++; } line(xplot1[j], 0.5*h,zplot1[j],xplot2[j], 0.5*h,zplot2[j]); line(xplot1[j], 0.5*h,zplot1[j],xplot1[j],-0.5*h,zplot1[j]); line(xplot2[j],-0.5*h,zplot2[j],xplot2[j], 0.5*h,zplot2[j]); line(xplot1[j],-0.5*h,zplot1[j],xplot2[j],-0.5*h,zplot2[j]); %} END