source: sasmodels/Models/code_coreshellcyl.py @ 14de349

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

cylinder now MUCH faster!

  • Property mode set to 100644
File size: 3.8 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4import numpy as np
5import pyopencl as cl
6
7from weights import GaussianDispersion
8from sasmodel import card, set_precision
9
10class GpuCoreShellCylinder(object):
11    PARS = {'scale':1, 'radius':1, 'thickness':1, 'length':1, 'core_sld':1e-6, 'shell_sld':-1e-6, 'solvent_sld':0,
12            'background':0, 'axis_theta':0, 'axis_phi':0}
13    PD_PARS = ['radius', 'length', 'thickness', 'axis_phi', 'axis_theta']
14
15    def __init__(self, qx, qy, dtype='float32'):
16        #create context, queue, and build program
17        ctx,_queue = card()
18        src, qx, qy = set_precision(open('Kernel/NR_BessJ1.cpp').read()+"\n"+open('Kernel/Kernel-CoreShellCylinder.cpp').read(), qx, qy, dtype=dtype)
19        self.prg = cl.Program(ctx, src).build()
20        self.qx, self.qy = qx, qy
21
22
23        #buffers
24        mf = cl.mem_flags
25        self.qx_b = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=self.qx)
26        self.qy_b = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=self.qy)
27        self.res_b = cl.Buffer(ctx, mf.WRITE_ONLY, qx.nbytes)
28        self.res = np.empty_like(qx)
29
30    def eval(self, pars):
31
32        _ctx,queue = card()
33        self.res[:] = 0
34        cl.enqueue_copy(queue, self.res_b, self.res)
35        radius, length, thickness, axis_phi, axis_theta = [GaussianDispersion(int(pars[base+'_pd_n']), pars[base+'_pd'], pars[base+'_pd_nsigma'])
36                                     for base in GpuCoreShellCylinder.PD_PARS]
37
38        radius.value, radius.weight = radius.get_weights(pars['radius'], 0, 10000, True)
39        length.value, length.weight = length.get_weights(pars['length'], 0, 10000, True)
40        thickness.value, thickness.weight = thickness.get_weights(pars['thickness'], 0, 10000, True)
41        axis_phi.value, axis_phi.weight = axis_phi.get_weights(pars['axis_phi'], -90, 180, False)
42        axis_theta.value, axis_theta.weight = axis_theta.get_weights(pars['axis_theta'], -90, 180, False)
43
44        sum, norm, norm_vol, vol = 0.0, 0.0, 0.0, 0.0
45        size = len(axis_theta.weight)
46
47        real = np.float32 if self.qx.dtype == np.dtype('float32') else np.float64
48        for r in xrange(len(radius.weight)):
49            for l in xrange(len(length.weight)):
50                for th in xrange(len(thickness.weight)):
51
52                    vol += radius.weight[r]*length.weight[l]*thickness.weight[th]*pow(radius.value[r]+thickness.value[th],2)\
53                                   *(length.value[l]+2.0*thickness.value[th])
54                    norm_vol += radius.weight[r]*length.weight[l]*thickness.weight[th]
55
56                    for at in xrange(len(axis_theta.weight)):
57                        for p in xrange(len(axis_phi.weight)):
58
59                            self.prg.CoreShellCylinderKernel(queue, self.qx.shape, None, self.qx_b, self.qy_b, self.res_b,
60                                    real(axis_theta.value[at]), real(axis_phi.value[p]), real(thickness.value[th]),
61                                    real(length.value[l]), real(radius.value[r]), real(pars['scale']),
62                                    real(radius.weight[r]), real(length.weight[l]), real(thickness.weight[th]),
63                                    real(axis_theta.weight[at]), real(axis_phi.weight[p]), real(pars['core_sld']),
64                                    real(pars['shell_sld']), real(pars['solvent_sld']),np.uint32(size),
65                                    np.uint32(self.qx.size))
66
67                            norm += radius.weight[r]*length.weight[l]*thickness.weight[th]*axis_theta.weight[at]\
68                                    *axis_phi.weight[p]
69
70        #if size>1:
71         #   norm /= math.asin(1.0)
72        cl.enqueue_copy(queue, self.res, self.res_b)
73        sum = self.res
74        if vol != 0.0 and norm_vol != 0.0:
75            sum *= norm_vol/vol
76
77        return sum/norm + pars['background']
Note: See TracBrowser for help on using the repository browser.