def resolution(E, Ei, E0, a, b, R, sigma=5., t0=0., geom=None): """compute reoslution function given energy transfer axis (E) and other parameters. The resolution function calculated should be centered around E0, the nominal energy transfer. E: energy transfer axis Ei: incident energy E0: nominal energy transfer a,b,R Ikeda Carpenter function parameters sigma: additional gaussian broadening t0: emission time geom: instrument geometry. Geom instance """ from mcni.utils.conversion import e2v, SE2V source = Source() source.a = a source.b = b source.R = R icg = ICG(source, sigma, geom, t0) Ef = Ei - E0 vf = e2v(Ef) vi = e2v(Ei) l3 = geom.l3 t = -l3 / vf + l3 / np.sqrt(vi**2 - SE2V**2 * E) t *= 1e6 r = icg.ICG(t) r[r != r] = 0 # t may overflow, for them r should be 0 return r
def _configure(self): AbstractComponent._configure(self) velocity = self.inventory.velocity assert len(velocity) == 3 self.velocity = velocity energy = self.inventory.energy if energy: from mcni.utils.conversion import e2v v = e2v(energy) import numpy.linalg as nl, numpy as np norm = nl.norm(velocity) velocity = np.array(velocity) velocity *= v / norm self.velocity = velocity energy_width = self.inventory.energy_width if energy_width < 0: raise ValueError, "energy width must be not negative" self.energy_width = energy_width position = self.inventory.position assert len(position) == 3 self.position = position self.width = self.inventory.width self.height = self.inventory.height self.time = self.inventory.time self.probability = self.inventory.probability return
def test(self): E_Q = "Q*Q/3." S_Q = "1" Qmin = 0; Qmax = 10 absorption_coefficient = scattering_coefficient = 1. kernel = mccomponentsbp.create_E_Q_Kernel( E_Q, S_Q, Qmin, Qmax, absorption_coefficient, scattering_coefficient, ) ei = 500 # meV from mcni.utils import conversion vil = conversion.e2v(ei) vi = (0,0,vil) import numpy.linalg as nl import numpy as np for i in range(10): event = mcni.neutron( r = (0,0,0), v = vi, prob = 1, time = 0 ) kernel.scatter( event ); vf = np.array(event.state.velocity) diffv = vi - vf Q = conversion.v2k(nl.norm(diffv)) ef = conversion.v2e(nl.norm(vf)) E = ei - ef # print E, Q, event E1 = eval(E_Q) self.assertAlmostEqual(E, E1) continue return
def make_neutrons(N): neutrons = mcni.neutron_buffer(N) # # randomly select E, the energy transfer E = core.Emin + np.random.random(N) * (core.Emax-core.Emin) # the final energy Ef = core.Ei - E # the final velocity vf = conversion.e2v(Ef) # choose cos(theta) between -1 and 1 cos_t = np.random.random(N) * 2 - 1 # theta theta = np.arccos(cos_t) # sin(theta) sin_t = np.sin(theta) # phi: 0 - 2pi phi = np.random.random(N) * 2 * np.pi # compute final velocity vector vx,vy,vz = vf*sin_t*np.cos(phi), vf*sin_t*np.sin(phi), vf*cos_t # neutron position, spin, tof are set to zero x = y = z = sx = sy = t = np.zeros(N, dtype="float64") # probability prob = np.ones(N, dtype="float64") * (vf/vi) # XXX: this assumes a specific data layout of neutron struct n_arr = np.array([x,y,z,vx,vy,vz, sx,sy, t, prob]).T.copy() neutrons.from_npyarr(n_arr) return neutrons
def runMonitorsAtSample(E, LMS, m2sout, out): from mcni.utils.conversion import e2v v = e2v(E) from pyre.units.time import second L = LMM + LMS t = L/v neutronfile = os.path.join(m2sout, 'neutrons') from mcni.neutron_storage.idf_usenumpy import count n = count(neutronfile) cmd = ['mcvine_analyze_beam'] cmd += ['--output-dir=%s' % out] cmd += ['--ncount=%s' % n] cmd += ['--buffer_size=%s' % min(n, 1e6)] # XXX: -0.15 comes from the fact that the in hyspec_moderator2sample # XXX: the neutron storage is 0.15 before the sample position cmd += ['--geometer.source="((0,0,-0.15),(0,0,0))"'] cmd += ['--source.path=%s' % neutronfile] # fix monitor params that depend on incident energy cmd += ['--monitor.mtof.tofmin=%s' % (t*0.9)] cmd += ['--monitor.mtof.tofmax=%s' % (t*1.1)] cmd += ['--monitor.mtof.ntof=%s' % (1000)] cmd += ['--monitor.menergy.energymin=%s' % (E*0.9)] cmd += ['--monitor.menergy.energymax=%s' % (E*1.1)] cmd += ['--monitor.menergy.nenergy=%s' % (1000)] cmd = ' '.join(cmd) print('Running beam monitors...') _exec(cmd) print('done.') time.sleep(1) return
def _configure(self): AbstractComponent._configure(self) velocity = self.inventory.velocity assert len(velocity)==3 self.velocity = velocity energy = self.inventory.energy if energy: from mcni.utils.conversion import e2v v = e2v(energy) import numpy.linalg as nl, numpy as np norm = nl.norm(velocity) velocity = np.array(velocity) velocity *= v/norm self.velocity = velocity energy_width = self.inventory.energy_width if energy_width < 0: raise ValueError, "energy width must be not negative" self.energy_width = energy_width position = self.inventory.position assert len(position)==3 self.position = position self.width = self.inventory.width self.height = self.inventory.height self.time = self.inventory.time self.probability = self.inventory.probability return
def run(m2sout, out, Ei, LSAMPLE): """this is the main function for arcs beam postprocessing it calls several sub-routines to perform a series of postprocesing steps. """ # compute flux at sample position and make sure flux is nonzero flux = computeFlux(m2sout) # simulate spectra for fake monitors at sample position runMonitorsAtSample(Ei, m2sout, out, LSAMPLE) # copy neutrons to output dir copyNeutronsToOutputDir(m2sout, out) # compute average incident energy at sample energy = computeAverageEnergy(out) # compute average tof at sample tof = computeAverageTof(out) # compute emission time from mcni.utils import conversion vi = conversion.e2v(energy) t0 = tof - LSAMPLE / vi # compute fwhm of energy spetrum at sample fwhm = computeFWHM(out) fwhm *= 1e6 # convert to microsecond # props = { 'flux': '%s counts per 34kJ pulse' % flux, 'average energy': '%s meV' % energy, 'tof fwhm': '%s microsecond' % fwhm, "emission time": '%s microsecond' % (t0 * 1e6), 'average tof': '%s microsecond' % (tof * 1e6), } open(os.path.join(out, 'props.json'), 'w').write(str(props)) return
def runMonitorsAtSample(E, m2sout, out, L=LSAMPLE, instrument='arcs'): from mcni.utils.conversion import e2v v = e2v(E) from pyre.units.time import second t = L/v neutronfile = os.path.join(m2sout, 'neutrons') from mcni.neutron_storage.idf_usenumpy import count n = count(neutronfile) cmd = ['mcvine instruments %s analyze_beam' % instrument] cmd += ['--output-dir=%s' % out] cmd += ['--ncount=%s' % n] cmd += ['--buffer_size=%s' % min(n, int(1e6))] cmd += ['--source.path=%s' % neutronfile] # fix monitor params that depend on incident energy cmd += ['--monitor.mtof.tofmin=%s' % (t*0.9)] cmd += ['--monitor.mtof.tofmax=%s' % (t*1.1)] cmd += ['--monitor.mtof.ntof=%s' % (1000)] cmd += ['--monitor.menergy.energymin=%s' % (E*0.9)] cmd += ['--monitor.menergy.energymax=%s' % (E*1.1)] cmd += ['--monitor.menergy.nenergy=%s' % (1000)] cmd = ' '.join(cmd) print('Running beam monitors...') _exec(cmd) print('done.') time.sleep(1) return
def computeFocusedSpectraForRealMonitors(E, m2sout, out): from mcni.utils.conversion import e2v v = e2v(E) from pyre.units.time import second import histogram.hdf as hh, histogram as H m1 = hh.load(os.path.join(m2sout, "mon1-tof.h5"), "I(tof)") L1 = 11.831 t1 = L1 / v # * second m1p = m1[(t1 * 0.9, t1 * 1.1)] m1pc = H.histogram("I(tof)", m1p.axes(), data=m1p.I, errors=m1p.E2) m1pc.setAttribute("title", "Monitor 1 I(tof)") hh.dump(m1pc, os.path.join(out, "mon1-itof-focused.h5"), "/", "c") m2 = hh.load(os.path.join(m2sout, "mon2-tof.h5"), "I(tof)") L2 = 18.5 t2 = L2 / v # * second m2p = m2[(t2 * 0.9, t2 * 1.1)] m2pc = H.histogram("I(tof)", m2p.axes(), data=m2p.I, errors=m2p.E2) m2pc.setAttribute("title", "Monitor 2 I(tof)") hh.dump(m2pc, os.path.join(out, "mon2-itof-focused.h5"), "/", "c") return
def runMonitorsAtSample(E, m2sout, out): from mcni.utils.conversion import e2v v = e2v(E) from pyre.units.time import second L = 13.6 t = L/v neutronfile = os.path.join(m2sout, 'neutrons') from mcni.neutron_storage.idf_usenumpy import count n = count(neutronfile) cmd = ['arcs_analyze_beam'] cmd += ['--output-dir=%s' % out] cmd += ['--ncount=%s' % n] cmd += ['--buffer_size=%s' % min(n, 1e6)] cmd += ['--source.path=%s' % neutronfile] # fix monitor params that depend on incident energy cmd += ['--monitor.mtof.tofmin=%s' % (t*0.9)] cmd += ['--monitor.mtof.tofmax=%s' % (t*1.1)] cmd += ['--monitor.mtof.ntof=%s' % (1000)] cmd += ['--monitor.menergy.energymin=%s' % (E*0.9)] cmd += ['--monitor.menergy.energymax=%s' % (E*1.1)] cmd += ['--monitor.menergy.nenergy=%s' % (1000)] cmd = ' '.join(cmd) print 'Running beam monitors...' _exec(cmd) print 'done.' time.sleep(1) return
def make_neutrons(N): neutrons = mcni.neutron_buffer(N) # # randomly select E, the energy transfer E = core.Emin + np.random.random(N) * (core.Emax - core.Emin) # the final energy Ef = core.Ei - E # the final velocity vf = conversion.e2v(Ef) # choose cos(theta) between -1 and 1 cos_t = np.random.random(N) * 2 - 1 # theta theta = np.arccos(cos_t) # sin(theta) sin_t = np.sin(theta) # phi: 0 - 2pi phi = np.random.random(N) * 2 * np.pi # compute final velocity vector vx, vy, vz = vf * sin_t * np.cos(phi), vf * sin_t * np.sin( phi), vf * cos_t # neutron position, spin, tof are set to zero x = y = z = sx = sy = t = np.zeros(N, dtype="float64") # probability prob = np.ones(N, dtype="float64") * (vf / vi) # XXX: this assumes a specific data layout of neutron struct n_arr = np.array([x, y, z, vx, vy, vz, sx, sy, t, prob]).T.copy() neutrons.from_npyarr(n_arr) return neutrons
def test1(self): "conversion: e2v" e = 100 v = conversion.e2v(e) self.assertAlmostEqual(v, 4373.9331, 3) e1 = conversion.v2e(v) self.assertAlmostEqual(e1, e, 3) return
def test2(self): "mccomponents.sample.samplecomponent: E_vQ_Kernel - discontinued dispersion surface" import mcni from mcni.utils import conversion ei = 60 vil = conversion.e2v(ei) vi = (0, 0, vil) neutron = mcni.neutron(r=(0, 0, 0), v=vi, time=0, prob=1) from mcni.components.MonochromaticSource import MonochromaticSource component1 = MonochromaticSource("source", neutron) from mccomponents.sample import samplecomponent component2 = samplecomponent("Al", "sampleassemblies/Al-E_vQ_withdiscontinuity-kernel/sampleassembly.xml") E_Q = "np.where(Qx*Qx+Qy*Qy+Qz*Qz>30, 25, 15)" # in sampleassemblies/Al-E_vQ-kernel/Al-scatterer.xml instrument = mcni.instrument([component1, component2]) geometer = mcni.geometer() geometer.register(component1, (0, 0, 0), (0, 0, 0)) geometer.register(component2, (0, 0, 1), (0, 0, 0)) N0 = 10000 neutrons = mcni.neutron_buffer(N0) mcni.simulate(instrument, geometer, neutrons) N = len(neutrons) import numpy.linalg as nl import numpy as np from math import sin N_noscatt = 0 for i in range(N): neutron = neutrons[i] vf = np.array(neutron.state.velocity) diffv = vi - vf # no scattering is fine if np.linalg.norm(diffv) < 1e-12: N_noscatt += 1 continue Q = conversion.V2K * diffv Qx, Qy, Qz = Q ef = conversion.v2e(nl.norm(vf)) E = ei - ef # print E, Q, neutron E1 = eval(E_Q) self.assertAlmostEqual(E, E1) continue print "\n* percentage of no scattering (Q happen to be at a singular point):", N_noscatt * 100.0 / N, "%" return
def computeEi_and_t0(beampath, instrument): """use Ei saved in props.json. use saved neutrons information to compute t0 """ Ei = getEi(beampath) tof = getTof(beampath) from mcni.utils import conversion as Conv vi = Conv.e2v(Ei) L_m2s = mcvine.units.parse(instrument.L_m2s) / mcvine.units.meter t0 = tof - L_m2s / vi # print Ei, t0*1e6 return Ei, t0 * 1e6
def test1(self): 'mccomponents.sample: ConstantQEKernel' # momentum and energy transfer. defined in the scatterer xml file Q0 = 3 E0 = 30 import mcni from mcni.utils import conversion ei = 60 vi = conversion.e2v(ei) Vi = (0, 0, vi) neutron = mcni.neutron(r=(0, 0, 0), v=Vi, time=0, prob=1) from mcni.components.MonochromaticSource import MonochromaticSource component1 = MonochromaticSource('source', neutron) from mccomponents.sample import samplecomponent component2 = samplecomponent( 'Al', 'sampleassemblies/Al-constantqekernel/sampleassembly.xml') instrument = mcni.instrument([component1, component2]) geometer = mcni.geometer() geometer.register(component1, (0, 0, 0), (0, 0, 0)) geometer.register(component2, (0, 0, 1), (0, 0, 0)) N0 = 1000 neutrons = mcni.neutron_buffer(N0) mcni.simulate(instrument, geometer, neutrons) N = len(neutrons) import numpy.linalg as nl, numpy as np for i in range(10): neutron = neutrons[i] Vf = np.array(neutron.state.velocity) print Vf ef = conversion.v2e(nl.norm(Vf)) E = ei - ef dV = np.array(Vf) - np.array(Vi) qasv = nl.norm(dV) Q = conversion.v2k(qasv) self.assertAlmostEqual(E, E0, 7) self.assertAlmostEqual(Q, Q0, 7) continue return
def test1(self): "mccomponents.sample.samplecomponent: E_vQ_Kernel" import mcni from mcni.utils import conversion ei = 60 vil = conversion.e2v(ei) vi = (0, 0, vil) neutron = mcni.neutron(r=(0, 0, 0), v=vi, time=0, prob=1) from mcni.components.MonochromaticSource import MonochromaticSource component1 = MonochromaticSource("source", neutron) from mccomponents.sample import samplecomponent component2 = samplecomponent("Al", "sampleassemblies/Al-E_vQ-kernel/sampleassembly.xml") E_Q = "20 + 5 * sin(Qx+Qy+Qz)" # in sampleassemblies/Al-E_vQ-kernel/Al-scatterer.xml instrument = mcni.instrument([component1, component2]) geometer = mcni.geometer() geometer.register(component1, (0, 0, 0), (0, 0, 0)) geometer.register(component2, (0, 0, 1), (0, 0, 0)) N0 = 10000 neutrons = mcni.neutron_buffer(N0) mcni.simulate(instrument, geometer, neutrons) N = len(neutrons) import numpy.linalg as nl import numpy as np from math import sin for i in range(N): neutron = neutrons[i] vf = np.array(neutron.state.velocity) diffv = vi - vf Q = conversion.V2K * diffv Qx, Qy, Qz = Q ef = conversion.v2e(nl.norm(vf)) E = ei - ef # print E, Q, neutron E1 = eval(E_Q) self.assertAlmostEqual(E, E1) continue return
def test1(self): 'mccomponents.sample: ConstantvQEKernel' # momentum and energy transfer. defined in the scatterer xml file Q0 = 2,0,2 E0 = 28 import mcni from mcni.utils import conversion ei = 60 vi = conversion.e2v(ei) Vi = (0,0,vi) neutron = mcni.neutron( r = (0,0,0), v = Vi, time = 0, prob = 1 ) from mcni.components.MonochromaticSource import MonochromaticSource component1 = MonochromaticSource('source', neutron) from mccomponents.sample import samplecomponent component2 = samplecomponent( 'Al', 'sampleassemblies/Al-constantvqekernel/sampleassembly.xml' ) instrument = mcni.instrument( [component1, component2] ) geometer = mcni.geometer() geometer.register( component1, (0,0,0), (0,0,0) ) geometer.register( component2, (0,0,1), (0,0,0) ) N0 = 1000 neutrons = mcni.neutron_buffer(N0) mcni.simulate( instrument, geometer, neutrons ) N = len(neutrons) import numpy.linalg as nl, numpy as np for i in range(10): neutron = neutrons[i] Vf = np.array(neutron.state.velocity) # print Vf ef = conversion.v2e(nl.norm(Vf)) E = ei-ef dV = np.array(Vi) - np.array(Vf) Q = dV * conversion.V2K print E, Q, neutron.probability self.assertAlmostEqual(E, E0, 1) for i in range(3): self.assertAlmostEqual(Q[i], Q0[i], 7) continue return
def test2(self): "SNS_source_r1: angling" from mcstas2 import componentfactory factory = componentfactory(category, componentname) Emin = 59.99 Emax = 60.01 component = factory( "component", S_filename="source_sct521_bu_17_1.dat", width=0.001, height=0.001, dist=2.5, xw=0.001, yh=0.001, Emin=Emin, Emax=Emax, angling=30, ) import mcni N = 100 neutrons = mcni.neutron_buffer(N) for i in range(N): neutrons[i] = mcni.neutron(r=(0, 0, -1), v=(0, 0, 3000), time=0, prob=1) continue component.process(neutrons) from mcni.utils import conversion as Conv expected_vlen = Conv.e2v((Emin + Emax) / 2) import numpy as np for i in range(N): neutron = neutrons[i] state = neutron.state r = state.position assert abs(r[0]) < 0.001 assert abs(r[1]) < 0.001 assert abs(r[2]) < 0.001 v = np.array(state.velocity) vlen = np.linalg.norm(v) # print v, expected_vlen, vlen assert abs(vlen - expected_vlen) / expected_vlen < 0.01 assert abs(-v[0] - expected_vlen / 2.0) / expected_vlen < 0.01 assert abs(v[2] - expected_vlen * np.sqrt(3) / 2.0) / expected_vlen < 0.01 return
def test1(self): 'mccomponents.sample.samplecomponent: E_vQ_Kernel' import mcni from mcni.utils import conversion ei = 60 vil = conversion.e2v(ei) vi = (0, 0, vil) neutron = mcni.neutron(r=(0, 0, 0), v=vi, time=0, prob=1) from mcni.components.MonochromaticSource import MonochromaticSource component1 = MonochromaticSource('source', neutron) from mccomponents.sample import samplecomponent component2 = samplecomponent( 'Al', 'sampleassemblies/Al-E_vQ-kernel/sampleassembly.xml') E_Q = '20 + 5 * sin(Qx+Qy+Qz)' # in sampleassemblies/Al-E_vQ-kernel/Al-scatterer.xml instrument = mcni.instrument([component1, component2]) geometer = mcni.geometer() geometer.register(component1, (0, 0, 0), (0, 0, 0)) geometer.register(component2, (0, 0, 1), (0, 0, 0)) N0 = 1000 neutrons = mcni.neutron_buffer(N0) mcni.simulate(instrument, geometer, neutrons) N = len(neutrons) import numpy.linalg as nl import numpy as np from math import sin for i in range(N): neutron = neutrons[i] vf = np.array(neutron.state.velocity) diffv = vi - vf Q = conversion.V2K * diffv Qx, Qy, Qz = Q ef = conversion.v2e(nl.norm(vf)) E = ei - ef # print E, Q, neutron E1 = eval(E_Q) self.assertAlmostEqual(E, E1) continue return
def test1(self): 'mccomponents.sample.samplecomponent: Broadened_E_Q_Kernel' import mcni from mcni.utils import conversion ei = 600 vil = conversion.e2v(ei) vi = (0, 0, vil) neutron = mcni.neutron(r=(0, 0, 0), v=vi, time=0, prob=1) from mcni.components.MonochromaticSource import MonochromaticSource component1 = MonochromaticSource('source', neutron) from mccomponents.sample import samplecomponent component2 = samplecomponent( 'Al', 'sampleassemblies/Al-broadened-E_Q-kernel/sampleassembly.xml') E_Q = 'Q*Q/3.5' # in sampleassemblies/Al-broadened-E_Q-kernel/Al-scatterer.xml instrument = mcni.instrument([component1, component2]) geometer = mcni.geometer() geometer.register(component1, (0, 0, 0), (0, 0, 0)) geometer.register(component2, (0, 0, 1), (0, 0, 0)) N0 = 1000 neutrons = mcni.neutron_buffer(N0) mcni.simulate(instrument, geometer, neutrons) N = len(neutrons) import numpy.linalg as nl import numpy as np for i in range(10): neutron = neutrons[i] vf = np.array(neutron.state.velocity) diffv = vi - vf Q = conversion.v2k(nl.norm(diffv)) ef = conversion.v2e(nl.norm(vf)) E = ei - ef E1 = eval(E_Q) print E, Q, neutron, E - E1 continue return
def test1(self): 'mccomponents.sample.samplecomponent: Broadened_E_Q_Kernel' import mcni from mcni.utils import conversion ei = 600 vil = conversion.e2v(ei) vi = (0,0,vil) neutron = mcni.neutron( r = (0,0,0), v = vi, time = 0, prob = 1 ) from mcni.components.MonochromaticSource import MonochromaticSource component1 = MonochromaticSource('source', neutron) from mccomponents.sample import samplecomponent component2 = samplecomponent( 'Al', 'sampleassemblies/Al-broadened-E_Q-kernel/sampleassembly.xml' ) E_Q = 'Q*Q/3.5' # in sampleassemblies/Al-broadened-E_Q-kernel/Al-scatterer.xml instrument = mcni.instrument( [component1, component2] ) geometer = mcni.geometer() geometer.register( component1, (0,0,0), (0,0,0) ) geometer.register( component2, (0,0,1), (0,0,0) ) N0 = 1000 neutrons = mcni.neutron_buffer(N0) mcni.simulate( instrument, geometer, neutrons ) N = len(neutrons) import numpy.linalg as nl import numpy as np for i in range(10): neutron = neutrons[i] vf = np.array(neutron.state.velocity) diffv = vi - vf Q = conversion.v2k(nl.norm(diffv)) ef = conversion.v2e(nl.norm(vf)) E = ei - ef E1 = eval(E_Q) print E, Q, neutron, E-E1 continue return
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 runMonitorsAtSample(E, m2sout, out, L): from mcni.utils.conversion import e2v v = e2v(E) from pyre.units.time import second t = L / v neutronfile = os.path.abspath(os.path.join(m2sout, 'neutrons')) from mcni.neutron_storage.idf_usenumpy import count n = count(neutronfile) # cmd = ['mcvine instruments %s analyze_beam' % instrument] app = os.path.join(here, 'dgs_bpp_analyze_beam.py') # create a temp dir to run the simulation import tempfile tmpd = tempfile.mkdtemp() def copy2tmpd(fn): src = os.path.join(here, fn) dest = os.path.join(tmpd, fn) shutil.copyfile(src, dest) copy2tmpd('dgs_bpp_analyze_beam.pml') copy2tmpd('beam_analyzer.odb') cmd = ['python {}'.format(app)] cmd += ['--output-dir=%s' % os.path.abspath(out)] cmd += ['--ncount=%s' % n] cmd += ['--buffer_size=%s' % min(n, int(1e6))] cmd += ['--source.path=%s' % neutronfile] # fix monitor params that depend on incident energy cmd += ['--monitor.mtof.tofmin=%s' % (t * 0.9)] cmd += ['--monitor.mtof.tofmax=%s' % (t * 1.1)] cmd += ['--monitor.mtof.ntof=%s' % (1000)] cmd += ['--monitor.menergy.energymin=%s' % (E * 0.9)] cmd += ['--monitor.menergy.energymax=%s' % (E * 1.1)] cmd += ['--monitor.menergy.nenergy=%s' % (1000)] cmd = ' '.join(cmd) print('Running beam monitors...') from mcvine.run_script import _exec print(cmd, tmpd) _exec(cmd, cwd=tmpd) print('done.') time.sleep(1) # shutil.rmtree(tmpd) return
def test1(self): 'mccomponents.sample.samplecomponent' # energy transfer. defined in the scatterer xml file E0 = 10 import mcni from mcni.utils import conversion ei = 60 vi = conversion.e2v(ei) neutron = mcni.neutron(r=(0, 0, 0), v=(0, 0, vi), time=0, prob=1) from mcni.components.MonochromaticSource import MonochromaticSource component1 = MonochromaticSource('source', neutron) from mccomponents.sample import samplecomponent component2 = samplecomponent( 'Al', 'sampleassemblies/Al-constantenergytransfer/sampleassembly.xml') instrument = mcni.instrument([component1, component2]) geometer = mcni.geometer() geometer.register(component1, (0, 0, 0), (0, 0, 0)) geometer.register(component2, (0, 0, 1), (0, 0, 0)) N0 = 1000 neutrons = mcni.neutron_buffer(N0) mcni.simulate(instrument, geometer, neutrons) N = len(neutrons) import numpy.linalg as nl for i in range(10): neutron = neutrons[i] vf = nl.norm(neutron.state.velocity) ef = conversion.v2e(vf) E = ei - ef self.assertAlmostEqual(E, E0, 7) continue return
def runMonitorsAtSample(E, LMS, m2sout, out): from mcni.utils.conversion import e2v v = e2v(E) from pyre.units.time import second # this is copied from hyspec_moderator2sample.instr # XXX: duplicate code. will need to change this # XXX: if the instrument changes. L1 = 9.93 L2 = 48.0 * 0.501 L3 = 5.0 LMM = L1 + L2 + L3 L = LMM + LMS t = L / v neutronfile = os.path.join(m2sout, "neutrons") from mcni.neutron_storage.idf_usenumpy import count n = count(neutronfile) cmd = ["mcvine_analyze_beam"] cmd += ["--output-dir=%s" % out] cmd += ["--ncount=%s" % n] cmd += ["--buffer_size=%s" % min(n, 1e6)] # XXX: -0.15 comes from the fact that the in hyspec_moderator2sample # XXX: the neutron storage is 0.15 before the sample position cmd += ['--geometer.source="((0,0,-0.15),(0,0,0))"'] cmd += ["--source.path=%s" % neutronfile] # fix monitor params that depend on incident energy cmd += ["--monitor.mtof.tofmin=%s" % (t * 0.9)] cmd += ["--monitor.mtof.tofmax=%s" % (t * 1.1)] cmd += ["--monitor.mtof.ntof=%s" % (1000)] cmd += ["--monitor.menergy.energymin=%s" % (E * 0.9)] cmd += ["--monitor.menergy.energymax=%s" % (E * 1.1)] cmd += ["--monitor.menergy.nenergy=%s" % (1000)] cmd = " ".join(cmd) print "Running beam monitors..." _exec(cmd) print "done." time.sleep(1) return
def test(self): E = 10 #meV kernel = mccomponentsbp.ConstantEnergyTransferKernel(E, 1, 1) ei = 100 # meV from mcni.utils import conversion vi = conversion.e2v(ei) import numpy.linalg as nl for i in range(10): event = mcni.neutron(r=(0, 0, 0), v=(0, 0, vi), prob=1, time=0) kernel.scatter(event) vf = event.state.velocity vf = nl.norm(vf) ef = conversion.v2e(vf) # print ef self.assertAlmostEqual(ei - ef, E, 5) continue return
def test(self): E=10 #meV kernel = mccomponentsbp.ConstantEnergyTransferKernel(E, 1,1) ei = 100 # meV from mcni.utils import conversion vi = conversion.e2v(ei) import numpy.linalg as nl for i in range(10): event = mcni.neutron( r = (0,0,0), v = (0,0,vi), prob = 1, time = 0 ) kernel.scatter( event ); vf = event.state.velocity vf = nl.norm(vf) ef = conversion.v2e(vf) # print ef self.assertAlmostEqual(ei-ef, E, 5) continue return
def getEiToffset(mod2sample): from histogram.hdf import load import os # I(energy) ie = load(os.path.join(mod2sample, 'out-analyzer/ienergy.h5'), 'ienergy') # average energy e = (ie.I * ie.energy).sum() / ie.I.sum() # I(tof) itof = load(os.path.join(mod2sample, 'out-analyzer/itof.h5'), 'itof') # average tof tof = (itof.I * itof.tof).sum() / itof.I.sum() from mcni.utils.conversion import e2v v = e2v(e) L = mod2sample_distance toffset = tof - (L / v) # energy: meV, toffset: microsecond return e, toffset * 1e6
def test1(self): 'mccomponents.sample.samplecomponent' # energy transfer. defined in the scatterer xml file E0 = 10 import mcni from mcni.utils import conversion ei = 60 vi = conversion.e2v(ei) neutron = mcni.neutron( r = (0,0,0), v = (0,0,vi), time = 0, prob = 1 ) from mcni.components.MonochromaticSource import MonochromaticSource component1 = MonochromaticSource('source', neutron) from mccomponents.sample import samplecomponent component2 = samplecomponent( 'Al', 'sampleassemblies/Al-constantenergytransfer/sampleassembly.xml' ) instrument = mcni.instrument( [component1, component2] ) geometer = mcni.geometer() geometer.register( component1, (0,0,0), (0,0,0) ) geometer.register( component2, (0,0,1), (0,0,0) ) N0 = 1000 neutrons = mcni.neutron_buffer(N0) mcni.simulate( instrument, geometer, neutrons ) N = len(neutrons) import numpy.linalg as nl for i in range(10): neutron = neutrons[i] vf = nl.norm(neutron.state.velocity) ef = conversion.v2e(vf) E = ei-ef self.assertAlmostEqual(E, E0, 7) continue return
def computeFocusedSpectraForRealMonitors(E, m2sout, out): from mcni.utils.conversion import e2v v = e2v(E) from pyre.units.time import second import histogram.hdf as hh, histogram as H m1 = hh.load(os.path.join(m2sout, 'mon1-tof.h5'), 'I(tof)') t1 = LM1/v #* second m1p = m1[(t1*0.9, t1*1.1)] m1pc = H.histogram('I(tof)', m1p.axes(), data=m1p.I, errors=m1p.E2) m1pc.setAttribute('title', 'Monitor 1 I(tof)') hh.dump(m1pc, os.path.join(out, 'mon1-itof-focused.h5'), '/', 'c') m2 = hh.load(os.path.join(m2sout, 'mon2-tof.h5'), 'I(tof)') t2 = LM2/v #* second m2p = m2[(t2*0.9, t2*1.1)] m2pc = H.histogram('I(tof)', m2p.axes(), data=m2p.I, errors=m2p.E2) m2pc.setAttribute('title', 'Monitor 2 I(tof)') hh.dump(m2pc, os.path.join(out, 'mon2-itof-focused.h5'), '/', 'c') return
def computeFocusedSpectraForRealMonitors(E, m2sout, out, LM1=LM1, LM2=LM2): from mcni.utils.conversion import e2v v = e2v(E) from pyre.units.time import second import histogram.hdf as hh, histogram as H m1 = hh.load(os.path.join(m2sout, 'mon1-tof.h5'), 'I(tof)') t1 = LM1/v #* second m1p = m1[(t1*0.9, t1*1.1)] m1pc = H.histogram('I(tof)', m1p.axes(), data=m1p.I, errors=m1p.E2) m1pc.setAttribute('title', 'Monitor 1 I(tof)') hh.dump(m1pc, os.path.join(out, 'mon1-itof-focused.h5'), '/', 'c') m2 = hh.load(os.path.join(m2sout, 'mon2-tof.h5'), 'I(tof)') t2 = LM2/v #* second m2p = m2[(t2*0.9, t2*1.1)] m2pc = H.histogram('I(tof)', m2p.axes(), data=m2p.I, errors=m2p.E2) m2pc.setAttribute('title', 'Monitor 2 I(tof)') hh.dump(m2pc, os.path.join(out, 'mon2-itof-focused.h5'), '/', 'c') return
def getEiToffset(mod2sample): from histogram.hdf import load import os # I(energy) ie = load(os.path.join(mod2sample, 'out-analyzer/ienergy.h5'), 'ienergy') # average energy e = (ie.I * ie.energy).sum()/ie.I.sum() # I(tof) itof = load(os.path.join(mod2sample, 'out-analyzer/itof.h5'), 'itof') # average tof tof = (itof.I*itof.tof).sum()/itof.I.sum() from mcni.utils.conversion import e2v v = e2v(e) L = mod2sample_distance toffset = tof - (L/v) # energy: meV, toffset: microsecond return e, toffset * 1e6
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 test(self): E_Q = "Q*Q/3." S_Q = "1" Qmin = 0 Qmax = 10 absorption_coefficient = scattering_coefficient = 1. kernel = mccomponentsbp.create_E_Q_Kernel( E_Q, S_Q, Qmin, Qmax, absorption_coefficient, scattering_coefficient, ) ei = 500 # meV from mcni.utils import conversion vil = conversion.e2v(ei) vi = (0, 0, vil) import numpy.linalg as nl import numpy as np for i in range(10): event = mcni.neutron(r=(0, 0, 0), v=vi, prob=1, time=0) kernel.scatter(event) vf = np.array(event.state.velocity) diffv = vi - vf Q = conversion.v2k(nl.norm(diffv)) ef = conversion.v2e(nl.norm(vf)) E = ei - ef # print E, Q, event E1 = eval(E_Q) self.assertAlmostEqual(E, E1) continue return
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 pass # end of TestCase mass = 50 temperature = 300 Ei = 70 from mcni.utils import conversion as C vi = C.e2v(Ei) def makeKernel(): max_omega = 50 max_Q = 13 nMCsteps_to_calc_RARV = 1000 return b.phonon_coherentinelastic_polyxtal_kernel( makeDispersion(), makeDW(), makeMatter(), temperature=temperature, max_omega=max_omega, )
#!/usr/bin/env python """ compute phase (degree) of fermi chopper at t=0 """ Ei = 686.62 freq = 600. dist = 11.61 # mod to fc t_emission = 3.8 * 1e-6 from mcni.utils import conversion as Conv vi = Conv.e2v(Ei) t_fc = dist/vi + t_emission phase = -t_fc * freq * 360. print phase
def getNormalization(monitor, N=None, epsilon=1e-7): # randomly shoot neutrons to monitor in 4pi solid angle print "* start computing normalizer..." core = monitor.core() if N is None: N = core.nQ * core.nE * 10000 import mcni, random, mcni.utils.conversion as conversion, math, os import numpy as np # incident velocity vi = conversion.e2v(core.Ei) # 1. create neutrons def make_neutrons(N): neutrons = mcni.neutron_buffer(N) # # randomly select E, the energy transfer E = core.Emin + np.random.random(N) * (core.Emax - core.Emin) # the final energy Ef = core.Ei - E # the final velocity vf = conversion.e2v(Ef) # choose cos(theta) between -1 and 1 cos_t = np.random.random(N) * 2 - 1 # theta theta = np.arccos(cos_t) # sin(theta) sin_t = np.sin(theta) # phi: 0 - 2pi phi = np.random.random(N) * 2 * np.pi # compute final velocity vector vx, vy, vz = vf * sin_t * np.cos(phi), vf * sin_t * np.sin( phi), vf * cos_t # neutron position, spin, tof are set to zero x = y = z = sx = sy = t = np.zeros(N, dtype="float64") # probability prob = np.ones(N, dtype="float64") * (vf / vi) # XXX: this assumes a specific data layout of neutron struct n_arr = np.array([x, y, z, vx, vy, vz, sx, sy, t, prob]).T.copy() neutrons.from_npyarr(n_arr) return neutrons # 2. create a copy of the original monitor from mcstas2 import componentfactory cf = componentfactory(type='IQE_monitor', category='monitors') props = [ 'Ei', 'Emin', 'Emax', 'nE', 'Qmin', 'Qmax', 'nQ', 'max_angle_out_of_plane', 'min_angle_out_of_plane', 'max_angle_in_plane', 'min_angle_in_plane', ] kwds = {} for p in props: kwds[p] = getattr(core, p) import tempfile tmpdir = tempfile.mkdtemp() outfilename = os.path.join(tmpdir, 'mon.dat') kwds['filename'] = outfilename monitorcopy = cf('monitor', **kwds) # 3. send neutrons to monitor copy N1 = 0 dN = int(1e6) print " - total neutrons needed :", N while N1 < N: n = min(N - N1, dN) neutrons = make_neutrons(n) monitorcopy.process(neutrons) N1 += n print " - processed %s" % N1 continue h = get_histogram(monitorcopy) # for debug # import histogram.hdf as hh # hh.dump(h, 'tmp.h5', '/', 'c') h.I[h.I < epsilon] = 1 # print " - done computing normalizer" return h
def run(Ei, ncount, nodes, moderator_erange=None, fermichopper=None, fermi_nu=None, T0_nu=None, emission_time=None, dry_run=False): fermichopper = fermichopper or "100-1.5-SMI" emission_time = emission_time or -1 fermi_nu = fermi_nu or 600 T0_nu = T0_nu or 120 # generate configration cmd = """ arcs-m2s \ --fermi_nu=%(fermi_nu)s \ --T0_nu=%(T0_nu)s \ --E=%(Ei)s \ --emission_time=%(emission_time)s \ --fermi_chopper=%(fermichopper)s \ --- \ -dump-pml """ % locals() execute(cmd) # fine tune configuraiton cmd = ["arcs_moderator2sample --overwrite-datafiles"] Emin, Emax = moderator_erange cmd.append('--moderator.Emin=%s' % Emin) cmd.append('--moderator.Emax=%s' % Emax) cmd.append("--dump-pml") cmd = ' '.join(cmd) execute(cmd) # run simulation import os, shutil if os.path.exists('out'): shutil.rmtree('out') cmd = "arcs_moderator2sample -ncount=%(ncount)s " % locals() # ... moderator data file moddat = os.path.join( os.environ['MCVINE_DIR'], 'share', 'mcvine', 'instruments', 'ARCS', 'source_sct521_bu_17_1.dat', ) cmd += ' -moderator.S_filename=%s ' % moddat cmd += ' -mpirun.nodes=%s' % nodes cmd += '> m2s.log 2> m2s.err' if dry_run: print cmd else: execute(cmd) # analyze output # ... number of neutrons left neutronfile = os.path.join('out', 'neutrons') from mcni.neutron_storage.idf_usenumpy import count if dry_run: ncountatsample = 1000 else: ncountatsample = count(neutronfile) if ncountatsample == 0: raise RuntimeError, "no neutrons at sample. need to increase mc samples at mod2sample simulation" cmd = [ 'arcs_analyze_beam', '-source.path=%(neutronfile)s' % locals(), '-ncount=%(ncountatsample)s' % locals(), '--output-dir=out-analyzer', ] # ... compute enegy range from mcni.utils.conversion import e2v v = e2v(Ei) from pyre.units.time import second L = 13.6 t = L / v # ... build command line with monitor parameters cmd += ['--monitor.mtof.tofmin=%s' % (t * 0.9)] cmd += ['--monitor.mtof.tofmax=%s' % (t * 1.1)] cmd += ['--monitor.mtof.ntof=%s' % (1000)] cmd += ['--monitor.menergy.energymin=%s' % (Ei * 0.9)] cmd += ['--monitor.menergy.energymax=%s' % (Ei * 1.1)] cmd += ['--monitor.menergy.nenergy=%s' % (1000)] # ... run cmd = ' '.join(cmd) if dry_run: print cmd else: execute(cmd) return
): """source neutrons come from (x,y) going to direction z """ import os, shutil if os.path.exists('out'): shutil.rmtree('out') # run main sim cmd = './sss --source.position="%s,%s,0"' % (x,y,) execute(cmd) return mod2sample_distance = 13.6 Ei = 687 from mcni.utils import conversion vi = conversion.e2v(Ei) def createScatteringKernel(E_Q,S_Q, Qmin, Qmax): import os tf = os.path.join('sampleassembly', 'He4-scatterer.xml.template') t = open(tf).read() t = t.replace('$E_Q$', E_Q) t = t.replace('$S_Q$', S_Q) t = t.replace('$Qmin$', str(Qmin)) t = t.replace('$Qmax$', str(Qmax)) f = os.path.join('sampleassembly', 'He4-scatterer.xml') open(f, 'w').write(t) return
def run(Ei, ncount, nodes, moderator_erange = None, fermichopper=None, fermi_nu=None, T0_nu = None, emission_time = None, dry_run=False): fermichopper = fermichopper or "100-1.5-SMI" emission_time = emission_time or -1 fermi_nu = fermi_nu or 600 T0_nu = T0_nu or 120 # generate configration cmd = """ arcs-m2s \ --fermi_nu=%(fermi_nu)s \ --T0_nu=%(T0_nu)s \ --E=%(Ei)s \ --emission_time=%(emission_time)s \ --fermi_chopper=%(fermichopper)s \ --- \ -dump-pml """ % locals() execute(cmd) # fine tune configuraiton cmd = ["arcs_moderator2sample --overwrite-datafiles"] Emin, Emax = moderator_erange cmd.append('--moderator.Emin=%s' % Emin) cmd.append('--moderator.Emax=%s' % Emax) cmd.append("--dump-pml") cmd = ' '.join(cmd) execute(cmd) # run simulation import os, shutil if os.path.exists('out'): shutil.rmtree('out') cmd = "arcs_moderator2sample -ncount=%(ncount)s " % locals() # ... moderator data file moddat = os.path.join( os.environ['MCVINE_DIR'], 'share', 'mcvine', 'instruments', 'ARCS', 'source_sct521_bu_17_1.dat', ) cmd += ' -moderator.S_filename=%s ' % moddat cmd += ' -mpirun.nodes=%s' % nodes cmd += '> m2s.log 2> m2s.err' if dry_run: print cmd else: execute(cmd) # analyze output # ... number of neutrons left neutronfile = os.path.join('out', 'neutrons') from mcni.neutron_storage.idf_usenumpy import count if dry_run: ncountatsample = 1000 else: ncountatsample = count(neutronfile) if ncountatsample == 0: raise RuntimeError, "no neutrons at sample. need to increase mc samples at mod2sample simulation" cmd = [ 'arcs_analyze_beam', '-source.path=%(neutronfile)s' % locals(), '-ncount=%(ncountatsample)s' % locals(), '--output-dir=out-analyzer', ] # ... compute enegy range from mcni.utils.conversion import e2v v = e2v(Ei) from pyre.units.time import second L = 13.6 t = L/v # ... build command line with monitor parameters cmd += ['--monitor.mtof.tofmin=%s' % (t*0.9)] cmd += ['--monitor.mtof.tofmax=%s' % (t*1.1)] cmd += ['--monitor.mtof.ntof=%s' % (1000)] cmd += ['--monitor.menergy.energymin=%s' % (Ei*0.9)] cmd += ['--monitor.menergy.energymax=%s' % (Ei*1.1)] cmd += ['--monitor.menergy.nenergy=%s' % (1000)] # ... run cmd = ' '.join(cmd) if dry_run: print cmd else: execute(cmd) return
def setup(outdir, sampleyml, beam, E, hkl, hkl_projection, psi_axis, instrument, pixel, log=None): """setup the simulation directory and scripts and input files - outdir: output dir - sampleyml: path. should contain * name * chemical_formula * lattice * orientation * shape - beam: mcvine beam simulation path - E: energy transfer - hkl: momentum transfer - hkl_projection: hkl projection axis for slice - psi_axis: psi scan - instrument: instrument object with geometry data such as L1 and L2 - pixel: pixel object with pixe, height, pressure. and position - log: logger object """ if log is None: import sys log = sys.stdout # load beam from ._beam import computeEi_and_t0 Ei, t0 = computeEi_and_t0(beam, instrument) log.write( "Ei=%s, t0=%s\n" % (Ei, t0) ) # load sample from mcvine.workflow.sample import loadSampleYml sample = loadSampleYml(sampleyml) # the sample kernel need information of E and hkl Q, hkl2Qmat, psi = calcQ(sampleyml, Ei, E, hkl, psi_axis, Npsisegments=10) log.write( "Computed:\n" ) log.write( "* psi=%s degree\n" % (psi/np.pi*180,) ) log.write( "* Q=%s\n" % (Q,) ) log.write( "* hkl2Qmat=%s\n" % (hkl2Qmat,) ) kfv, Ef = computeKf(Ei, E, Q, log) log.write( "* Ef=%s\n" % (Ef,)) pixel_position, pixel_orientation = computePixelPositionOrientation(kfv, instrument, log) # at this point the coordinates have convention of z vertical up # ** coordinate system for calculated position: z is vertical ** # this pixel_position is in the instrument coordinate system. # we need, however, the pixel_position in the instrument # coordinate system rorated psi angle. from numpy import sin, cos x,y,z=pixel_position x2,y2,z2 = x*cos(psi)+y*sin(psi), -x*sin(psi)+y*cos(psi), z # convert to z along beam pixel_position3 = y2, z2, x2 # compute nominal tof from mod to sample vi = Conv.e2v(Ei) L_m2s = mcvine.units.parse(instrument.L_m2s)/mcvine.units.meter t_m2s = L_m2s/vi + t0*1e-6 # nominal tof from mod to pixel vf = Conv.e2v(Ef) t_s2p = np.linalg.norm(pixel_position)/vf t_m2p = t_m2s + t_s2p log.write( "t_m2s=%s, t_s2p=%s, t_m2p=%s\n" % (t_m2s, t_s2p, t_m2p)) # tof passing through the pixel r = mcvine.units.parse(pixel.radius)/mcvine.units.meter h = mcvine.units.parse(pixel.height)/mcvine.units.meter dtof = np.sqrt(4*r*r+h*h)*1.1/vf # decorate the sample kernel kernel = sample.excitations[0] kernel.target_position = "%s*meter,%s*meter,%s*meter" % pixel_position3 kernel.target_radius = "%s*meter" % (np.sqrt(r*r+h*h/4)*1.1,) kernel.tof_at_target = "%s*microsecond" % (t_m2p*1e6) kernel.dtof = "%s*microsecond" % (dtof*1e6,) # create sample assembly from mcvine.workflow.singlextal.scaffolding import createSampleAssembly sampledir = os.path.abspath(os.path.join(outdir, 'sample')) createSampleAssembly(sampledir, sample, add_elastic_line=False) # save instrument object ofstream = tpf.NamedTemporaryFile( dir=outdir, prefix='instrument', suffix='.pkl', delete=False) pkl.dump(instrument, ofstream) instr_fn = os.path.abspath(ofstream.name) ofstream.close() # save pixel object pixel.position = pixel_position pixel.orientation = pixel_orientation ofstream = tpf.NamedTemporaryFile( dir=outdir, prefix='pixel', suffix='.pkl', delete=False) pkl.dump(pixel, ofstream) pixel_fn = os.path.abspath(ofstream.name) ofstream.close() # create sim script params = dict( beam_neutrons_path = os.path.join(beam, 'out', 'neutrons'), instr_fn = instr_fn, pixel_fn = pixel_fn, samplexmlpath = os.path.join(sampledir, "sampleassembly.xml"), psi = psi, hkl2Q = hkl2Qmat, t_m2p = t_m2p, Q = Q, E = E, hkl_projection = hkl_projection, ) script = sim_script_template % params open(os.path.join(outdir, 'run.py'), 'wt').write(script) return
def compute(sample_yml, Ei, dynamics, psi_scan, instrument, pixel, tofwidths, beamdivs, samplethickness, plot=False): # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX # should P be the T0 chopper? L_PM = mcvine.units.parse( instrument.L_m2fc ) / mcvine.units.meter # P chopper to M chopper distance L_PS = mcvine.units.parse( instrument.L_m2s) / mcvine.units.meter # P chopper to sample L_MS = L_PS - L_PM # R = mcvine.units.parse(instrument.detsys_radius) / mcvine.units.meter # hkl0 = dynamics.hkl0 hkl_dir = dynamics.hkl_dir # projection psimin = psi_scan.min psimax = psi_scan.max dpsi = psi_scan.step # dynamics calculations E = dynamics.E dq = dynamics.dq hkl = hkl0 + dq * hkl_dir from mcni.utils import conversion as Conv vi = Conv.e2v(Ei) ti = L_PM / vi * 1e6 # microsecond Ef = Ei - E vf = Conv.e2v(Ef) # find the psi angle from mcvine.workflow.singlextal.io import loadXtalOriFromSampleYml xtalori = loadXtalOriFromSampleYml(sample_yml) from mcvine.workflow.singlextal.solve_psi import solve results = solve(xtalori, Ei, hkl, E, psimin, psimax, Nsegments=NSEGMENTS_SOLVE_PSI) from mcvine.workflow.singlextal.coords_transform import hkl2Q for r in results: xtalori.psi = r * np.pi / 180 print("psi=%s, Q=%s" % (r, hkl2Q(hkl, xtalori))) print("hkl2Q=%r\n(Q = hkl dot hkl2Q)" % (xtalori.hkl2cartesian_mat(), )) # these are the psi angles that the particular point of interest will be measured # print results assert len(results) # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX # only select the first one. this is OK for most cases but there are cases where more than # one psi angles satisfy the condition psi = results[0] xtalori.psi = psi * np.pi / 180 Q = hkl2Q(hkl, xtalori) hkl2Q_mat = xtalori.hkl2cartesian_mat() # print Q # print hkl2Q_mat # Q_len = np.linalg.norm(Q) # print Q_len ki = Conv.e2k(Ei) # print ki kiv = np.array([ki, 0, 0]) kfv = kiv - Q # print kfv # # ** Verify the momentum and energy transfers ** # print Ei-Conv.k2e(np.linalg.norm(kfv)) # print Ei-Ef assert np.isclose(Ei - Ef, E) # ** Compute detector pixel position ** z = kfv[2] / (kfv[0]**2 + kfv[1]**2)**.5 * R L_SD = (z**2 + R**2)**.5 # print z, L_SD # ### Constants eV = 1.60218e-19 meV = eV * 1e-3 mus = 1.e-6 hbar = 1.0545718e-34 AA = 1e-10 m = 1.6750e-24 * 1e-3 #kg from numpy import sin, cos # dE calcuation starts here # ## Differentials pE_pt = -m * (vi**3 / L_PM + vf**3 / L_SD * L_MS / L_PM) # convert to eV/microsecond pE_pt /= meV / mus # print pE_pt pE_ptMD = m * vf**3 / L_SD pE_ptMD /= meV / mus # print pE_ptMD pE_pLPM = m / L_PM * (vi**2 + vf**3 / vi * L_MS / L_SD) pE_pLPM /= meV # print pE_pLPM pE_pLMS = -m / L_SD * (vf**3 / vi) pE_pLMS /= meV # print pE_pLMS pE_pLSD = -m * vf * vf / L_SD pE_pLSD /= meV # print pE_pLSD # we don't need pE_pLSD, instead we need pE_pR and pE_pz. R and z are cylinder radius and z coordinate pE_pR = pE_pLSD * (R / L_SD) pE_pz = pE_pLSD * (z / L_SD) # print pE_pR, pE_pz # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX # ## ** Paramters: Estimate of standard deviations # tau_P = 10 # microsecond # tau_M = 8 # microsecond tau_P = tofwidths.P tau_M = tofwidths.M # # tau_D = 10 # microsecond tau_D = mcvine.units.parse( pixel.radius) / mcvine.units.meter * 2 / vf * 1e6 # microsecond # ## Calculations pE_p_vec = [pE_pt, pE_ptMD, pE_pLPM, pE_pLMS, pE_pR, pE_pz] pE_p_vec = np.array(pE_p_vec) J_E = pE_p_vec / E # print J_E sigma_t = (tau_P**2 + tau_M**2)**.5 sigma_tMD = (tau_M**2 + tau_D**2)**.5 # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX div = (beamdivs.theta**2 + beamdivs.phi**2)**.5 # a crude approx sigma_LPM = L_PM * div * div # mainly due to sample size sigma_LMS = samplethickness # mainly due to det tube diameter sigma_R = mcvine.units.parse(pixel.radius) / mcvine.units.meter * 2 # pixel size sigma_z = mcvine.units.parse(pixel.height) / mcvine.units.meter sigma = np.array( [sigma_t, sigma_tMD, sigma_LPM, sigma_LMS, sigma_R, sigma_z]) # print sigma sigma2 = sigma * sigma # print sigma2 sigma2 = np.diag(sigma2) # print J_E # print np.dot(sigma2, J_E) cov = np.dot(J_E, np.dot(sigma2, J_E)) # print cov, np.sqrt(cov) sigma_E = E * np.sqrt(cov) # print sigma_E # Not sure if this is right: # # * ** Note: this may be more like FWHM than sigma_E because of the approx I made ** # * ** FWHM is 2.355 sigma ** # ## Include Q # print "ti=",ti tf = L_SD / vf * 1e6 # print "tf=",tf thetai = 0 phii = 0 # print "R=", R # print "Q=", Q eeta = np.arctan2(kfv[1], kfv[0]) # print "eeta=", eeta pQx_pt = -m / hbar * (L_PM / ti / ti / mus / mus * cos(thetai) * cos(phii) + R / tf / tf / mus / mus * L_MS / L_PM * cos(eeta)) pQx_pt /= 1. / AA / mus # print pQx_pt pQx_ptMD = m / hbar * R / tf / tf * cos(eeta) / mus / mus pQx_ptMD /= 1. / AA / mus # print pQx_ptMD pQx_pLPM = m / hbar * (cos(thetai) * cos(phii) / ti + ti / tf / tf * R * L_MS / L_PM / L_PM * cos(eeta)) / mus pQx_pLPM /= 1. / AA # print pQx_pLPM pQx_pLMS = -m / hbar * R / tf / tf * ti / L_PM * cos(eeta) / mus pQx_pLMS /= 1. / AA # print pQx_pLMS pQx_pR = -m / hbar / tf * cos(eeta) / mus pQx_pR /= 1. / AA # print pQx_pR pQx_peeta = m / hbar * R / tf * sin(eeta) / mus pQx_peeta /= 1. / AA # print pQx_peeta pQx_pthetai = -m / hbar * L_PM / ti * sin(thetai) * cos(phii) / mus pQx_pthetai /= 1. / AA # print pQx_pthetai pQx_pphii = -m / hbar * L_PM / ti * cos(thetai) * sin(phii) / mus pQx_pphii /= 1. / AA # print pQx_pphii pQx_p_vec = [ pQx_pt, pQx_ptMD, pQx_pLPM, pQx_pLMS, pQx_pR, 0, pQx_peeta, pQx_pthetai, pQx_pphii ] pQx_p_vec = np.array(pQx_p_vec) J_Qx = pQx_p_vec / Q_len # **Qy** pQy_pt = -m / hbar * (L_PM / ti / ti * sin(thetai) * cos(phii) + R / tf / tf * L_MS / L_PM * sin(eeta)) / mus / mus pQy_pt /= 1. / AA / mus # print pQy_pt pQy_ptMD = m / hbar * R / tf / tf * sin(eeta) / mus / mus pQy_ptMD /= 1. / AA / mus # print pQy_ptMD pQy_pLPM = m / hbar * (sin(thetai) * cos(phii) / ti + ti / tf / tf * R * L_MS / L_PM / L_PM * sin(eeta)) / mus pQy_pLPM /= 1. / AA # print pQy_pLPM pQy_pLMS = -m / hbar * R / tf / tf * ti / L_PM * sin(eeta) / mus pQy_pLMS /= 1. / AA # print pQy_pLMS pQy_pR = -m / hbar / tf * sin(eeta) / mus pQy_pR /= 1. / AA # print pQy_pR pQy_peeta = -m / hbar * R / tf * cos(eeta) / mus pQy_peeta /= 1. / AA # print pQy_peeta pQy_pthetai = m / hbar * L_PM / ti * cos(thetai) * cos(phii) / mus pQy_pthetai /= 1. / AA # print pQy_pthetai pQy_pphii = -m / hbar * L_PM / ti * sin(thetai) * sin(phii) / mus pQy_pphii /= 1. / AA # print pQy_pphii pQy_p_vec = [ pQy_pt, pQy_ptMD, pQy_pLPM, pQy_pLMS, pQy_pR, 0, pQy_peeta, pQy_pthetai, pQy_pphii ] pQy_p_vec = np.array(pQy_p_vec) J_Qy = pQy_p_vec / Q_len # ** Qz ** pQz_pt = -m / hbar * (L_PM / ti / ti * sin(phii) + z / tf / tf * L_MS / L_PM) / mus / mus pQz_pt /= 1. / AA / mus # print pQz_pt pQz_ptMD = m / hbar * z / tf / tf / mus / mus pQz_ptMD /= 1. / AA / mus # print pQz_ptMD pQz_pLPM = m / hbar * (sin(phii) / ti + ti / tf / tf * z * L_MS / L_PM / L_PM) / mus pQz_pLPM /= 1. / AA # print pQz_pLPM pQz_pLMS = -m / hbar * z / tf / tf * ti / L_PM / mus pQz_pLMS /= 1. / AA # print pQz_pLMS pQz_pz = -m / hbar / tf / mus pQz_pz /= 1. / AA # print pQz_pz pQz_pphii = m / hbar * L_PM / ti * cos(phii) / mus pQz_pphii /= 1. / AA # print pQz_pphii pQz_p_vec = [ pQz_pt, pQz_ptMD, pQz_pLPM, pQz_pLMS, 0, pQz_pz, 0, 0, pQz_pphii ] pQz_p_vec = np.array(pQz_p_vec) J_Qz = pQz_p_vec / Q_len # ** Here we need to extend the J vector for E to include the additional variables eeta, thetai, and phii ** pE_p_vec = [pE_pt, pE_ptMD, pE_pLPM, pE_pLMS, pE_pR, pE_pz, 0, 0, 0] pE_p_vec = np.array(pE_p_vec) J_E = pE_p_vec / E J = np.array((J_Qx, J_Qy, J_Qz, J_E)) # ## ** Parameters sigma_eeta = mcvine.units.parse(pixel.radius) / mcvine.units.parse( instrument.detsys_radius) # sigma_thetai = 0.01 sigma_thetai = beamdivs.theta # sigma_phii = 0.01 sigma_phii = beamdivs.phi sigma = np.array([ sigma_t, sigma_tMD, sigma_LPM, sigma_LMS, sigma_R, sigma_z, sigma_eeta, sigma_thetai, sigma_phii ]) sigma2 = sigma**2 sigma2 = np.diag(sigma2) # print J.shape, sigma2.shape cov = np.dot(J, np.dot(sigma2, J.T)) # print cov M = np.linalg.inv(cov) # print M # ## Ellipsoid # hkl = hkl0+hkl_dir*x # dh,dk,dl = dx2dhkl*dx dx2dhkl = np.array(hkl_dir) # dQ = dx * dx2dhkl dot hkl2Q # so dx2dQ = dx2dhkl * hkl2Q # dQ = dx * dx2dQ dx2dQ = np.dot(dx2dhkl, hkl2Q_mat) # print dx2dQ # [dQx,dQy,dQz,dE] = [dx dE] dot dxdE2dQdE L = dxdE2dQdE = np.array([list(dx2dQ) + [0], [0., 0., 0., 1]]) # np.dot([1,1], dxdE2dQdE) # $ [dX1,\; dX2,\; dX3,\; dX4]\; M\; [dX1,\; dX2,\; dX3,\; dX4 ]^T = 2ln(2)$ # # $ dX_i = \frac{dQ_i}{|Q|}$ for i = 1,2,3 # # $ dX_4 = \frac{dE}{E}$ # # Let # $ U = diag\big( \frac{1}{|Q|},\; \frac{1}{|Q|},\; \frac{1}{|Q|},\; 1/E \big) $ # # $ [dx,\; dE]\; L U MU^TL^T [dx,\; dE ]^T = 2ln(2)$ # # Let $N=L U MU^TL^T $ # print Q_len, E U = np.diag([1. / Q_len, 1. / Q_len, 1. / Q_len, 1. / E]) N = LUMUTLT = np.dot(L, np.dot(U, np.dot(M, np.dot(U.T, L.T)))) # print N # print 2*np.log(2) r = np.linalg.eig(N) mR = r[1] lambdas = r[0] # print np.dot(mR, mR.T) # print np.dot(np.dot(mR.T, N), mR) # Make 4-D inverse covariance matrix: InvCov4D = UMUT = np.dot(U, np.dot(M, U.T)) hklE2QE = scipy.linalg.block_diag(hkl2Q_mat, 1.) InvCov4D = np.dot(np.dot(hklE2QE, InvCov4D), hklE2QE.T) # print np.dot(cov, M) # should be Eye # $ u = [dx,\;dE]$ # # $ u N u^T = 2ln(2)$ .... (1) # # Find eigen values ($\lambda_1$, $\lambda_2$) and eigne vectors ($e_1$, $e_2$, column vectors) of N, # and let # # $ R = [e_1,\;e_2] $ # # Then # # $ N' = R^T N R = diag([\lambda_1, \lambda_2]) $ # # or # # $ N = R N' R^T $ # # With $N'$ we can rewrite (1) as # # $ u'N'{u'}^T = 2ln2 = \lambda_1 {u'}_1^2 + \lambda_2 {u'}_2^2 $ # # where # # $ u' = u . R $ # ${u'}_1 = \sqrt{2ln2/\lambda_1}*cos(\theta)$ # # ${u'}_2 = \sqrt{2ln2/\lambda_2}*sin(\theta)$ # In[ ]: RR = 2 * np.log(2) theta = np.arange(0, 360, 1.) * np.pi / 180 u1p = np.sqrt(RR / lambdas[0]) * np.cos(theta) u2p = np.sqrt(RR / lambdas[1]) * np.sin(theta) up = np.array([u1p, u2p]).T # print up.shape u = np.dot(up, mR.T) if plot: from matplotlib import pyplot as plt plt.plot(u[:, 0], u[:, 1], '.') # plt.xlim(-.35, .1) # plt.ylim(-5., 5.) plt.show() # u: 2D ellipsoid coordinates # mR: 2D eigen vectors # lambdas: and 2D eigen values of the scaled inverse covariance # QxQyQzE_cov: 4D covariance matrix for Qx,Qy,Qz,E in instrument coordinate system # hklE_inv_cov: inverse 4D covariance matrix for hklE return dict(u=u, mR=mR, lambdas=lambdas, QxQyQzE_cov=cov, hklE_inv_cov=InvCov4D)
hist = get_histogram(component) if self.interactive: from histogram.plotter import defaultPlotter defaultPlotter.plot(hist) return pass # end of TestCase mass = 50 temperature = 300 Ei = 70 from mcni.utils import conversion as C vi = C.e2v(Ei) dispersion_dir = 'phonon-dispersion-fccNi-cubic-reciprocal-unitcell' def makeKernel(): max_omega = 50 max_Q = 13 nMCsteps_to_calc_RARV = 1000 return b.phonon_coherentinelastic_polyxtal_kernel( makeDispersion(), makeDW(), makeUnitcell(), temperature=temperature, Ei=Ei, max_omega=max_omega, max_Q=max_Q, nMCsteps_to_calc_RARV=nMCsteps_to_calc_RARV) def makeUnitcell():
def getNormalization(monitor, N=None, epsilon=1e-7): # randomly shoot neutrons to monitor in 4pi solid angle print "* start computing normalizer..." core = monitor.core() if N is None: N = core.nQ * core.nE * 10000 import mcni, random, mcni.utils.conversion as conversion, math, os import numpy as np # incident velocity vi = conversion.e2v(core.Ei) # 1. create neutrons def make_neutrons(N): neutrons = mcni.neutron_buffer(N) # # randomly select E, the energy transfer E = core.Emin + np.random.random(N) * (core.Emax-core.Emin) # the final energy Ef = core.Ei - E # the final velocity vf = conversion.e2v(Ef) # choose cos(theta) between -1 and 1 cos_t = np.random.random(N) * 2 - 1 # theta theta = np.arccos(cos_t) # sin(theta) sin_t = np.sin(theta) # phi: 0 - 2pi phi = np.random.random(N) * 2 * np.pi # compute final velocity vector vx,vy,vz = vf*sin_t*np.cos(phi), vf*sin_t*np.sin(phi), vf*cos_t # neutron position, spin, tof are set to zero x = y = z = sx = sy = t = np.zeros(N, dtype="float64") # probability prob = np.ones(N, dtype="float64") * (vf/vi) # XXX: this assumes a specific data layout of neutron struct n_arr = np.array([x,y,z,vx,vy,vz, sx,sy, t, prob]).T.copy() neutrons.from_npyarr(n_arr) return neutrons # 2. create a copy of the original monitor from mcstas2 import componentfactory cf = componentfactory(type='IQE_monitor', category='monitors') props = [ 'Ei', 'Emin', 'Emax', 'nE', 'Qmin', 'Qmax', 'nQ', 'max_angle_out_of_plane', 'min_angle_out_of_plane', 'max_angle_in_plane', 'min_angle_in_plane', ] kwds = {} for p in props: kwds[p] = getattr(core, p) import tempfile tmpdir = tempfile.mkdtemp() outfilename = os.path.join(tmpdir, 'mon.dat') kwds['filename'] = outfilename monitorcopy = cf('monitor', **kwds) # 3. send neutrons to monitor copy N1 = 0; dN = int(1e6) print " - total neutrons needed :", N while N1 < N: n = min(N-N1, dN) neutrons = make_neutrons(n) monitorcopy.process(neutrons) N1 += n print " - processed %s" % N1 continue h = get_histogram(monitorcopy) # for debug # import histogram.hdf as hh # hh.dump(h, 'tmp.h5', '/', 'c') h.I[h.I<epsilon] = 1 # print " - done computing normalizer" return h