- Timestamp:
- Jan 25, 2018 12:05:09 PM (6 years ago)
- Branches:
- master, core_shell_microgels, magnetic_model, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
- Children:
- a69d8cd, 95498a3
- Parents:
- 3fb9404 (diff), 7a516d0 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - git-author:
- Adam Washington <rprospero@…> (01/25/18 12:05:09)
- git-committer:
- GitHub <noreply@…> (01/25/18 12:05:09)
- Location:
- sasmodels
- Files:
-
- 1 added
- 43 edited
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/core.py
r2d81cfe r7a516d0 148 148 used with functions in generate to build the docs or extract model info. 149 149 """ 150 if '@' in model_string: 151 parts = model_string.split('@') 152 if len(parts) != 2: 153 raise ValueError("Use P@S to apply a structure factor S to model P") 154 P_info, Q_info = [load_model_info(part) for part in parts] 155 return product.make_product_info(P_info, Q_info) 156 157 product_parts = [] 158 addition_parts = [] 159 160 addition_parts_names = model_string.split('+') 161 if len(addition_parts_names) >= 2: 162 addition_parts = [load_model_info(part) for part in addition_parts_names] 163 elif len(addition_parts_names) == 1: 164 product_parts_names = model_string.split('*') 165 if len(product_parts_names) >= 2: 166 product_parts = [load_model_info(part) for part in product_parts_names] 167 elif len(product_parts_names) == 1: 168 if "custom." in product_parts_names[0]: 169 # Extract ModelName from "custom.ModelName" 170 pattern = "custom.([A-Za-z0-9_-]+)" 171 result = re.match(pattern, product_parts_names[0]) 172 if result is None: 173 raise ValueError("Model name in invalid format: " + product_parts_names[0]) 174 model_name = result.group(1) 175 # Use ModelName to find the path to the custom model file 176 model_path = joinpath(CUSTOM_MODEL_PATH, model_name + ".py") 177 if not os.path.isfile(model_path): 178 raise ValueError("The model file {} doesn't exist".format(model_path)) 179 kernel_module = custom.load_custom_kernel_module(model_path) 180 return modelinfo.make_model_info(kernel_module) 181 # Model is a core model 182 kernel_module = generate.load_kernel_module(product_parts_names[0]) 183 return modelinfo.make_model_info(kernel_module) 184 185 model = None 186 if len(product_parts) > 1: 187 model = mixture.make_mixture_info(product_parts, operation='*') 188 if len(addition_parts) > 1: 189 if model is not None: 190 addition_parts.append(model) 191 model = mixture.make_mixture_info(addition_parts, operation='+') 192 return model 150 if "+" in model_string: 151 parts = [load_model_info(part) 152 for part in model_string.split("+")] 153 return mixture.make_mixture_info(parts, operation='+') 154 elif "*" in model_string: 155 parts = [load_model_info(part) 156 for part in model_string.split("*")] 157 return mixture.make_mixture_info(parts, operation='*') 158 elif "@" in model_string: 159 p_info, q_info = [load_model_info(part) 160 for part in model_string.split("@")] 161 return product.make_product_info(p_info, q_info) 162 # We are now dealing with a pure model 163 elif "custom." in model_string: 164 pattern = "custom.([A-Za-z0-9_-]+)" 165 result = re.match(pattern, model_string) 166 if result is None: 167 raise ValueError("Model name in invalid format: " + model_string) 168 model_name = result.group(1) 169 # Use ModelName to find the path to the custom model file 170 model_path = joinpath(CUSTOM_MODEL_PATH, model_name + ".py") 171 if not os.path.isfile(model_path): 172 raise ValueError("The model file {} doesn't exist".format(model_path)) 173 kernel_module = custom.load_custom_kernel_module(model_path) 174 return modelinfo.make_model_info(kernel_module) 175 kernel_module = generate.load_kernel_module(model_string) 176 return modelinfo.make_model_info(kernel_module) 193 177 194 178 … … 336 320 print("\n".join(list_models(kind))) 337 321 322 def test_load(): 323 # type: () -> None 324 """Check that model load works""" 325 def test_models(fst, snd): 326 """Confirm that two models produce the same parameters""" 327 fst = load_model(fst) 328 snd = load_model(snd) 329 # Remove the upper case characters frin the parameters, since 330 # they lasndel the order of events and we specfically are 331 # changin that aspect 332 fst = [[x for x in p.name if x == x.lower()] for p in fst.info.parameters.kernel_parameters] 333 snd = [[x for x in p.name if x == x.lower()] for p in snd.info.parameters.kernel_parameters] 334 assert sorted(fst) == sorted(snd), "{} != {}".format(fst, snd) 335 336 337 test_models( 338 "cylinder+sphere", 339 "sphere+cylinder") 340 test_models( 341 "cylinder*sphere", 342 "sphere*cylinder") 343 test_models( 344 "cylinder@hardsphere*sphere", 345 "sphere*cylinder@hardsphere") 346 test_models( 347 "barbell+sphere*cylinder@hardsphere", 348 "sphere*cylinder@hardsphere+barbell") 349 test_models( 350 "barbell+cylinder@hardsphere*sphere", 351 "cylinder@hardsphere*sphere+barbell") 352 test_models( 353 "barbell+sphere*cylinder@hardsphere", 354 "barbell+cylinder@hardsphere*sphere") 355 test_models( 356 "sphere*cylinder@hardsphere+barbell", 357 "cylinder@hardsphere*sphere+barbell") 358 test_models( 359 "barbell+sphere*cylinder@hardsphere", 360 "cylinder@hardsphere*sphere+barbell") 361 test_models( 362 "barbell+cylinder@hardsphere*sphere", 363 "sphere*cylinder@hardsphere+barbell") 364 365 #Test the the model produces the parameters that we would expect 366 model = load_model("cylinder@hardsphere*sphere") 367 actual = [p.name for p in model.info.parameters.kernel_parameters] 368 target = ("sld sld_solvent radius length theta phi volfraction" 369 " A_sld A_sld_solvent A_radius").split() 370 assert target == actual, "%s != %s"%(target, actual) 371 338 372 if __name__ == "__main__": 339 373 list_models_main() -
sasmodels/mixture.py
r2d81cfe r7fec3b7 94 94 # If model is a sum model, each constituent model gets its own scale parameter 95 95 scale_prefix = prefix 96 if prefix == '' and part.operation == '*':96 if prefix == '' and hasattr(part,"operation") and part.operation == '*': 97 97 # `part` is a composition product model. Find the prefixes of 98 98 # it's parameters to form a new prefix for the scale, eg: … … 233 233 return self 234 234 235 def next(self):235 def __next__(self): 236 236 # type: () -> Tuple[List[Callable], CallDetails, np.ndarray] 237 237 if self.part_num >= len(self.parts): … … 251 251 252 252 return kernel, call_details, values 253 254 # CRUFT: py2 support 255 next = __next__ 253 256 254 257 def _part_details(self, info, par_index): -
sasmodels/compare.py
r2d81cfe r2a7e20e 42 42 from .data import plot_theory, empty_data1D, empty_data2D, load_data 43 43 from .direct_model import DirectModel, get_mesh 44 from .generate import FLOAT_RE 44 from .generate import FLOAT_RE, set_integration_size 45 45 from .weights import plot_weights 46 46 … … 92 92 -accuracy=Low accuracy of the resolution calculation Low, Mid, High, Xhigh 93 93 -neval=1 sets the number of evals for more accurate timing 94 -ngauss=0 overrides the number of points in the 1-D gaussian quadrature 94 95 95 96 === precision options === … … 693 694 data = empty_data2D(q, resolution=res) 694 695 data.accuracy = opts['accuracy'] 695 set_beam_stop(data, 0.0004)696 set_beam_stop(data, qmin) 696 697 index = ~data.mask 697 698 else: … … 706 707 return data, index 707 708 708 def make_engine(model_info, data, dtype, cutoff ):709 def make_engine(model_info, data, dtype, cutoff, ngauss=0): 709 710 # type: (ModelInfo, Data, str, float) -> Calculator 710 711 """ … … 714 715 than OpenCL. 715 716 """ 717 if ngauss: 718 set_integration_size(model_info, ngauss) 719 716 720 if dtype is None or not dtype.endswith('!'): 717 721 return eval_opencl(model_info, data, dtype=dtype, cutoff=cutoff) … … 954 958 'poly', 'mono', 'cutoff=', 955 959 'magnetic', 'nonmagnetic', 956 'accuracy=', 960 'accuracy=', 'ngauss=', 957 961 'neval=', # for timing... 958 962 … … 1089 1093 'show_weights' : False, 1090 1094 'sphere' : 0, 1095 'ngauss' : '0', 1091 1096 } 1092 1097 for arg in flags: … … 1115 1120 elif arg.startswith('-engine='): opts['engine'] = arg[8:] 1116 1121 elif arg.startswith('-neval='): opts['count'] = arg[7:] 1122 elif arg.startswith('-ngauss='): opts['ngauss'] = arg[8:] 1117 1123 elif arg.startswith('-random='): 1118 1124 opts['seed'] = int(arg[8:]) … … 1169 1175 1170 1176 comparison = any(PAR_SPLIT in v for v in values) 1177 1171 1178 if PAR_SPLIT in name: 1172 1179 names = name.split(PAR_SPLIT, 2) … … 1181 1188 return None 1182 1189 1190 if PAR_SPLIT in opts['ngauss']: 1191 opts['ngauss'] = [int(k) for k in opts['ngauss'].split(PAR_SPLIT, 2)] 1192 comparison = True 1193 else: 1194 opts['ngauss'] = [int(opts['ngauss'])]*2 1195 1183 1196 if PAR_SPLIT in opts['engine']: 1184 1197 opts['engine'] = opts['engine'].split(PAR_SPLIT, 2) … … 1199 1212 opts['cutoff'] = [float(opts['cutoff'])]*2 1200 1213 1201 base = make_engine(model_info[0], data, opts['engine'][0], opts['cutoff'][0]) 1214 base = make_engine(model_info[0], data, opts['engine'][0], 1215 opts['cutoff'][0], opts['ngauss'][0]) 1202 1216 if comparison: 1203 comp = make_engine(model_info[1], data, opts['engine'][1], opts['cutoff'][1]) 1217 comp = make_engine(model_info[1], data, opts['engine'][1], 1218 opts['cutoff'][1], opts['ngauss'][1]) 1204 1219 else: 1205 1220 comp = None … … 1274 1289 if model_info != model_info2: 1275 1290 pars2 = randomize_pars(model_info2, pars2) 1276 limit_dimensions(model_info , pars2, maxdim)1291 limit_dimensions(model_info2, pars2, maxdim) 1277 1292 # Share values for parameters with the same name 1278 1293 for k, v in pars.items(): -
sasmodels/details.py
r2d81cfe r108e70e 258 258 # type: (...) -> Sequence[np.ndarray] 259 259 """ 260 **Deprecated** Theta weights will be computed in the kernel wrapper if 261 they are needed. 262 260 263 If there is a theta parameter, update the weights of that parameter so that 261 264 the cosine weighting required for polar integration is preserved. … … 272 275 Returns updated weights vectors 273 276 """ 274 # TODO: explain in a comment why scale and background are missing275 277 # Apparently the parameters.theta_offset similarly skips scale and 276 278 # and background, so the indexing works out, but they are still shipped … … 279 281 index = parameters.theta_offset 280 282 theta = dispersity[index] 281 # TODO: modify the dispersity vector to avoid the theta=-90,90,270,...282 283 theta_weight = abs(cos(radians(theta))) 283 284 weights = tuple(theta_weight*w if k == index else w -
sasmodels/generate.py
r2d81cfe r108e70e 7 7 particular dimensions averaged over all orientations. 8 8 9 *Iqxy(qx, qy, p1, p2, ...)* returns the scattering at qx, qy for a form 10 with particular dimensions for a single orientation. 11 12 *Imagnetic(qx, qy, result[], p1, p2, ...)* returns the scattering for the 13 polarized neutron spin states (up-up, up-down, down-up, down-down) for 14 a form with particular dimensions for a single orientation. 9 *Iqac(qab, qc, p1, p2, ...)* returns the scattering at qab, qc 10 for a rotationally symmetric form with particular dimensions. 11 qab, qc are determined from shape orientation and scattering angles. 12 This call is used if the shape has orientation parameters theta and phi. 13 14 *Iqabc(qa, qb, qc, p1, p2, ...)* returns the scattering at qa, qb, qc 15 for a form with particular dimensions. qa, qb, qc are determined from 16 shape orientation and scattering angles. This call is used if the shape 17 has orientation parameters theta, phi and psi. 18 19 *Iqxy(qx, qy, p1, p2, ...)* returns the scattering at qx, qy. Use this 20 to create an arbitrary 2D theory function, needed for q-dependent 21 background functions and for models with non-uniform magnetism. 15 22 16 23 *form_volume(p1, p2, ...)* returns the volume of the form with particular … … 31 38 scale and background parameters for each model. 32 39 33 *Iq*, *Iqxy*, *Imagnetic* and *form_volume* should be stylized C-99 34 functions written for OpenCL. All functions need prototype declarations 35 even if the are defined before they are used. OpenCL does not support 36 *#include* preprocessor directives, so instead the list of includes needs 37 to be given as part of the metadata in the kernel module definition. 38 The included files should be listed using a path relative to the kernel 39 module, or if using "lib/file.c" if it is one of the standard includes 40 provided with the sasmodels source. The includes need to be listed in 41 order so that functions are defined before they are used. 40 C code should be stylized C-99 functions written for OpenCL. All functions 41 need prototype declarations even if the are defined before they are used. 42 Although OpenCL supports *#include* preprocessor directives, the list of 43 includes should be given as part of the metadata in the kernel module 44 definition. The included files should be listed using a path relative to the 45 kernel module, or if using "lib/file.c" if it is one of the standard includes 46 provided with the sasmodels source. The includes need to be listed in order 47 so that functions are defined before they are used. 42 48 43 49 Floating point values should be declared as *double*. For single precision … … 107 113 present, the volume ratio is 1. 108 114 109 *form_volume*, *Iq*, *Iq xy*, *Imagnetic* are strings containing the110 C source code for the body of the volume, Iq, and Iqxyfunctions115 *form_volume*, *Iq*, *Iqac*, *Iqabc* are strings containing 116 the C source code for the body of the volume, Iq, and Iqac functions 111 117 respectively. These can also be defined in the last source file. 112 118 113 *Iq* and *Iqxy* also be instead be python functions defining the119 *Iq*, *Iqac*, *Iqabc* also be instead be python functions defining the 114 120 kernel. If they are marked as *Iq.vectorized = True* then the 115 121 kernel is passed the entire *q* vector at once, otherwise it is … … 168 174 from zlib import crc32 169 175 from inspect import currentframe, getframeinfo 176 import logging 170 177 171 178 import numpy as np # type: ignore … … 181 188 pass 182 189 # pylint: enable=unused-import 190 191 logger = logging.getLogger(__name__) 183 192 184 193 # jitter projection to use in the kernel code. See explore/jitter.py … … 270 279 """ 271 280 281 282 def set_integration_size(info, n): 283 # type: (ModelInfo, int) -> None 284 """ 285 Update the model definition, replacing the gaussian integration with 286 a gaussian integration of a different size. 287 288 Note: this really ought to be a method in modelinfo, but that leads to 289 import loops. 290 """ 291 if (info.source and any(lib.startswith('lib/gauss') for lib in info.source)): 292 import os.path 293 from .gengauss import gengauss 294 path = os.path.join(MODEL_PATH, "lib", "gauss%d.c"%n) 295 if not os.path.exists(path): 296 gengauss(n, path) 297 info.source = ["lib/gauss%d.c"%n if lib.startswith('lib/gauss') 298 else lib for lib in info.source] 272 299 273 300 def format_units(units): … … 608 635 609 636 """ 610 def _gen_fn( name, pars, body, filename, line):611 # type: ( str, List[Parameter], str, str, int) -> str637 def _gen_fn(model_info, name, pars): 638 # type: (ModelInfo, str, List[Parameter]) -> str 612 639 """ 613 640 Generate a function given pars and body. … … 621 648 """ 622 649 par_decl = ', '.join(p.as_function_argument() for p in pars) if pars else 'void' 650 body = getattr(model_info, name) 651 filename = model_info.filename 652 # Note: if symbol is defined strangely in the module then default it to 1 653 lineno = model_info.lineno.get(name, 1) 623 654 return _FN_TEMPLATE % { 624 655 'name': name, 'pars': par_decl, 'body': body, 625 'filename': filename.replace('\\', '\\\\'), 'line': line ,656 'filename': filename.replace('\\', '\\\\'), 'line': lineno, 626 657 } 627 658 … … 638 669 639 670 # type in IQXY pattern could be single, float, double, long double, ... 640 _IQXY_PATTERN = re.compile( "^((inline|static) )? *([a-z ]+ )? *Iqxy *([(]|$)",671 _IQXY_PATTERN = re.compile(r"(^|\s)double\s+I(?P<mode>q(ab?c|xy))\s*[(]", 641 672 flags=re.MULTILINE) 642 def _have_Iqxy(sources):673 def find_xy_mode(source): 643 674 # type: (List[str]) -> bool 644 675 """ 645 Return t rue if any file defines Iqxy.676 Return the xy mode as qa, qac, qabc or qxy. 646 677 647 678 Note this is not a C parser, and so can be easily confused by 648 679 non-standard syntax. Also, it will incorrectly identify the following 649 as having Iqxy::680 as having 2D models:: 650 681 651 682 /* 652 double Iq xy(qx, qy, ...) { ... fill this in later ... }683 double Iqac(qab, qc, ...) { ... fill this in later ... } 653 684 */ 654 685 655 If you want to comment out an Iqxy function, use // on the front of the 656 line instead. 657 """ 658 for _path, code in sources: 659 if _IQXY_PATTERN.search(code): 660 return True 661 return False 662 663 664 def _add_source(source, code, path): 686 If you want to comment out the function, use // on the front of the 687 line:: 688 689 /* 690 // double Iqac(qab, qc, ...) { ... fill this in later ... } 691 */ 692 693 """ 694 for code in source: 695 m = _IQXY_PATTERN.search(code) 696 if m is not None: 697 return m.group('mode') 698 return 'qa' 699 700 701 def _add_source(source, code, path, lineno=1): 665 702 """ 666 703 Add a file to the list of source code chunks, tagged with path and line. 667 704 """ 668 705 path = path.replace('\\', '\\\\') 669 source.append('#line 1 "%s"' % path)706 source.append('#line %d "%s"' % (lineno, path)) 670 707 source.append(code) 671 708 … … 698 735 user_code = [(f, open(f).read()) for f in model_sources(model_info)] 699 736 700 # What kind of 2D model do we need?701 xy_mode = ('qa' if not _have_Iqxy(user_code) and not isinstance(model_info.Iqxy, str)702 else 'qac' if not partable.is_asymmetric703 else 'qabc')704 705 737 # Build initial sources 706 738 source = [] … … 709 741 _add_source(source, code, path) 710 742 743 if model_info.c_code: 744 _add_source(source, model_info.c_code, model_info.filename, 745 lineno=model_info.lineno.get('c_code', 1)) 746 711 747 # Make parameters for q, qx, qy so that we can use them in declarations 712 q, qx, qy = [Parameter(name=v) for v in ('q', 'qx', 'qy')] 748 q, qx, qy, qab, qa, qb, qc \ 749 = [Parameter(name=v) for v in 'q qx qy qab qa qb qc'.split()] 713 750 # Generate form_volume function, etc. from body only 714 751 if isinstance(model_info.form_volume, str): 715 752 pars = partable.form_volume_parameters 716 source.append(_gen_fn('form_volume', pars, model_info.form_volume, 717 model_info.filename, model_info._form_volume_line)) 753 source.append(_gen_fn(model_info, 'form_volume', pars)) 718 754 if isinstance(model_info.Iq, str): 719 755 pars = [q] + partable.iq_parameters 720 source.append(_gen_fn('Iq', pars, model_info.Iq, 721 model_info.filename, model_info._Iq_line)) 756 source.append(_gen_fn(model_info, 'Iq', pars)) 722 757 if isinstance(model_info.Iqxy, str): 723 pars = [qx, qy] + partable.iqxy_parameters 724 source.append(_gen_fn('Iqxy', pars, model_info.Iqxy, 725 model_info.filename, model_info._Iqxy_line)) 758 pars = [qx, qy] + partable.iq_parameters + partable.orientation_parameters 759 source.append(_gen_fn(model_info, 'Iqxy', pars)) 760 if isinstance(model_info.Iqac, str): 761 pars = [qab, qc] + partable.iq_parameters 762 source.append(_gen_fn(model_info, 'Iqac', pars)) 763 if isinstance(model_info.Iqabc, str): 764 pars = [qa, qb, qc] + partable.iq_parameters 765 source.append(_gen_fn(model_info, 'Iqabc', pars)) 766 767 # What kind of 2D model do we need? Is it consistent with the parameters? 768 xy_mode = find_xy_mode(source) 769 if xy_mode == 'qabc' and not partable.is_asymmetric: 770 raise ValueError("asymmetric oriented models need to define Iqabc") 771 elif xy_mode == 'qac' and partable.is_asymmetric: 772 raise ValueError("symmetric oriented models need to define Iqac") 773 elif not partable.orientation_parameters and xy_mode in ('qac', 'qabc'): 774 raise ValueError("Unexpected function I%s for unoriented shape"%xy_mode) 775 elif partable.orientation_parameters and xy_mode not in ('qac', 'qabc'): 776 if xy_mode == 'qxy': 777 logger.warn("oriented shapes should define Iqac or Iqabc") 778 else: 779 raise ValueError("Expected function Iqac or Iqabc for oriented shape") 726 780 727 781 # Define the parameter table … … 749 803 if xy_mode == 'qabc': 750 804 pars = ",".join(["_qa", "_qb", "_qc"] + model_refs) 751 call_iqxy = "#define CALL_IQ_ABC(_qa,_qb,_qc,_v) Iq xy(%s)" % pars805 call_iqxy = "#define CALL_IQ_ABC(_qa,_qb,_qc,_v) Iqabc(%s)" % pars 752 806 clear_iqxy = "#undef CALL_IQ_ABC" 753 807 elif xy_mode == 'qac': 754 808 pars = ",".join(["_qa", "_qc"] + model_refs) 755 call_iqxy = "#define CALL_IQ_AC(_qa,_qc,_v) Iq xy(%s)" % pars809 call_iqxy = "#define CALL_IQ_AC(_qa,_qc,_v) Iqac(%s)" % pars 756 810 clear_iqxy = "#undef CALL_IQ_AC" 757 el se: # xy_mode == 'qa'811 elif xy_mode == 'qa': 758 812 pars = ",".join(["_qa"] + model_refs) 759 813 call_iqxy = "#define CALL_IQ_A(_qa,_v) Iq(%s)" % pars 760 814 clear_iqxy = "#undef CALL_IQ_A" 815 elif xy_mode == 'qxy': 816 orientation_refs = _call_pars("_v.", partable.orientation_parameters) 817 pars = ",".join(["_qx", "_qy"] + model_refs + orientation_refs) 818 call_iqxy = "#define CALL_IQ_XY(_qx,_qy,_v) Iqxy(%s)" % pars 819 clear_iqxy = "#undef CALL_IQ_XY" 820 if partable.orientation_parameters: 821 call_iqxy += "\n#define HAVE_THETA" 822 clear_iqxy += "\n#undef HAVE_THETA" 823 if partable.is_asymmetric: 824 call_iqxy += "\n#define HAVE_PSI" 825 clear_iqxy += "\n#undef HAVE_PSI" 826 761 827 762 828 magpars = [k-2 for k, p in enumerate(partable.call_parameters) -
sasmodels/jitter.py
rff10479 r0d5a655 1 1 #!/usr/bin/env python 2 2 """ 3 Application to explore the difference between sasview 3.x orientation 4 dispersity and possible replacement algorithms. 3 Jitter Explorer 4 =============== 5 6 Application to explore orientation angle and angular dispersity. 5 7 """ 6 8 from __future__ import division, print_function … … 124 126 def draw_parallelepiped(ax, size, view, jitter, steps=None, alpha=1): 125 127 """Draw a parallelepiped.""" 126 a, b,c = size128 a, b, c = size 127 129 x = a*np.array([ 1,-1, 1,-1, 1,-1, 1,-1]) 128 130 y = b*np.array([ 1, 1,-1,-1, 1, 1,-1,-1]) … … 142 144 ax.plot_trisurf(x, y, triangles=tri, Z=z, color='w', alpha=alpha) 143 145 146 # Draw pink face on box. 147 # Since I can't control face color, instead draw a thin box situated just 148 # in front of the "a+" face. 149 if 1: 150 x = a*np.array([ 1,-1, 1,-1, 1,-1, 1,-1]) 151 y = b*np.array([ 1, 1,-1,-1, 1, 1,-1,-1]) 152 z = c*np.array([ 1, 1, 1, 1,-1,-1,-1,-1]) 153 x, y, z = transform_xyz(view, jitter, abs(x)*1.05, y, z) 154 ax.plot_trisurf(x, y, triangles=tri, Z=z, color=[1,0.6,0.6], alpha=alpha) 155 144 156 draw_labels(ax, view, jitter, [ 145 157 ('c+', [ 0, 0, c], [ 1, 0, 0]), … … 165 177 # constants in kernel_iq.c 166 178 'equirectangular', 'sinusoidal', 'guyou', 'azimuthal_equidistance', 179 'azimuthal_equal_area', 167 180 ] 168 181 def draw_mesh(ax, view, jitter, radius=1.2, n=11, dist='gaussian', … … 607 620 Show an interactive orientation and jitter demo. 608 621 609 *model_name* is one of the models available in :func:`select_model`. 622 *model_name* is one of: sphere, cylinder, ellipsoid, parallelepiped, 623 triaxial_ellipsoid, or bcc_paracrystal. 624 625 *size* gives the dimensions (a, b, c) of the shape. 626 627 *dist* is the type of dispersition: gaussian, rectangle, or uniform. 628 629 *mesh* is the number of points in the dispersion mesh. 630 631 *projection* is the map projection to use for the mesh: equirectangular, 632 sinusoidal, guyou, azimuthal_equidistance, or azimuthal_equal_area. 610 633 """ 611 634 # projection number according to 1-order position in list, but -
sasmodels/kernel_header.c
r8698a0d r108e70e 150 150 inline double cube(double x) { return x*x*x; } 151 151 inline double sas_sinx_x(double x) { return x==0 ? 1.0 : sin(x)/x; } 152 153 // CRUFT: support old style models with orientation received qx, qy and angles 154 155 // To rotate from the canonical position to theta, phi, psi, first rotate by 156 // psi about the major axis, oriented along z, which is a rotation in the 157 // detector plane xy. Next rotate by theta about the y axis, aligning the major 158 // axis in the xz plane. Finally, rotate by phi in the detector plane xy. 159 // To compute the scattering, undo these rotations in reverse order: 160 // rotate in xy by -phi, rotate in xz by -theta, rotate in xy by -psi 161 // The returned q is the length of the q vector and (xhat, yhat, zhat) is a unit 162 // vector in the q direction. 163 // To change between counterclockwise and clockwise rotation, change the 164 // sign of phi and psi. 165 166 #if 1 167 //think cos(theta) should be sin(theta) in new coords, RKH 11Jan2017 168 #define ORIENT_SYMMETRIC(qx, qy, theta, phi, q, sn, cn) do { \ 169 SINCOS(phi*M_PI_180, sn, cn); \ 170 q = sqrt(qx*qx + qy*qy); \ 171 cn = (q==0. ? 1.0 : (cn*qx + sn*qy)/q * sin(theta*M_PI_180)); \ 172 sn = sqrt(1 - cn*cn); \ 173 } while (0) 174 #else 175 // SasView 3.x definition of orientation 176 #define ORIENT_SYMMETRIC(qx, qy, theta, phi, q, sn, cn) do { \ 177 SINCOS(theta*M_PI_180, sn, cn); \ 178 q = sqrt(qx*qx + qy*qy);\ 179 cn = (q==0. ? 1.0 : (cn*cos(phi*M_PI_180)*qx + sn*qy)/q); \ 180 sn = sqrt(1 - cn*cn); \ 181 } while (0) 182 #endif 183 184 #if 1 185 #define ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, xhat, yhat, zhat) do { \ 186 q = sqrt(qx*qx + qy*qy); \ 187 const double qxhat = qx/q; \ 188 const double qyhat = qy/q; \ 189 double sin_theta, cos_theta; \ 190 double sin_phi, cos_phi; \ 191 double sin_psi, cos_psi; \ 192 SINCOS(theta*M_PI_180, sin_theta, cos_theta); \ 193 SINCOS(phi*M_PI_180, sin_phi, cos_phi); \ 194 SINCOS(psi*M_PI_180, sin_psi, cos_psi); \ 195 xhat = qxhat*(-sin_phi*sin_psi + cos_theta*cos_phi*cos_psi) \ 196 + qyhat*( cos_phi*sin_psi + cos_theta*sin_phi*cos_psi); \ 197 yhat = qxhat*(-sin_phi*cos_psi - cos_theta*cos_phi*sin_psi) \ 198 + qyhat*( cos_phi*cos_psi - cos_theta*sin_phi*sin_psi); \ 199 zhat = qxhat*(-sin_theta*cos_phi) \ 200 + qyhat*(-sin_theta*sin_phi); \ 201 } while (0) 202 #else 203 // SasView 3.x definition of orientation 204 #define ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, cos_alpha, cos_mu, cos_nu) do { \ 205 q = sqrt(qx*qx + qy*qy); \ 206 const double qxhat = qx/q; \ 207 const double qyhat = qy/q; \ 208 double sin_theta, cos_theta; \ 209 double sin_phi, cos_phi; \ 210 double sin_psi, cos_psi; \ 211 SINCOS(theta*M_PI_180, sin_theta, cos_theta); \ 212 SINCOS(phi*M_PI_180, sin_phi, cos_phi); \ 213 SINCOS(psi*M_PI_180, sin_psi, cos_psi); \ 214 cos_alpha = cos_theta*cos_phi*qxhat + sin_theta*qyhat; \ 215 cos_mu = (-sin_theta*cos_psi*cos_phi - sin_psi*sin_phi)*qxhat + cos_theta*cos_psi*qyhat; \ 216 cos_nu = (-cos_phi*sin_psi*sin_theta + sin_phi*cos_psi)*qxhat + sin_psi*cos_theta*qyhat; \ 217 } while (0) 218 #endif -
sasmodels/kernel_iq.c
r6aee3ab r924a119 31 31 // CALL_IQ_AC(qa, qc, table) : call the Iqxy function for symmetric shapes 32 32 // CALL_IQ_ABC(qa, qc, table) : call the Iqxy function for asymmetric shapes 33 // CALL_IQ_XY(qx, qy, table) : call the Iqxy function for arbitrary models 33 34 // INVALID(table) : test if the current point is feesible to calculate. This 34 35 // will be defined in the kernel definition file. … … 173 174 static double 174 175 qac_apply( 175 QACRotation rotation,176 QACRotation *rotation, 176 177 double qx, double qy, 177 178 double *qa_out, double *qc_out) 178 179 { 179 const double dqc = rotation .R31*qx + rotation.R32*qy;180 const double dqc = rotation->R31*qx + rotation->R32*qy; 180 181 // Indirect calculation of qab, from qab^2 = |q|^2 - qc^2 181 182 const double dqa = sqrt(-dqc*dqc + qx*qx + qy*qy); … … 246 247 static double 247 248 qabc_apply( 248 QABCRotation rotation,249 QABCRotation *rotation, 249 250 double qx, double qy, 250 251 double *qa_out, double *qb_out, double *qc_out) 251 252 { 252 *qa_out = rotation .R11*qx + rotation.R12*qy;253 *qb_out = rotation .R21*qx + rotation.R22*qy;254 *qc_out = rotation .R31*qx + rotation.R32*qy;253 *qa_out = rotation->R11*qx + rotation->R12*qy; 254 *qb_out = rotation->R21*qx + rotation->R22*qy; 255 *qc_out = rotation->R31*qx + rotation->R32*qy; 255 256 } 256 257 … … 453 454 // theta, phi, dtheta, dphi are defined below in projection to avoid repeated code. 454 455 #define BUILD_ROTATION() qac_rotation(&rotation, theta, phi, dtheta, dphi); 455 #define APPLY_ROTATION() qac_apply( rotation, qx, qy, &qa, &qc)456 #define APPLY_ROTATION() qac_apply(&rotation, qx, qy, &qa, &qc) 456 457 #define CALL_KERNEL() CALL_IQ_AC(qa, qc, local_values.table) 457 458 … … 467 468 local_values.table.psi = 0.; 468 469 #define BUILD_ROTATION() qabc_rotation(&rotation, theta, phi, psi, dtheta, dphi, local_values.table.psi) 469 #define APPLY_ROTATION() qabc_apply( rotation, qx, qy, &qa, &qb, &qc)470 #define APPLY_ROTATION() qabc_apply(&rotation, qx, qy, &qa, &qb, &qc) 470 471 #define CALL_KERNEL() CALL_IQ_ABC(qa, qb, qc, local_values.table) 471 #endif 472 473 // Doing jitter projection code outside the previous if block so that we don't 474 // need to repeat the identical logic in the IQ_AC and IQ_ABC branches. This 475 // will become more important if we implement more projections, or more 476 // complicated projections. 477 #if defined(CALL_IQ) || defined(CALL_IQ_A) 472 #elif defined(CALL_IQ_XY) 473 // direct call to qx,qy calculator 474 double qx, qy; 475 #define FETCH_Q() do { qx = q[2*q_index]; qy = q[2*q_index+1]; } while (0) 476 #define BUILD_ROTATION() do {} while(0) 477 #define APPLY_ROTATION() do {} while(0) 478 #define CALL_KERNEL() CALL_IQ_XY(qx, qy, local_values.table) 479 #endif 480 481 // Define APPLY_PROJECTION depending on model symmetries. We do this outside 482 // the previous if block so that we don't need to repeat the identical 483 // logic in the IQ_AC and IQ_ABC branches. This will become more important 484 // if we implement more projections, or more complicated projections. 485 #if defined(CALL_IQ) || defined(CALL_IQ_A) // no orientation 478 486 #define APPLY_PROJECTION() const double weight=weight0 479 #else // !spherosymmetric projection 487 #elif defined(CALL_IQ_XY) // pass orientation to the model 488 // CRUFT: support oriented model which define Iqxy rather than Iqac or Iqabc 489 // Need to plug the values for the orientation angles back into parameter 490 // table in case they were overridden by the orientation offset. This 491 // means that orientation dispersity will not work for these models, but 492 // it was broken anyway, so no matter. Still want to provide Iqxy in case 493 // the user model wants full control of orientation/magnetism. 494 #if defined(HAVE_PSI) 495 const double theta = values[details->theta_par+2]; 496 const double phi = values[details->theta_par+3]; 497 const double psi = values[details->theta_par+4]; 498 double weight; 499 #define APPLY_PROJECTION() do { \ 500 local_values.table.theta = theta; \ 501 local_values.table.phi = phi; \ 502 local_values.table.psi = psi; \ 503 weight=weight0; \ 504 } while (0) 505 #elif defined(HAVE_THETA) 506 const double theta = values[details->theta_par+2]; 507 const double phi = values[details->theta_par+3]; 508 double weight; 509 #define APPLY_PROJECTION() do { \ 510 local_values.table.theta = theta; \ 511 local_values.table.phi = phi; \ 512 weight=weight0; \ 513 } while (0) 514 #else 515 #define APPLY_PROJECTION() const double weight=weight0 516 #endif 517 #else // apply jitter and view before calling the model 480 518 // Grab the "view" angles (theta, phi, psi) from the initial parameter table. 481 519 const double theta = values[details->theta_par+2]; … … 488 526 // we go through the mesh. 489 527 double dtheta, dphi, weight; 490 #if PROJECTION == 1 528 #if PROJECTION == 1 // equirectangular 491 529 #define APPLY_PROJECTION() do { \ 492 530 dtheta = local_values.table.theta; \ … … 494 532 weight = fabs(cos(dtheta*M_PI_180)) * weight0; \ 495 533 } while (0) 496 #elif PROJECTION == 2 534 #elif PROJECTION == 2 // sinusoidal 497 535 #define APPLY_PROJECTION() do { \ 498 536 dtheta = local_values.table.theta; \ … … 504 542 } while (0) 505 543 #endif 506 #endif // !spherosymmetric projection544 #endif // done defining APPLY_PROJECTION 507 545 508 546 // ** define looping macros ** -
sasmodels/kernelpy.py
r2d81cfe r108e70e 26 26 # pylint: enable=unused-import 27 27 28 logger = logging.getLogger(__name__) 29 28 30 class PyModel(KernelModel): 29 31 """ … … 31 33 """ 32 34 def __init__(self, model_info): 33 # Make sure Iq and Iqxy areavailable and vectorized35 # Make sure Iq is available and vectorized 34 36 _create_default_functions(model_info) 35 37 self.info = model_info 36 38 self.dtype = np.dtype('d') 37 logg ing.info("load python model " + self.info.name)39 logger.info("load python model " + self.info.name) 38 40 39 41 def make_kernel(self, q_vectors): 40 42 q_input = PyInput(q_vectors, dtype=F64) 41 kernel = self.info.Iqxy if q_input.is_2d else self.info.Iq 42 return PyKernel(kernel, self.info, q_input) 43 return PyKernel(self.info, q_input) 43 44 44 45 def release(self): … … 89 90 Callable SAS kernel. 90 91 91 *kernel* is the DllKernel object to call.92 *kernel* is the kernel object to call. 92 93 93 94 *model_info* is the module information … … 104 105 Call :meth:`release` when done with the kernel instance. 105 106 """ 106 def __init__(self, kernel,model_info, q_input):107 def __init__(self, model_info, q_input): 107 108 # type: (callable, ModelInfo, List[np.ndarray]) -> None 108 109 self.dtype = np.dtype('d') … … 110 111 self.q_input = q_input 111 112 self.res = np.empty(q_input.nq, q_input.dtype) 112 self.kernel = kernel113 113 self.dim = '2d' if q_input.is_2d else '1d' 114 114 … … 159 159 # Generate a closure which calls the form_volume if it exists. 160 160 form_volume = model_info.form_volume 161 self._volume = ((lambda: form_volume(*volume_args)) if form_volume 162 else(lambda: 1.0))161 self._volume = ((lambda: form_volume(*volume_args)) if form_volume else 162 (lambda: 1.0)) 163 163 164 164 def __call__(self, call_details, values, cutoff, magnetic): … … 261 261 any functions that are not already marked as vectorized. 262 262 """ 263 # Note: must call create_vector_Iq before create_vector_Iqxy 263 264 _create_vector_Iq(model_info) 264 _create_vector_Iqxy(model_info) # call create_vector_Iq() first265 _create_vector_Iqxy(model_info) 265 266 266 267 … … 280 281 model_info.Iq = vector_Iq 281 282 283 282 284 def _create_vector_Iqxy(model_info): 283 285 """ 284 286 Define Iqxy as a vector function if it exists, or default it from Iq(). 285 287 """ 286 Iq , Iqxy = model_info.Iq, model_info.Iqxy288 Iqxy = getattr(model_info, 'Iqxy', None) 287 289 if callable(Iqxy): 288 290 if not getattr(Iqxy, 'vectorized', False): … … 295 297 vector_Iqxy.vectorized = True 296 298 model_info.Iqxy = vector_Iqxy 297 el if callable(Iq):299 else: 298 300 #print("defaulting Iqxy") 299 301 # Iq is vectorized because create_vector_Iq was already called. 302 Iq = model_info.Iq 300 303 def default_Iqxy(qx, qy, *args): 301 304 """ -
sasmodels/modelinfo.py
r2d81cfe r108e70e 37 37 38 38 # assumptions about common parameters exist throughout the code, such as: 39 # (1) kernel functions Iq, Iqxy, form_volume, ... don't see them39 # (1) kernel functions Iq, Iqxy, Iqac, Iqabc, form_volume, ... don't see them 40 40 # (2) kernel drivers assume scale is par[0] and background is par[1] 41 41 # (3) mixture models drop the background on components and replace the scale … … 256 256 257 257 *type* indicates how the parameter will be used. "volume" parameters 258 will be used in all functions. "orientation" parameters will be used259 in *Iqxy* and *Imagnetic*. "magnetic* parameters will be used in260 *I magnetic* only. If *type* is the empty string, the parameter will258 will be used in all functions. "orientation" parameters are not passed, 259 but will be used to convert from *qx*, *qy* to *qa*, *qb*, *qc* in calls to 260 *Iqxy* and *Imagnetic*. If *type* is the empty string, the parameter will 261 261 be used in all of *Iq*, *Iqxy* and *Imagnetic*. "sld" parameters 262 262 can automatically be promoted to magnetic parameters, each of which … … 386 386 with vector parameter p sent as p[]. 387 387 388 * [removed] *iqxy_parameters* is the list of parameters to the Iqxy(qx, qy, ...)389 function, with vector parameter p sent as p[].390 391 388 * *form_volume_parameters* is the list of parameters to the form_volume(...) 392 389 function, with vector parameter p sent as p[]. … … 443 440 self.iq_parameters = [p for p in self.kernel_parameters 444 441 if p.type not in ('orientation', 'magnetic')] 445 # note: orientation no longer sent to Iqxy, so its the same as 446 #self.iqxy_parameters = [p for p in self.kernel_parameters 447 # if p.type != 'magnetic'] 442 self.orientation_parameters = [p for p in self.kernel_parameters 443 if p.type == 'orientation'] 448 444 self.form_volume_parameters = [p for p in self.kernel_parameters 449 445 if p.type == 'volume'] … … 490 486 if p.type != 'orientation': 491 487 raise TypeError("psi must be an orientation parameter") 488 elif p.type == 'orientation': 489 raise TypeError("only theta, phi and psi can be orientation parameters") 492 490 if theta >= 0 and phi >= 0: 491 last_par = len(self.kernel_parameters) - 1 493 492 if phi != theta+1: 494 493 raise TypeError("phi must follow theta") 495 494 if psi >= 0 and psi != phi+1: 496 495 raise TypeError("psi must follow phi") 496 #if (psi >= 0 and psi != last_par) or (psi < 0 and phi != last_par): 497 # raise TypeError("orientation parameters must appear at the " 498 # "end of the parameter table") 497 499 elif theta >= 0 or phi >= 0 or psi >= 0: 498 500 raise TypeError("oriented shapes must have both theta and phi and maybe psi") … … 715 717 716 718 719 #: Set of variables defined in the model that might contain C code 720 C_SYMBOLS = ['Imagnetic', 'Iq', 'Iqxy', 'Iqac', 'Iqabc', 'form_volume', 'c_code'] 721 717 722 def _find_source_lines(model_info, kernel_module): 718 723 # type: (ModelInfo, ModuleType) -> None … … 720 725 Identify the location of the C source inside the model definition file. 721 726 722 This code runs through the source of the kernel module looking for 723 lines that start with 'Iq', 'Iqxy' or 'form_volume'. Clearly there are 724 all sorts of reasons why this might not work (e.g., code commented out 725 in a triple-quoted line block, code built using string concatenation, 726 or code defined in the branch of an 'if' block), but it should work 727 properly in the 95% case, and getting the incorrect line number will 728 be harmless. 729 """ 730 # Check if we need line numbers at all 731 if callable(model_info.Iq): 732 return None 733 734 if (model_info.Iq is None 735 and model_info.Iqxy is None 736 and model_info.Imagnetic is None 737 and model_info.form_volume is None): 727 This code runs through the source of the kernel module looking for lines 728 that contain C code (because it is a c function definition). Clearly 729 there are all sorts of reasons why this might not work (e.g., code 730 commented out in a triple-quoted line block, code built using string 731 concatenation, code defined in the branch of an 'if' block, code imported 732 from another file), but it should work properly in the 95% case, and for 733 the remainder, getting the incorrect line number will merely be 734 inconvenient. 735 """ 736 # Only need line numbers if we are creating a C module and the C symbols 737 # are defined. 738 if (callable(model_info.Iq) 739 or not any(hasattr(model_info, s) for s in C_SYMBOLS)): 738 740 return 739 741 740 # find the defintion lines for the different code blocks742 # load the module source if we can 741 743 try: 742 744 source = inspect.getsource(kernel_module) 743 745 except IOError: 744 746 return 745 for k, v in enumerate(source.split('\n')): 746 if v.startswith('Imagnetic'): 747 model_info._Imagnetic_line = k+1 748 elif v.startswith('Iqxy'): 749 model_info._Iqxy_line = k+1 750 elif v.startswith('Iq'): 751 model_info._Iq_line = k+1 752 elif v.startswith('form_volume'): 753 model_info._form_volume_line = k+1 754 747 748 # look for symbol at the start of the line 749 for lineno, line in enumerate(source.split('\n')): 750 for name in C_SYMBOLS: 751 if line.startswith(name): 752 # Add 1 since some compilers complain about "#line 0" 753 model_info.lineno[name] = lineno + 1 754 break 755 755 756 756 def make_model_info(kernel_module): … … 761 761 Fill in default values for parts of the module that are not provided. 762 762 763 Note: vectorized Iq and Iq xyfunctions will be created for python763 Note: vectorized Iq and Iqac/Iqabc functions will be created for python 764 764 models when the model is first called, not when the model is loaded. 765 765 """ … … 790 790 info.profile_axes = getattr(kernel_module, 'profile_axes', ['x', 'y']) 791 791 info.source = getattr(kernel_module, 'source', []) 792 info.c_code = getattr(kernel_module, 'c_code', None) 792 793 # TODO: check the structure of the tests 793 794 info.tests = getattr(kernel_module, 'tests', []) … … 797 798 info.Iq = getattr(kernel_module, 'Iq', None) # type: ignore 798 799 info.Iqxy = getattr(kernel_module, 'Iqxy', None) # type: ignore 800 info.Iqac = getattr(kernel_module, 'Iqac', None) # type: ignore 801 info.Iqabc = getattr(kernel_module, 'Iqabc', None) # type: ignore 799 802 info.Imagnetic = getattr(kernel_module, 'Imagnetic', None) # type: ignore 800 803 info.profile = getattr(kernel_module, 'profile', None) # type: ignore … … 811 814 info.hidden = getattr(kernel_module, 'hidden', None) # type: ignore 812 815 816 if callable(info.Iq) and parameters.has_2d: 817 raise ValueError("oriented python models not supported") 818 819 info.lineno = {} 813 820 _find_source_lines(info, kernel_module) 814 821 … … 824 831 825 832 The structure should be mostly static, other than the delayed definition 826 of *Iq* and *Iqxy* if they need to be defined.833 of *Iq*, *Iqac* and *Iqabc* if they need to be defined. 827 834 """ 828 835 #: Full path to the file defining the kernel, if any. … … 906 913 structure_factor = None # type: bool 907 914 #: List of C source files used to define the model. The source files 908 #: should define the *Iq* function, and possibly *Iq xy*, though a default909 #: *Iqxy = Iq(sqrt(qx**2+qy**2)* will be created if no *Iqxy* is provided.910 #: Files containing the most basic functions must appear first in the list,911 #: followed by the files that use those functions. Form factors are912 #: indicated by providing a:attr:`ER` function.915 #: should define the *Iq* function, and possibly *Iqac* or *Iqabc* if the 916 #: model defines orientation parameters. Files containing the most basic 917 #: functions must appear first in the list, followed by the files that 918 #: use those functions. Form factors are indicated by providing 919 #: an :attr:`ER` function. 913 920 source = None # type: List[str] 914 921 #: The set of tests that must pass. The format of the tests is described … … 935 942 #: See :attr:`ER` for details on the parameters. 936 943 VR = None # type: Optional[Callable[[np.ndarray], Tuple[np.ndarray, np.ndarray]]] 944 #: Arbitrary C code containing supporting functions, etc., to be inserted 945 #: after everything in source. This can include Iq and Iqxy functions with 946 #: the full function signature, including all parameters. 947 c_code = None 937 948 #: Returns the form volume for python-based models. Form volume is needed 938 949 #: for volume normalization in the polydispersity integral. If no … … 955 966 #: include the decimal point. See :mod:`generate` for more details. 956 967 Iq = None # type: Union[None, str, Callable[[np.ndarray], np.ndarray]] 957 #: Returns *I(qx, qy, a, b, ...)*. The interface follows :attr:`Iq`. 958 Iqxy = None # type: Union[None, str, Callable[[np.ndarray], np.ndarray]] 968 #: Returns *I(qab, qc, a, b, ...)*. The interface follows :attr:`Iq`. 969 Iqac = None # type: Union[None, str, Callable[[np.ndarray], np.ndarray]] 970 #: Returns *I(qa, qb, qc, a, b, ...)*. The interface follows :attr:`Iq`. 971 Iqabc = None # type: Union[None, str, Callable[[np.ndarray], np.ndarray]] 959 972 #: Returns *I(qx, qy, a, b, ...)*. The interface follows :attr:`Iq`. 960 973 Imagnetic = None # type: Union[None, str, Callable[[np.ndarray], np.ndarray]] … … 972 985 #: Returns a random parameter set for the model 973 986 random = None # type: Optional[Callable[[], Dict[str, float]]] 974 975 # line numbers within the python file for bits of C source, if defined 976 # NB: some compilers fail with a "#line 0" directive, so default to 1. 977 _Imagnetic_line = 1 978 _Iqxy_line = 1 979 _Iq_line = 1 980 _form_volume_line = 1 981 987 #: Line numbers for symbols defining C code 988 lineno = None # type: Dict[str, int] 982 989 983 990 def __init__(self): -
sasmodels/models/_spherepy.py
ref07e95 r108e70e 88 88 Iq.vectorized = True # Iq accepts an array of q values 89 89 90 def Iqxy(qx, qy, sld, sld_solvent, radius):91 return Iq(sqrt(qx ** 2 + qy ** 2), sld, sld_solvent, radius)92 Iqxy.vectorized = True # Iqxy accepts arrays of qx, qy values93 94 90 def sesans(z, sld, sld_solvent, radius): 95 91 """ -
sasmodels/models/barbell.c
rbecded3 r108e70e 23 23 const double qab_r = radius_bell*qab; // Q*R*sin(theta) 24 24 double total = 0.0; 25 for (int i = 0; i < 76; i++){26 const double t = G auss76Z[i]*zm + zb;25 for (int i = 0; i < GAUSS_N; i++){ 26 const double t = GAUSS_Z[i]*zm + zb; 27 27 const double radical = 1.0 - t*t; 28 28 const double bj = sas_2J1x_x(qab_r*sqrt(radical)); 29 29 const double Fq = cos(m*t + b) * radical * bj; 30 total += G auss76Wt[i] * Fq;30 total += GAUSS_W[i] * Fq; 31 31 } 32 32 // translate dx in [-1,1] to dx in [lower,upper] … … 73 73 const double zb = M_PI_4; 74 74 double total = 0.0; 75 for (int i = 0; i < 76; i++){76 const double alpha= G auss76Z[i]*zm + zb;75 for (int i = 0; i < GAUSS_N; i++){ 76 const double alpha= GAUSS_Z[i]*zm + zb; 77 77 double sin_alpha, cos_alpha; // slots to hold sincos function output 78 78 SINCOS(alpha, sin_alpha, cos_alpha); 79 79 const double Aq = _fq(q*sin_alpha, q*cos_alpha, h, radius_bell, radius, half_length); 80 total += G auss76Wt[i] * Aq * Aq * sin_alpha;80 total += GAUSS_W[i] * Aq * Aq * sin_alpha; 81 81 } 82 82 // translate dx in [-1,1] to dx in [lower,upper] … … 90 90 91 91 static double 92 Iq xy(double qab, double qc,92 Iqac(double qab, double qc, 93 93 double sld, double solvent_sld, 94 94 double radius_bell, double radius, double length) -
sasmodels/models/bcc_paracrystal.c
rea60e08 r108e70e 81 81 82 82 double outer_sum = 0.0; 83 for(int i=0; i< 150; i++) {83 for(int i=0; i<GAUSS_N; i++) { 84 84 double inner_sum = 0.0; 85 const double theta = G auss150Z[i]*theta_m + theta_b;85 const double theta = GAUSS_Z[i]*theta_m + theta_b; 86 86 double sin_theta, cos_theta; 87 87 SINCOS(theta, sin_theta, cos_theta); 88 88 const double qc = q*cos_theta; 89 89 const double qab = q*sin_theta; 90 for(int j=0;j< 150;j++) {91 const double phi = G auss150Z[j]*phi_m + phi_b;90 for(int j=0;j<GAUSS_N;j++) { 91 const double phi = GAUSS_Z[j]*phi_m + phi_b; 92 92 double sin_phi, cos_phi; 93 93 SINCOS(phi, sin_phi, cos_phi); … … 95 95 const double qb = qab*sin_phi; 96 96 const double form = bcc_Zq(qa, qb, qc, dnn, d_factor); 97 inner_sum += G auss150Wt[j] * form;97 inner_sum += GAUSS_W[j] * form; 98 98 } 99 99 inner_sum *= phi_m; // sum(f(x)dx) = sum(f(x)) dx 100 outer_sum += G auss150Wt[i] * inner_sum * sin_theta;100 outer_sum += GAUSS_W[i] * inner_sum * sin_theta; 101 101 } 102 102 outer_sum *= theta_m; … … 107 107 108 108 109 static double Iq xy(double qa, double qb, double qc,109 static double Iqabc(double qa, double qb, double qc, 110 110 double dnn, double d_factor, double radius, 111 111 double sld, double solvent_sld) -
sasmodels/models/capped_cylinder.c
rbecded3 r108e70e 30 30 const double qab_r = radius_cap*qab; // Q*R*sin(theta) 31 31 double total = 0.0; 32 for (int i=0; i< 76 ;i++) {33 const double t = G auss76Z[i]*zm + zb;32 for (int i=0; i<GAUSS_N; i++) { 33 const double t = GAUSS_Z[i]*zm + zb; 34 34 const double radical = 1.0 - t*t; 35 35 const double bj = sas_2J1x_x(qab_r*sqrt(radical)); 36 36 const double Fq = cos(m*t + b) * radical * bj; 37 total += G auss76Wt[i] * Fq;37 total += GAUSS_W[i] * Fq; 38 38 } 39 39 // translate dx in [-1,1] to dx in [lower,upper] … … 95 95 const double zb = M_PI_4; 96 96 double total = 0.0; 97 for (int i=0; i< 76;i++) {98 const double theta = G auss76Z[i]*zm + zb;97 for (int i=0; i<GAUSS_N ;i++) { 98 const double theta = GAUSS_Z[i]*zm + zb; 99 99 double sin_theta, cos_theta; // slots to hold sincos function output 100 100 SINCOS(theta, sin_theta, cos_theta); … … 103 103 const double Aq = _fq(qab, qc, h, radius_cap, radius, half_length); 104 104 // scale by sin_theta for spherical coord integration 105 total += G auss76Wt[i] * Aq * Aq * sin_theta;105 total += GAUSS_W[i] * Aq * Aq * sin_theta; 106 106 } 107 107 // translate dx in [-1,1] to dx in [lower,upper] … … 115 115 116 116 static double 117 Iq xy(double qab, double qc,117 Iqac(double qab, double qc, 118 118 double sld, double solvent_sld, double radius, 119 119 double radius_cap, double length) -
sasmodels/models/core_shell_bicelle.c
rbecded3 r108e70e 52 52 53 53 double total = 0.0; 54 for(int i=0;i< N_POINTS_76;i++) {55 double theta = (G auss76Z[i] + 1.0)*uplim;54 for(int i=0;i<GAUSS_N;i++) { 55 double theta = (GAUSS_Z[i] + 1.0)*uplim; 56 56 double sin_theta, cos_theta; // slots to hold sincos function output 57 57 SINCOS(theta, sin_theta, cos_theta); 58 58 double fq = bicelle_kernel(q*sin_theta, q*cos_theta, radius, thick_radius, thick_face, 59 59 halflength, sld_core, sld_face, sld_rim, sld_solvent); 60 total += G auss76Wt[i]*fq*fq*sin_theta;60 total += GAUSS_W[i]*fq*fq*sin_theta; 61 61 } 62 62 … … 67 67 68 68 static double 69 Iq xy(double qab, double qc,69 Iqac(double qab, double qc, 70 70 double radius, 71 71 double thick_rim, -
sasmodels/models/core_shell_bicelle_elliptical.c
r82592da r108e70e 37 37 //initialize integral 38 38 double outer_sum = 0.0; 39 for(int i=0;i< 76;i++) {39 for(int i=0;i<GAUSS_N;i++) { 40 40 //setup inner integral over the ellipsoidal cross-section 41 41 //const double va = 0.0; 42 42 //const double vb = 1.0; 43 //const double cos_theta = ( G auss76Z[i]*(vb-va) + va + vb )/2.0;44 const double cos_theta = ( G auss76Z[i] + 1.0 )/2.0;43 //const double cos_theta = ( GAUSS_Z[i]*(vb-va) + va + vb )/2.0; 44 const double cos_theta = ( GAUSS_Z[i] + 1.0 )/2.0; 45 45 const double sin_theta = sqrt(1.0 - cos_theta*cos_theta); 46 46 const double qab = q*sin_theta; … … 49 49 const double si2 = sas_sinx_x((halfheight+thick_face)*qc); 50 50 double inner_sum=0.0; 51 for(int j=0;j< 76;j++) {51 for(int j=0;j<GAUSS_N;j++) { 52 52 //76 gauss points for the inner integral (WAS 20 points,so this may make unecessarily slow, but playing safe) 53 53 // inner integral limits 54 54 //const double vaj=0.0; 55 55 //const double vbj=M_PI; 56 //const double phi = ( G auss76Z[j]*(vbj-vaj) + vaj + vbj )/2.0;57 const double phi = ( G auss76Z[j] +1.0)*M_PI_2;56 //const double phi = ( GAUSS_Z[j]*(vbj-vaj) + vaj + vbj )/2.0; 57 const double phi = ( GAUSS_Z[j] +1.0)*M_PI_2; 58 58 const double rr = sqrt(r2A - r2B*cos(phi)); 59 59 const double be1 = sas_2J1x_x(rr*qab); … … 61 61 const double fq = dr1*si1*be1 + dr2*si2*be2 + dr3*si2*be1; 62 62 63 inner_sum += G auss76Wt[j] * fq * fq;63 inner_sum += GAUSS_W[j] * fq * fq; 64 64 } 65 65 //now calculate outer integral 66 outer_sum += G auss76Wt[i] * inner_sum;66 outer_sum += GAUSS_W[i] * inner_sum; 67 67 } 68 68 … … 71 71 72 72 static double 73 Iq xy(double qa, double qb, double qc,73 Iqabc(double qa, double qb, double qc, 74 74 double r_minor, 75 75 double x_core, -
sasmodels/models/core_shell_bicelle_elliptical_belt_rough.c
r82592da r108e70e 7 7 double length) 8 8 { 9 return M_PI*( (r_minor + thick_rim)*(r_minor*x_core + thick_rim)* length + 9 return M_PI*( (r_minor + thick_rim)*(r_minor*x_core + thick_rim)* length + 10 10 square(r_minor)*x_core*2.0*thick_face ); 11 11 } … … 47 47 //initialize integral 48 48 double outer_sum = 0.0; 49 for(int i=0;i< 76;i++) {49 for(int i=0;i<GAUSS_N;i++) { 50 50 //setup inner integral over the ellipsoidal cross-section 51 51 // since we generate these lots of times, why not store them somewhere? 52 //const double cos_alpha = ( G auss76Z[i]*(vb-va) + va + vb )/2.0;53 const double cos_alpha = ( G auss76Z[i] + 1.0 )/2.0;52 //const double cos_alpha = ( GAUSS_Z[i]*(vb-va) + va + vb )/2.0; 53 const double cos_alpha = ( GAUSS_Z[i] + 1.0 )/2.0; 54 54 const double sin_alpha = sqrt(1.0 - cos_alpha*cos_alpha); 55 55 double inner_sum=0; … … 58 58 si1 = sas_sinx_x(sinarg1); 59 59 si2 = sas_sinx_x(sinarg2); 60 for(int j=0;j< 76;j++) {60 for(int j=0;j<GAUSS_N;j++) { 61 61 //76 gauss points for the inner integral (WAS 20 points,so this may make unecessarily slow, but playing safe) 62 //const double beta = ( G auss76Z[j]*(vbj-vaj) + vaj + vbj )/2.0;63 const double beta = ( G auss76Z[j] +1.0)*M_PI_2;62 //const double beta = ( GAUSS_Z[j]*(vbj-vaj) + vaj + vbj )/2.0; 63 const double beta = ( GAUSS_Z[j] +1.0)*M_PI_2; 64 64 const double rr = sqrt(r2A - r2B*cos(beta)); 65 65 double besarg1 = q*rr*sin_alpha; … … 67 67 be1 = sas_2J1x_x(besarg1); 68 68 be2 = sas_2J1x_x(besarg2); 69 inner_sum += G auss76Wt[j] *square(dr1*si1*be1 +69 inner_sum += GAUSS_W[j] *square(dr1*si1*be1 + 70 70 dr2*si1*be2 + 71 71 dr3*si2*be1); 72 72 } 73 73 //now calculate outer integral 74 outer_sum += G auss76Wt[i] * inner_sum;74 outer_sum += GAUSS_W[i] * inner_sum; 75 75 } 76 76 … … 79 79 80 80 static double 81 Iq xy(double qa, double qb, double qc,81 Iqabc(double qa, double qb, double qc, 82 82 double r_minor, 83 83 double x_core, … … 114 114 return 1.0e-4 * Aq*exp(-0.5*(square(qa) + square(qb) + square(qc) )*square(sigma)); 115 115 } 116 -
sasmodels/models/core_shell_bicelle_elliptical_belt_rough.py
r110f69c r108e70e 149 149 ["sld_rim", "1e-6/Ang^2", 1, [-inf, inf], "sld", "Cylinder rim scattering length density"], 150 150 ["sld_solvent", "1e-6/Ang^2", 6, [-inf, inf], "sld", "Solvent scattering length density"], 151 ["sigma", "Ang", 0, [0, inf], "", "interfacial roughness"], 151 152 ["theta", "degrees", 90.0, [-360, 360], "orientation", "cylinder axis to beam angle"], 152 153 ["phi", "degrees", 0, [-360, 360], "orientation", "rotation about beam"], 153 154 ["psi", "degrees", 0, [-360, 360], "orientation", "rotation about cylinder axis"], 154 ["sigma", "Ang", 0, [0, inf], "", "interfacial roughness"]155 155 ] 156 156 -
sasmodels/models/core_shell_cylinder.c
rbecded3 r108e70e 30 30 const double shell_vd = form_volume(radius,thickness,length) * (shell_sld-solvent_sld); 31 31 double total = 0.0; 32 for (int i=0; i< 76;i++) {32 for (int i=0; i<GAUSS_N ;i++) { 33 33 // translate a point in [-1,1] to a point in [0, pi/2] 34 //const double theta = ( G auss76Z[i]*(upper-lower) + upper + lower )/2.0;34 //const double theta = ( GAUSS_Z[i]*(upper-lower) + upper + lower )/2.0; 35 35 double sin_theta, cos_theta; 36 const double theta = G auss76Z[i]*M_PI_4 + M_PI_4;36 const double theta = GAUSS_Z[i]*M_PI_4 + M_PI_4; 37 37 SINCOS(theta, sin_theta, cos_theta); 38 38 const double qab = q*sin_theta; … … 40 40 const double fq = _cyl(core_vd, core_r*qab, core_h*qc) 41 41 + _cyl(shell_vd, shell_r*qab, shell_h*qc); 42 total += G auss76Wt[i] * fq * fq * sin_theta;42 total += GAUSS_W[i] * fq * fq * sin_theta; 43 43 } 44 44 // translate dx in [-1,1] to dx in [lower,upper] … … 48 48 49 49 50 double Iq xy(double qab, double qc,50 double Iqac(double qab, double qc, 51 51 double core_sld, 52 52 double shell_sld, -
sasmodels/models/core_shell_ellipsoid.c
rbecded3 r108e70e 59 59 const double b = 0.5; 60 60 double total = 0.0; //initialize intergral 61 for(int i=0;i< 76;i++) {62 const double cos_theta = G auss76Z[i]*m + b;61 for(int i=0;i<GAUSS_N;i++) { 62 const double cos_theta = GAUSS_Z[i]*m + b; 63 63 const double sin_theta = sqrt(1.0 - cos_theta*cos_theta); 64 64 double fq = _cs_ellipsoid_kernel(q*sin_theta, q*cos_theta, … … 66 66 equat_shell, polar_shell, 67 67 sld_core_shell, sld_shell_solvent); 68 total += G auss76Wt[i] * fq * fq;68 total += GAUSS_W[i] * fq * fq; 69 69 } 70 70 total *= m; … … 75 75 76 76 static double 77 Iq xy(double qab, double qc,77 Iqac(double qab, double qc, 78 78 double radius_equat_core, 79 79 double x_core, -
sasmodels/models/core_shell_parallelepiped.c
r904cd9c re077231 1 // Set OVERLAPPING to 1 in order to fill in the edges of the box, with 2 // c endcaps and b overlapping a. With the proper choice of parameters, 3 // (setting rim slds to sld, core sld to solvent, rim thickness to thickness 4 // and subtracting 2*thickness from length, this should match the hollow 5 // rectangular prism.) Set it to 0 for the documented behaviour. 6 #define OVERLAPPING 0 1 7 static double 2 8 form_volume(double length_a, double length_b, double length_c, 3 9 double thick_rim_a, double thick_rim_b, double thick_rim_c) 4 10 { 5 //return length_a * length_b * length_c; 6 return length_a * length_b * length_c + 7 2.0 * thick_rim_a * length_b * length_c + 8 2.0 * thick_rim_b * length_a * length_c + 9 2.0 * thick_rim_c * length_a * length_b; 11 return 12 #if OVERLAPPING 13 // Hollow rectangular prism only includes the volume of the shell 14 // so uncomment the next line when comparing. Solid rectangular 15 // prism, or parallelepiped want filled cores, so comment when 16 // comparing. 17 //-length_a * length_b * length_c + 18 (length_a + 2.0*thick_rim_a) * 19 (length_b + 2.0*thick_rim_b) * 20 (length_c + 2.0*thick_rim_c); 21 #else 22 length_a * length_b * length_c + 23 2.0 * thick_rim_a * length_b * length_c + 24 2.0 * length_a * thick_rim_b * length_c + 25 2.0 * length_a * length_b * thick_rim_c; 26 #endif 10 27 } 11 28 … … 24 41 double thick_rim_c) 25 42 { 26 // Code converted from functions CSPPKernel and CSParallelepiped in libCylinder.c _scaled43 // Code converted from functions CSPPKernel and CSParallelepiped in libCylinder.c 27 44 // Did not understand the code completely, it should be rechecked (Miguel Gonzalez) 28 //Code is rewritten,the code is compliant with Diva Singhs thesis now (Dirk Honecker) 45 // Code is rewritten, the code is compliant with Diva Singh's thesis now (Dirk Honecker) 46 // Code rewritten; cross checked against hollow rectangular prism and realspace (PAK) 29 47 30 const double mu = 0.5 * q * length_b;48 const double half_q = 0.5*q; 31 49 32 //calculate volume before rescaling (in original code, but not used) 33 //double vol = form_volume(length_a, length_b, length_c, thick_rim_a, thick_rim_b, thick_rim_c); 34 //double vol = length_a * length_b * length_c + 35 // 2.0 * thick_rim_a * length_b * length_c + 36 // 2.0 * thick_rim_b * length_a * length_c + 37 // 2.0 * thick_rim_c * length_a * length_b; 50 const double tA = length_a + 2.0*thick_rim_a; 51 const double tB = length_b + 2.0*thick_rim_b; 52 const double tC = length_c + 2.0*thick_rim_c; 38 53 39 // Scale sides by B 40 const double a_scaled = length_a / length_b; 41 const double c_scaled = length_c / length_b; 42 43 double ta = a_scaled + 2.0*thick_rim_a/length_b; // incorrect ta = (a_scaled + 2.0*thick_rim_a)/length_b; 44 double tb = 1+ 2.0*thick_rim_b/length_b; // incorrect tb = (a_scaled + 2.0*thick_rim_b)/length_b; 45 double tc = c_scaled + 2.0*thick_rim_c/length_b; //not present 46 47 double Vin = length_a * length_b * length_c; 48 //double Vot = (length_a * length_b * length_c + 49 // 2.0 * thick_rim_a * length_b * length_c + 50 // 2.0 * length_a * thick_rim_b * length_c + 51 // 2.0 * length_a * length_b * thick_rim_c); 52 double V1 = (2.0 * thick_rim_a * length_b * length_c); // incorrect V1 (aa*bb*cc+2*ta*bb*cc) 53 double V2 = (2.0 * length_a * thick_rim_b * length_c); // incorrect V2(aa*bb*cc+2*aa*tb*cc) 54 double V3 = (2.0 * length_a * length_b * thick_rim_c); //not present 55 56 // Scale factors (note that drC is not used later) 57 const double drho0 = (core_sld-solvent_sld); 58 const double drhoA = (arim_sld-solvent_sld); 59 const double drhoB = (brim_sld-solvent_sld); 60 const double drhoC = (crim_sld-solvent_sld); // incorrect const double drC_Vot = (crim_sld-solvent_sld)*Vot; 61 62 63 // Precompute scale factors for combining cross terms from the shape 64 const double scale23 = drhoA*V1; 65 const double scale14 = drhoB*V2; 66 const double scale24 = drhoC*V3; 67 const double scale11 = drho0*Vin; 68 const double scale12 = drho0*Vin - scale23 - scale14 - scale24; 54 // Scale factors 55 const double dr0 = (core_sld-solvent_sld); 56 const double drA = (arim_sld-solvent_sld); 57 const double drB = (brim_sld-solvent_sld); 58 const double drC = (crim_sld-solvent_sld); 69 59 70 60 // outer integral (with gauss points), integration limits = 0, 1 71 double outer_total = 0; //initialize integral 61 double outer_sum = 0; //initialize integral 62 for( int i=0; i<GAUSS_N; i++) { 63 const double cos_alpha = 0.5 * ( GAUSS_Z[i] + 1.0 ); 64 const double mu = half_q * sqrt(1.0-cos_alpha*cos_alpha); 72 65 73 for( int i=0; i<76; i++) { 74 double sigma = 0.5 * ( Gauss76Z[i] + 1.0 ); 75 double mu_proj = mu * sqrt(1.0-sigma*sigma); 66 // inner integral (with gauss points), integration limits = 0, pi/2 67 const double siC = length_c * sas_sinx_x(length_c * cos_alpha * half_q); 68 const double siCt = tC * sas_sinx_x(tC * cos_alpha * half_q); 69 double inner_sum = 0.0; 70 for(int j=0; j<GAUSS_N; j++) { 71 const double beta = 0.5 * ( GAUSS_Z[j] + 1.0 ); 72 double sin_beta, cos_beta; 73 SINCOS(M_PI_2*beta, sin_beta, cos_beta); 74 const double siA = length_a * sas_sinx_x(length_a * mu * sin_beta); 75 const double siB = length_b * sas_sinx_x(length_b * mu * cos_beta); 76 const double siAt = tA * sas_sinx_x(tA * mu * sin_beta); 77 const double siBt = tB * sas_sinx_x(tB * mu * cos_beta); 76 78 77 // inner integral (with gauss points), integration limits = 0, 1 78 double inner_total = 0.0;79 double inner_total_crim = 0.0;80 for(int j=0; j<76; j++) {81 const double uu = 0.5 * ( Gauss76Z[j] + 1.0);82 double sin_uu, cos_uu; 83 SINCOS(M_PI_2*uu, sin_uu, cos_uu);84 const double si1 = sas_sinx_x(mu_proj * sin_uu * a_scaled);85 const double si2 = sas_sinx_x(mu_proj * cos_uu );86 const double si3 = sas_sinx_x(mu_proj * sin_uu * ta);87 const double si4 = sas_sinx_x(mu_proj * cos_uu * tb); 79 #if OVERLAPPING 80 const double f = dr0*siA*siB*siC 81 + drA*(siAt-siA)*siB*siC 82 + drB*siAt*(siBt-siB)*siC 83 + drC*siAt*siBt*(siCt-siC); 84 #else 85 const double f = dr0*siA*siB*siC 86 + drA*(siAt-siA)*siB*siC 87 + drB*siA*(siBt-siB)*siC 88 + drC*siA*siB*(siCt-siC); 89 #endif 88 90 89 // Expression in libCylinder.c (neither drC nor Vot are used) 90 const double form = scale12*si1*si2 + scale23*si2*si3 + scale14*si1*si4; 91 const double form_crim = scale11*si1*si2; 92 93 // correct FF : sum of square of phase factors 94 inner_total += Gauss76Wt[j] * form * form; 95 inner_total_crim += Gauss76Wt[j] * form_crim * form_crim; 91 inner_sum += GAUSS_W[j] * f * f; 96 92 } 97 inner_total *= 0.5; 98 inner_total_crim *= 0.5; 93 inner_sum *= 0.5; 99 94 // now sum up the outer integral 100 const double si = sas_sinx_x(mu * c_scaled * sigma); 101 const double si_crim = sas_sinx_x(mu * tc * sigma); 102 outer_total += Gauss76Wt[i] * (inner_total * si * si + inner_total_crim * si_crim * si_crim); 95 outer_sum += GAUSS_W[i] * inner_sum; 103 96 } 104 outer_ total*= 0.5;97 outer_sum *= 0.5; 105 98 106 99 //convert from [1e-12 A-1] to [cm-1] 107 return 1.0e-4 * outer_ total;100 return 1.0e-4 * outer_sum; 108 101 } 109 102 110 103 static double 111 Iq xy(double qa, double qb, double qc,104 Iqabc(double qa, double qb, double qc, 112 105 double core_sld, 113 106 double arim_sld, … … 128 121 const double drC = crim_sld-solvent_sld; 129 122 130 double Vin = length_a * length_b * length_c;131 double V1 = 2.0 * thick_rim_a * length_b * length_c; // incorrect V1(aa*bb*cc+2*ta*bb*cc)132 double V2 = 2.0 * length_a * thick_rim_b * length_c; // incorrect V2(aa*bb*cc+2*aa*tb*cc)133 double V3 = 2.0 * length_a * length_b * thick_rim_c;134 // As for the 1D case, Vot is not used135 //double Vot = (length_a * length_b * length_c +136 // 2.0 * thick_rim_a * length_b * length_c +137 // 2.0 * length_a * thick_rim_b * length_c +138 // 2.0 * length_a * length_b * thick_rim_c);123 const double tA = length_a + 2.0*thick_rim_a; 124 const double tB = length_b + 2.0*thick_rim_b; 125 const double tC = length_c + 2.0*thick_rim_c; 126 const double siA = length_a*sas_sinx_x(0.5*length_a*qa); 127 const double siB = length_b*sas_sinx_x(0.5*length_b*qb); 128 const double siC = length_c*sas_sinx_x(0.5*length_c*qc); 129 const double siAt = tA*sas_sinx_x(0.5*tA*qa); 130 const double siBt = tB*sas_sinx_x(0.5*tB*qb); 131 const double siCt = tC*sas_sinx_x(0.5*tC*qc); 139 132 140 // The definitions of ta, tb, tc are not the same as in the 1D case because there is no 141 // the scaling by B. 142 double ta = length_a + 2.0*thick_rim_a; 143 double tb = length_b + 2.0*thick_rim_b; 144 double tc = length_c + 2.0*thick_rim_c; 145 //handle arg=0 separately, as sin(t)/t -> 1 as t->0 146 double siA = sas_sinx_x(0.5*length_a*qa); 147 double siB = sas_sinx_x(0.5*length_b*qb); 148 double siC = sas_sinx_x(0.5*length_c*qc); 149 double siAt = sas_sinx_x(0.5*ta*qa); 150 double siBt = sas_sinx_x(0.5*tb*qb); 151 double siCt = sas_sinx_x(0.5*tc*qc); 152 153 154 // f uses Vin, V1, V2, and V3 and it seems to have more sense than the value computed 155 // in the 1D code, but should be checked! 156 double f = ( dr0*siA*siB*siC*Vin 157 + drA*(siAt-siA)*siB*siC*V1 158 + drB*siA*(siBt-siB)*siC*V2 159 + drC*siA*siB*(siCt-siC)*V3); 133 #if OVERLAPPING 134 const double f = dr0*siA*siB*siC 135 + drA*(siAt-siA)*siB*siC 136 + drB*siAt*(siBt-siB)*siC 137 + drC*siAt*siBt*(siCt-siC); 138 #else 139 const double f = dr0*siA*siB*siC 140 + drA*(siAt-siA)*siB*siC 141 + drB*siA*(siBt-siB)*siC 142 + drC*siA*siB*(siCt-siC); 143 #endif 160 144 161 145 return 1.0e-4 * f * f; -
sasmodels/models/core_shell_parallelepiped.py
r2d81cfe r97be877 5 5 Calculates the form factor for a rectangular solid with a core-shell structure. 6 6 The thickness and the scattering length density of the shell or 7 "rim" can be different on each (pair) of faces. However at this time the 1D 8 calculation does **NOT** actually calculate a c face rim despite the presence 9 of the parameter. Some other aspects of the 1D calculation may be wrong. 10 11 .. note:: 12 This model was originally ported from NIST IGOR macros. However, it is not 13 yet fully understood by the SasView developers and is currently under review. 7 "rim" can be different on each (pair) of faces. 14 8 15 9 The form factor is normalized by the particle volume $V$ such that … … 21 15 where $\langle \ldots \rangle$ is an average over all possible orientations 22 16 of the rectangular solid. 23 24 17 25 18 The function calculated is the form factor of the rectangular solid below. … … 41 34 V = ABC + 2t_ABC + 2t_BAC + 2t_CAB 42 35 43 **meaning that there are "gaps" at the corners of the solid.** Again note that 44 $t_C = 0$ currently. 36 **meaning that there are "gaps" at the corners of the solid.** 45 37 46 38 The intensity calculated follows the :ref:`parallelepiped` model, with the 47 39 core-shell intensity being calculated as the square of the sum of the 48 amplitudes of the core and shell, in the same manner as a core-shell model. 49 50 .. math:: 51 52 F_{a}(Q,\alpha,\beta)= 53 \left[\frac{\sin(\tfrac{1}{2}Q(L_A+2t_A)\sin\alpha \sin\beta) 54 }{\tfrac{1}{2}Q(L_A+2t_A)\sin\alpha\sin\beta} 55 - \frac{\sin(\tfrac{1}{2}QL_A\sin\alpha \sin\beta) 56 }{\tfrac{1}{2}QL_A\sin\alpha \sin\beta} \right] 57 \left[\frac{\sin(\tfrac{1}{2}QL_B\sin\alpha \sin\beta) 58 }{\tfrac{1}{2}QL_B\sin\alpha \sin\beta} \right] 59 \left[\frac{\sin(\tfrac{1}{2}QL_C\sin\alpha \sin\beta) 60 }{\tfrac{1}{2}QL_C\sin\alpha \sin\beta} \right] 61 62 .. note:: 63 64 Why does t_B not appear in the above equation? 65 For the calculation of the form factor to be valid, the sides of the solid 66 MUST (perhaps not any more?) be chosen such that** $A < B < C$. 67 If this inequality is not satisfied, the model will not report an error, 68 but the calculation will not be correct and thus the result wrong. 40 amplitudes of the core and the slabs on the edges. 41 42 the scattering amplitude is computed for a particular orientation of the 43 core-shell parallelepiped with respect to the scattering vector and then 44 averaged over all possible orientations, where $\alpha$ is the angle between 45 the $z$ axis and the $C$ axis of the parallelepiped, $\beta$ is 46 the angle between projection of the particle in the $xy$ detector plane 47 and the $y$ axis. 48 49 .. math:: 50 51 F(Q) 52 &= (\rho_\text{core}-\rho_\text{solvent}) 53 S(Q_A, A) S(Q_B, B) S(Q_C, C) \\ 54 &+ (\rho_\text{A}-\rho_\text{solvent}) 55 \left[S(Q_A, A+2t_A) - S(Q_A, Q)\right] S(Q_B, B) S(Q_C, C) \\ 56 &+ (\rho_\text{B}-\rho_\text{solvent}) 57 S(Q_A, A) \left[S(Q_B, B+2t_B) - S(Q_B, B)\right] S(Q_C, C) \\ 58 &+ (\rho_\text{C}-\rho_\text{solvent}) 59 S(Q_A, A) S(Q_B, B) \left[S(Q_C, C+2t_C) - S(Q_C, C)\right] 60 61 with 62 63 .. math:: 64 65 S(Q, L) = L \frac{\sin \tfrac{1}{2} Q L}{\tfrac{1}{2} Q L} 66 67 and 68 69 .. math:: 70 71 Q_A &= \sin\alpha \sin\beta \\ 72 Q_B &= \sin\alpha \cos\beta \\ 73 Q_C &= \cos\alpha 74 75 76 where $\rho_\text{core}$, $\rho_\text{A}$, $\rho_\text{B}$ and $\rho_\text{C}$ 77 are the scattering length of the parallelepiped core, and the rectangular 78 slabs of thickness $t_A$, $t_B$ and $t_C$, respectively. $\rho_\text{solvent}$ 79 is the scattering length of the solvent. 69 80 70 81 FITTING NOTES 82 ~~~~~~~~~~~~~ 83 71 84 If the scale is set equal to the particle volume fraction, $\phi$, the returned 72 value is the scattered intensity per unit volume, $I(q) = \phi P(q)$. 73 However, **no interparticle interference effects are included in this 74 calculation.** 85 value is the scattered intensity per unit volume, $I(q) = \phi P(q)$. However, 86 **no interparticle interference effects are included in this calculation.** 75 87 76 88 There are many parameters in this model. Hold as many fixed as possible with 77 89 known values, or you will certainly end up at a solution that is unphysical. 78 90 79 Constraints must be applied during fitting to ensure that the inequality80 $A < B < C$ is not violated. The calculation will not report an error,81 but the results will not be correct.82 83 91 The returned value is in units of |cm^-1|, on absolute scale. 84 92 85 93 NB: The 2nd virial coefficient of the core_shell_parallelepiped is calculated 86 94 based on the the averaged effective radius $(=\sqrt{(A+2t_A)(B+2t_B)/\pi})$ 87 and length $(C+2t_C)$ values, after appropriately 88 sorting the three dimensions to give an oblate or prolate particle, to give an 89 effective radius,for $S(Q)$ when $P(Q) * S(Q)$ is applied.95 and length $(C+2t_C)$ values, after appropriately sorting the three dimensions 96 to give an oblate or prolate particle, to give an effective radius, 97 for $S(Q)$ when $P(Q) * S(Q)$ is applied. 90 98 91 99 For 2d data the orientation of the particle is required, described using 92 angles $\theta$, $\phi$ and $\Psi$ as in the diagrams below, for further details93 of the calculation and angular dispersions see :ref:`orientation`.100 angles $\theta$, $\phi$ and $\Psi$ as in the diagrams below, for further 101 details of the calculation and angular dispersions see :ref:`orientation`. 94 102 The angle $\Psi$ is the rotational angle around the *long_c* axis. For example, 95 103 $\Psi = 0$ when the *short_b* axis is parallel to the *x*-axis of the detector. 104 105 For 2d, constraints must be applied during fitting to ensure that the 106 inequality $A < B < C$ is not violated, and hence the correct definition 107 of angles is preserved. The calculation will not report an error, 108 but the results may be not correct. 96 109 97 110 .. figure:: img/parallelepiped_angle_definition.png … … 114 127 Equations (1), (13-14). (in German) 115 128 .. [#] D Singh (2009). *Small angle scattering studies of self assembly in 116 lipid mixtures*, John 's Hopkins University Thesis (2009) 223-225. `Available129 lipid mixtures*, Johns Hopkins University Thesis (2009) 223-225. `Available 117 130 from Proquest <http://search.proquest.com/docview/304915826?accountid 118 131 =26379>`_ … … 123 136 * **Author:** NIST IGOR/DANSE **Date:** pre 2010 124 137 * **Converted to sasmodels by:** Miguel Gonzales **Date:** February 26, 2016 125 * **Last Modified by:** Wojciech Potrzebowski **Date:** January 11, 2017 126 * **Currently Under review by:** Paul Butler 138 * **Last Modified by:** Paul Kienzle **Date:** October 17, 2017 139 * Cross-checked against hollow rectangular prism and rectangular prism for 140 equal thickness overlapping sides, and by Monte Carlo sampling of points 141 within the shape for non-uniform, non-overlapping sides. 127 142 """ 128 143 … … 175 190 Return equivalent radius (ER) 176 191 """ 177 178 # surface average radius (rough approximation) 179 surf_rad = sqrt((length_a + 2.0*thick_rim_a) * (length_b + 2.0*thick_rim_b) / pi) 180 181 height = length_c + 2.0*thick_rim_c 182 183 ddd = 0.75 * surf_rad * (2 * surf_rad * height + (height + surf_rad) * (height + pi * surf_rad)) 184 return 0.5 * (ddd) ** (1. / 3.) 192 from .parallelepiped import ER as ER_p 193 194 a = length_a + 2*thick_rim_a 195 b = length_b + 2*thick_rim_b 196 c = length_c + 2*thick_rim_c 197 return ER_p(a, b, c) 185 198 186 199 # VR defaults to 1.0 … … 216 229 psi_pd=10, psi_pd_n=1) 217 230 218 # rkh 7/4/17 add random unit test for 2d, note make all params different, 2d values not tested against other codes or models 231 # rkh 7/4/17 add random unit test for 2d, note make all params different, 232 # 2d values not tested against other codes or models 219 233 if 0: # pak: model rewrite; need to update tests 220 234 qx, qy = 0.2 * cos(pi/6.), 0.2 * sin(pi/6.) -
sasmodels/models/cylinder.c
rbecded3 r108e70e 21 21 22 22 double total = 0.0; 23 for (int i=0; i< 76;i++) {24 const double theta = G auss76Z[i]*zm + zb;23 for (int i=0; i<GAUSS_N ;i++) { 24 const double theta = GAUSS_Z[i]*zm + zb; 25 25 double sin_theta, cos_theta; // slots to hold sincos function output 26 26 // theta (theta,phi) the projection of the cylinder on the detector plane 27 27 SINCOS(theta , sin_theta, cos_theta); 28 28 const double form = fq(q*sin_theta, q*cos_theta, radius, length); 29 total += G auss76Wt[i] * form * form * sin_theta;29 total += GAUSS_W[i] * form * form * sin_theta; 30 30 } 31 31 // translate dx in [-1,1] to dx in [lower,upper] … … 45 45 46 46 static double 47 Iq xy(double qab, double qc,47 Iqac(double qab, double qc, 48 48 double sld, 49 49 double solvent_sld, -
sasmodels/models/ellipsoid.c
rbecded3 r108e70e 22 22 23 23 // translate a point in [-1,1] to a point in [0, 1] 24 // const double u = G auss76Z[i]*(upper-lower)/2 + (upper+lower)/2;24 // const double u = GAUSS_Z[i]*(upper-lower)/2 + (upper+lower)/2; 25 25 const double zm = 0.5; 26 26 const double zb = 0.5; 27 27 double total = 0.0; 28 for (int i=0;i< 76;i++) {29 const double u = G auss76Z[i]*zm + zb;28 for (int i=0;i<GAUSS_N;i++) { 29 const double u = GAUSS_Z[i]*zm + zb; 30 30 const double r = radius_equatorial*sqrt(1.0 + u*u*v_square_minus_one); 31 31 const double f = sas_3j1x_x(q*r); 32 total += G auss76Wt[i] * f * f;32 total += GAUSS_W[i] * f * f; 33 33 } 34 34 // translate dx in [-1,1] to dx in [lower,upper] … … 39 39 40 40 static double 41 Iq xy(double qab, double qc,41 Iqac(double qab, double qc, 42 42 double sld, 43 43 double sld_solvent, -
sasmodels/models/elliptical_cylinder.c
r82592da r108e70e 22 22 //initialize integral 23 23 double outer_sum = 0.0; 24 for(int i=0;i< 76;i++) {24 for(int i=0;i<GAUSS_N;i++) { 25 25 //setup inner integral over the ellipsoidal cross-section 26 const double cos_val = ( G auss76Z[i]*(vb-va) + va + vb )/2.0;26 const double cos_val = ( GAUSS_Z[i]*(vb-va) + va + vb )/2.0; 27 27 const double sin_val = sqrt(1.0 - cos_val*cos_val); 28 28 //const double arg = radius_minor*sin_val; 29 29 double inner_sum=0; 30 for(int j=0;j<76;j++) { 31 //20 gauss points for the inner integral, increase to 76, RKH 6Nov2017 32 const double theta = ( Gauss76Z[j]*(vbj-vaj) + vaj + vbj )/2.0; 30 for(int j=0;j<GAUSS_N;j++) { 31 const double theta = ( GAUSS_Z[j]*(vbj-vaj) + vaj + vbj )/2.0; 33 32 const double r = sin_val*sqrt(rA - rB*cos(theta)); 34 33 const double be = sas_2J1x_x(q*r); 35 inner_sum += G auss76Wt[j] * be * be;34 inner_sum += GAUSS_W[j] * be * be; 36 35 } 37 36 //now calculate the value of the inner integral … … 40 39 //now calculate outer integral 41 40 const double si = sas_sinx_x(q*0.5*length*cos_val); 42 outer_sum += G auss76Wt[i] * inner_sum * si * si;41 outer_sum += GAUSS_W[i] * inner_sum * si * si; 43 42 } 44 43 outer_sum *= 0.5*(vb-va); … … 55 54 56 55 static double 57 Iq xy(double qa, double qb, double qc,56 Iqabc(double qa, double qb, double qc, 58 57 double radius_minor, double r_ratio, double length, 59 58 double sld, double solvent_sld) -
sasmodels/models/elliptical_cylinder.py
r2d81cfe ra261a83 121 121 # pylint: enable=bad-whitespace, line-too-long 122 122 123 source = ["lib/polevl.c", "lib/sas_J1.c", "lib/gauss76.c", "lib/gauss20.c", 124 "elliptical_cylinder.c"] 123 source = ["lib/polevl.c", "lib/sas_J1.c", "lib/gauss76.c", "elliptical_cylinder.c"] 125 124 126 125 demo = dict(scale=1, background=0, radius_minor=100, axis_ratio=1.5, length=400.0, -
sasmodels/models/fcc_paracrystal.c
rf728001 r108e70e 53 53 54 54 double outer_sum = 0.0; 55 for(int i=0; i< 150; i++) {55 for(int i=0; i<GAUSS_N; i++) { 56 56 double inner_sum = 0.0; 57 const double theta = G auss150Z[i]*theta_m + theta_b;57 const double theta = GAUSS_Z[i]*theta_m + theta_b; 58 58 double sin_theta, cos_theta; 59 59 SINCOS(theta, sin_theta, cos_theta); 60 60 const double qc = q*cos_theta; 61 61 const double qab = q*sin_theta; 62 for(int j=0;j< 150;j++) {63 const double phi = G auss150Z[j]*phi_m + phi_b;62 for(int j=0;j<GAUSS_N;j++) { 63 const double phi = GAUSS_Z[j]*phi_m + phi_b; 64 64 double sin_phi, cos_phi; 65 65 SINCOS(phi, sin_phi, cos_phi); … … 67 67 const double qb = qab*sin_phi; 68 68 const double form = fcc_Zq(qa, qb, qc, dnn, d_factor); 69 inner_sum += G auss150Wt[j] * form;69 inner_sum += GAUSS_W[j] * form; 70 70 } 71 71 inner_sum *= phi_m; // sum(f(x)dx) = sum(f(x)) dx 72 outer_sum += G auss150Wt[i] * inner_sum * sin_theta;72 outer_sum += GAUSS_W[i] * inner_sum * sin_theta; 73 73 } 74 74 outer_sum *= theta_m; … … 80 80 81 81 82 static double Iq xy(double qa, double qb, double qc,82 static double Iqabc(double qa, double qb, double qc, 83 83 double dnn, double d_factor, double radius, 84 84 double sld, double solvent_sld) -
sasmodels/models/flexible_cylinder_elliptical.c
r592343f r74768cb 17 17 double sum=0.0; 18 18 19 for(int i=0;i< N_POINTS_76;i++) {20 const double zi = ( G auss76Z[i] + 1.0 )*M_PI_4;19 for(int i=0;i<GAUSS_N;i++) { 20 const double zi = ( GAUSS_Z[i] + 1.0 )*M_PI_4; 21 21 double sn, cn; 22 22 SINCOS(zi, sn, cn); 23 23 const double arg = q*sqrt(a*a*sn*sn + b*b*cn*cn); 24 24 const double yyy = sas_2J1x_x(arg); 25 sum += G auss76Wt[i] * yyy * yyy;25 sum += GAUSS_W[i] * yyy * yyy; 26 26 } 27 27 sum *= 0.5; -
sasmodels/models/hollow_cylinder.c
rbecded3 r108e70e 38 38 39 39 double summ = 0.0; //initialize intergral 40 for (int i=0;i< 76;i++) {41 const double cos_theta = 0.5*( G auss76Z[i] * (upper-lower) + lower + upper );40 for (int i=0;i<GAUSS_N;i++) { 41 const double cos_theta = 0.5*( GAUSS_Z[i] * (upper-lower) + lower + upper ); 42 42 const double sin_theta = sqrt(1.0 - cos_theta*cos_theta); 43 43 const double form = _fq(q*sin_theta, q*cos_theta, 44 44 radius, thickness, length); 45 summ += G auss76Wt[i] * form * form;45 summ += GAUSS_W[i] * form * form; 46 46 } 47 47 … … 52 52 53 53 static double 54 Iq xy(double qab, double qc,54 Iqac(double qab, double qc, 55 55 double radius, double thickness, double length, 56 56 double sld, double solvent_sld) -
sasmodels/models/hollow_rectangular_prism.c
r1e7b0db0 r108e70e 1 1 double form_volume(double length_a, double b2a_ratio, double c2a_ratio, double thickness); 2 double Iq(double q, double sld, double solvent_sld, double length_a, 2 double Iq(double q, double sld, double solvent_sld, double length_a, 3 3 double b2a_ratio, double c2a_ratio, double thickness); 4 4 … … 37 37 const double v2a = 0.0; 38 38 const double v2b = M_PI_2; //phi integration limits 39 39 40 40 double outer_sum = 0.0; 41 for(int i=0; i< 76; i++) {41 for(int i=0; i<GAUSS_N; i++) { 42 42 43 const double theta = 0.5 * ( G auss76Z[i]*(v1b-v1a) + v1a + v1b );43 const double theta = 0.5 * ( GAUSS_Z[i]*(v1b-v1a) + v1a + v1b ); 44 44 double sin_theta, cos_theta; 45 45 SINCOS(theta, sin_theta, cos_theta); … … 49 49 50 50 double inner_sum = 0.0; 51 for(int j=0; j< 76; j++) {51 for(int j=0; j<GAUSS_N; j++) { 52 52 53 const double phi = 0.5 * ( G auss76Z[j]*(v2b-v2a) + v2a + v2b );53 const double phi = 0.5 * ( GAUSS_Z[j]*(v2b-v2a) + v2a + v2b ); 54 54 double sin_phi, cos_phi; 55 55 SINCOS(phi, sin_phi, cos_phi); … … 66 66 const double AP2 = vol_core * termA2 * termB2 * termC2; 67 67 68 inner_sum += G auss76Wt[j] * square(AP1-AP2);68 inner_sum += GAUSS_W[j] * square(AP1-AP2); 69 69 } 70 70 inner_sum *= 0.5 * (v2b-v2a); 71 71 72 outer_sum += G auss76Wt[i] * inner_sum * sin(theta);72 outer_sum += GAUSS_W[i] * inner_sum * sin(theta); 73 73 } 74 74 outer_sum *= 0.5*(v1b-v1a); … … 84 84 return 1.0e-4 * delrho * delrho * form; 85 85 } 86 87 double Iqabc(double qa, double qb, double qc, 88 double sld, 89 double solvent_sld, 90 double length_a, 91 double b2a_ratio, 92 double c2a_ratio, 93 double thickness) 94 { 95 const double length_b = length_a * b2a_ratio; 96 const double length_c = length_a * c2a_ratio; 97 const double a_half = 0.5 * length_a; 98 const double b_half = 0.5 * length_b; 99 const double c_half = 0.5 * length_c; 100 const double vol_total = length_a * length_b * length_c; 101 const double vol_core = 8.0 * (a_half-thickness) * (b_half-thickness) * (c_half-thickness); 102 103 // Amplitude AP from eqn. (13) 104 105 const double termA1 = sas_sinx_x(qa * a_half); 106 const double termA2 = sas_sinx_x(qa * (a_half-thickness)); 107 108 const double termB1 = sas_sinx_x(qb * b_half); 109 const double termB2 = sas_sinx_x(qb * (b_half-thickness)); 110 111 const double termC1 = sas_sinx_x(qc * c_half); 112 const double termC2 = sas_sinx_x(qc * (c_half-thickness)); 113 114 const double AP1 = vol_total * termA1 * termB1 * termC1; 115 const double AP2 = vol_core * termA2 * termB2 * termC2; 116 117 // Multiply by contrast^2. Factor corresponding to volume^2 cancels with previous normalization. 118 const double delrho = sld - solvent_sld; 119 120 // Convert from [1e-12 A-1] to [cm-1] 121 return 1.0e-4 * square(delrho * (AP1-AP2)); 122 } -
sasmodels/models/hollow_rectangular_prism.py
r2d81cfe r0e55afe 5 5 This model provides the form factor, $P(q)$, for a hollow rectangular 6 6 parallelepiped with a wall of thickness $\Delta$. 7 It computes only the 1D scattering, not the 2D. 7 8 8 9 9 Definition … … 66 66 (which is unitless). 67 67 68 **The 2D scattering intensity is not computed by this model.** 68 For 2d data the orientation of the particle is required, described using 69 angles $\theta$, $\phi$ and $\Psi$ as in the diagrams below, for further details 70 of the calculation and angular dispersions see :ref:`orientation` . 71 The angle $\Psi$ is the rotational angle around the long *C* axis. For example, 72 $\Psi = 0$ when the *B* axis is parallel to the *x*-axis of the detector. 73 74 For 2d, constraints must be applied during fitting to ensure that the inequality 75 $A < B < C$ is not violated, and hence the correct definition of angles is preserved. The calculation will not report an error, 76 but the results may be not correct. 77 78 .. figure:: img/parallelepiped_angle_definition.png 79 80 Definition of the angles for oriented hollow rectangular prism. 81 Note that rotation $\theta$, initially in the $xz$ plane, is carried out first, then 82 rotation $\phi$ about the $z$ axis, finally rotation $\Psi$ is now around the axis of the prism. 83 The neutron or X-ray beam is along the $z$ axis. 84 85 .. figure:: img/parallelepiped_angle_projection.png 86 87 Examples of the angles for oriented hollow rectangular prisms against the 88 detector plane. 69 89 70 90 … … 113 133 ["thickness", "Ang", 1, [0, inf], "volume", 114 134 "Thickness of parallelepiped"], 135 ["theta", "degrees", 0, [-360, 360], "orientation", 136 "c axis to beam angle"], 137 ["phi", "degrees", 0, [-360, 360], "orientation", 138 "rotation about beam"], 139 ["psi", "degrees", 0, [-360, 360], "orientation", 140 "rotation about c axis"], 115 141 ] 116 142 -
sasmodels/models/hollow_rectangular_prism_thin_walls.c
rab2aea8 r74768cb 1 1 double form_volume(double length_a, double b2a_ratio, double c2a_ratio); 2 double Iq(double q, double sld, double solvent_sld, double length_a, 2 double Iq(double q, double sld, double solvent_sld, double length_a, 3 3 double b2a_ratio, double c2a_ratio); 4 4 … … 29 29 const double v2a = 0.0; 30 30 const double v2b = M_PI_2; //phi integration limits 31 31 32 32 double outer_sum = 0.0; 33 for(int i=0; i< 76; i++) {34 const double theta = 0.5 * ( G auss76Z[i]*(v1b-v1a) + v1a + v1b );33 for(int i=0; i<GAUSS_N; i++) { 34 const double theta = 0.5 * ( GAUSS_Z[i]*(v1b-v1a) + v1a + v1b ); 35 35 36 36 double sin_theta, cos_theta; … … 44 44 45 45 double inner_sum = 0.0; 46 for(int j=0; j< 76; j++) {47 const double phi = 0.5 * ( G auss76Z[j]*(v2b-v2a) + v2a + v2b );46 for(int j=0; j<GAUSS_N; j++) { 47 const double phi = 0.5 * ( GAUSS_Z[j]*(v2b-v2a) + v2a + v2b ); 48 48 49 49 double sin_phi, cos_phi; … … 62 62 * ( cos_a*sin_b/cos_phi + cos_b*sin_a/sin_phi ); 63 63 64 inner_sum += G auss76Wt[j] * square(AL+AT);64 inner_sum += GAUSS_W[j] * square(AL+AT); 65 65 } 66 66 67 67 inner_sum *= 0.5 * (v2b-v2a); 68 outer_sum += G auss76Wt[i] * inner_sum * sin_theta;68 outer_sum += GAUSS_W[i] * inner_sum * sin_theta; 69 69 } 70 70 -
sasmodels/models/lib/gauss150.c
r994d77f r99b84ec 1 /* 2 * GaussWeights.c 3 * SANSAnalysis 4 * 5 * Created by Andrew Jackson on 4/23/07. 6 * Copyright 2007 __MyCompanyName__. All rights reserved. 7 * 8 */ 1 // Created by Andrew Jackson on 4/23/07 9 2 10 // Gaussians 11 constant double Gauss150Z[150]={ 3 #ifdef GAUSS_N 4 # undef GAUSS_N 5 # undef GAUSS_Z 6 # undef GAUSS_W 7 #endif 8 #define GAUSS_N 150 9 #define GAUSS_Z Gauss150Z 10 #define GAUSS_W Gauss150Wt 11 12 13 // Note: using array size 152 rather than 150 so that it is a multiple of 4. 14 // Some OpenCL devices prefer that vectors start and end on nice boundaries. 15 constant double Gauss150Z[152]={ 12 16 -0.9998723404457334, 13 17 -0.9993274305065947, … … 159 163 0.9983473449340834, 160 164 0.9993274305065947, 161 0.9998723404457334 165 0.9998723404457334, 166 0., // zero padding is ignored 167 0. // zero padding is ignored 162 168 }; 163 169 164 constant double Gauss150Wt[15 0]={170 constant double Gauss150Wt[152]={ 165 171 0.0003276086705538, 166 172 0.0007624720924706, … … 312 318 0.0011976474864367, 313 319 0.0007624720924706, 314 0.0003276086705538 320 0.0003276086705538, 321 0., // zero padding is ignored 322 0. // zero padding is ignored 315 323 }; -
sasmodels/models/lib/gauss20.c
r994d77f r99b84ec 1 /* 2 * GaussWeights.c 3 * SANSAnalysis 4 * 5 * Created by Andrew Jackson on 4/23/07. 6 * Copyright 2007 __MyCompanyName__. All rights reserved. 7 * 8 */ 1 // Created by Andrew Jackson on 4/23/07 2 3 #ifdef GAUSS_N 4 # undef GAUSS_N 5 # undef GAUSS_Z 6 # undef GAUSS_W 7 #endif 8 #define GAUSS_N 20 9 #define GAUSS_Z Gauss20Z 10 #define GAUSS_W Gauss20Wt 9 11 10 12 // Gaussians -
sasmodels/models/lib/gauss76.c
r66d119f r99b84ec 1 /* 2 * GaussWeights.c 3 * SANSAnalysis 4 * 5 * Created by Andrew Jackson on 4/23/07. 6 * Copyright 2007 __MyCompanyName__. All rights reserved. 7 * 8 */ 9 #define N_POINTS_76 76 1 // Created by Andrew Jackson on 4/23/07 2 3 #ifdef GAUSS_N 4 # undef GAUSS_N 5 # undef GAUSS_Z 6 # undef GAUSS_W 7 #endif 8 #define GAUSS_N 76 9 #define GAUSS_Z Gauss76Z 10 #define GAUSS_W Gauss76Wt 10 11 11 12 // Gaussians 12 constant double Gauss76Wt[ N_POINTS_76]={13 constant double Gauss76Wt[76]={ 13 14 .00126779163408536, //0 14 15 .00294910295364247, … … 89 90 }; 90 91 91 constant double Gauss76Z[ N_POINTS_76]={92 constant double Gauss76Z[76]={ 92 93 -.999505948362153, //0 93 94 -.997397786355355, -
sasmodels/models/line.py
r2d81cfe r108e70e 57 57 Iq.vectorized = True # Iq accepts an array of q values 58 58 59 59 60 def Iqxy(qx, qy, *args): 60 61 """ … … 69 70 70 71 Iqxy.vectorized = True # Iqxy accepts an array of qx qy values 72 73 # uncomment the following to test Iqxy in C models 74 #del Iq, Iqxy 75 #c_code = """ 76 #static double Iq(double q, double b, double m) { return m*q+b; } 77 #static double Iqxy(double qx, double qy, double b, double m) 78 #{ return (m*qx+b)*(m*qy+b); } 79 #""" 71 80 72 81 def random(): -
sasmodels/models/parallelepiped.c
r9b7b23f r108e70e 23 23 double outer_total = 0; //initialize integral 24 24 25 for( int i=0; i< 76; i++) {26 const double sigma = 0.5 * ( G auss76Z[i] + 1.0 );25 for( int i=0; i<GAUSS_N; i++) { 26 const double sigma = 0.5 * ( GAUSS_Z[i] + 1.0 ); 27 27 const double mu_proj = mu * sqrt(1.0-sigma*sigma); 28 28 … … 30 30 // corresponding to angles from 0 to pi/2. 31 31 double inner_total = 0.0; 32 for(int j=0; j< 76; j++) {33 const double uu = 0.5 * ( G auss76Z[j] + 1.0 );32 for(int j=0; j<GAUSS_N; j++) { 33 const double uu = 0.5 * ( GAUSS_Z[j] + 1.0 ); 34 34 double sin_uu, cos_uu; 35 35 SINCOS(M_PI_2*uu, sin_uu, cos_uu); 36 36 const double si1 = sas_sinx_x(mu_proj * sin_uu * a_scaled); 37 37 const double si2 = sas_sinx_x(mu_proj * cos_uu); 38 inner_total += G auss76Wt[j] * square(si1 * si2);38 inner_total += GAUSS_W[j] * square(si1 * si2); 39 39 } 40 40 inner_total *= 0.5; 41 41 42 42 const double si = sas_sinx_x(mu * c_scaled * sigma); 43 outer_total += G auss76Wt[i] * inner_total * si * si;43 outer_total += GAUSS_W[i] * inner_total * si * si; 44 44 } 45 45 outer_total *= 0.5; … … 53 53 54 54 static double 55 Iq xy(double qa, double qb, double qc,55 Iqabc(double qa, double qb, double qc, 56 56 double sld, 57 57 double solvent_sld, -
sasmodels/models/pringle.c
r1e7b0db0 r74768cb 29 29 double sumC = 0.0; // initialize integral 30 30 double r; 31 for (int i=0; i < 76; i++) {32 r = G auss76Z[i]*zm + zb;31 for (int i=0; i < GAUSS_N; i++) { 32 r = GAUSS_Z[i]*zm + zb; 33 33 34 34 const double qrs = r*q_sin_psi; 35 35 const double qrrc = r*r*q_cos_psi; 36 36 37 double y = G auss76Wt[i] * r * sas_JN(n, beta*qrrc) * sas_JN(2*n, qrs);37 double y = GAUSS_W[i] * r * sas_JN(n, beta*qrrc) * sas_JN(2*n, qrs); 38 38 double S, C; 39 39 SINCOS(alpha*qrrc, S, C); … … 86 86 87 87 double sum = 0.0; 88 for (int i = 0; i < 76; i++) {89 double psi = G auss76Z[i]*zm + zb;88 for (int i = 0; i < GAUSS_N; i++) { 89 double psi = GAUSS_Z[i]*zm + zb; 90 90 double sin_psi, cos_psi; 91 91 SINCOS(psi, sin_psi, cos_psi); … … 93 93 double sinc_term = square(sas_sinx_x(q * thickness * cos_psi / 2.0)); 94 94 double pringle_kernel = 4.0 * sin_psi * bessel_term * sinc_term; 95 sum += G auss76Wt[i] * pringle_kernel;95 sum += GAUSS_W[i] * pringle_kernel; 96 96 } 97 97 -
sasmodels/models/rectangular_prism.c
r1e7b0db0 r108e70e 1 1 double form_volume(double length_a, double b2a_ratio, double c2a_ratio); 2 double Iq(double q, double sld, double solvent_sld, double length_a, 2 double Iq(double q, double sld, double solvent_sld, double length_a, 3 3 double b2a_ratio, double c2a_ratio); 4 4 … … 26 26 const double v2a = 0.0; 27 27 const double v2b = M_PI_2; //phi integration limits 28 28 29 29 double outer_sum = 0.0; 30 for(int i=0; i< 76; i++) {31 const double theta = 0.5 * ( G auss76Z[i]*(v1b-v1a) + v1a + v1b );30 for(int i=0; i<GAUSS_N; i++) { 31 const double theta = 0.5 * ( GAUSS_Z[i]*(v1b-v1a) + v1a + v1b ); 32 32 double sin_theta, cos_theta; 33 33 SINCOS(theta, sin_theta, cos_theta); … … 36 36 37 37 double inner_sum = 0.0; 38 for(int j=0; j< 76; j++) {39 double phi = 0.5 * ( G auss76Z[j]*(v2b-v2a) + v2a + v2b );38 for(int j=0; j<GAUSS_N; j++) { 39 double phi = 0.5 * ( GAUSS_Z[j]*(v2b-v2a) + v2a + v2b ); 40 40 double sin_phi, cos_phi; 41 41 SINCOS(phi, sin_phi, cos_phi); … … 45 45 const double termB = sas_sinx_x(q * b_half * sin_theta * cos_phi); 46 46 const double AP = termA * termB * termC; 47 inner_sum += G auss76Wt[j] * AP * AP;47 inner_sum += GAUSS_W[j] * AP * AP; 48 48 } 49 49 inner_sum = 0.5 * (v2b-v2a) * inner_sum; 50 outer_sum += G auss76Wt[i] * inner_sum * sin_theta;50 outer_sum += GAUSS_W[i] * inner_sum * sin_theta; 51 51 } 52 52 53 53 double answer = 0.5*(v1b-v1a)*outer_sum; 54 54 55 // Normalize by Pi (Eqn. 16). 56 // The term (ABC)^2 does not appear because it was introduced before on 55 // Normalize by Pi (Eqn. 16). 56 // The term (ABC)^2 does not appear because it was introduced before on 57 57 // the definitions of termA, termB, termC. 58 // The factor 2 appears because the theta integral has been defined between 58 // The factor 2 appears because the theta integral has been defined between 59 59 // 0 and pi/2, instead of 0 to pi. 60 60 answer /= M_PI_2; //Form factor P(q) … … 64 64 answer *= square((sld-solvent_sld)*volume); 65 65 66 // Convert from [1e-12 A-1] to [cm-1] 66 // Convert from [1e-12 A-1] to [cm-1] 67 67 answer *= 1.0e-4; 68 68 69 69 return answer; 70 70 } 71 72 73 double Iqabc(double qa, double qb, double qc, 74 double sld, 75 double solvent_sld, 76 double length_a, 77 double b2a_ratio, 78 double c2a_ratio) 79 { 80 const double length_b = length_a * b2a_ratio; 81 const double length_c = length_a * c2a_ratio; 82 const double a_half = 0.5 * length_a; 83 const double b_half = 0.5 * length_b; 84 const double c_half = 0.5 * length_c; 85 const double volume = length_a * length_b * length_c; 86 87 // Amplitude AP from eqn. (13) 88 89 const double termA = sas_sinx_x(qa * a_half); 90 const double termB = sas_sinx_x(qb * b_half); 91 const double termC = sas_sinx_x(qc * c_half); 92 93 const double AP = termA * termB * termC; 94 95 // Multiply by contrast^2. Factor corresponding to volume^2 cancels with previous normalization. 96 const double delrho = sld - solvent_sld; 97 98 // Convert from [1e-12 A-1] to [cm-1] 99 return 1.0e-4 * square(volume * delrho * AP); 100 } -
sasmodels/models/rectangular_prism.py
r2d81cfe r0e55afe 12 12 the prism (e.g. setting $b/a = 1$ and $c/a = 1$ and applying polydispersity 13 13 to *a* will generate a distribution of cubes of different sizes). 14 Note also that, contrary to :ref:`parallelepiped`, it does not compute15 the 2D scattering.16 14 17 15 … … 26 24 that reference), with $\theta$ corresponding to $\alpha$ in that paper, 27 25 and not to the usual convention used for example in the 28 :ref:`parallelepiped` model. As the present model does not compute 29 the 2D scattering, this has no further consequences. 26 :ref:`parallelepiped` model. 30 27 31 28 In this model the scattering from a massive parallelepiped with an … … 65 62 units) *scale* represents the volume fraction (which is unitless). 66 63 67 **The 2D scattering intensity is not computed by this model.** 64 For 2d data the orientation of the particle is required, described using 65 angles $\theta$, $\phi$ and $\Psi$ as in the diagrams below, for further details 66 of the calculation and angular dispersions see :ref:`orientation` . 67 The angle $\Psi$ is the rotational angle around the long *C* axis. For example, 68 $\Psi = 0$ when the *B* axis is parallel to the *x*-axis of the detector. 69 70 For 2d, constraints must be applied during fitting to ensure that the inequality 71 $A < B < C$ is not violated, and hence the correct definition of angles is preserved. The calculation will not report an error, 72 but the results may be not correct. 73 74 .. figure:: img/parallelepiped_angle_definition.png 75 76 Definition of the angles for oriented core-shell parallelepipeds. 77 Note that rotation $\theta$, initially in the $xz$ plane, is carried out first, then 78 rotation $\phi$ about the $z$ axis, finally rotation $\Psi$ is now around the axis of the cylinder. 79 The neutron or X-ray beam is along the $z$ axis. 80 81 .. figure:: img/parallelepiped_angle_projection.png 82 83 Examples of the angles for oriented rectangular prisms against the 84 detector plane. 85 68 86 69 87 … … 108 126 ["c2a_ratio", "", 1, [0, inf], "volume", 109 127 "Ratio sides c/a"], 128 ["theta", "degrees", 0, [-360, 360], "orientation", 129 "c axis to beam angle"], 130 ["phi", "degrees", 0, [-360, 360], "orientation", 131 "rotation about beam"], 132 ["psi", "degrees", 0, [-360, 360], "orientation", 133 "rotation about c axis"], 110 134 ] 111 135 -
sasmodels/models/sc_paracrystal.c
rf728001 r108e70e 54 54 55 55 double outer_sum = 0.0; 56 for(int i=0; i< 150; i++) {56 for(int i=0; i<GAUSS_N; i++) { 57 57 double inner_sum = 0.0; 58 const double theta = G auss150Z[i]*theta_m + theta_b;58 const double theta = GAUSS_Z[i]*theta_m + theta_b; 59 59 double sin_theta, cos_theta; 60 60 SINCOS(theta, sin_theta, cos_theta); 61 61 const double qc = q*cos_theta; 62 62 const double qab = q*sin_theta; 63 for(int j=0;j< 150;j++) {64 const double phi = G auss150Z[j]*phi_m + phi_b;63 for(int j=0;j<GAUSS_N;j++) { 64 const double phi = GAUSS_Z[j]*phi_m + phi_b; 65 65 double sin_phi, cos_phi; 66 66 SINCOS(phi, sin_phi, cos_phi); … … 68 68 const double qb = qab*sin_phi; 69 69 const double form = sc_Zq(qa, qb, qc, dnn, d_factor); 70 inner_sum += G auss150Wt[j] * form;70 inner_sum += GAUSS_W[j] * form; 71 71 } 72 72 inner_sum *= phi_m; // sum(f(x)dx) = sum(f(x)) dx 73 outer_sum += G auss150Wt[i] * inner_sum * sin_theta;73 outer_sum += GAUSS_W[i] * inner_sum * sin_theta; 74 74 } 75 75 outer_sum *= theta_m; … … 82 82 83 83 static double 84 Iq xy(double qa, double qb, double qc,84 Iqabc(double qa, double qb, double qc, 85 85 double dnn, double d_factor, double radius, 86 86 double sld, double solvent_sld) -
sasmodels/models/stacked_disks.c
rbecded3 r108e70e 81 81 double halfheight = 0.5*thick_core; 82 82 83 for(int i=0; i< N_POINTS_76; i++) {84 double zi = (G auss76Z[i] + 1.0)*M_PI_4;83 for(int i=0; i<GAUSS_N; i++) { 84 double zi = (GAUSS_Z[i] + 1.0)*M_PI_4; 85 85 double sin_alpha, cos_alpha; // slots to hold sincos function output 86 86 SINCOS(zi, sin_alpha, cos_alpha); … … 95 95 solvent_sld, 96 96 d); 97 summ += G auss76Wt[i] * yyy * sin_alpha;97 summ += GAUSS_W[i] * yyy * sin_alpha; 98 98 } 99 99 … … 142 142 143 143 static double 144 Iq xy(double qab, double qc,144 Iqac(double qab, double qc, 145 145 double thick_core, 146 146 double thick_layer, -
sasmodels/models/triaxial_ellipsoid.c
rbecded3 r108e70e 21 21 const double zb = M_PI_4; 22 22 double outer = 0.0; 23 for (int i=0;i< 76;i++) {24 //const double u = G auss76Z[i]*(upper-lower)/2 + (upper + lower)/2;25 const double phi = G auss76Z[i]*zm + zb;23 for (int i=0;i<GAUSS_N;i++) { 24 //const double u = GAUSS_Z[i]*(upper-lower)/2 + (upper + lower)/2; 25 const double phi = GAUSS_Z[i]*zm + zb; 26 26 const double pa_sinsq_phi = pa*square(sin(phi)); 27 27 … … 29 29 const double um = 0.5; 30 30 const double ub = 0.5; 31 for (int j=0;j< 76;j++) {31 for (int j=0;j<GAUSS_N;j++) { 32 32 // translate a point in [-1,1] to a point in [0, 1] 33 const double usq = square(G auss76Z[j]*um + ub);33 const double usq = square(GAUSS_Z[j]*um + ub); 34 34 const double r = radius_equat_major*sqrt(pa_sinsq_phi*(1.0-usq) + 1.0 + pc*usq); 35 35 const double fq = sas_3j1x_x(q*r); 36 inner += G auss76Wt[j] * fq * fq;36 inner += GAUSS_W[j] * fq * fq; 37 37 } 38 outer += G auss76Wt[i] * inner; // correcting for dx later38 outer += GAUSS_W[i] * inner; // correcting for dx later 39 39 } 40 40 // translate integration ranges from [-1,1] to [lower,upper] and normalize by 4 pi … … 46 46 47 47 static double 48 Iq xy(double qa, double qb, double qc,48 Iqabc(double qa, double qb, double qc, 49 49 double sld, 50 50 double sld_solvent, -
sasmodels/special.py
re65c3ba rdf69efa 3 3 ................. 4 4 5 The C code follows the C99 standard, with the usual math functions, 6 as defined in 7 `OpenCL <https://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/mathFunctions.html>`_. 8 This includes the following: 5 This following standard C99 math functions are available: 9 6 10 7 M_PI, M_PI_2, M_PI_4, M_SQRT1_2, M_E: 11 8 $\pi$, $\pi/2$, $\pi/4$, $1/\sqrt{2}$ and Euler's constant $e$ 12 9 13 exp, log, pow(x,y), expm1, sqrt:14 Power functions $e^x$, $\ln x$, $x^y$, $e^x - 1$, $\ sqrt{x}$.15 The function expm1(x) is accurate across all $x$, including $x$16 very close to zero.10 exp, log, pow(x,y), expm1, log1p, sqrt, cbrt: 11 Power functions $e^x$, $\ln x$, $x^y$, $e^x - 1$, $\ln 1 + x$, 12 $\sqrt{x}$, $\sqrt[3]{x}$. The functions expm1(x) and log1p(x) 13 are accurate across all $x$, including $x$ very close to zero. 17 14 18 15 sin, cos, tan, asin, acos, atan: … … 29 26 quadrants II and IV when $x$ and $y$ have opposite sign. 30 27 31 f min(x,y), fmax(x,y), trunc, rint:28 fabs(x), fmin(x,y), fmax(x,y), trunc, rint: 32 29 Floating point functions. rint(x) returns the nearest integer. 33 30 … … 35 32 NaN, Not a Number, $0/0$. Use isnan(x) to test for NaN. Note that 36 33 you cannot use :code:`x == NAN` to test for NaN values since that 37 will always return false. NAN does not equal NAN! 34 will always return false. NAN does not equal NAN! The alternative, 35 :code:`x != x` may fail if the compiler optimizes the test away. 38 36 39 37 INFINITY: … … 89 87 for forcing a constant to stay double precision. 90 88 91 The following special functions and scattering calculations are defined in 92 `sasmodels/models/lib <https://github.com/SasView/sasmodels/tree/master/sasmodels/models/lib>`_. 89 The following special functions and scattering calculations are defined. 93 90 These functions have been tuned to be fast and numerically stable down 94 91 to $q=0$ even in single precision. In some cases they work around bugs … … 184 181 185 182 186 Gauss76Z[i], Gauss76Wt[i]:183 gauss76.n, gauss76.z[i], gauss76.w[i]: 187 184 Points $z_i$ and weights $w_i$ for 76-point Gaussian quadrature, respectively, 188 185 computing $\int_{-1}^1 f(z)\,dz \approx \sum_{i=1}^{76} w_i\,f(z_i)$. 189 190 Similar arrays are available in :code:`gauss20.c` for 20-point 191 quadrature and in :code:`gauss150.c` for 150-point quadrature. 192 186 When translating the model to C, include 'lib/gauss76.c' in the source 187 and use :code:`GAUSS_N`, :code:`GAUSS_Z`, and :code:`GAUSS_W`. 188 189 Similar arrays are available in :code:`gauss20` for 20-point quadrature 190 and :code:`gauss150.c` for 150-point quadrature. By using 191 :code:`import gauss76 as gauss` it is easy to change the number of 192 points in the integration. 193 193 """ 194 194 # pylint: disable=unused-import … … 200 200 201 201 # C99 standard math library functions 202 from numpy import exp, log, power as pow, expm1, sqrt202 from numpy import exp, log, power as pow, expm1, log1p, sqrt, cbrt 203 203 from numpy import sin, cos, tan, arcsin as asin, arccos as acos, arctan as atan 204 204 from numpy import sinh, cosh, tanh, arcsinh as asinh, arccosh as acosh, arctanh as atanh 205 205 from numpy import arctan2 as atan2 206 from numpy import fmin, fmax, trunc, rint 207 from numpy import NAN, inf as INFINITY 208 206 from numpy import fabs, fmin, fmax, trunc, rint 207 from numpy import pi, nan, inf 209 208 from scipy.special import gamma as sas_gamma 210 209 from scipy.special import erf as sas_erf … … 218 217 # C99 standard math constants 219 218 M_PI, M_PI_2, M_PI_4, M_SQRT1_2, M_E = np.pi, np.pi/2, np.pi/4, np.sqrt(0.5), np.e 219 NAN = nan 220 INFINITY = inf 220 221 221 222 # non-standard constants … … 226 227 """return sin(x), cos(x)""" 227 228 return sin(x), cos(x) 229 sincos = SINCOS 228 230 229 231 def square(x): … … 294 296 295 297 # Gaussians 296 297 Gauss20Wt = np.array([ 298 .0176140071391521, 299 .0406014298003869, 300 .0626720483341091, 301 .0832767415767047, 302 .10193011981724, 303 .118194531961518, 304 .131688638449177, 305 .142096109318382, 306 .149172986472604, 307 .152753387130726, 308 .152753387130726, 309 .149172986472604, 310 .142096109318382, 311 .131688638449177, 312 .118194531961518, 313 .10193011981724, 314 .0832767415767047, 315 .0626720483341091, 316 .0406014298003869, 317 .0176140071391521 318 ]) 319 320 Gauss20Z = np.array([ 321 -.993128599185095, 322 -.963971927277914, 323 -.912234428251326, 324 -.839116971822219, 325 -.746331906460151, 326 -.636053680726515, 327 -.510867001950827, 328 -.37370608871542, 329 -.227785851141645, 330 -.076526521133497, 331 .0765265211334973, 332 .227785851141645, 333 .37370608871542, 334 .510867001950827, 335 .636053680726515, 336 .746331906460151, 337 .839116971822219, 338 .912234428251326, 339 .963971927277914, 340 .993128599185095 341 ]) 342 343 Gauss76Wt = np.array([ 344 .00126779163408536, #0 345 .00294910295364247, 346 .00462793522803742, 347 .00629918049732845, 348 .00795984747723973, 349 .00960710541471375, 350 .0112381685696677, 351 .0128502838475101, 352 .0144407317482767, 353 .0160068299122486, 354 .0175459372914742, #10 355 .0190554584671906, 356 .020532847967908, 357 .0219756145344162, 358 .0233813253070112, 359 .0247476099206597, 360 .026072164497986, 361 .0273527555318275, 362 .028587223650054, 363 .029773487255905, 364 .0309095460374916, #20 365 .0319934843404216, 366 .0330234743977917, 367 .0339977794120564, 368 .0349147564835508, 369 .0357728593807139, 370 .0365706411473296, 371 .0373067565423816, 372 .0379799643084053, 373 .0385891292645067, 374 .0391332242205184, #30 375 .0396113317090621, 376 .0400226455325968, 377 .040366472122844, 378 .0406422317102947, 379 .0408494593018285, 380 .040987805464794, 381 .0410570369162294, 382 .0410570369162294, 383 .040987805464794, 384 .0408494593018285, #40 385 .0406422317102947, 386 .040366472122844, 387 .0400226455325968, 388 .0396113317090621, 389 .0391332242205184, 390 .0385891292645067, 391 .0379799643084053, 392 .0373067565423816, 393 .0365706411473296, 394 .0357728593807139, #50 395 .0349147564835508, 396 .0339977794120564, 397 .0330234743977917, 398 .0319934843404216, 399 .0309095460374916, 400 .029773487255905, 401 .028587223650054, 402 .0273527555318275, 403 .026072164497986, 404 .0247476099206597, #60 405 .0233813253070112, 406 .0219756145344162, 407 .020532847967908, 408 .0190554584671906, 409 .0175459372914742, 410 .0160068299122486, 411 .0144407317482767, 412 .0128502838475101, 413 .0112381685696677, 414 .00960710541471375, #70 415 .00795984747723973, 416 .00629918049732845, 417 .00462793522803742, 418 .00294910295364247, 419 .00126779163408536 #75 (indexed from 0) 420 ]) 421 422 Gauss76Z = np.array([ 423 -.999505948362153, #0 424 -.997397786355355, 425 -.993608772723527, 426 -.988144453359837, 427 -.981013938975656, 428 -.972229228520377, 429 -.961805126758768, 430 -.949759207710896, 431 -.936111781934811, 432 -.92088586125215, 433 -.904107119545567, #10 434 -.885803849292083, 435 -.866006913771982, 436 -.844749694983342, 437 -.822068037328975, 438 -.7980001871612, 439 -.77258672828181, 440 -.74587051350361, 441 -.717896592387704, 442 -.688712135277641, 443 -.658366353758143, #20 444 -.626910417672267, 445 -.594397368836793, 446 -.560882031601237, 447 -.526420920401243, 448 -.491072144462194, 449 -.454895309813726, 450 -.417951418780327, 451 -.380302767117504, 452 -.342012838966962, 453 -.303146199807908, #30 454 -.263768387584994, 455 -.223945802196474, 456 -.183745593528914, 457 -.143235548227268, 458 -.102483975391227, 459 -.0615595913906112, 460 -.0205314039939986, 461 .0205314039939986, 462 .0615595913906112, 463 .102483975391227, #40 464 .143235548227268, 465 .183745593528914, 466 .223945802196474, 467 .263768387584994, 468 .303146199807908, 469 .342012838966962, 470 .380302767117504, 471 .417951418780327, 472 .454895309813726, 473 .491072144462194, #50 474 .526420920401243, 475 .560882031601237, 476 .594397368836793, 477 .626910417672267, 478 .658366353758143, 479 .688712135277641, 480 .717896592387704, 481 .74587051350361, 482 .77258672828181, 483 .7980001871612, #60 484 .822068037328975, 485 .844749694983342, 486 .866006913771982, 487 .885803849292083, 488 .904107119545567, 489 .92088586125215, 490 .936111781934811, 491 .949759207710896, 492 .961805126758768, 493 .972229228520377, #70 494 .981013938975656, 495 .988144453359837, 496 .993608772723527, 497 .997397786355355, 498 .999505948362153 #75 499 ]) 500 501 Gauss150Z = np.array([ 502 -0.9998723404457334, 503 -0.9993274305065947, 504 -0.9983473449340834, 505 -0.9969322929775997, 506 -0.9950828645255290, 507 -0.9927998590434373, 508 -0.9900842691660192, 509 -0.9869372772712794, 510 -0.9833602541697529, 511 -0.9793547582425894, 512 -0.9749225346595943, 513 -0.9700655145738374, 514 -0.9647858142586956, 515 -0.9590857341746905, 516 -0.9529677579610971, 517 -0.9464345513503147, 518 -0.9394889610042837, 519 -0.9321340132728527, 520 -0.9243729128743136, 521 -0.9162090414984952, 522 -0.9076459563329236, 523 -0.8986873885126239, 524 -0.8893372414942055, 525 -0.8795995893549102, 526 -0.8694786750173527, 527 -0.8589789084007133, 528 -0.8481048644991847, 529 -0.8368612813885015, 530 -0.8252530581614230, 531 -0.8132852527930605, 532 -0.8009630799369827, 533 -0.7882919086530552, 534 -0.7752772600680049, 535 -0.7619248049697269, 536 -0.7482403613363824, 537 -0.7342298918013638, 538 -0.7198995010552305, 539 -0.7052554331857488, 540 -0.6903040689571928, 541 -0.6750519230300931, 542 -0.6595056411226444, 543 -0.6436719971150083, 544 -0.6275578900977726, 545 -0.6111703413658551, 546 -0.5945164913591590, 547 -0.5776035965513142, 548 -0.5604390262878617, 549 -0.5430302595752546, 550 -0.5253848818220803, 551 -0.5075105815339176, 552 -0.4894151469632753, 553 -0.4711064627160663, 554 -0.4525925063160997, 555 -0.4338813447290861, 556 -0.4149811308476706, 557 -0.3959000999390257, 558 -0.3766465660565522, 559 -0.3572289184172501, 560 -0.3376556177463400, 561 -0.3179351925907259, 562 -0.2980762356029071, 563 -0.2780873997969574, 564 -0.2579773947782034, 565 -0.2377549829482451, 566 -0.2174289756869712, 567 -0.1970082295132342, 568 -0.1765016422258567, 569 -0.1559181490266516, 570 -0.1352667186271445, 571 -0.1145563493406956, 572 -0.0937960651617229, 573 -0.0729949118337358, 574 -0.0521619529078925, 575 -0.0313062657937972, 576 -0.0104369378042598, 577 0.0104369378042598, 578 0.0313062657937972, 579 0.0521619529078925, 580 0.0729949118337358, 581 0.0937960651617229, 582 0.1145563493406956, 583 0.1352667186271445, 584 0.1559181490266516, 585 0.1765016422258567, 586 0.1970082295132342, 587 0.2174289756869712, 588 0.2377549829482451, 589 0.2579773947782034, 590 0.2780873997969574, 591 0.2980762356029071, 592 0.3179351925907259, 593 0.3376556177463400, 594 0.3572289184172501, 595 0.3766465660565522, 596 0.3959000999390257, 597 0.4149811308476706, 598 0.4338813447290861, 599 0.4525925063160997, 600 0.4711064627160663, 601 0.4894151469632753, 602 0.5075105815339176, 603 0.5253848818220803, 604 0.5430302595752546, 605 0.5604390262878617, 606 0.5776035965513142, 607 0.5945164913591590, 608 0.6111703413658551, 609 0.6275578900977726, 610 0.6436719971150083, 611 0.6595056411226444, 612 0.6750519230300931, 613 0.6903040689571928, 614 0.7052554331857488, 615 0.7198995010552305, 616 0.7342298918013638, 617 0.7482403613363824, 618 0.7619248049697269, 619 0.7752772600680049, 620 0.7882919086530552, 621 0.8009630799369827, 622 0.8132852527930605, 623 0.8252530581614230, 624 0.8368612813885015, 625 0.8481048644991847, 626 0.8589789084007133, 627 0.8694786750173527, 628 0.8795995893549102, 629 0.8893372414942055, 630 0.8986873885126239, 631 0.9076459563329236, 632 0.9162090414984952, 633 0.9243729128743136, 634 0.9321340132728527, 635 0.9394889610042837, 636 0.9464345513503147, 637 0.9529677579610971, 638 0.9590857341746905, 639 0.9647858142586956, 640 0.9700655145738374, 641 0.9749225346595943, 642 0.9793547582425894, 643 0.9833602541697529, 644 0.9869372772712794, 645 0.9900842691660192, 646 0.9927998590434373, 647 0.9950828645255290, 648 0.9969322929775997, 649 0.9983473449340834, 650 0.9993274305065947, 651 0.9998723404457334 652 ]) 653 654 Gauss150Wt = np.array([ 655 0.0003276086705538, 656 0.0007624720924706, 657 0.0011976474864367, 658 0.0016323569986067, 659 0.0020663664924131, 660 0.0024994789888943, 661 0.0029315036836558, 662 0.0033622516236779, 663 0.0037915348363451, 664 0.0042191661429919, 665 0.0046449591497966, 666 0.0050687282939456, 667 0.0054902889094487, 668 0.0059094573005900, 669 0.0063260508184704, 670 0.0067398879387430, 671 0.0071507883396855, 672 0.0075585729801782, 673 0.0079630641773633, 674 0.0083640856838475, 675 0.0087614627643580, 676 0.0091550222717888, 677 0.0095445927225849, 678 0.0099300043714212, 679 0.0103110892851360, 680 0.0106876814158841, 681 0.0110596166734735, 682 0.0114267329968529, 683 0.0117888704247183, 684 0.0121458711652067, 685 0.0124975796646449, 686 0.0128438426753249, 687 0.0131845093222756, 688 0.0135194311690004, 689 0.0138484622795371, 690 0.0141714592928592, 691 0.0144882814685445, 692 0.0147987907597169, 693 0.0151028518701744, 694 0.0154003323133401, 695 0.0156911024699895, 696 0.0159750356447283, 697 0.0162520081211971, 698 0.0165218992159766, 699 0.0167845913311726, 700 0.0170399700056559, 701 0.0172879239649355, 702 0.0175283451696437, 703 0.0177611288626114, 704 0.0179861736145128, 705 0.0182033813680609, 706 0.0184126574807331, 707 0.0186139107660094, 708 0.0188070535331042, 709 0.0189920016251754, 710 0.0191686744559934, 711 0.0193369950450545, 712 0.0194968900511231, 713 0.0196482898041878, 714 0.0197911283358190, 715 0.0199253434079123, 716 0.0200508765398072, 717 0.0201676730337687, 718 0.0202756819988200, 719 0.0203748563729175, 720 0.0204651529434560, 721 0.0205465323660984, 722 0.0206189591819181, 723 0.0206824018328499, 724 0.0207368326754401, 725 0.0207822279928917, 726 0.0208185680053983, 727 0.0208458368787627, 728 0.0208640227312962, 729 0.0208731176389954, 730 0.0208731176389954, 731 0.0208640227312962, 732 0.0208458368787627, 733 0.0208185680053983, 734 0.0207822279928917, 735 0.0207368326754401, 736 0.0206824018328499, 737 0.0206189591819181, 738 0.0205465323660984, 739 0.0204651529434560, 740 0.0203748563729175, 741 0.0202756819988200, 742 0.0201676730337687, 743 0.0200508765398072, 744 0.0199253434079123, 745 0.0197911283358190, 746 0.0196482898041878, 747 0.0194968900511231, 748 0.0193369950450545, 749 0.0191686744559934, 750 0.0189920016251754, 751 0.0188070535331042, 752 0.0186139107660094, 753 0.0184126574807331, 754 0.0182033813680609, 755 0.0179861736145128, 756 0.0177611288626114, 757 0.0175283451696437, 758 0.0172879239649355, 759 0.0170399700056559, 760 0.0167845913311726, 761 0.0165218992159766, 762 0.0162520081211971, 763 0.0159750356447283, 764 0.0156911024699895, 765 0.0154003323133401, 766 0.0151028518701744, 767 0.0147987907597169, 768 0.0144882814685445, 769 0.0141714592928592, 770 0.0138484622795371, 771 0.0135194311690004, 772 0.0131845093222756, 773 0.0128438426753249, 774 0.0124975796646449, 775 0.0121458711652067, 776 0.0117888704247183, 777 0.0114267329968529, 778 0.0110596166734735, 779 0.0106876814158841, 780 0.0103110892851360, 781 0.0099300043714212, 782 0.0095445927225849, 783 0.0091550222717888, 784 0.0087614627643580, 785 0.0083640856838475, 786 0.0079630641773633, 787 0.0075585729801782, 788 0.0071507883396855, 789 0.0067398879387430, 790 0.0063260508184704, 791 0.0059094573005900, 792 0.0054902889094487, 793 0.0050687282939456, 794 0.0046449591497966, 795 0.0042191661429919, 796 0.0037915348363451, 797 0.0033622516236779, 798 0.0029315036836558, 799 0.0024994789888943, 800 0.0020663664924131, 801 0.0016323569986067, 802 0.0011976474864367, 803 0.0007624720924706, 804 0.0003276086705538 805 ]) 298 class Gauss: 299 def __init__(self, w, z): 300 self.n = len(w) 301 self.w = w 302 self.z = z 303 304 gauss20 = Gauss( 305 w=np.array([ 306 .0176140071391521, 307 .0406014298003869, 308 .0626720483341091, 309 .0832767415767047, 310 .10193011981724, 311 .118194531961518, 312 .131688638449177, 313 .142096109318382, 314 .149172986472604, 315 .152753387130726, 316 .152753387130726, 317 .149172986472604, 318 .142096109318382, 319 .131688638449177, 320 .118194531961518, 321 .10193011981724, 322 .0832767415767047, 323 .0626720483341091, 324 .0406014298003869, 325 .0176140071391521 326 ]), 327 z=np.array([ 328 -.993128599185095, 329 -.963971927277914, 330 -.912234428251326, 331 -.839116971822219, 332 -.746331906460151, 333 -.636053680726515, 334 -.510867001950827, 335 -.37370608871542, 336 -.227785851141645, 337 -.076526521133497, 338 .0765265211334973, 339 .227785851141645, 340 .37370608871542, 341 .510867001950827, 342 .636053680726515, 343 .746331906460151, 344 .839116971822219, 345 .912234428251326, 346 .963971927277914, 347 .993128599185095 348 ]) 349 ) 350 351 gauss76 = Gauss( 352 w=np.array([ 353 .00126779163408536, #0 354 .00294910295364247, 355 .00462793522803742, 356 .00629918049732845, 357 .00795984747723973, 358 .00960710541471375, 359 .0112381685696677, 360 .0128502838475101, 361 .0144407317482767, 362 .0160068299122486, 363 .0175459372914742, #10 364 .0190554584671906, 365 .020532847967908, 366 .0219756145344162, 367 .0233813253070112, 368 .0247476099206597, 369 .026072164497986, 370 .0273527555318275, 371 .028587223650054, 372 .029773487255905, 373 .0309095460374916, #20 374 .0319934843404216, 375 .0330234743977917, 376 .0339977794120564, 377 .0349147564835508, 378 .0357728593807139, 379 .0365706411473296, 380 .0373067565423816, 381 .0379799643084053, 382 .0385891292645067, 383 .0391332242205184, #30 384 .0396113317090621, 385 .0400226455325968, 386 .040366472122844, 387 .0406422317102947, 388 .0408494593018285, 389 .040987805464794, 390 .0410570369162294, 391 .0410570369162294, 392 .040987805464794, 393 .0408494593018285, #40 394 .0406422317102947, 395 .040366472122844, 396 .0400226455325968, 397 .0396113317090621, 398 .0391332242205184, 399 .0385891292645067, 400 .0379799643084053, 401 .0373067565423816, 402 .0365706411473296, 403 .0357728593807139, #50 404 .0349147564835508, 405 .0339977794120564, 406 .0330234743977917, 407 .0319934843404216, 408 .0309095460374916, 409 .029773487255905, 410 .028587223650054, 411 .0273527555318275, 412 .026072164497986, 413 .0247476099206597, #60 414 .0233813253070112, 415 .0219756145344162, 416 .020532847967908, 417 .0190554584671906, 418 .0175459372914742, 419 .0160068299122486, 420 .0144407317482767, 421 .0128502838475101, 422 .0112381685696677, 423 .00960710541471375, #70 424 .00795984747723973, 425 .00629918049732845, 426 .00462793522803742, 427 .00294910295364247, 428 .00126779163408536 #75 (indexed from 0) 429 ]), 430 z=np.array([ 431 -.999505948362153, #0 432 -.997397786355355, 433 -.993608772723527, 434 -.988144453359837, 435 -.981013938975656, 436 -.972229228520377, 437 -.961805126758768, 438 -.949759207710896, 439 -.936111781934811, 440 -.92088586125215, 441 -.904107119545567, #10 442 -.885803849292083, 443 -.866006913771982, 444 -.844749694983342, 445 -.822068037328975, 446 -.7980001871612, 447 -.77258672828181, 448 -.74587051350361, 449 -.717896592387704, 450 -.688712135277641, 451 -.658366353758143, #20 452 -.626910417672267, 453 -.594397368836793, 454 -.560882031601237, 455 -.526420920401243, 456 -.491072144462194, 457 -.454895309813726, 458 -.417951418780327, 459 -.380302767117504, 460 -.342012838966962, 461 -.303146199807908, #30 462 -.263768387584994, 463 -.223945802196474, 464 -.183745593528914, 465 -.143235548227268, 466 -.102483975391227, 467 -.0615595913906112, 468 -.0205314039939986, 469 .0205314039939986, 470 .0615595913906112, 471 .102483975391227, #40 472 .143235548227268, 473 .183745593528914, 474 .223945802196474, 475 .263768387584994, 476 .303146199807908, 477 .342012838966962, 478 .380302767117504, 479 .417951418780327, 480 .454895309813726, 481 .491072144462194, #50 482 .526420920401243, 483 .560882031601237, 484 .594397368836793, 485 .626910417672267, 486 .658366353758143, 487 .688712135277641, 488 .717896592387704, 489 .74587051350361, 490 .77258672828181, 491 .7980001871612, #60 492 .822068037328975, 493 .844749694983342, 494 .866006913771982, 495 .885803849292083, 496 .904107119545567, 497 .92088586125215, 498 .936111781934811, 499 .949759207710896, 500 .961805126758768, 501 .972229228520377, #70 502 .981013938975656, 503 .988144453359837, 504 .993608772723527, 505 .997397786355355, 506 .999505948362153 #75 507 ]) 508 ) 509 510 gauss150 = Gauss( 511 z=np.array([ 512 -0.9998723404457334, 513 -0.9993274305065947, 514 -0.9983473449340834, 515 -0.9969322929775997, 516 -0.9950828645255290, 517 -0.9927998590434373, 518 -0.9900842691660192, 519 -0.9869372772712794, 520 -0.9833602541697529, 521 -0.9793547582425894, 522 -0.9749225346595943, 523 -0.9700655145738374, 524 -0.9647858142586956, 525 -0.9590857341746905, 526 -0.9529677579610971, 527 -0.9464345513503147, 528 -0.9394889610042837, 529 -0.9321340132728527, 530 -0.9243729128743136, 531 -0.9162090414984952, 532 -0.9076459563329236, 533 -0.8986873885126239, 534 -0.8893372414942055, 535 -0.8795995893549102, 536 -0.8694786750173527, 537 -0.8589789084007133, 538 -0.8481048644991847, 539 -0.8368612813885015, 540 -0.8252530581614230, 541 -0.8132852527930605, 542 -0.8009630799369827, 543 -0.7882919086530552, 544 -0.7752772600680049, 545 -0.7619248049697269, 546 -0.7482403613363824, 547 -0.7342298918013638, 548 -0.7198995010552305, 549 -0.7052554331857488, 550 -0.6903040689571928, 551 -0.6750519230300931, 552 -0.6595056411226444, 553 -0.6436719971150083, 554 -0.6275578900977726, 555 -0.6111703413658551, 556 -0.5945164913591590, 557 -0.5776035965513142, 558 -0.5604390262878617, 559 -0.5430302595752546, 560 -0.5253848818220803, 561 -0.5075105815339176, 562 -0.4894151469632753, 563 -0.4711064627160663, 564 -0.4525925063160997, 565 -0.4338813447290861, 566 -0.4149811308476706, 567 -0.3959000999390257, 568 -0.3766465660565522, 569 -0.3572289184172501, 570 -0.3376556177463400, 571 -0.3179351925907259, 572 -0.2980762356029071, 573 -0.2780873997969574, 574 -0.2579773947782034, 575 -0.2377549829482451, 576 -0.2174289756869712, 577 -0.1970082295132342, 578 -0.1765016422258567, 579 -0.1559181490266516, 580 -0.1352667186271445, 581 -0.1145563493406956, 582 -0.0937960651617229, 583 -0.0729949118337358, 584 -0.0521619529078925, 585 -0.0313062657937972, 586 -0.0104369378042598, 587 0.0104369378042598, 588 0.0313062657937972, 589 0.0521619529078925, 590 0.0729949118337358, 591 0.0937960651617229, 592 0.1145563493406956, 593 0.1352667186271445, 594 0.1559181490266516, 595 0.1765016422258567, 596 0.1970082295132342, 597 0.2174289756869712, 598 0.2377549829482451, 599 0.2579773947782034, 600 0.2780873997969574, 601 0.2980762356029071, 602 0.3179351925907259, 603 0.3376556177463400, 604 0.3572289184172501, 605 0.3766465660565522, 606 0.3959000999390257, 607 0.4149811308476706, 608 0.4338813447290861, 609 0.4525925063160997, 610 0.4711064627160663, 611 0.4894151469632753, 612 0.5075105815339176, 613 0.5253848818220803, 614 0.5430302595752546, 615 0.5604390262878617, 616 0.5776035965513142, 617 0.5945164913591590, 618 0.6111703413658551, 619 0.6275578900977726, 620 0.6436719971150083, 621 0.6595056411226444, 622 0.6750519230300931, 623 0.6903040689571928, 624 0.7052554331857488, 625 0.7198995010552305, 626 0.7342298918013638, 627 0.7482403613363824, 628 0.7619248049697269, 629 0.7752772600680049, 630 0.7882919086530552, 631 0.8009630799369827, 632 0.8132852527930605, 633 0.8252530581614230, 634 0.8368612813885015, 635 0.8481048644991847, 636 0.8589789084007133, 637 0.8694786750173527, 638 0.8795995893549102, 639 0.8893372414942055, 640 0.8986873885126239, 641 0.9076459563329236, 642 0.9162090414984952, 643 0.9243729128743136, 644 0.9321340132728527, 645 0.9394889610042837, 646 0.9464345513503147, 647 0.9529677579610971, 648 0.9590857341746905, 649 0.9647858142586956, 650 0.9700655145738374, 651 0.9749225346595943, 652 0.9793547582425894, 653 0.9833602541697529, 654 0.9869372772712794, 655 0.9900842691660192, 656 0.9927998590434373, 657 0.9950828645255290, 658 0.9969322929775997, 659 0.9983473449340834, 660 0.9993274305065947, 661 0.9998723404457334 662 ]), 663 w=np.array([ 664 0.0003276086705538, 665 0.0007624720924706, 666 0.0011976474864367, 667 0.0016323569986067, 668 0.0020663664924131, 669 0.0024994789888943, 670 0.0029315036836558, 671 0.0033622516236779, 672 0.0037915348363451, 673 0.0042191661429919, 674 0.0046449591497966, 675 0.0050687282939456, 676 0.0054902889094487, 677 0.0059094573005900, 678 0.0063260508184704, 679 0.0067398879387430, 680 0.0071507883396855, 681 0.0075585729801782, 682 0.0079630641773633, 683 0.0083640856838475, 684 0.0087614627643580, 685 0.0091550222717888, 686 0.0095445927225849, 687 0.0099300043714212, 688 0.0103110892851360, 689 0.0106876814158841, 690 0.0110596166734735, 691 0.0114267329968529, 692 0.0117888704247183, 693 0.0121458711652067, 694 0.0124975796646449, 695 0.0128438426753249, 696 0.0131845093222756, 697 0.0135194311690004, 698 0.0138484622795371, 699 0.0141714592928592, 700 0.0144882814685445, 701 0.0147987907597169, 702 0.0151028518701744, 703 0.0154003323133401, 704 0.0156911024699895, 705 0.0159750356447283, 706 0.0162520081211971, 707 0.0165218992159766, 708 0.0167845913311726, 709 0.0170399700056559, 710 0.0172879239649355, 711 0.0175283451696437, 712 0.0177611288626114, 713 0.0179861736145128, 714 0.0182033813680609, 715 0.0184126574807331, 716 0.0186139107660094, 717 0.0188070535331042, 718 0.0189920016251754, 719 0.0191686744559934, 720 0.0193369950450545, 721 0.0194968900511231, 722 0.0196482898041878, 723 0.0197911283358190, 724 0.0199253434079123, 725 0.0200508765398072, 726 0.0201676730337687, 727 0.0202756819988200, 728 0.0203748563729175, 729 0.0204651529434560, 730 0.0205465323660984, 731 0.0206189591819181, 732 0.0206824018328499, 733 0.0207368326754401, 734 0.0207822279928917, 735 0.0208185680053983, 736 0.0208458368787627, 737 0.0208640227312962, 738 0.0208731176389954, 739 0.0208731176389954, 740 0.0208640227312962, 741 0.0208458368787627, 742 0.0208185680053983, 743 0.0207822279928917, 744 0.0207368326754401, 745 0.0206824018328499, 746 0.0206189591819181, 747 0.0205465323660984, 748 0.0204651529434560, 749 0.0203748563729175, 750 0.0202756819988200, 751 0.0201676730337687, 752 0.0200508765398072, 753 0.0199253434079123, 754 0.0197911283358190, 755 0.0196482898041878, 756 0.0194968900511231, 757 0.0193369950450545, 758 0.0191686744559934, 759 0.0189920016251754, 760 0.0188070535331042, 761 0.0186139107660094, 762 0.0184126574807331, 763 0.0182033813680609, 764 0.0179861736145128, 765 0.0177611288626114, 766 0.0175283451696437, 767 0.0172879239649355, 768 0.0170399700056559, 769 0.0167845913311726, 770 0.0165218992159766, 771 0.0162520081211971, 772 0.0159750356447283, 773 0.0156911024699895, 774 0.0154003323133401, 775 0.0151028518701744, 776 0.0147987907597169, 777 0.0144882814685445, 778 0.0141714592928592, 779 0.0138484622795371, 780 0.0135194311690004, 781 0.0131845093222756, 782 0.0128438426753249, 783 0.0124975796646449, 784 0.0121458711652067, 785 0.0117888704247183, 786 0.0114267329968529, 787 0.0110596166734735, 788 0.0106876814158841, 789 0.0103110892851360, 790 0.0099300043714212, 791 0.0095445927225849, 792 0.0091550222717888, 793 0.0087614627643580, 794 0.0083640856838475, 795 0.0079630641773633, 796 0.0075585729801782, 797 0.0071507883396855, 798 0.0067398879387430, 799 0.0063260508184704, 800 0.0059094573005900, 801 0.0054902889094487, 802 0.0050687282939456, 803 0.0046449591497966, 804 0.0042191661429919, 805 0.0037915348363451, 806 0.0033622516236779, 807 0.0029315036836558, 808 0.0024994789888943, 809 0.0020663664924131, 810 0.0016323569986067, 811 0.0011976474864367, 812 0.0007624720924706, 813 0.0003276086705538 814 ]) 815 )
Note: See TracChangeset
for help on using the changeset viewer.