source: sasmodels/code_triaxialellipse.py @ 2de9a5e

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

Update for Aaron

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