source: sasmodels/sasmodels/details.py @ 0ff62d4

core_shell_microgelscostrafo411magnetic_modelrelease_v0.94release_v0.95ticket-1257-vesicle-productticket_1156ticket_1265_superballticket_822_more_unit_tests
Last change on this file since 0ff62d4 was 0ff62d4, checked in by Paul Kienzle <pkienzle@…>, 8 years ago

refactor: move dispersion_mesh alongside build_details in kernel.py

  • Property mode set to 100644
File size: 4.4 KB
Line 
1import numpy as np  # type: ignore
2
3try:
4    from typing import List
5except ImportError:
6    pass
7else:
8    from .modelinfo import ModelInfo
9
10
11class CallDetails(object):
12    parts = None  # type: List["CallDetails"]
13    def __init__(self, model_info):
14        # type: (ModelInfo) -> None
15        parameters = model_info.parameters
16        max_pd = parameters.max_pd
17        npars = parameters.npars
18        par_offset = 4*max_pd
19        self.buffer = np.zeros(par_offset + 3 * npars + 4, 'i4')
20
21        # generate views on different parts of the array
22        self._pd_par     = self.buffer[0 * max_pd:1 * max_pd]
23        self._pd_length  = self.buffer[1 * max_pd:2 * max_pd]
24        self._pd_offset  = self.buffer[2 * max_pd:3 * max_pd]
25        self._pd_stride  = self.buffer[3 * max_pd:4 * max_pd]
26        self._par_offset = self.buffer[par_offset + 0 * npars:par_offset + 1 * npars]
27        self._par_coord  = self.buffer[par_offset + 1 * npars:par_offset + 2 * npars]
28        self._pd_coord   = self.buffer[par_offset + 2 * npars:par_offset + 3 * npars]
29
30        # theta_par is fixed
31        self.buffer[-1] = parameters.theta_offset
32
33    @property
34    def pd_par(self): return self._pd_par
35
36    @property
37    def pd_length(self): return self._pd_length
38
39    @property
40    def pd_offset(self): return self._pd_offset
41
42    @property
43    def pd_stride(self): return self._pd_stride
44
45    @property
46    def pd_coord(self): return self._pd_coord
47
48    @property
49    def par_coord(self): return self._par_coord
50
51    @property
52    def par_offset(self): return self._par_offset
53
54    @property
55    def num_active(self): return self.buffer[-4]
56    @num_active.setter
57    def num_active(self, v): self.buffer[-4] = v
58
59    @property
60    def total_pd(self): return self.buffer[-3]
61    @total_pd.setter
62    def total_pd(self, v): self.buffer[-3] = v
63
64    @property
65    def num_coord(self): return self.buffer[-2]
66    @num_coord.setter
67    def num_coord(self, v): self.buffer[-2] = v
68
69    @property
70    def theta_par(self): return self.buffer[-1]
71
72    def show(self):
73        print("total_pd", self.total_pd)
74        print("num_active", self.num_active)
75        print("pd_par", self.pd_par)
76        print("pd_length", self.pd_length)
77        print("pd_offset", self.pd_offset)
78        print("pd_stride", self.pd_stride)
79        print("par_offsets", self.par_offset)
80        print("num_coord", self.num_coord)
81        print("par_coord", self.par_coord)
82        print("pd_coord", self.pd_coord)
83        print("theta par", self.buffer[-1])
84
85def mono_details(model_info):
86    call_details = CallDetails(model_info)
87    # The zero defaults for monodisperse systems are mostly fine
88    call_details.par_offset[:] = np.arange(2, len(call_details.par_offset)+2)
89    return call_details
90
91def poly_details(model_info, weights):
92    #print("weights",weights)
93    weights = weights[2:] # Skip scale and background
94
95    # Decreasing list of polydispersity lengths
96    # Note: the reversing view, x[::-1], does not require a copy
97    pd_length = np.array([len(w) for w in weights])
98    num_active = np.sum(pd_length>1)
99    if num_active > model_info.parameters.max_pd:
100        raise ValueError("Too many polydisperse parameters")
101
102    pd_offset = np.cumsum(np.hstack((0, pd_length)))
103    idx = np.argsort(pd_length)[::-1][:num_active]
104    par_length = np.array([max(len(w),1) for w in weights])
105    pd_stride = np.cumprod(np.hstack((1, par_length[idx])))
106    par_offsets = np.cumsum(np.hstack((2, par_length)))
107
108    call_details = CallDetails(model_info)
109    call_details.pd_par[:num_active] = idx
110    call_details.pd_length[:num_active] = pd_length[idx]
111    call_details.pd_offset[:num_active] = pd_offset[idx]
112    call_details.pd_stride[:num_active] = pd_stride[:-1]
113    call_details.par_offset[:] = par_offsets[:-1]
114    call_details.total_pd = pd_stride[-1]
115    call_details.num_active = num_active
116    # Without constraints coordinated parameters are just the pd parameters
117    call_details.par_coord[:num_active] = idx
118    call_details.pd_coord[:num_active] = 2**np.arange(num_active)
119    call_details.num_coord = num_active
120    #call_details.show()
121    return call_details
122
123def constrained_poly_details(model_info, weights, constraints):
124    # Need to find the independently varying pars and sort them
125    # Need to build a coordination list for the dependent variables
126    # Need to generate a constraints function which takes values
127    # and weights, returning par blocks
128    raise NotImplementedError("Can't handle constraints yet")
129
Note: See TracBrowser for help on using the repository browser.