Beispiel #1
0
def help_test_slit_beamstop(component, passes):
    # Where the neutron is when it reaches the component.
    xs_arrived = np.arange(-9, 10)  # 19
    ys_arrived = np.arange(-9, 10)  # 19
    # How the neutron position is different before it reaches the component.
    dxs = np.arange(-3, 4)  # 7
    dys = np.arange(-3, 4)  # 7
    # Try various neutron weights.
    ws = deque(np.arange(0.2, 1.1, 0.2))
    # Pattern of weights should be irregular against geometry of test data.
    assert gcd(len(ws), prod(map(len, [xs_arrived, ys_arrived, dxs, dys]))) == 1
    # Fill a neutron buffer with a range of neutrons that approach the plane of
    # the component.
    neutrons_start = []
    neutrons_end_expected = []
    (any_pass, any_fail) = (False, False)
    for x_arrived in xs_arrived:
        for y_arrived in ys_arrived:
            for dx in dxs:
                for dy in dys:
                    # Construct an incoming neutron 2m before.
                    distance = sqrt(sum([2, pow(dx, 2), pow(dy, 2)]))
                    position_start = [x_arrived + dx, y_arrived + dy, -2]
                    velocity = [n / distance for n in [-dx, -dy, 2]]  # 1 m/s
                    w = ws[0]
                    ws.rotate()  # A different weight for the next neutron.
                    neutrons_start.append(neutron(
                        r=position_start, v=velocity, prob=w))
                    if passes(x_arrived, y_arrived, w):
                        # Construct a neutron expected from the component.
                        position_arrived = [x_arrived, y_arrived, 0]
                        neutrons_end_expected.append(neutron(
                            r=position_arrived, v=velocity, prob=w,
                            time=distance))
                        any_pass = True
                    else:
                        any_fail = True
    assert any_pass and any_fail
    neutrons_end_expected = neutron_buffer_from_array(neutrons_end_expected)

    # Propagate the neutrons.
    neutrons_buffer = neutron_buffer_from_array(neutrons_start)
    component.process(neutrons_buffer)

    # Compare the actual neutrons with the expectation.
    tolerance = 1e-6 if get_numpy_floattype() == np.float32 else 1e-15
    assert np.allclose(neutrons_as_npyarr(neutrons_buffer),
                       neutrons_as_npyarr(neutrons_end_expected),
                       atol=tolerance)
Beispiel #2
0
    def process(self, neutrons):
        if not len(neutrons):
            return
        from mcni.neutron_storage import neutrons_as_npyarr, ndblsperneutron # number of doubles per neutrons thats means each neutron is represented by x, y, z, vx, vy, vz, s1, s2, t, t0, p (10 double variables)

        arr = neutrons_as_npyarr(neutrons) #converting the input neutrons to array
        arr.shape = -1, ndblsperneutron
        x = arr[:, 0]; y = arr[:, 1]; z = arr[:, 2]
        vx = arr[:, 3]; vy = arr[:, 4]; vz = arr[:, 5]
        s1 = arr[:, 6]; s2 = arr[:, 7];
        t = arr[:, 8]; t0 = t.copy()
        p = arr[:, 9]

        # propagate to Z = 0
        self._propagateToZ0(x, y, z, vx, vy, vz, t)

        # Filter
        ftr = (x >= -self.xwidth / 2) * (x < self.xwidth / 2) \
              * (y >= -self.yheight / 2) * (y < self.yheight / 2) \
              * (t > t0)
        #
        xindex = (x+self.xwidth/2)//self.dx; xindex[xindex<0] = 0; xindex[xindex>=self.Nx]=self.Nx-1
        yindex = (y+self.yheight/2)//self.dy; yindex[yindex<0] = 0; yindex[yindex>=self.Ny]=self.Ny-1
        index = yindex + xindex * self.Ny
        N = ftr.sum()
        from mccomponents.detector.event_utils import datatype
        events = np.zeros(N, dtype=datatype)
        events['pixelID'] = index[ftr]
        events['tofChannelNo']=t[ftr]*1e6/self.tofbinsize
        events['p'] = p[ftr]
        self._save(events)
        return
Beispiel #3
0
    def process(self, neutrons):
        if not len(neutrons):
            return
        from mcni.neutron_storage import neutrons_as_npyarr, ndblsperneutron
        arr = neutrons_as_npyarr(neutrons)
        arr.shape = -1, ndblsperneutron
        x = arr[:,0]; y = arr[:,1]; z = arr[:,2]
        vx = arr[:,3]; vy = arr[:,4]; vz = arr[:,5]
        s1 = arr[:,6]; s2 = arr[:,7];
        t = arr[:,8];  t0 = t.copy()
        p = arr[:,9]

        # propagate to z = 0
        self._propagateToZ0(x,y,z,vx,vy,vz,t)

        # Apply filter if area is positive
        assert self.xwidth > 0 and self.yheight > 0

        # Filter
        ftr    = (x >= -self.xwidth/2)*(x <= self.xwidth/2)*(y >= -self.yheight/2)*(y <= self.yheight/2)*(t>t0)

        x = x[ftr]; y = y[ftr]; z = z[ftr];
        vx = vx[ftr]; vy = vy[ftr]; vz = vz[ftr];
        s1 = s1[ftr]; s2 = s2[ftr]; t = t[ftr]; p = p[ftr];
        events = x,y,z,t,p
        self.save(events)
        return
Beispiel #4
0
    def process(self, neutrons):
        """
        Propagate a buffer of particles through this guide.
        Adjusts the buffer to include only the particles that exit,
        at the moment of exit.

        Parameters:
        neutrons: a buffer containing the particles
        """
        (entrance_width, entrance_height, R0, Qc, alpha, m, W) = self.nature
        neutron_array = neutrons_as_npyarr(neutrons)
        neutron_array.shape = -1, ndblsperneutron

        threads_per_block = 256
        number_of_blocks = ceil(len(neutrons) / threads_per_block)
        guide_process[number_of_blocks,
                      threads_per_block](entrance_width, entrance_height, R0,
                                         Qc, alpha, m, W, self.sides,
                                         neutron_array)
        cuda.synchronize()

        mask = array(list(map(lambda weight: weight > 0, neutron_array.T[9])),
                     dtype=bool)
        neutrons.resize(count_nonzero(mask), neutrons[0])
        neutrons.from_npyarr(neutron_array[mask])
 def process(self, neutrons):
     if not len(neutrons):
         return
     from mcni.neutron_storage import neutrons_as_npyarr, ndblsperneutron
     arr = neutrons_as_npyarr(neutrons)
     arr.shape = -1, ndblsperneutron
     x = arr[:,0]; y = arr[:,1]; z = arr[:,2]
     vx = arr[:,3]; vy = arr[:,4]; vz = arr[:,5]
     s1 = arr[:,6]; s2 = arr[:,7];
     t = arr[:,8]; 
     p = arr[:,9]
     
     #
     theta_osc = self.oscillation * np.random.rand(len(neutrons))
     x1,y1,z1 = self.intersectCylinder(
         (z,x,y), (vz,vx,vy), (self.radius1, self.height1))
     theta1 = np.arctan2(y1,x1)  + theta_osc
     x2,y2,z2 = self.intersectCylinder(
         (z,x,y), (vz,vx,vy), (self.radius2, self.height2))
     theta2 = np.arctan2(y2,x2) + theta_osc
     good = (x1==x1) \
         * (z1<self.height1/2.) * (z1>-self.height1/2.) \
         * (z2<self.height2/2.) * (z2>-self.height2/2.) \
         * (theta1 > self.theta1) * (theta1 < self.theta2) \
         * (theta2 > self.theta1) * (theta2 < self.theta2) \
         * ((theta1-self.theta1)//self.dtheta == (theta2-self.theta1)//self.dtheta)
     good = arr[good, :]
     
     neutrons.resize(good.shape[0], neutrons[0])
     neutrons.from_npyarr(good)
     return
Beispiel #6
0
 def process(self, neutrons):
     from time import time
     from mcni.neutron_storage import neutrons_as_npyarr, ndblsperneutron
     t1 = time()
     neutron_array = neutrons_as_npyarr(neutrons)
     neutron_array.shape = -1, ndblsperneutron
     neutron_array_dtype_api = neutron_array.dtype
     neutron_array_dtype_int = self.get_numpy_floattype()
     needs_cast = neutron_array_dtype_api != neutron_array_dtype_int
     if needs_cast:
         neutron_array = neutron_array.astype(neutron_array_dtype_int)
     t2 = time()
     from ..config import ntotalthreads, threads_per_block
     self.call_process(
         self.__class__.process_kernel,
         neutron_array,
         ntotthreads=ntotalthreads, threads_per_block = threads_per_block,
     )
     t3 = time()
     if needs_cast:
         neutron_array = neutron_array.astype(neutron_array_dtype_api)
     good = neutron_array[:, -1] > 0
     neutrons.resize(int(good.sum()), neutrons[0])
     neutrons.from_npyarr(neutron_array[good])
     t4 = time()
     print(self.name, ":prepare input array: ", t2-t1)
     print(self.name, ":call_process: ", t3-t2)
     print(self.name, ":prepare output neutrons: ", t4-t3)
     return neutrons
Beispiel #7
0
    def _write_neutrons(self, neutrons):
        # from mcni.neutron_storage import dump
        # dump( packet, os.path.join( self.path, filename ) )

        stream = self.stream
        arr = neutrons_as_npyarr(neutrons)
        idfio.append(arr, stream=stream)
        return
Beispiel #8
0
    def _write_neutrons(self, neutrons):
        # from mcni.neutron_storage import dump
        # dump( packet, os.path.join( self.path, filename ) )

        stream = self.stream
        arr = neutrons_as_npyarr(neutrons)
        idfio.append(arr, stream=stream)
        return
    def process(self, neutrons):
        if not len(neutrons):
            return
        from mcni.neutron_storage import neutrons_as_npyarr, ndblsperneutron
        arr = neutrons_as_npyarr(neutrons)
        arr.shape = -1, ndblsperneutron
        x = arr[:, 0]
        y = arr[:, 1]
        z = arr[:, 2]
        vx = arr[:, 3]
        vy = arr[:, 4]
        vz = arr[:, 5]
        s1 = arr[:, 6]
        s2 = arr[:, 7]
        t = arr[:, 8]
        p = arr[:, 9]

        # propagate to z = 0
        self._propagateToZ0(x, y, z, vx, vy, vz, t)

        # Apply filter if area is positive
        assert self.xmax > self.xmin and self.ymax > self.ymin and self.tofmax > self.tofmin

        # Filter
        ftr = (x >= self.xmin) * (x < self.xmax) * (y >= self.ymin) * (
            y < self.ymax) * (t >= self.tofmin) * (t < self.tofmax)

        x = x[ftr]
        # after filtering, there might be no neutrons left
        if len(x) == 0:
            return

        y = y[ftr]
        z = z[ftr]
        # vx = vx[ftr]; vy = vy[ftr]; vz = vz[ftr];
        # s1 = s1[ftr]; s2 = s2[ftr];
        t = t[ftr]
        p = p[ftr]

        # create empty events
        from mccomponents.detector import event_utils
        import numpy
        events = numpy.zeros(x.size, dtype=event_utils.datatype)

        # x,y
        dx = (self.xmax - self.xmin) / self.nx
        x_index = (x - self.xmin) / dx
        dy = (self.ymax - self.ymin) / self.ny
        y_index = (y - self.ymin) / dy
        events['pixelID'] = x_index * self.ny + y_index
        # t
        dt = (self.tofmax - self.tofmin) / self.ntof
        events['tofChannelNo'] = (t - self.tofmin) / dt
        # p
        events['p'] = p

        self.events = events
        return
Beispiel #10
0
    def process(self, neutrons):
        if not len(neutrons):
            return
        from mcni.neutron_storage import neutrons_as_npyarr, ndblsperneutron
        arr = neutrons_as_npyarr(neutrons)
        arr.shape = -1, ndblsperneutron
        x = arr[:, 0]
        y = arr[:, 1]
        z = arr[:, 2]
        vx = arr[:, 3]
        vy = arr[:, 4]
        vz = arr[:, 5]
        s1 = arr[:, 6]
        s2 = arr[:, 7]
        t = arr[:, 8]
        p = arr[:, 9]

        # propagate to z = 0
        self._propagateToZ0(x, y, z, vx, vy, vz, t)

        # Apply filter if area is positive
        assert self.xwidth > 0 and self.yheight > 0

        # Filter
        ftr = (x >= -self.xwidth / 2) * (x <= self.xwidth / 2) * (
            y >= -self.yheight / 2) * (y <= self.yheight / 2)

        x = x[ftr]
        y = y[ftr]
        z = z[ftr]
        vx = vx[ftr]
        vy = vy[ftr]
        vz = vz[ftr]
        s1 = s1[ftr]
        s2 = s2[ftr]
        t = t[ftr]
        p = p[ftr]

        # after filtering, there might be no neutrons left
        if len(x) == 0:
            return

        from numpy import sqrt  # some expressions use 'sqrt()' function
        from numpy import histogramdd as hdd
        from mcni.utils import conversion
        sample = [eval(e) for e in self.expressions]

        bins = self.bins
        ranges = self.ranges
        self.histogram.I += hdd(sample, bins, ranges, weights=p)[0]
        self.histogram.E2 += hdd(sample, bins, ranges, weights=p * p)[0]
        return
Beispiel #11
0
    def __call__(self, neutrons, context=None):
        if context:
            context.identify(self)

        from mcni.neutron_storage import neutrons_as_npyarr
        a = neutrons_as_npyarr(neutrons)
        a.shape = -1, 10
        r = a[:, :3]
        v = a[:, 3:6]
        p = a[:, -1]
        self._store.append(_N(r, v, p))
        sys.stdout.write(".")
        sys.stdout.flush()
        return
    def process(self, neutrons):
        if not len(neutrons):
            return
        from mcni.neutron_storage import neutrons_as_npyarr, ndblsperneutron
        arr = neutrons_as_npyarr(neutrons)
        arr.shape = -1, ndblsperneutron
        x = arr[:,0]; y = arr[:,1]; z = arr[:,2]
        vx = arr[:,3]; vy = arr[:,4]; vz = arr[:,5]
        s1 = arr[:,6]; s2 = arr[:,7];
        t = arr[:,8]; 
        p = arr[:,9]
        
        # propagate to z = 0
        self._propagateToZ0(x,y,z,vx,vy,vz,t)

        # Apply filter if area is positive
        assert self.xmax > self.xmin and self.ymax > self.ymin and self.tofmax > self.tofmin
        
        # Filter
        ftr    = (x >= self.xmin)*(x < self.xmax)*(y >= self.ymin)*(y < self.ymax)*(t >= self.tofmin)*(t<self.tofmax)
        
        x = x[ftr]
        # after filtering, there might be no neutrons left
        if len(x) == 0:
            return
        
        y = y[ftr]; z = z[ftr];
        # vx = vx[ftr]; vy = vy[ftr]; vz = vz[ftr];
        # s1 = s1[ftr]; s2 = s2[ftr]; 
        t = t[ftr]; p = p[ftr];
        
        # create empty events
        from mccomponents.detector import event_utils
        import numpy
        events = numpy.zeros(x.size, dtype=event_utils.datatype)
        
        # x,y
        dx = (self.xmax-self.xmin)/self.nx
        x_index = (x-self.xmin)/dx
        dy = (self.ymax-self.ymin)/self.ny
        y_index = (y-self.ymin)/dy
        events['pixelID'] = x_index * self.ny + y_index
        # t
        dt = (self.tofmax-self.tofmin)/self.ntof
        events['tofChannelNo'] = (t-self.tofmin)/dt
        # p
        events['p'] = p
        
        self.events = events
        return
Beispiel #13
0
def test(neutron_fn=DEFAULT_NEUTRON_FILE, niter=1):
    # load file and store copy to avoid reloading for multiple iterations
    from mcni.neutron_storage import load, neutrons_from_npyarr, \
        neutrons_as_npyarr, ndblsperneutron
    neutrons_orig = load(neutron_fn)
    neutrons_orig = neutrons_as_npyarr(neutrons_orig)
    neutrons_orig.shape = -1, ndblsperneutron

    from mcvine.acc.components.optics import guide_tapering
    g = guide_tapering.Guide(
        name='guide',
        option="file={}".format(guide11_dat),
        l=guide11_len,
        mx=guide11_mx,
        my=guide11_my,
    )
    times = []
    for i in range(niter):
        neutrons = neutrons_from_npyarr(neutrons_orig)
        t1 = time.time_ns()
        g.process(neutrons)
        delta = time.time_ns() - t1
        times.append(delta)
        print("GPU processing time: {} ms ({} s)".format(
            1e-6 * delta, 1e-9 * delta))

    if niter > 1:
        # report average time over niter
        times = np.asarray(times)
        avg = times.sum() / len(times)
        print("--------")
        print("Average GPU time ({} iters): {} ms ({} s)".format(
            niter, 1e-6 * avg, 1e-9 * avg))
        print("--------")

    neutrons = neutrons_from_npyarr(neutrons_orig)
    import mcvine.components as mc
    g = mc.optics.Guide_tapering(
        name='guide',
        option="file={}".format(guide11_dat),
        l=guide11_len,
        mx=guide11_mx,
        my=guide11_my,
    )
    t1 = time.time()
    g.process(neutrons)
    print("CPU processing time:", time.time() - t1)
    return
Beispiel #14
0
    def process(self, neutrons): # input neutron is buffer
        if not len(neutrons):
            return

        # Number of doubles per neutrons thats means each neutron is represented
        # by x, y, z, vx, vy, vz, s1, s2, t, t0, p (10 double variables)
        arr = neutrons_as_npyarr(neutrons)
        arr.shape = -1, ndblsperneutron
        x = arr[:, 0];
        y = arr[:, 1];
        z = arr[:, 2]
        vx = arr[:, 3];
        vy = arr[:, 4];
        vz = arr[:, 5]
        t = arr[:, 8];
        t0 = t.copy()
        p = arr[:, 9]

        # Propagate to y = 0
        self._propagateToY0(x, y, z, vx, vy, vz, t)

        # Apply filter if area is positive
        assert self.xwidth > 0 and self.zheight > 0

        # Filter
        do_filter = True
        ftr = (x >= -self.xwidth / 2) * (x <= self.xwidth / 2) * (y >= -self.zheight / 2) * (y <= self.zheight / 2) * (t > t0)

        # Reflection
        speed = np.sqrt(vx**2+vy**2+vz**2)
        if do_filter:
            vy[ftr] *= -1
            #q = 2.0*conversion.V2K*speed[ftr] * vy[ftr]/vz[ftr]
            q = 2.0*conversion.V2K*vy[ftr]
            p[ftr] *= self.reflectivity(self.rq, q)
        else:
            vy *= -1
            #q = 2.0*conversion.V2K*speed * vy/vz
            q = 2.0*conversion.V2K*vy
            p *= self.reflectivity(self.rq, q)

        if DEBUG:
            for i in range(len(arr)):
                self.print_neutron(arr[i], q[i])

        neutrons.from_npyarr(arr)
        return  neutrons
Beispiel #15
0
    def process(self, neutrons):
        if not len(neutrons):
            return
        from mcni.neutron_storage import neutrons_as_npyarr, ndblsperneutron
        arr = neutrons_as_npyarr(neutrons)
        arr.shape = -1, ndblsperneutron
        x = arr[:,0]; y = arr[:,1]; z = arr[:,2]
        vx = arr[:,3]; vy = arr[:,4]; vz = arr[:,5]
        s1 = arr[:,6]; s2 = arr[:,7];
        t = arr[:,8]; 
        p = arr[:,9]

        # propagate to z = 0
        self._propagateToZ0(x,y,z,vx,vy,vz,t)

        # Apply filter if area is positive
        assert self.xwidth > 0 and self.yheight > 0

        # Filter
        ftr    = (x >= -self.xwidth/2)*(x <= self.xwidth/2)*(y >= -self.yheight/2)*(y <= self.yheight/2)

        x = x[ftr]; y = y[ftr]; z = z[ftr];
        vx = vx[ftr]; vy = vy[ftr]; vz = vz[ftr];
        s1 = s1[ftr]; s2 = s2[ftr]; t = t[ftr]; p = p[ftr];
        
        # after filtering, there might be no neutrons left
        if len(x) == 0:
            return
        
        from numpy import sqrt  # some expressions use 'sqrt()' function
        from numpy import histogramdd as hdd
        from mcni.utils import conversion
        sample = [eval(e) for e in self.expressions]
        
        bins = self.bins
        ranges = self.ranges
        self.histogram.I += hdd(sample, bins, ranges, weights=p)[0]
        self.histogram.E2 += hdd(sample, bins, ranges, weights=p*p)[0]
        return
Beispiel #16
0
    def process(self, neutrons):
        """
        Propagate a buffer of particles through this guide.
        Adjusts the buffer to include only the particles that exit,
        at the moment of exit.

        Parameters:
        neutrons: a buffer containing the particles
        """
        t1 = time.time()
        neutron_array = neutrons_as_npyarr(neutrons)
        neutron_array.shape = -1, ndblsperneutron
        t2 = time.time()
        call_process(*self._params, neutron_array)
        t3 = time.time()
        good = neutron_array[:, -1]>0
        neutrons.resize(int(good.sum()), neutrons[0])
        neutrons.from_npyarr(neutron_array[good])
        t4 = time.time()
        print("prepare input array: ", t2-t1)
        print("call_process: ", t3-t2)
        print("prepare output neutrons: ", t4-t3)
        return neutrons
Beispiel #17
0
def do_process(guide, neutrons):
    """
    Testing helper function to run a neutron through the guide and
    return the result as a numpy array

    Parameters
    ----------
    guide : instance of a Guide
    neutrons : a NeutronEvent or a list of NeutronEvents

    Returns
    -------
    Numpy array containing: [x, y, z, vx, vy, vz, s1, s2, t, p] for each
    input in neutrons
    """
    from mcni.mcnibp import NeutronEvent

    assert isinstance(guide, Guide)
    buffer = neutron_buffer(1)
    if isinstance(neutrons, list):
        buffer.resize(len(neutrons), neutron())
        for i in range(len(neutrons)):
            buffer[i] = neutrons[i]
    elif isinstance(neutrons, NeutronEvent):
        buffer[0] = neutrons
    else:
        raise RuntimeError(
            "Expected a NeutronEvent or a list of NeutronEvents")

    guide.process(buffer)
    result = neutrons_as_npyarr(buffer)
    result.shape = -1, ndblsperneutron
    if result.shape[0] == 1:
        # return only a single dim array to make test comparisons easier
        result = result[0]
    return result
Beispiel #18
0
    def process(self, neutrons):
        if not len(neutrons):
            return
        from mcni.neutron_storage import neutrons_as_npyarr, ndblsperneutron
        arr = neutrons_as_npyarr(neutrons)
        arr.shape = -1, ndblsperneutron
        x = arr[:, 0]
        y = arr[:, 1]
        z = arr[:, 2]
        vx = arr[:, 3]
        vy = arr[:, 4]
        vz = arr[:, 5]
        s1 = arr[:, 6]
        s2 = arr[:, 7]
        t = arr[:, 8]
        p = arr[:, 9]

        #
        theta_osc = self.oscillation * np.random.rand(len(neutrons))
        x1, y1, z1 = self.intersectCylinder((z, x, y), (vz, vx, vy),
                                            (self.radius1, self.height1))
        theta1 = np.arctan2(y1, x1) + theta_osc
        x2, y2, z2 = self.intersectCylinder((z, x, y), (vz, vx, vy),
                                            (self.radius2, self.height2))
        theta2 = np.arctan2(y2, x2) + theta_osc
        good = (x1==x1) \
            * (z1<self.height1/2.) * (z1>-self.height1/2.) \
            * (z2<self.height2/2.) * (z2>-self.height2/2.) \
            * (theta1 > self.theta1) * (theta1 < self.theta2) \
            * (theta2 > self.theta1) * (theta2 < self.theta2) \
            * ((theta1-self.theta1)//self.dtheta == (theta2-self.theta1)//self.dtheta)
        good = arr[good, :]

        neutrons.resize(good.shape[0], neutrons[0])
        neutrons.from_npyarr(good)
        return
Beispiel #19
0
    def process(self, neutrons):
        if not len(neutrons):
            return
        arr = neutrons_as_npyarr(neutrons)
        arr.shape = -1, ndblsperneutron

        # Filter out neutrons that do not hit guide entrance
        entrance_intersection, entrance_dur = \
            self.entrance.intersection_duration(arr[:, 0:3], arr[:, 3:6])
        mask = ((entrance_intersection[:, 0] < self.entrance_width / 2) &
                (entrance_intersection[:, 0] > -self.entrance_width / 2) &
                (entrance_intersection[:, 1] < self.entrance_height / 2) &
                (entrance_intersection[:, 1] > -self.entrance_height / 2) &
                ((entrance_dur.flatten() > 1e-10) |
                 numpy.isclose(arr[:, 2], 0.0))).flatten()
        arr = arr[mask]
        entrance_dur = entrance_dur[mask]
        neutrons.from_npyarr(arr)
        if not len(neutrons):
            return

        position = arr[:, 0:3]  # x, y, z
        velocity = arr[:, 3:6]  # vx, vy, vz
        time = arr[:, 8].reshape((arr.shape[0], 1))
        prob = arr[:, 9].reshape((arr.shape[0], 1))

        # initialize arrays containing neutron duration and side index
        side = numpy.full((arr.shape[0], 1), -2, dtype=int)
        old_side = side.copy()
        new_duration = numpy.full((arr.shape[0], 1), numpy.inf)

        # propagate to the guide entrance plane
        position += numpy.multiply(velocity, entrance_dur)
        time += entrance_dur

        # Iterate until all neutrons hit end of guide or are absorbed
        iter = 0
        while numpy.count_nonzero(side == 0) + numpy.count_nonzero(
                side == -1) != len(neutrons):
            duration = numpy.full((arr.shape[0], 1), numpy.inf)
            # Calculate minimum intersection time with all sides of the guide
            for s in range(0, len(self.sides)):
                intersection = self.sides[s].intersection_duration(position, velocity)
                new_duration = numpy.minimum(intersection[1], duration,
                                             where=((intersection[1] > 1e-10) &
                                                    (s != old_side) &
                                                    (old_side != 0) &
                                                    (old_side != -1)),
                                             out=new_duration)

                # Update the index of which side was hit based on new minimum
                side = numpy.where(new_duration != duration, s, side)
                duration = new_duration.copy()

                # If duration is inf, mark the side as invalid
                side = numpy.where(duration == numpy.inf, -1, side)

            # Propagate the neutrons based on the minimum times
            mask = (old_side != side).flatten()
            position[mask] += velocity[mask, :] * duration[mask]
            time[mask] += duration[mask]

            velocity_before = velocity.copy()

            # Update the velocity due to reflection
            mask = numpy.logical_and(old_side != side, side > 0)
            for s in range(1, len(self.sides)):
                # Only update the velocity if reflecting on one of the guide sides
                side_mask = numpy.logical_and(mask, side == s).flatten()
                velocity[side_mask] = self.sides[s].reflect(velocity[side_mask])

            # Calculate reflectivity
            mask = mask.flatten()
            reflectivity = self.calc_reflectivity(velocity_before[mask, :],
                                                  velocity[mask, :])
            prob[mask] = prob[mask] * reflectivity.reshape(
                reflectivity.shape[0], 1)
            side[prob <= 0] = -1

            old_side = side.copy()
            iter += 1

        print("process took {} iterations".format(iter))
        # Update neutron positions, velocities and times and select those that hit the guide exit
        arr[:, 0:3] = position
        arr[:, 3:6] = velocity
        arr[:, 8] = time.reshape((arr.shape[0],))
        arr[:, 9] = prob.reshape((arr.shape[0],))
        good = arr[(side == 0).flatten(), :]

        neutrons.resize(good.shape[0], neutrons[0])
        neutrons.from_npyarr(good)
Beispiel #20
0
def NEB_tonpyarr(self):
    from mcni.neutron_storage import neutrons_as_npyarr, ndblsperneutron
    arr = neutrons_as_npyarr(self)
    arr.shape = -1, ndblsperneutron
    return arr
Beispiel #21
0
 def _write_header(self, stream):
     # create header by writing empty neutron buffer
     buffer = mcni.neutron_buffer(0)
     arr = neutrons_as_npyarr(buffer)
     idfio.write(arr, stream=stream)
     return
def NEB_tonpyarr(self):
    from mcni.neutron_storage import neutrons_as_npyarr, ndblsperneutron
    arr = neutrons_as_npyarr(self)
    arr.shape = -1, ndblsperneutron
    return arr
Beispiel #23
0
 def _write_header(self, stream):
     # create header by writing empty neutron buffer
     buffer = mcni.neutron_buffer(0)
     arr = neutrons_as_npyarr(buffer)
     idfio.write(arr, stream=stream)
     return