def computeKf(Ei, E, Q, log): ki = Conv.e2k(Ei); log.write( "* ki=%s\n" % (ki,) ) kiv = np.array([ki, 0, 0]) kfv = kiv - Q log.write( "* vectors ki=%s, kf=%s\n" % (kiv, kfv) ) Ef = Ei - E # ** Verify the momentum and energy transfers ** log.write( "These two numbers should be very close:\n") log.write( " %s\n" % (Ei-Conv.k2e(np.linalg.norm(kfv)),) ) log.write( " %s\n" % (Ei-Ef,) ) assert np.isclose(Ef, Conv.k2e(np.linalg.norm(kfv))) log.write( " Ei=%s, Ef=%s\n" % (Ei,Ef) ) return kfv, Ef
def Eresidual(xtalori, hkl, Etarget, angles, Ei): """compute residual of energy transfer This method compute a series of psi angle and corresponding residual (E - Etarget). We only need to simulate crystal orientation where the residual is close to zero. """ from mcni.utils import conversion as conv ki = conv.e2k(Ei) kiv = np.array([ki,0,0]) r = np.zeros((len(angles), 2)) for i, psi in enumerate(angles): xtalori.psi = psi / 180. * np.pi hkl2cartesian = xtalori.hkl2cartesian_mat() # cart2hkl = xtalori.cartesian2hkl_mat() Qcart = np.dot(hkl, hkl2cartesian) # print hkl, np.dot(Qcart, cart2hkl) # print Qcart kfv = kiv - Qcart kf = np.linalg.norm(kfv) Ef = conv.k2e(kf) E = Ei - Ef r[i] = psi, E-Etarget continue return r
def calcIQE(uc, omega, pols, Qpoints, Q_bins, E_bins): """main part of IQE calculation. missing several corrections """ N = len(Qpoints) Qmag = np.linalg.norm(Qpoints, axis=-1) from ..atomic_scattering import AtomicScattering symbols = [a.element for a in uc] bs = [AtomicScattering(s).b() for s in symbols] masses = [AtomicScattering(s).mass for s in symbols] positions = np.array([a.xyz for a in uc]) bovermass = np.array(bs) / np.sqrt(masses) # import tqdm bins = Q_bins, E_bins # in reciprocal units hkls = np.dot(Qpoints, uc.lattice.base.T) / (2 * np.pi) I = 0 nQ, nbr, natoms, three = pols.shape assert three == 3 good = omega > 0 for ibr in tqdm.tqdm(range(nbr)): good1 = good[:, ibr] Qmag_good = Qmag[good1] omega_good = omega[good1, ibr] Q_cart = Qpoints[good1, :] good_hkls = hkls[good1, :] # exp_Q_dot_d = np.exp(1j * np.dot(good_hkls, positions.T) * 2 * np.pi) # nQ, natoms pols1 = pols[good1, ibr, :, :] # nQ, natoms, 3 Q_dot_pol = np.sum(np.transpose(pols1, (1, 0, 2)) * Q_cart, axis=-1).T # nQ, natoms # F = np.sum(exp_Q_dot_d * Q_dot_pol * bovermass, axis=-1) # nQ M = np.abs(F)**2 / omega_good # nQ I1, Qbb, Ebb = np.histogram2d(Qmag_good, omega_good, bins=bins, weights=M) I = I + I1 continue from mcni.utils import conversion I *= conversion.k2e(1.) # canceling unit: hbar^2Q^2/2M/(hbar*omega) # M is |b_d/sqrt(M_d)exp(iQ.d)(Q.e)|^2/omega # At this moment M (and I) is using b in fm. change it to barn I /= 100 # Need to consider the density of the Q points and the volume of the Q space sampled. uc_vol = uc.lattice.volume ruc_vol = (2 * np.pi)**3 / uc_vol max_Q = Q_bins[-1] I *= 1. / N * 4. / 3 * np.pi * max_Q**3 / ruc_vol return Qbb, Ebb, I
def test(self): "wrap IQE_monitor" from mcstas2 import componentfactory factory = componentfactory( category, componentname ) Ei = 70 Qmin=0; Qmax=13.; nQ=130 Emin=-50; Emax=50.; nE=100 component = factory( 'component', Ei=Ei, Qmin=Qmin, Qmax=Qmax, nQ=nQ, Emin=Emin, Emax=Emax, nE=nE, max_angle_out_of_plane=30, min_angle_out_of_plane=-30, max_angle_in_plane=120, min_angle_in_plane=-30, ) import mcni from mcni.utils import conversion as C neutrons = mcni.neutron_buffer( nQ*nE ) import numpy as N count = 0 for Q in N.arange(Qmin, Qmax, (Qmax-Qmin)/nQ): for E in N.arange(Emin,Emax,(Emax-Emin)/nE): Ef = Ei-E cosphi = (Ei+Ef-C.k2e(Q))/(2*N.sqrt(Ei)*N.sqrt(Ef)) vf = C.e2v(Ef) vfz = vf*cosphi sinphi = N.sqrt(1-cosphi*cosphi) vfx = vf*sinphi neutrons[count] = mcni.neutron(r=(0,0,0), v=(vfx,0,vfz), time = 0, prob = 1) count += 1 continue component.process( neutrons ) from mcstas2.pyre_support._component_interfaces.monitors.IQE_monitor import get_histogram hist = get_histogram(component) if interactive: from histogram.plotter import defaultPlotter defaultPlotter.plot(hist) return
def test1(self): 'kernel orientation' # source from mcni.components.MonochromaticSource import MonochromaticSource import mcni, numpy as np Ei = 100 from mcni.utils import conversion as Conv ki = Conv.e2k(Ei) vi = Conv.e2v(Ei) Qdir = np.array([np.sqrt(3)/2, 0, -1./2]) Q = Qdir * 2 kf = np.array([0,0,ki]) - Q Ef = Conv.k2e(np.linalg.norm(kf)) E = Ei-Ef dv = Qdir * Conv.k2v(Q) vf = np.array([0,0,vi]) - dv # print ki, Q, kf # print Ei, Ef, E neutron = mcni.neutron(r=(0,0,-1), v=(0,0,vi), prob=1) source = MonochromaticSource('s', neutron, dx=0.001, dy=0.001, dE=0) # sample from mccomponents.sample import samplecomponent scatterer = samplecomponent('sa', 'cyl/sampleassembly.xml' ) # incident N = 1000 neutrons = mcni.neutron_buffer(N) neutrons = source.process(neutrons) # print neutrons # scatter scatterer.process(neutrons) # print neutrons self.assertEqual(len(neutrons), N) for neutron in neutrons: np.allclose(neutron.state.velocity, vf) self.assert_(neutron.probability > 0) continue return
def qikr(wl_0=1., center_wl=13.05): """ @param wl_min: wavelength at the lower end of the bandwidth """ running_length = 0 k0 = 2*np.pi/wl_0 e0_max = conversion.k2e(k0) kmin = 2*np.pi/40.0 e0_min = conversion.k2e(kmin) instrument = mcvine.instrument() # Source - includes straight tube beam_width = 0.0266 tube_length = 1.0 mod = mcvine.components.sources.SNS_source_r1('moderator', S_filename='./SNS-STS-ROT1-15_sp.dat', width=beam_width, height=0.0266, dist=tube_length, xw=beam_width, yh=0.0327, Emin=0, Emax=e0_max) instrument.append(mod, position=(0,0,0)) #running_length += 0.001 # Source Tube ################################################################## #tube = mcvine.components.optics.Guide_channeled(name='source_tube', # w1=beam_width, h1=0.0266, w2=beam_width, h2=0.0327, # l=tube_length, mx=0, my=0) running_length += tube_length + 0.0001 # Ballistic Guide 1 ############################################################# # From 100 cm to 620 cm guide_1_length = 5.2 guide1 = mcvine.components.optics.Guide_channeled(name='guide_1', w1=beam_width, h1=0.0327, w2=beam_width, h2=0.0642, l=guide_1_length, mx=5, my=5) instrument.append(guide1, position=(0,0,running_length)) print ("Ballistic guide 1: %s m" % running_length) running_length += guide_1_length + 0.0001 # T0 chopper ################################################################### # From 620 cm to 664.8 cm #t0_chopper = mcvine.components.optics.Vertical_T0(name='t0chopper', len=0.448, # w1=beam_width, w2=beam_width, nu=120, delta=0.0, tc=0., ymin=-.045, ymax=0.045) #instrument.append(t0_chopper, position=(0,0,6.2)) running_length += 0.448 # Ballistic Guide 2 ############################################################# # From 664.8 cm to 714.8 cm guide_2_length = 0.5 guide2 = mcvine.components.optics.Guide_channeled(name='guide_2', w1=beam_width, h1=0.067, w2=beam_width, h2=0.07, l=guide_2_length, mx=5, my=5) instrument.append(guide2, position=(0,0,running_length)) print ("Ballistic guide 2: %s m" % running_length) running_length += guide_2_length + 0.0001 # Bandwidth chopper ############################################################ # From 714.8 cm to 722.1 cm instrument.append(mcvine.components.monitors.NeutronToStorage('save_pre', 'beam_pre_chopper.neutrons'), position=(0,0,running_length)) running_length += 0.0001 b_chopper_length = 0.073 b_chopper_dist = running_length + b_chopper_length/2.0 # center of chopper print ("Bandwidth chopper: %s m" % b_chopper_dist) aperture_bottom = 0.2689 aperture_top = 0.33949 radius_to_beam = 0.30390 open_angle = 111.964 kmid = 2*np.pi/center_wl v = conversion.k2v(kmid) delay = b_chopper_dist/v disk_chopper = mcvine.components.optics.DiskChopper_v2(name='band_chopper', yheight=aperture_top-aperture_bottom, nslit=1, radius=aperture_top, theta_0=open_angle, delay=delay, nu=7.5) running_length += 0.0001 instrument.append(disk_chopper, position=(0,0, b_chopper_dist)) instrument.append(mcvine.components.monitors.NeutronToStorage('save_post', 'beam_post_chopper.neutrons'), position=(0,0,running_length)) running_length += b_chopper_length + 0.0001 # Ballistic Guide 3 ############################################################# # From 722.1 cm to 1264 cm guide_3_length = 5.419 guide3 = mcvine.components.optics.Guide_channeled(name='guide_3', w1=beam_width, h1=0.07, w2=beam_width, h2=0.1033, l=guide_3_length, mx=5, my=5) instrument.append(guide3, position=(0,0,running_length)) running_length += guide_3_length + 0.0001 # Tapered guide ################################################################# # From 1264 cm to 1599 cm guide_4_length = 3.35 guide4 = mcvine.components.optics.Guide_channeled(name='guide_4', w1=beam_width, h1=0.1033, w2=beam_width, h2=0.02, l=guide_4_length, mx=5, my=5) instrument.append(guide4, position=(0,0,running_length)) running_length += guide_4_length + 0.0001 instrument.append(mcvine.components.monitors.NeutronToStorage('save', 'beam.neutrons'), position=(0,0,running_length)) running_length += 0.0001 print("End of instrument: %s m" % running_length) return instrument