source: sasmodels/Models/code_ellipse_f.py @ ae7d639

core_shell_microgelscostrafo411magnetic_modelrelease_v0.94release_v0.95ticket-1257-vesicle-productticket_1156ticket_1265_superballticket_822_more_unit_tests
Last change on this file since ae7d639 was ae7d639, checked in by HMP1 <helen.park@…>, 10 years ago

Ellipse now MUCH faster!

  • Property mode set to 100644
File size: 3.6 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4
5import ctypes
6from ctypes import c_int, c_double, c_void_p
7import numpy as np
8import pyopencl as cl
9from pyopencl import mem_flags as mf
10
11from weights import GaussianDispersion
12from sasmodel import card, set_precision, set_precision_1d, tic, toc
13
14class GpuEllipse(object):
15    PARS = {
16    'scale':1, 'radius_a':1, 'radius_b':1, 'sldEll':1e-6, 'sldSolv':0, 'background':0, 'axis_theta':0, 'axis_phi':0,
17    }
18    PD_PARS = ['radius_a', 'radius_b', 'axis_theta', 'axis_phi']
19
20    def __init__(self, qx, qy, dtype='float32', cutoff=1e-5):
21        ctx,_queue = card()
22        src, qx, qy = set_precision(open('Kernel/Kernel-Ellipse_f.cpp').read(), qx, qy, dtype=dtype)
23        self.prg = cl.Program(ctx, src).build()
24        self.qx, self.qy = qx, qy
25        self.cutoff = cutoff
26
27        self.qx_b = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=self.qx)
28        self.qy_b = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=self.qy)
29        self.res_b = cl.Buffer(ctx, mf.READ_WRITE, self.qx.nbytes)
30        self.res = np.empty_like(self.qx)
31
32    def eval(self, pars):
33        tic()
34
35        ctx, queue = card()
36
37        real = np.float32 if self.qx.dtype == np.dtype('float32') else np.float64
38        loops, loop_lengths = make_loops(pars, dtype=self.qx.dtype)
39        loops_b = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=loops)
40        loops_l = cl.LocalMemory(len(loops.data))
41
42        self.prg.EllipsoidKernel(queue, self.qx.shape, None, self.qx_b, self.qy_b, self.res_b,
43                                loops_b, loops_l, real(self.cutoff),
44                                real(pars['scale']), real(pars['background']),
45                                real(pars['sldEll']-pars['sldSolv']),
46                                *[np.uint32(pn) for pn in loop_lengths])
47
48        cl.enqueue_copy(queue, self.res, self.res_b)
49        print toc()*1000, self.qx.shape[0]
50
51        return self.res
52
53class CpuCylinder(GpuEllipse):
54    def __init__(self, qx, qy, dtype='float32', cutoff=1e-5):
55        self.qx, self.qy = [np.ascontiguousarray(v,'d') for v in qx,qy]
56        self.cutoff = cutoff
57        self.res = np.empty_like(self.qx)
58        self.dll = ctypes.CDLL('Kernel/ellipsoid.so')
59        self.fn = self.dll['EllipsoidKernel']
60        self.fn.argtypes = [
61            c_void_p, c_void_p, c_void_p, c_int,
62            c_void_p, c_double, c_double, c_double,
63            c_int, c_int, c_int, c_int
64        ]
65    def eval(self, pars):
66        loops, loop_lengths = make_loops(pars, dtype=self.qx.dtype)
67        self.fn(self.qx.ctypes.data, self.qy.ctypes.data, self.res.ctypes.data, len(self.qx),
68            loops.ctypes.data, self.cutoff, pars['scale'],
69            pars['sldEll']-pars['sldSolv'], *loop_lengths)
70
71        return self.res
72
73def make_loops(pars, dtype='double'):
74    # 0.2 ms on sparkle to form the final loops
75    radius_a, radius_b, theta, phi = \
76       [GaussianDispersion(int(pars[base+'_pd_n']), pars[base+'_pd'], pars[base+'_pd_nsigma'])
77         for base in GpuEllipse.PD_PARS]
78    parts = [
79        radius_a.get_weights(pars['radius_a'], 0, 10000, True),
80        radius_b.get_weights(pars['radius_b'], 0, 10000, True),
81        theta.get_weights(pars['axis_theta'], -np.inf, np.inf, False),
82        phi.get_weights(pars['axis_phi'], -np.inf, np.inf, False),
83        ]
84    # Make sure that weights are normalized to peaks at 1 so that
85    # the tolerance term can be used properly on truncated distributions
86    loops = np.hstack((v,w/w.max()) for v,w in parts)
87    #loops = np.hstack(parts)
88    loops = np.ascontiguousarray(loops.T, dtype).flatten()
89    return loops, [len(p[0]) for p in parts]
Note: See TracBrowser for help on using the repository browser.