source: sasmodels/Models/code_capcyl.py @ 1f21edf

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

cylinder now MUCH faster!

  • Property mode set to 100644
File size: 3.9 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4import numpy as np
5from math import sqrt, fabs, atan
6import pyopencl as cl
7
8from weights import GaussianDispersion
9from sasmodel import card, set_precision
10
11
12
13class GpuCapCylinder(object):
14    PARS = {'scale':1, 'rad_cyl':1, 'rad_cap':1, 'len_cyl':1, 'sld_capcyl':1e-6, 'sld_solv':0, 'background':0,
15             'theta':0, 'phi':0}
16
17    PD_PARS = ['rad_cyl', 'len_cyl', 'rad_cap', 'theta', 'phi']
18
19    def __init__(self, qx, qy, dtype='float32'):
20
21        #create context, queue, and build program
22        ctx,_queue = card()
23        trala = open('Kernel/NR_BessJ1.cpp').read()+"\n"+open('Kernel/Capcyl_Kfun.cpp').read()+"\n"+open('Kernel/Kernel-CapCyl.cpp').read()
24        src, qx, qy = set_precision(trala, qx, qy, dtype=dtype)
25        self.prg = cl.Program(ctx, src).build()
26        self.qx, self.qy = qx, qy
27
28
29        #buffers
30        mf = cl.mem_flags
31        self.qx_b = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=self.qx)
32        self.qy_b = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=self.qy)
33        self.res_b = cl.Buffer(ctx, mf.WRITE_ONLY, qx.nbytes)
34        self.res = np.empty_like(self.qx)
35
36    def eval(self, pars):
37
38        _ctx,queue = card()
39        self.res[:] = 0
40        cl.enqueue_copy(queue, self.res_b, self.res)
41
42        rad_cyl,len_cyl,rad_cap,theta,phi = \
43            [GaussianDispersion(int(pars[base+'_pd_n']), pars[base+'_pd'], pars[base+'_pd_nsigma'])
44             for base in GpuCapCylinder.PD_PARS]
45
46        rad_cyl.value, rad_cyl.weight = rad_cyl.get_weights(pars['rad_cyl'], 0, 10000, True)
47        rad_cap.value, rad_cap.weight = rad_cap.get_weights(pars['rad_cap'], 0, 10000, True)
48        len_cyl.value, len_cyl.weight = len_cyl.get_weights(pars['len_cyl'], 0, 10000, True)
49        theta.value, theta.weight = theta.get_weights(pars['theta'], -90, 180, False)
50        phi.value, phi.weight = phi.get_weights(pars['phi'], -90, 180, False)
51
52        sum, norm, norm_vol, vol = 0.0, 0.0, 0.0, 0.0
53        size = len(theta.weight)
54        sub = pars['sld_capcyl']-pars['sld_solv']
55        real = np.float32 if self.qx.dtype == np.dtype('float32') else np.float64
56
57        for i in xrange(len(rad_cyl.weight)):
58            for m in xrange(len(rad_cap.weight)):
59                for j in xrange(len(len_cyl.weight)):
60
61                    hDist = -1.0*sqrt(fabs(rad_cap.value[m]*rad_cap.value[m]-rad_cyl.value[i]*rad_cyl.value[i]))
62                    vol_i = 4.0*atan(1.0)*rad_cyl.value[i]*rad_cyl.value[i]*len_cyl.value[j]+2.0*4.0*atan(1.0)/3.0\
63                                    *((rad_cap.value[m]-hDist)*(rad_cap.value[m]-hDist)*(2*rad_cap.value[m]+hDist))
64                    vol += rad_cyl.weight[i]*len_cyl.weight[j]*rad_cap.weight[m]*vol_i
65                    norm_vol += rad_cyl.weight[i]*len_cyl.weight[j]*rad_cap.weight[m]
66
67                    for k in xrange(len(theta.weight)):
68                        for l in xrange(len(phi.weight)):
69
70                            self.prg.CapCylinderKernel(queue, self.qx.shape, None, self.qx_b, self.qy_b, self.res_b,
71                                        real(vol_i), real(hDist), real(rad_cyl.value[i]), real(rad_cap.value[m]), real(len_cyl.value[j]),
72                                        real(theta.value[k]), real(phi.value[l]), real(sub), real(pars['scale']),
73                                        real(phi.weight[l]), real(theta.weight[k]), real(rad_cap.weight[m]),
74                                        real(rad_cyl.weight[i]), real(len_cyl.weight[j]), real(theta.weight[k]), np.uint32(self.qx.size), np.uint32(size))
75
76                            norm += rad_cyl.weight[i]*len_cyl.weight[j]*rad_cap.weight[m]*theta.weight[k]*phi.weight[l]
77
78
79
80        #if size > 1:
81         #   norm /= asin(1.0)
82        cl.enqueue_copy(queue, self.res, self.res_b)
83        sum += self.res
84        if vol != 0.0 and norm_vol != 0.0:
85            sum *= norm_vol/vol
86
87        return sum/norm + pars['background']
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
Note: See TracBrowser for help on using the repository browser.