Changeset baa79c2 in sasmodels for sasmodels/details.py


Ignore:
Timestamp:
Aug 5, 2016 6:42:44 PM (8 years ago)
Author:
Paul Kienzle <pkienzle@…>
Branches:
master, core_shell_microgels, costrafo411, magnetic_model, release_v0.94, release_v0.95, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
Children:
cbf4604
Parents:
99f446a
Message:

lint

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sasmodels/details.py

    r4f1f876 rbaa79c2  
     1""" 
     2Kernel Call Details 
     3=================== 
     4 
     5When calling sas computational kernels with polydispersity there are a 
     6number of details that need to be sent to the caller.  This includes the 
     7list of polydisperse parameters, the number of points in the polydispersity 
     8weight distribution, and which parameter is the "theta" parameter for 
     9polar coordinate integration.  The :class:`CallDetails` object maintains 
     10this data.  Use :func:`build_details` to build a *details* object which 
     11can be passed to one of the computational kernels. 
     12""" 
     13 
    114from __future__ import print_function 
    215 
     
    2437 
    2538class CallDetails(object): 
     39    """ 
     40    Manage the polydispersity information for the kernel call. 
     41 
     42    Conceptually, a polydispersity calculation is an integral over a mesh 
     43    in n-D space where n is the number of polydisperse parameters.  In order 
     44    to keep the program responsive, and not crash the GPU, only a portion 
     45    of the mesh is computed at a time.  Meshes with a large number of points 
     46    will therefore require many calls to the polydispersity loop.  Restarting 
     47    a nested loop in the middle requires that the indices of the individual 
     48    mesh dimensions can be computed for the current loop location.  This 
     49    is handled by the *pd_stride* vector, with n//stride giving the loop 
     50    index and n%stride giving the position in the sub loops. 
     51 
     52    One of the parameters may be the latitude.  When integrating in polar 
     53    coordinates, the total circumference decreases as latitude varies from 
     54    pi r^2 at the equator to 0 at the pole, and the weight associated 
     55    with a range of phi values needs to be scaled by this circumference. 
     56    This scale factor needs to be updated each time the theta value 
     57    changes.  *theta_par* indicates which of the values in the parameter 
     58    vector is the latitude parameter, or -1 if there is no latitude 
     59    parameter in the model.  In practice, the normalization term cancels 
     60    if the latitude is not a polydisperse parameter. 
     61    """ 
    2662    parts = None  # type: List["CallDetails"] 
    2763    def __init__(self, model_info): 
     
    4278 
    4379        # generate views on different parts of the array 
    44         self._pd_par     = self.buffer[0 * max_pd:1 * max_pd] 
    45         self._pd_length  = self.buffer[1 * max_pd:2 * max_pd] 
    46         self._pd_offset  = self.buffer[2 * max_pd:3 * max_pd] 
    47         self._pd_stride  = self.buffer[3 * max_pd:4 * max_pd] 
     80        self._pd_par = self.buffer[0 * max_pd:1 * max_pd] 
     81        self._pd_length = self.buffer[1 * max_pd:2 * max_pd] 
     82        self._pd_offset = self.buffer[2 * max_pd:3 * max_pd] 
     83        self._pd_stride = self.buffer[3 * max_pd:4 * max_pd] 
    4884 
    4985        # theta_par is fixed 
     
    5187 
    5288    @property 
    53     def pd_par(self): return self._pd_par 
    54  
    55     @property 
    56     def pd_length(self): return self._pd_length 
    57  
    58     @property 
    59     def pd_offset(self): return self._pd_offset 
    60  
    61     @property 
    62     def pd_stride(self): return self._pd_stride 
    63  
    64     @property 
    65     def pd_prod(self): return self.buffer[-4] 
     89    def pd_par(self): 
     90        """List of polydisperse parameters""" 
     91        return self._pd_par 
     92 
     93    @property 
     94    def pd_length(self): 
     95        """Number of weights for each polydisperse parameter""" 
     96        return self._pd_length 
     97 
     98    @property 
     99    def pd_offset(self): 
     100        """Offsets for the individual weight vectors in the set of weights""" 
     101        return self._pd_offset 
     102 
     103    @property 
     104    def pd_stride(self): 
     105        """Stride in the pd mesh for each pd dimension""" 
     106        return self._pd_stride 
     107 
     108    @property 
     109    def pd_prod(self): 
     110        """Total size of the pd mesh""" 
     111        return self.buffer[-4] 
     112 
    66113    @pd_prod.setter 
    67     def pd_prod(self, v): self.buffer[-4] = v 
    68  
    69     @property 
    70     def pd_sum(self): return self.buffer[-3] 
     114    def pd_prod(self, v): 
     115        self.buffer[-4] = v 
     116 
     117    @property 
     118    def pd_sum(self): 
     119        """Total length of all the weight vectors""" 
     120        return self.buffer[-3] 
     121 
    71122    @pd_sum.setter 
    72     def pd_sum(self, v): self.buffer[-3] = v 
    73  
    74     @property 
    75     def num_active(self): return self.buffer[-2] 
     123    def pd_sum(self, v): 
     124        self.buffer[-3] = v 
     125 
     126    @property 
     127    def num_active(self): 
     128        """Number of active polydispersity loops""" 
     129        return self.buffer[-2] 
     130 
    76131    @num_active.setter 
    77     def num_active(self, v): self.buffer[-2] = v 
    78  
    79     @property 
    80     def theta_par(self): return self.buffer[-1] 
     132    def num_active(self, v): 
     133        self.buffer[-2] = v 
     134 
     135    @property 
     136    def theta_par(self): 
     137        """Location of the theta parameter in the parameter vector""" 
     138        return self.buffer[-1] 
     139 
    81140    @theta_par.setter 
    82     def theta_par(self, v): self.buffer[-1] = v 
     141    def theta_par(self, v): 
     142        self.buffer[-1] = v 
    83143 
    84144    def show(self): 
     145        """Print the polydispersity call details to the console""" 
    85146        print("num_active", self.num_active) 
    86147        print("pd_prod", self.pd_prod) 
     
    94155 
    95156def mono_details(model_info): 
     157    # type: (ModelInfo) -> CallDetails 
     158    """ 
     159    Return a :class:`CallDetails` object for a monodisperse calculation 
     160    of the model defined by *model_info*. 
     161    """ 
    96162    call_details = CallDetails(model_info) 
    97163    call_details.pd_prod = 1 
     
    105171 
    106172def poly_details(model_info, weights): 
     173    """ 
     174    Return a :class:`CallDetails` object for a polydisperse calculation 
     175    of the model defined by *model_info* for the given set of *weights*. 
     176    *weights* is a list of vectors, one for each parameter.  Monodisperse 
     177    parameters should provide a weight vector containing [1.0]. 
     178    """ 
     179    # type: (ModelInfo) -> CallDetails 
    107180    #print("weights",weights) 
    108181    #weights = weights[2:] # Skip scale and background 
     
    110183    # Decreasing list of polydispersity lengths 
    111184    #print([p.id for p in model_info.parameters.call_parameters]) 
    112     pd_length = np.array([len(w) for w in weights[2:2+model_info.parameters.npars]]) 
     185    pd_length = np.array([len(w) 
     186                          for w in weights[2:2+model_info.parameters.npars]]) 
    113187    num_active = np.sum(pd_length>1) 
    114188    max_pd = model_info.parameters.max_pd 
     
    137211 
    138212def dispersion_mesh(model_info, pars): 
     213    # type: (ModelInfo) -> Tuple[List[np.ndarray], List[np.ndarray]] 
    139214    """ 
    140215    Create a mesh grid of dispersion parameters and weights. 
     
    155230        offset = 0 
    156231        for n in lengths: 
    157             pars.append(np.vstack(value[offset:offset+n]) if n > 1 else value[offset]) 
     232            pars.append(np.vstack(value[offset:offset+n]) 
     233                        if n > 1 else value[offset]) 
    158234            offset += n 
    159235        value = pars 
     
    179255        data_len = 3*len(scalars) 
    180256        extra = ((data_len+31)//32)*32 - data_len 
    181         data = np.array(scalars+scalars+[1.]*len(scalars)+[0.]*extra, dtype=kernel.dtype) 
     257        data = np.array(scalars+scalars+[1.]*len(scalars)+[0.]*extra, 
     258                        dtype=kernel.dtype) 
    182259    else: 
    183260        call_details = poly_details(kernel.info, weights) 
     
    185262        data_len = len(scalars) + 2*sum(len(v) for v in values) 
    186263        extra = ((data_len+31)//32)*32 - data_len 
    187         data = np.hstack(scalars+list(values)+list(weights)+[0.]*extra).astype(kernel.dtype) 
     264        data = np.hstack(scalars+list(values)+list(weights)+[0.]*extra) 
     265        data = data.astype(kernel.dtype) 
    188266    is_magnetic = convert_magnetism(kernel.info.parameters, data) 
    189267    #call_details.show() 
     
    192270def convert_magnetism(parameters, values): 
    193271    """ 
    194     Convert magnetism in value table from polar to rectangular coordinates. 
     272    Convert magnetism values from polar to rectangular coordinates. 
    195273 
    196274    Returns True if any magnetism is present. 
Note: See TracChangeset for help on using the changeset viewer.