Changeset c036ddb in sasmodels for sasmodels/product.py


Ignore:
Timestamp:
Aug 7, 2018 8:45:45 PM (6 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:
7e923c2
Parents:
7b0abf8
Message:

refactor so Iq is not needed if Fq is defined

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sasmodels/product.py

    r01c8d9e rc036ddb  
    3737ER_ID = "radius_effective" 
    3838VF_ID = "volfraction" 
     39BETA_DEFINITION = ("beta_mode", "", 0, [["P*S"],["P*(1+beta*(S-1))"]], "", 
     40                   "Structure factor dispersion calculation mode") 
    3941 
    4042# TODO: core_shell_sphere model has suppressed the volume ratio calculation 
     
    7476    translate_name = dict((old.id, new.id) for old, new 
    7577                          in zip(s_pars.kernel_parameters[1:], s_list)) 
    76     beta_parameter = Parameter("beta_mode", "", 0, [["P*S"],["P*(1+beta*(S-1))"], "", "Structure factor dispersion calculation mode"]) 
    77     combined_pars = p_pars.kernel_parameters + s_list + [beta_parameter] 
     78    beta = [Parameter(*BETA_DEFINITION)] if p_info.have_Fq else [] 
     79    combined_pars = p_pars.kernel_parameters + s_list + beta 
    7880    parameters = ParameterTable(combined_pars) 
    7981    parameters.max_pd = p_pars.max_pd + s_pars.max_pd 
     
    152154        #: Structure factor modelling interaction between particles. 
    153155        self.S = S 
    154          
     156 
    155157        #: Model precision. This is not really relevant, since it is the 
    156158        #: individual P and S models that control the effective dtype, 
     
    170172        # in opencl; or both in opencl, but one in single precision and the 
    171173        # other in double precision). 
    172          
     174 
    173175        p_kernel = self.P.make_kernel(q_vectors) 
    174176        s_kernel = self.S.make_kernel(q_vectors) 
     
    196198        # type: (CallDetails, np.ndarray, float, bool) -> np.ndarray 
    197199        p_info, s_info = self.info.composition[1] 
     200 
    198201        # if there are magnetic parameters, they will only be on the 
    199202        # form factor P, not the structure factor S. 
     
    207210        nweights = call_details.num_weights 
    208211        weights = values[nvalues:nvalues + 2*nweights] 
     212 
    209213        # Construct the calling parameters for P. 
    210214        p_npars = p_info.parameters.npars 
     
    212216        p_offset = call_details.offset[:p_npars] 
    213217        p_details = make_details(p_info, p_length, p_offset, nweights) 
     218 
    214219        # Set p scale to the volume fraction in s, which is the first of the 
    215220        # 'S' parameters in the parameter list, or 2+np in 0-origin. 
     
    219224        p_values.append([0.]*spacer) 
    220225        p_values = np.hstack(p_values).astype(self.p_kernel.dtype) 
     226 
    221227        # Call ER and VR for P since these are needed for S. 
    222228        p_er, p_vr = calc_er_vr(p_info, p_details, p_values) 
    223229        s_vr = (volfrac/p_vr if p_vr != 0. else volfrac) 
    224230        #print("volfrac:%g p_er:%g p_vr:%g s_vr:%g"%(volfrac,p_er,p_vr,s_vr)) 
     231 
    225232        # Construct the calling parameters for S. 
    226233        # The  effective radius is not in the combined parameter list, so 
     
    252259        s_values.append([0.]*spacer) 
    253260        s_values = np.hstack(s_values).astype(self.s_kernel.dtype) 
     261 
    254262        # beta mode is the first parameter after the structure factor pars 
    255263        beta_index = 2+p_npars+s_npars 
    256264        beta_mode = values[beta_index] 
     265 
    257266        # Call the kernels 
    258         if beta_mode: # beta: 
     267        s_result = self.s_kernel.Iq(s_details, s_values, cutoff, False) 
     268        scale, background = values[0], values[1] 
     269        if beta_mode: 
    259270            F1, F2, volume_avg = self.p_kernel.beta(p_details, p_values, cutoff, magnetic) 
     271            combined_scale = scale*volfrac/volume_avg 
     272            # Define lazy results based on intermediate values. 
     273            # The return value for the calculation should be an ordered 
     274            # dictionary containing any result the user might want to see 
     275            # at the end of the calculation, including scalars, strings, 
     276            # and plottable data.  Don't want to build this structure during 
     277            # fits, only when displaying the final result (or a one-off 
     278            # computation which asks for it). 
     279            # Do not use the current hack of storing the intermediate values 
     280            # in self.results since that leads to awkward threading issues. 
     281            # Instead return the function along with the bundle of inputs. 
     282            # P and Q may themselves have intermediate results they want to 
     283            # include, such as A and B if P = A + B.  Might use this mechanism 
     284            # to return the computed effective radius as well. 
     285            #def lazy_results(Q, S, F1, F2, scale): 
     286            #    """ 
     287            #    beta = F1**2 / F2  # what about divide by zero errors? 
     288            #    return { 
     289            #        'P' : Data1D(Q, scale*F2), 
     290            #        'beta': Data1D(Q, beta), 
     291            #        'S' : Data1D(Q, S), 
     292            #        'Seff': Data1D(Q, 1 + beta*(S-1)), 
     293            #        'I' : Data1D(Q, scale*(F2 + (F1**2)*(S-1)) + background), 
     294            #    } 
     295            #lazy_pars = s_result, F1, F2, combined_scale 
     296            self.results = [F2, s_result] 
     297            final_result = combined_scale*(F2 + (F1**2)*(s_result - 1)) + background 
    260298        else: 
    261299            p_result = self.p_kernel.Iq(p_details, p_values, cutoff, magnetic) 
    262         s_result = self.s_kernel.Iq(s_details, s_values, cutoff, False) 
    263         #print("p_npars",p_npars,s_npars,p_er,s_vr,values[2+p_npars+1:2+p_npars+s_npars]) 
     300            # remember the parts for plotting later 
     301            self.results = [p_result, s_result] 
     302            final_result = scale*(p_result*s_result) + background 
     303 
    264304        #call_details.show(values) 
    265305        #print("values", values) 
     
    272312        #plt.subplot(212); plt.loglog(self.s_kernel.q_input.q, s_result, '-') 
    273313        #plt.figure() 
    274         if beta_mode:#beta 
    275             beta_factor = F1**2/F2 
    276             Sq_eff = 1+beta_factor*(s_result - 1) 
    277             self.results = [F2, Sq_eff,F1,s_result] 
    278             final_result = volfrac*values[0]*(F2 + (F1**2)*(s_result - 1))/volume_avg+values[1] 
    279             #final_result =  volfrac * values[0] * F2 * Sq_eff / volume_avg + values[1] 
    280         else: 
    281             # remember the parts for plotting later 
    282             self.results = [p_result, s_result] 
    283             final_result = values[0]*(p_result*s_result) + values[1] 
    284314        return final_result 
    285315 
Note: See TracChangeset for help on using the changeset viewer.