Example #1
0
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
Example #2
0
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
Example #3
0
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
Example #6
0
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