Changes in sasmodels/generate.py [6e45516:5399809] in sasmodels
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/generate.py
r6e45516 r5399809 671 671 672 672 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*[(]", 675 674 flags=re.MULTILINE) 676 675 def find_xy_mode(source): … … 701 700 return 'qa' 702 701 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) 706 def 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 703 716 704 717 def _add_source(source, code, path, lineno=1): … … 730 743 # dispersion. Need to be careful that necessary parameters are available 731 744 # for computing volume even if we allow non-disperse volume parameters. 732 733 745 partable = model_info.parameters 734 746 … … 743 755 for path, code in user_code: 744 756 _add_source(source, code, path) 745 746 757 if model_info.c_code: 747 758 _add_source(source, model_info.c_code, model_info.filename, … … 751 762 q, qx, qy, qab, qa, qb, qc \ 752 763 = [Parameter(name=v) for v in 'q qx qy qab qa qb qc'.split()] 764 753 765 # Generate form_volume function, etc. from body only 754 766 if isinstance(model_info.form_volume, str): … … 789 801 source.append("\\\n".join(p.as_definition() 790 802 for p in partable.kernel_parameters)) 791 792 803 # Define the function calls 804 call_effective_radius = "#define CALL_EFFECTIVE_RADIUS(mode, v) 0.0" 793 805 if partable.form_volume_parameters: 794 806 refs = _call_pars("_v.", partable.form_volume_parameters) 795 807 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)) 796 810 else: 797 811 # Model doesn't have volume. We could make the kernel run a little … … 800 814 call_volume = "#define CALL_VOLUME(v) 1.0" 801 815 source.append(call_volume) 802 816 source.append(call_effective_radius) 803 817 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" 806 827 if xy_mode == 'qabc': 807 828 pars = ",".join(["_qa", "_qb", "_qc"] + model_refs) … … 812 833 call_iqxy = "#define CALL_IQ_AC(_qa,_qc,_v) Iqac(%s)" % pars 813 834 clear_iqxy = "#undef CALL_IQ_AC" 814 elif xy_mode == 'qa' :835 elif xy_mode == 'qa' and not model_info.have_Fq: 815 836 pars = ",".join(["_qa"] + model_refs) 816 837 call_iqxy = "#define CALL_IQ_A(_qa,_v) Iq(%s)" % pars 817 838 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" 818 847 elif xy_mode == 'qxy': 819 848 orientation_refs = _call_pars("_v.", partable.orientation_parameters) … … 831 860 magpars = [k-2 for k, p in enumerate(partable.call_parameters) 832 861 if p.type == 'sld'] 833 834 862 # Fill in definitions for numbers of parameters 835 863 source.append("#define MAX_PD %s"%partable.max_pd) … … 839 867 source.append("#define MAGNETIC_PARS %s"%",".join(str(k) for k in magpars)) 840 868 source.append("#define PROJECTION %d"%PROJECTION) 841 842 869 # 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 846 873 result = { 847 874 'dll': '\n'.join(source+dll[0]+dll[1]+dll[2]), 848 875 'opencl': '\n'.join(source+ocl[0]+ocl[1]+ocl[2]), 849 876 } 850 851 877 return result 852 878 853 879 854 def _kernels(kernel, call_iq, c all_iqxy, clear_iqxy, name):880 def _kernels(kernel, call_iq, clear_iq, call_iqxy, clear_iqxy, name): 855 881 # type: ([str,str], str, str, str) -> List[str] 856 882 code = kernel[0] … … 862 888 '#line 1 "%s Iq"' % path, 863 889 code, 864 "#undef CALL_IQ",890 clear_iq, 865 891 "#undef KERNEL_NAME", 866 892 ] … … 965 991 docs = model_info.docs if model_info.docs is not None else "" 966 992 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) 972 995 subst = dict(id=model_info.id.replace('_', '-'), 973 996 name=model_info.name, 974 997 title=model_info.title, 975 parameters=par table,998 parameters=pars, 976 999 returns=Sq_units if model_info.structure_factor else Iq_units, 977 1000 docs=docs)
Note: See TracChangeset
for help on using the changeset viewer.