Source code for mcramp.scat.powderN

from .sprim import SPrim

import numpy as np
import pyopencl as cl
import pyopencl.array as clarr

import os

[docs]class SPowderN(SPrim): """ Scattering kernel for Bragg scattering powder sample. Recreates the functionality of the PowderN component in McStas. If a neutron satisfies the Bragg condition, it is scattered at an angle twotheta into a random angle on the Debye-Scherrer cone. Phi focusing is implemented to improve simulation performance. WARNING: Neutron weights are NOT verified to be physically accurate for the scattering from this component, however the lineshape is correct. Parameters ---------- d_spacing : float array Lattice spacings corresponding to the Bragg powder lines in AA pack : float in range [0, 1] Packing fraction of the sample vc : float Volume of the sample unit cell in AA^3 sigma_abs : float Absorption cross section of the sample at 2200 m/s in barns multiplicity : int array Multiplicity of the powder lines DW : float in range [0, 1] Debye-Waller factor F2 : float array Structure factors of the powder lines d_phi : float in range [0.0, 180.0] Max angle around Debye-Scherrer cone into which neutrons are scattered Methods ------- Data None Plot None Save None """ def __init__(self, d_spacing=[0.0], pack=0.0, vc=0.0, sigma_abs=0.0, multiplicity=[0], DW=0.0, F2=[0.0], d_phi=180.0, transmit=1, idx=0, ctx=None, **kwargs): # F2 in barns mf = cl.mem_flags # Scattering cross section will be divided by v^2 in Kernel # Absorption cross section will be divided by v in Kernel q = np.array((2 * np.pi) / np.array(d_spacing), dtype=np.float32) sigma_scat_numer = np.array(4 * np.pi ** 3.0 * pack * np.array(multiplicity) * np.array(F2) * 100 * DW, dtype=np.float32) sigma_scat_denom = vc ** 2.0 * q sigma_scat_v2 = (sigma_scat_numer / sigma_scat_denom) self.sigma_abs_v = np.float32(pack * sigma_abs / vc * 100) self.idx = np.uint32(idx) self.d_phi = np.float32(d_phi) self.sigma_scat_v2_cl = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=sigma_scat_v2) self.q_cl = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=q) self.num_lines = np.uint32(len(d_spacing)) self.transmit = np.uint32(transmit) with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'powderN.cl'), mode='r') as f: self.prg = cl.Program(ctx, f.read()).build(options=r'-I "{}/include"'.format(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) def scatter_prg(self, queue, N, neutron_buf, intersection_buf, iidx_buf): self.prg.powderN(queue, (N, ), None, neutron_buf, intersection_buf, iidx_buf, self.idx, self.sigma_scat_v2_cl, self.sigma_abs_v, self.q_cl, self.d_phi, self.num_lines, self.transmit)