source: sasmodels/Models/code_triaxialellipse.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.9 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 GpuTriEllipse:
11    PARS = {'scale':1, 'semi_axisA':35, 'semi_axisB':100, 'semi_axisC':400, 'sldEll':1e-6, 'sldSolv':6.3e-6, 'background':0,
12            'axis_theta':0, 'axis_phi':0, 'axis_psi':0}
13
14    PD_PARS = ['semi_axisA', 'semi_axisB', 'semi_axisC', 'axis_theta', 'axis_phi', 'axis_psi']
15
16    def __init__(self, qx, qy, dtype='float32'):
17        ctx,_queue = card()
18        src, qx, qy = set_precision(open('Kernel/Kernel-TriaxialEllipse.cpp').read(), qx, qy, dtype=dtype)
19        self.prg = cl.Program(ctx, src).build()
20        self.qx, self.qy = qx, qy
21
22        #buffers
23        mf = cl.mem_flags
24        self.qx_b = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=self.qx)
25        self.qy_b = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=self.qy)
26        self.res_b = cl.Buffer(ctx, mf.WRITE_ONLY, qx.nbytes)
27        self.res = np.empty_like(self.qx)
28
29    def eval(self, pars):
30
31        _ctx,queue = card()
32        self.res[:] = 0
33        cl.enqueue_copy(queue, self.res_b, self.res)
34        semi_axisA, semi_axisB, semi_axisC, axis_theta, axis_phi, axis_psi = \
35            [GaussianDispersion(int(pars[base+'_pd_n']), pars[base+'_pd'], pars[base+'_pd_nsigma'])
36             for base in GpuTriEllipse.PD_PARS]
37
38        semi_axisA.value, semi_axisA.weight = semi_axisA.get_weights(pars['semi_axisA'], 0, 10000, True)
39        semi_axisB.value, semi_axisB.weight = semi_axisB.get_weights(pars['semi_axisB'], 0, 10000, True)
40        semi_axisC.value, semi_axisC.weight = semi_axisC.get_weights(pars['semi_axisC'], 0, 10000, True)
41        axis_theta.value, axis_theta.weight = axis_theta.get_weights(pars['axis_theta'], -90, 180, False)
42        axis_phi.value, axis_phi.weight = axis_phi.get_weights(pars['axis_phi'], -90, 180, False)
43        axis_psi.value, axis_psi.weight = axis_psi.get_weights(pars['axis_psi'], -90, 180, False)
44
45        sum, norm, norm_vol, vol = 0.0, 0.0, 0.0, 0.0
46        size = len(axis_theta.weight)
47        sub = pars['sldEll'] - pars['sldSolv']
48
49        real = np.float32 if self.qx.dtype == np.dtype('float32') else np.float64
50        for a in xrange(len(semi_axisA.weight)):
51            for b in xrange(len(semi_axisB.weight)):
52                for c in xrange(len(semi_axisC.weight)):
53
54                    vol += semi_axisA.weight[a]*semi_axisB.weight[b]*semi_axisC.weight[c]*semi_axisA.value[a]*semi_axisB.value[b]*semi_axisC.value[c]
55                    norm_vol += semi_axisA.weight[a]*semi_axisB.weight[b]*semi_axisC.weight[c]
56
57                    for t in xrange(len(axis_theta.weight)):
58                        for i in xrange(len(axis_phi.weight)):
59                            for s in xrange(len(axis_psi.weight)):
60                                self.prg.TriaxialEllipseKernel(queue, self.qx.shape, None, self.qx_b, self.qy_b, self.res_b,
61                                            real(sub), real(pars['scale']), real(semi_axisA.value[a]), real(semi_axisB.value[b]),
62                                            real(semi_axisC.value[c]), real(axis_phi.value[i]), real(axis_theta.value[t]), real(axis_psi.value[s]),
63                                            real(semi_axisA.weight[a]), real(semi_axisB.weight[b]), real(semi_axisC.weight[c]), real(axis_psi.weight[s]),
64                                            real(axis_phi.weight[i]), real(axis_theta.weight[t]), np.uint32(self.qx.size), np.uint32(size))
65
66                                norm += semi_axisA.weight[a]*semi_axisB.weight[b]*semi_axisC.weight[c]*axis_theta.weight[t]*axis_phi.weight[i]*axis_psi.weight[s]
67
68
69      #  if size > 1:
70       #     norm /= asin(1.0)
71        cl.enqueue_copy(queue, self.res, self.res_b)
72        sum = self.res
73        if vol != 0.0 and norm_vol != 0.0:
74            sum *= norm_vol/vol
75
76        return sum/norm + pars['background']
77
78
79
80
81
82
83
84
85
86
87
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
Note: See TracBrowser for help on using the repository browser.