Changes in sasmodels/generate.py [6e45516:5399809] in sasmodels


Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • sasmodels/generate.py

    r6e45516 r5399809  
    671671 
    672672 
    673 # type in IQXY pattern could be single, float, double, long double, ... 
    674 _IQXY_PATTERN = re.compile(r"(^|\s)double\s+I(?P<mode>q(ab?c|xy))\s*[(]", 
     673_IQXY_PATTERN = re.compile(r"(^|\s)double\s+I(?P<mode>q(ac|abc|xy))\s*[(]", 
    675674                           flags=re.MULTILINE) 
    676675def find_xy_mode(source): 
     
    701700    return 'qa' 
    702701 
     702# Note: not presently used.  Need to know whether Fq is available before 
     703# trying to compile the source.  Leave the code here in case we decide that 
     704# define have_Fq for each form factor is too tedious and error prone. 
     705_FQ_PATTERN = re.compile(r"(^|\s)void\s+Fq[(]", flags=re.MULTILINE) 
     706def contains_Fq(source): 
     707    # type: (List[str]) -> bool 
     708    """ 
     709    Return True if C source defines "void Fq(". 
     710    """ 
     711    for code in source: 
     712        m = _FQ_PATTERN.search(code) 
     713        if m is not None: 
     714            return True 
     715    return False 
    703716 
    704717def _add_source(source, code, path, lineno=1): 
     
    730743    # dispersion.  Need to be careful that necessary parameters are available 
    731744    # for computing volume even if we allow non-disperse volume parameters. 
    732  
    733745    partable = model_info.parameters 
    734746 
     
    743755    for path, code in user_code: 
    744756        _add_source(source, code, path) 
    745  
    746757    if model_info.c_code: 
    747758        _add_source(source, model_info.c_code, model_info.filename, 
     
    751762    q, qx, qy, qab, qa, qb, qc \ 
    752763        = [Parameter(name=v) for v in 'q qx qy qab qa qb qc'.split()] 
     764 
    753765    # Generate form_volume function, etc. from body only 
    754766    if isinstance(model_info.form_volume, str): 
     
    789801    source.append("\\\n".join(p.as_definition() 
    790802                              for p in partable.kernel_parameters)) 
    791  
    792803    # Define the function calls 
     804    call_effective_radius = "#define CALL_EFFECTIVE_RADIUS(mode, v) 0.0" 
    793805    if partable.form_volume_parameters: 
    794806        refs = _call_pars("_v.", partable.form_volume_parameters) 
    795807        call_volume = "#define CALL_VOLUME(_v) form_volume(%s)"%(",".join(refs)) 
     808        if model_info.effective_radius_type: 
     809            call_effective_radius = "#define CALL_EFFECTIVE_RADIUS(mode, _v) effective_radius(mode, %s)"%(",".join(refs)) 
    796810    else: 
    797811        # Model doesn't have volume.  We could make the kernel run a little 
     
    800814        call_volume = "#define CALL_VOLUME(v) 1.0" 
    801815    source.append(call_volume) 
    802  
     816    source.append(call_effective_radius) 
    803817    model_refs = _call_pars("_v.", partable.iq_parameters) 
    804     pars = ",".join(["_q"] + model_refs) 
    805     call_iq = "#define CALL_IQ(_q, _v) Iq(%s)" % pars 
     818 
     819    if model_info.have_Fq: 
     820        pars = ",".join(["_q", "&_F1", "&_F2",] + model_refs) 
     821        call_iq = "#define CALL_FQ(_q, _F1, _F2, _v) Fq(%s)" % pars 
     822        clear_iq = "#undef CALL_FQ" 
     823    else: 
     824        pars = ",".join(["_q"] + model_refs) 
     825        call_iq = "#define CALL_IQ(_q, _v) Iq(%s)" % pars 
     826        clear_iq = "#undef CALL_IQ" 
    806827    if xy_mode == 'qabc': 
    807828        pars = ",".join(["_qa", "_qb", "_qc"] + model_refs) 
     
    812833        call_iqxy = "#define CALL_IQ_AC(_qa,_qc,_v) Iqac(%s)" % pars 
    813834        clear_iqxy = "#undef CALL_IQ_AC" 
    814     elif xy_mode == 'qa': 
     835    elif xy_mode == 'qa' and not model_info.have_Fq: 
    815836        pars = ",".join(["_qa"] + model_refs) 
    816837        call_iqxy = "#define CALL_IQ_A(_qa,_v) Iq(%s)" % pars 
    817838        clear_iqxy = "#undef CALL_IQ_A" 
     839    elif xy_mode == 'qa' and model_info.have_Fq: 
     840        pars = ",".join(["_qa", "&_F1", "&_F2",] + model_refs) 
     841        # Note: uses rare C construction (expr1, expr2) which computes 
     842        # expr1 then expr2 and evaluates to expr2.  This allows us to 
     843        # leave it looking like a function even though it is returning 
     844        # its values by reference. 
     845        call_iqxy = "#define CALL_FQ_A(_qa,_F1,_F2,_v) (Fq(%s),_F2)" % pars 
     846        clear_iqxy = "#undef CALL_FQ_A" 
    818847    elif xy_mode == 'qxy': 
    819848        orientation_refs = _call_pars("_v.", partable.orientation_parameters) 
     
    831860    magpars = [k-2 for k, p in enumerate(partable.call_parameters) 
    832861               if p.type == 'sld'] 
    833  
    834862    # Fill in definitions for numbers of parameters 
    835863    source.append("#define MAX_PD %s"%partable.max_pd) 
     
    839867    source.append("#define MAGNETIC_PARS %s"%",".join(str(k) for k in magpars)) 
    840868    source.append("#define PROJECTION %d"%PROJECTION) 
    841  
    842869    # TODO: allow mixed python/opencl kernels? 
    843  
    844     ocl = _kernels(kernel_code, call_iq, call_iqxy, clear_iqxy, model_info.name) 
    845     dll = _kernels(kernel_code, call_iq, call_iqxy, clear_iqxy, model_info.name) 
     870    ocl = _kernels(kernel_code, call_iq, clear_iq, call_iqxy, clear_iqxy, model_info.name) 
     871    dll = _kernels(kernel_code, call_iq, clear_iq, call_iqxy, clear_iqxy, model_info.name) 
     872 
    846873    result = { 
    847874        'dll': '\n'.join(source+dll[0]+dll[1]+dll[2]), 
    848875        'opencl': '\n'.join(source+ocl[0]+ocl[1]+ocl[2]), 
    849876    } 
    850  
    851877    return result 
    852878 
    853879 
    854 def _kernels(kernel, call_iq, call_iqxy, clear_iqxy, name): 
     880def _kernels(kernel, call_iq, clear_iq, call_iqxy, clear_iqxy, name): 
    855881    # type: ([str,str], str, str, str) -> List[str] 
    856882    code = kernel[0] 
     
    862888        '#line 1 "%s Iq"' % path, 
    863889        code, 
    864         "#undef CALL_IQ", 
     890        clear_iq, 
    865891        "#undef KERNEL_NAME", 
    866892        ] 
     
    965991    docs = model_info.docs if model_info.docs is not None else "" 
    966992    docs = convert_section_titles_to_boldface(docs) 
    967     if model_info.structure_factor: 
    968         pars = model_info.parameters.kernel_parameters 
    969     else: 
    970         pars = model_info.parameters.COMMON + model_info.parameters.kernel_parameters 
    971     partable = make_partable(pars) 
     993    pars = make_partable(model_info.parameters.COMMON 
     994                         + model_info.parameters.kernel_parameters) 
    972995    subst = dict(id=model_info.id.replace('_', '-'), 
    973996                 name=model_info.name, 
    974997                 title=model_info.title, 
    975                  parameters=partable, 
     998                 parameters=pars, 
    976999                 returns=Sq_units if model_info.structure_factor else Iq_units, 
    9771000                 docs=docs) 
Note: See TracChangeset for help on using the changeset viewer.