Changeset d4c33d6 in sasmodels


Ignore:
Timestamp:
Apr 12, 2017 10:50:29 AM (7 years ago)
Author:
Paul Kienzle <pkienzle@…>
Branches:
master, core_shell_microgels, magnetic_model, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
Children:
597878a
Parents:
535fee6
Message:

send cos-weighted theta values to kernel rather than computing them inside

Files:
6 edited

Legend:

Unmodified
Added
Removed
  • explore/jitter.py

    r8678a34 rd4c33d6  
    191191def apply_jitter(jitter, points): 
    192192    dtheta, dphi, dpsi = jitter 
    193     points = Rz(dpsi)*Ry(dtheta)*Rx(dphi)*points 
     193    points = Rx(dphi)*Ry(dtheta)*Rz(dpsi)*points 
    194194    return points 
    195195 
     
    257257        ax.cla() 
    258258        draw_beam(ax, (0, 0)) 
    259         if 0: 
    260             draw_jitter(ax, view, jitter) 
    261         else: 
    262             draw_jitter(ax, view, (0,0,0)) 
    263             draw_mesh(ax, view, jitter) 
     259        draw_jitter(ax, view, jitter) 
     260        #draw_jitter(ax, view, (0,0,0)) 
     261        draw_mesh(ax, view, jitter) 
    264262        plt.gcf().canvas.draw() 
    265263 
  • sasmodels/details.py

    rccd5f01 rd4c33d6  
    1515 
    1616import numpy as np  # type: ignore 
    17 from numpy import pi, cos, sin 
     17from numpy import pi, cos, sin, radians 
    1818 
    1919try: 
     
    2929 
    3030try: 
    31     from typing import List 
     31    from typing import List, Tuple, Sequence 
    3232except ImportError: 
    3333    pass 
    3434else: 
    3535    from .modelinfo import ModelInfo 
     36    from .modelinfo import ParameterTable 
    3637 
    3738 
     
    5354    coordinates, the total circumference decreases as latitude varies from 
    5455    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    with a range of latitude values needs to be scaled by this circumference. 
    5657    This scale factor needs to be updated each time the theta value 
    5758    changes.  *theta_par* indicates which of the values in the parameter 
     
    231232    nvalues = kernel.info.parameters.nvalues 
    232233    scalars = [(v[0] if len(v) else np.NaN) for v, w in pairs] 
    233     values, weights = zip(*pairs[2:npars+2]) if npars else ((),()) 
     234    values, weights = zip(*pairs[2:npars+2]) if npars else ((), ()) 
     235    weights = correct_theta_weights(kernel.info.parameters, values, weights) 
    234236    length = np.array([len(w) for w in weights]) 
    235237    offset = np.cumsum(np.hstack((0, length))) 
     
    244246    return call_details, data, is_magnetic 
    245247 
     248def correct_theta_weights(parameters, values, weights): 
     249    # type: (ParameterTable, Sequence[np.ndarray], Sequence[np.ndarray]) -> Sequence[np.ndarray] 
     250    """ 
     251    If there is a theta parameter, update the weights of that parameter so that 
     252    the cosine weighting required for polar integration is preserved.  Avoid 
     253    evaluation strictly at the pole, which would otherwise send the weight to 
     254    zero. 
     255    """ 
     256    if parameters.theta_offset >= 0: 
     257        index = parameters.theta_offset+len(parameters.COMMON) 
     258        theta = values[index] 
     259        theta_weight = np.minimum(cos(radians(theta)), 1e-6) 
     260        # copy the weights list so we can update it 
     261        weights = list(weights) 
     262        weights[index] = theta_weight*weights[index] 
     263        weights = tuple(weights) 
     264    return weights 
     265 
    246266 
    247267def convert_magnetism(parameters, values): 
     268    # type: (ParameterTable, Sequence[np.ndarray]) -> bool 
    248269    """ 
    249270    Convert magnetism values from polar to rectangular coordinates. 
     
    255276    scale = mag[:,0] 
    256277    if np.any(scale): 
    257         theta, phi = mag[:, 1]*pi/180., mag[:, 2]*pi/180. 
     278        theta, phi = radians(mag[:, 1]), radians(mag[:, 2]) 
    258279        cos_theta = cos(theta) 
    259280        mag[:, 0] = scale*cos_theta*cos(phi)  # mx 
     
    269290    """ 
    270291    Create a mesh grid of dispersion parameters and weights. 
     292 
     293    pars is a list of pairs (values, weights), where the values are the 
     294    individual parameter values at which to evaluate the polydispersity 
     295    distribution and weights are the weights associated with each value. 
     296 
     297    Only the volume parameters should be included in this list.  Orientation 
     298    parameters do not affect the calculation of effective radius or volume 
     299    ratio. 
    271300 
    272301    Returns [p1,p2,...],w where pj is a vector of values for parameter j 
  • sasmodels/kernel_iq.c

    rbde38b5 rd4c33d6  
    2525    int32_t num_weights;        // total length of the weights vector 
    2626    int32_t num_active;         // number of non-trivial pd loops 
    27     int32_t theta_par;          // id of spherical correction variable 
     27    int32_t theta_par;          // id of spherical correction variable (not used) 
    2828} ProblemDetails; 
    2929 
     
    173173 
    174174 
    175 #if MAX_PD>0 
    176   const int theta_par = details->theta_par; 
    177   const int fast_theta = (theta_par == p0); 
    178   const int slow_theta = (theta_par >= 0 && !fast_theta); 
    179   double spherical_correction = 1.0; 
    180 #else 
    181   // Note: if not polydisperse the weights cancel and we don't need the 
    182   // spherical correction. 
    183   const double spherical_correction = 1.0; 
    184 #endif 
    185  
    186175  int step = pd_start; 
    187176 
     
    220209#endif 
    221210#if MAX_PD>0 
    222   if (slow_theta) { // Theta is not in inner loop 
    223     spherical_correction = fmax(fabs(cos(M_PI_180*local_values.vector[theta_par])), 1.e-6); 
    224   } 
    225211  while(i0 < n0) { 
    226212    local_values.vector[p0] = v0[i0]; 
    227213    double weight0 = w0[i0] * weight1; 
    228214//printf("step:%d level %d: p:%d i:%d n:%d value:%g weight:%g\n", step, 0, p0, i0, n0, local_values.vector[p0], weight0); 
    229     if (fast_theta) { // Theta is in inner loop 
    230       spherical_correction = fmax(fabs(cos(M_PI_180*local_values.vector[p0])), 1.e-6); 
    231     } 
    232215#else 
    233216    const double weight0 = 1.0; 
     
    244227      // Note: weight==0 must always be excluded 
    245228      if (weight0 > cutoff) { 
    246         // spherical correction is set at a minimum of 1e-6, otherwise there 
    247         // would be problems looking at models with theta=90. 
    248         const double weight = weight0 * spherical_correction; 
    249         pd_norm += weight * CALL_VOLUME(local_values.table); 
     229        pd_norm += weight0 * CALL_VOLUME(local_values.table); 
    250230 
    251231        #ifdef USE_OPENMP 
     
    304284#endif // !MAGNETIC 
    305285//printf("q_index:%d %g %g %g %g\n",q_index, scattering, weight, spherical_correction, weight0); 
    306           result[q_index] += weight * scattering; 
     286          result[q_index] += weight0 * scattering; 
    307287        } 
    308288      } 
  • sasmodels/kernel_iq.cl

    rbde38b5 rd4c33d6  
    2525    int32_t num_weights;        // total length of the weights vector 
    2626    int32_t num_active;         // number of non-trivial pd loops 
    27     int32_t theta_par;          // id of spherical correction variable 
     27    int32_t theta_par;          // id of spherical correction variable (not used) 
    2828} ProblemDetails; 
    2929 
     
    169169 
    170170 
    171 #if MAX_PD>0 
    172   const int theta_par = details->theta_par; 
    173   const bool fast_theta = (theta_par == p0); 
    174   const bool slow_theta = (theta_par >= 0 && !fast_theta); 
    175   double spherical_correction = 1.0; 
    176 #else 
    177   // Note: if not polydisperse the weights cancel and we don't need the 
    178   // spherical correction. 
    179   const double spherical_correction = 1.0; 
    180 #endif 
    181  
    182171  int step = pd_start; 
    183172 
     
    217206#endif 
    218207#if MAX_PD>0 
    219   if (slow_theta) { // Theta is not in inner loop 
    220     spherical_correction = fmax(fabs(cos(M_PI_180*local_values.vector[theta_par])), 1.e-6); 
    221   } 
    222208  while(i0 < n0) { 
    223209    local_values.vector[p0] = v0[i0]; 
    224210    double weight0 = w0[i0] * weight1; 
    225211//if (q_index == 0) printf("step:%d level %d: p:%d i:%d n:%d value:%g weight:%g\n", step, 0, p0, i0, n0, local_values.vector[p0], weight0); 
    226     if (fast_theta) { // Theta is in inner loop 
    227       spherical_correction = fmax(fabs(cos(M_PI_180*local_values.vector[p0])), 1.e-6); 
    228     } 
    229212#else 
    230213    const double weight0 = 1.0; 
     
    232215 
    233216//if (q_index == 0) {printf("step:%d of %d, pars:",step,pd_stop); for (int i=0; i < NUM_PARS; i++) printf("p%d=%g ",i, local_values.vector[i]); printf("\n"); } 
    234 //if (q_index == 0) printf("sphcor: %g\n", spherical_correction); 
    235217 
    236218    #ifdef INVALID 
     
    241223      // Note: weight==0 must always be excluded 
    242224      if (weight0 > cutoff) { 
    243         // spherical correction is set at a minimum of 1e-6, otherwise there 
    244         // would be problems looking at models with theta=90. 
    245         const double weight = weight0 * spherical_correction; 
    246         pd_norm += weight * CALL_VOLUME(local_values.table); 
     225        pd_norm += weight0 * CALL_VOLUME(local_values.table); 
    247226 
    248227#if defined(MAGNETIC) && NUM_MAGNETIC > 0 
     
    296275        const double scattering = CALL_IQ(q, q_index, local_values.table); 
    297276#endif // !MAGNETIC 
    298         this_result += weight * scattering; 
     277        this_result += weight0 * scattering; 
    299278      } 
    300279    } 
  • sasmodels/kernelpy.py

    rdbfd471 rd4c33d6  
    197197 
    198198    pd_norm = 0.0 
    199     spherical_correction = 1.0 
    200199    partial_weight = np.NaN 
    201200    weight = np.NaN 
    202201 
    203202    p0_par = call_details.pd_par[0] 
    204     p0_is_theta = (p0_par == call_details.theta_par) 
    205203    p0_length = call_details.pd_length[0] 
    206204    p0_index = p0_length 
     
    219217            parameters[pd_par] = pd_value[pd_offset+pd_index] 
    220218            partial_weight = np.prod(pd_weight[pd_offset+pd_index][1:]) 
    221             if call_details.theta_par >= 0: 
    222                 cor = sin(pi / 180 * parameters[call_details.theta_par]) 
    223                 spherical_correction = max(abs(cor), 1e-6) 
    224219            p0_index = loop_index%p0_length 
    225220 
    226221        weight = partial_weight * pd_weight[p0_offset + p0_index] 
    227222        parameters[p0_par] = pd_value[p0_offset + p0_index] 
    228         if p0_is_theta: 
    229             cor = cos(pi/180 * parameters[p0_par]) 
    230             spherical_correction = max(abs(cor), 1e-6) 
    231223        p0_index += 1 
    232224        if weight > cutoff: 
     
    239231 
    240232            # update value and norm 
    241             weight *= spherical_correction 
    242233            total += weight * Iq 
    243234            pd_norm += weight * form_volume() 
  • sasmodels/weights.py

    r41e7f2e rd4c33d6  
    5555        """ 
    5656        sigma = self.width * center if relative else self.width 
     57        if not relative: 
     58            # For orientation, the jitter is relative to 0 not the angle 
     59            #center = 0 
     60            pass 
    5761        if sigma == 0 or self.npts < 2: 
    5862            if lb <= center <= ub: 
Note: See TracChangeset for help on using the changeset viewer.