Changeset 502c7b8 in sasmodels
- Timestamp:
- Aug 7, 2018 5:14:59 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:
- 7b0abf8
- Parents:
- cdd676e (diff), 01c8d9e (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. - Files:
-
- 6 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
explore/beta/sasfit_compare.py
rcdd676e r502c7b8 3 3 import sys, os 4 4 BETA_DIR = os.path.dirname(os.path.realpath(__file__)) 5 SASMODELS_DIR = os.path.dirname(os.path.dirname(BETA_DIR)) 5 #SASMODELS_DIR = os.path.dirname(os.path.dirname(BETA_DIR)) 6 SASMODELS_DIR = r"C:\Source\sasmodels" 6 7 sys.path.insert(0, SASMODELS_DIR) 7 8 … … 61 62 calculator = DirectModel(data, model,cutoff=0) 62 63 calculator.pars = pars.copy() 63 calculator.pars.setdefault('background', 1e-3)64 calculator.pars.setdefault('background', 0) 64 65 return calculator 65 66 … … 231 232 # = F2/total_volume 232 233 IQD = F2/average_volume*1e-4*volfraction 234 F1 *= 1e-2 # Yun is using sld in 1/A^2, not 1e-6/A^2 235 F2 *= 1e-4 233 236 elif norm == 'yun': 234 237 F1 *= 1e-6 # Yun is using sld in 1/A^2, not 1e-6/A^2 … … 336 339 I = build_model(Pname+"@hardsphere", q) 337 340 Pq = P(**Ppars)*pars.get('volfraction', 1) 338 #Sq = S(**Spars)341 Sq = S(**Spars) 339 342 Iq = I(**Ipars) 340 343 #Iq = Pq*Sq*pars.get('volfraction', 1) 341 Sq = Iq/Pq 342 return Theory(Q=q, F1=None, F2=None, P=Pq, S=Sq, I=Iq, Seff=None, Ibeta=None) 344 #Sq = Iq/Pq 345 #Iq = None#= Sq = None 346 r=I._kernel.results 347 return Theory(Q=q, F1=None, F2=None, P=Pq, S=None, I=None, Seff=r[1], Ibeta=Iq) 343 348 344 349 def compare(title, target, actual, fields='F1 F2 P S I Seff Ibeta'): … … 400 405 radius_equatorial_pd=.1, radius_equatorial_pd_type=pd_type, 401 406 volfraction=0.15, 407 radius_effective=270.7543927018, 402 408 #radius_effective=12.59921049894873, 403 409 ) 404 target = sasmodels_theory(q, model, **pars)410 target = sasmodels_theory(q, model, beta_mode=1, **pars) 405 411 actual = ellipsoid_pe(q, norm='sasview', **pars) 406 412 title = " ".join(("sasmodels", model, pd_type)) … … 450 456 S = data[5] 451 457 Seff = data[6] 452 target = Theory(Q=Q, F1=F1, F2=F2,P=P, S=S, Seff=Seff)458 target = Theory(Q=Q, F1=F1, P=P, S=S, Seff=Seff) 453 459 actual = sphere_r(Q, norm='yun', **pars) 454 460 title = " ".join(("yun", "sphere", "10% dispersion 10% Vf")) … … 462 468 S = data[5] 463 469 Seff = data[6] 464 target = Theory(Q=Q, F1=F1, F2=F2,P=P, S=S, Seff=Seff)470 target = Theory(Q=Q, F1=F1, P=P, S=S, Seff=Seff) 465 471 actual = sphere_r(Q, norm='yun', **pars) 466 472 title = " ".join(("yun", "sphere", "15% dispersion 10% Vf")) -
sasmodels/core.py
r3221de0 r01c8d9e 140 140 used with functions in generate to build the docs or extract model info. 141 141 """ 142 142 143 if "+" in model_string: 143 144 parts = [load_model_info(part) … … 205 206 206 207 numpy_dtype, fast, platform = parse_dtype(model_info, dtype, platform) 207 208 208 source = generate.make_source(model_info) 209 209 if platform == "dll": … … 265 265 # Assign default platform, overriding ocl with dll if OpenCL is unavailable 266 266 # If opencl=False OpenCL is switched off 267 268 267 if platform is None: 269 268 platform = "ocl" … … 291 290 else: 292 291 numpy_dtype = np.dtype(dtype) 293 294 292 # Make sure that the type is supported by opencl, otherwise use dll 295 293 if platform == "ocl": -
sasmodels/data.py
r65fbf7c r01c8d9e 329 329 else: 330 330 dq = resolution * q 331 332 331 data = Data1D(q, Iq, dx=dq, dy=dIq) 333 332 data.filename = "fake data" … … 523 522 else 'log') 524 523 plt.xscale(xscale) 524 525 525 plt.xlabel("$q$/A$^{-1}$") 526 526 plt.yscale(yscale) -
sasmodels/generate.py
rd86f0fc r01c8d9e 672 672 673 673 # type in IQXY pattern could be single, float, double, long double, ... 674 _IQXY_PATTERN = re.compile(r"(^|\s)double\s+I(?P<mode>q(a b?c|xy))\s*[(]",674 _IQXY_PATTERN = re.compile(r"(^|\s)double\s+I(?P<mode>q(ac|abc|xy))\s*[(]", 675 675 flags=re.MULTILINE) 676 676 def find_xy_mode(source): … … 701 701 return 'qa' 702 702 703 # type in IQXY pattern could be single, float, double, long double, ... 704 _FQ_PATTERN = re.compile(r"(^|\s)void\s+Fq[(]", flags=re.MULTILINE) 705 def has_Fq(source): 706 for code in source: 707 m = _FQ_PATTERN.search(code) 708 if m is not None: 709 return True 710 return False 703 711 704 712 def _add_source(source, code, path, lineno=1): … … 730 738 # dispersion. Need to be careful that necessary parameters are available 731 739 # for computing volume even if we allow non-disperse volume parameters. 732 733 740 partable = model_info.parameters 734 735 741 # Load templates and user code 736 742 kernel_header = load_template('kernel_header.c') 737 743 kernel_code = load_template('kernel_iq.c') 738 744 user_code = [(f, open(f).read()) for f in model_sources(model_info)] 739 740 745 # Build initial sources 741 746 source = [] … … 743 748 for path, code in user_code: 744 749 _add_source(source, code, path) 745 746 750 if model_info.c_code: 747 751 _add_source(source, model_info.c_code, model_info.filename, … … 789 793 source.append("\\\n".join(p.as_definition() 790 794 for p in partable.kernel_parameters)) 791 792 795 # Define the function calls 793 796 if partable.form_volume_parameters: … … 800 803 call_volume = "#define CALL_VOLUME(v) 1.0" 801 804 source.append(call_volume) 802 803 805 model_refs = _call_pars("_v.", partable.iq_parameters) 804 pars = ",".join(["_q"] + model_refs) 805 call_iq = "#define CALL_IQ(_q, _v) Iq(%s)" % pars 806 #create varaible BETA to turn on and off beta approximation 807 BETA = has_Fq(source) 808 if not BETA: 809 pars = ",".join(["_q"] + model_refs) 810 call_iq = "#define CALL_IQ(_q, _v) Iq(%s)" % pars 811 else: 812 pars = ",".join(["_q", "&_F1", "&_F2",] + model_refs) 813 call_iq = "#define CALL_IQ(_q, _F1, _F2, _v) Fq(%s)" % pars 806 814 if xy_mode == 'qabc': 807 815 pars = ",".join(["_qa", "_qb", "_qc"] + model_refs) … … 831 839 magpars = [k-2 for k, p in enumerate(partable.call_parameters) 832 840 if p.type == 'sld'] 833 834 841 # Fill in definitions for numbers of parameters 842 source.append("#define BETA %d" %(1 if BETA else 0)) 835 843 source.append("#define MAX_PD %s"%partable.max_pd) 836 844 source.append("#define NUM_PARS %d"%partable.npars) … … 839 847 source.append("#define MAGNETIC_PARS %s"%",".join(str(k) for k in magpars)) 840 848 source.append("#define PROJECTION %d"%PROJECTION) 841 842 849 # TODO: allow mixed python/opencl kernels? 843 844 850 ocl = _kernels(kernel_code, call_iq, call_iqxy, clear_iqxy, model_info.name) 845 851 dll = _kernels(kernel_code, call_iq, call_iqxy, clear_iqxy, model_info.name) 852 846 853 result = { 847 854 'dll': '\n'.join(source+dll[0]+dll[1]+dll[2]), 848 855 'opencl': '\n'.join(source+ocl[0]+ocl[1]+ocl[2]), 849 856 } 850 857 #print(result['dll']) 851 858 return result 852 859 … … 1068 1075 model_info = make_model_info(kernel_module) 1069 1076 source = make_source(model_info) 1070 print(source['dll'])1077 #print(source['dll']) 1071 1078 1072 1079 -
sasmodels/kernel_iq.c
r7c35fda r01c8d9e 36 36 // PROJECTION : equirectangular=1, sinusoidal=2 37 37 // see explore/jitter.py for definitions. 38 38 39 39 40 #ifndef _PAR_BLOCK_ // protected block so we can include this code twice. … … 270 271 #endif // _QABC_SECTION 271 272 272 273 273 // ==================== KERNEL CODE ======================== 274 275 274 kernel 276 275 void KERNEL_NAME( … … 339 338 // The code differs slightly between opencl and dll since opencl is only 340 339 // seeing one q value (stored in the variable "this_result") while the dll 341 // version must loop over all q. 340 // version must loop over all q 341 #if BETA 342 double *beta_result = &(result[nq+1]); // = result + nq + 1 343 double weight_norm = (pd_start == 0 ? 0.0 : result[2*nq+1]); 344 #endif 342 345 #ifdef USE_OPENCL 343 346 double pd_norm = (pd_start == 0 ? 0.0 : result[nq]); 344 347 double this_result = (pd_start == 0 ? 0.0 : result[q_index]); 348 #if BETA 349 double this_beta_result = (pd_start == 0 ? 0.0 : result[nq + q_index]; 345 350 #else // !USE_OPENCL 346 double pd_norm = (pd_start == 0 ? 0.0 : result[nq]); 351 double pd_norm = (pd_start == 0 ? 0.0 : result[nq]); 347 352 if (pd_start == 0) { 348 353 #ifdef USE_OPENMP … … 350 355 #endif 351 356 for (int q_index=0; q_index < nq; q_index++) result[q_index] = 0.0; 357 #if BETA 358 for (int q_index=0; q_index < nq; q_index++) beta_result[q_index] = 0.0; 359 #endif 352 360 } 353 361 //if (q_index==0) printf("start %d %g %g\n", pd_start, pd_norm, result[0]); 354 362 #endif // !USE_OPENCL 363 364 365 355 366 356 367 … … 442 453 // inner loop and defines the macros that use them. 443 454 455 444 456 #if defined(CALL_IQ) 445 457 // unoriented 1D 446 458 double qk; 447 #define FETCH_Q() do { qk = q[q_index]; } while (0) 448 #define BUILD_ROTATION() do {} while(0) 449 #define APPLY_ROTATION() do {} while(0) 450 #define CALL_KERNEL() CALL_IQ(qk, local_values.table) 459 #if BETA == 0 460 #define FETCH_Q() do { qk = q[q_index]; } while (0) 461 #define BUILD_ROTATION() do {} while(0) 462 #define APPLY_ROTATION() do {} while(0) 463 #define CALL_KERNEL() CALL_IQ(qk,local_values.table) 464 465 // unoriented 1D Beta 466 #elif BETA == 1 467 double F1, F2; 468 #define FETCH_Q() do { qk = q[q_index]; } while (0) 469 #define BUILD_ROTATION() do {} while(0) 470 #define APPLY_ROTATION() do {} while(0) 471 #define CALL_KERNEL() CALL_IQ(qk,F1,F2,local_values.table) 472 #endif 451 473 452 474 #elif defined(CALL_IQ_A) … … 647 669 pd_norm += weight * CALL_VOLUME(local_values.table); 648 670 BUILD_ROTATION(); 649 671 #if BETA 672 if (weight > cutoff) { 673 weight_norm += weight;} 674 #endif 650 675 #ifndef USE_OPENCL 651 676 // DLL needs to explicitly loop over the q values. … … 693 718 } 694 719 #else // !MAGNETIC 695 const double scattering = CALL_KERNEL(); 720 #if defined(CALL_IQ) && BETA == 1 721 CALL_KERNEL(); 722 const double scatteringF1 = F1; 723 const double scatteringF2 = F2; 724 #else 725 const double scattering = CALL_KERNEL(); 726 #endif 696 727 #endif // !MAGNETIC 697 728 //printf("q_index:%d %g %g %g %g\n", q_index, scattering, weight0); 698 729 699 730 #ifdef USE_OPENCL 700 this_result += weight * scattering; 731 #if defined(CALL_IQ)&& BETA == 1 732 this_result += weight * scatteringF2; 733 this_beta_result += weight * scatteringF1; 734 #else 735 this_result += weight * scattering; 736 #endif 701 737 #else // !USE_OPENCL 702 result[q_index] += weight * scattering; 738 #if defined(CALL_IQ)&& BETA == 1 739 result[q_index] += weight * scatteringF2; 740 beta_result[q_index] += weight * scatteringF1; 741 #endif 742 #else 743 result[q_index] += weight * scattering; 744 #endif 703 745 #endif // !USE_OPENCL 704 746 } 705 747 } 706 748 } 707 708 749 // close nested loops 709 750 ++step; … … 728 769 result[q_index] = this_result; 729 770 if (q_index == 0) result[nq] = pd_norm; 771 #if BETA 772 beta_result[q_index] = this_beta_result; 773 #endif 774 if (q_index == 0) result[nq] = pd_norm; 775 730 776 //if (q_index == 0) printf("res: %g/%g\n", result[0], pd_norm); 731 777 #else // !USE_OPENCL 732 778 result[nq] = pd_norm; 779 #if BETA 780 result[2*nq+1] = weight_norm; 781 #endif 733 782 //printf("res: %g/%g\n", result[0], pd_norm); 734 783 #endif // !USE_OPENCL -
sasmodels/kernelcl.py
rd86f0fc r01c8d9e 420 420 if self.program is None: 421 421 compile_program = environment().compile_program 422 with open('model.c','w') as fid: 423 print(self.source['opencl'], file=fid) 422 424 timestamp = generate.ocl_timestamp(self.info) 423 425 self.program = compile_program( … … 539 541 self.dim = '2d' if q_input.is_2d else '1d' 540 542 # plus three for the normalization values 541 self.result = np.empty( q_input.nq+1,dtype)543 self.result = np.empty(2*q_input.nq+2,dtype) 542 544 543 545 # Inputs and outputs for each kernel call … … 555 557 else np.float16 if dtype == generate.F16 556 558 else np.float32) # will never get here, so use np.float32 557 558 def __call__(self, call_details, values, cutoff, magnetic): 559 __call__= Iq 560 561 def Iq(self, call_details, values, cutoff, magnetic): 559 562 # type: (CallDetails, np.ndarray, np.ndarray, float, bool) -> np.ndarray 560 563 context = self.queue.context … … 572 575 ] 573 576 #print("Calling OpenCL") 574 #call_details.show(values)575 # 577 call_details.show(values) 578 #Call kernel and retrieve results 576 579 wait_for = None 577 580 last_nap = time.clock() … … 604 607 return scale*self.result[:self.q_input.nq] + background 605 608 # return self.result[:self.q_input.nq] 609 #NEEDS TO BE FINISHED FOR OPENCL 610 def beta(): 611 return 0 606 612 607 613 def release(self): -
sasmodels/kerneldll.py
r33969b6 r01c8d9e 258 258 # Note: if there is a syntax error then compile raises an error 259 259 # and the source file will not be deleted. 260 os.unlink(filename)261 #print("saving compiled file in %r"%filename)260 #os.unlink(filename) 261 print("saving compiled file in %r"%filename) 262 262 return dll 263 263 … … 371 371 def __init__(self, kernel, model_info, q_input): 372 372 # type: (Callable[[], np.ndarray], ModelInfo, PyInput) -> None 373 #,model_info,q_input) 373 374 self.kernel = kernel 374 375 self.info = model_info … … 376 377 self.dtype = q_input.dtype 377 378 self.dim = '2d' if q_input.is_2d else '1d' 378 self.result = np.empty( q_input.nq+1, q_input.dtype)379 self.result = np.empty(2*q_input.nq+2, q_input.dtype) 379 380 self.real = (np.float32 if self.q_input.dtype == generate.F32 380 381 else np.float64 if self.q_input.dtype == generate.F64 381 382 else np.float128) 382 383 383 def __call__(self, call_details, values, cutoff, magnetic):384 def Iq(self, call_details, values, cutoff, magnetic): 384 385 # type: (CallDetails, np.ndarray, np.ndarray, float, bool) -> np.ndarray 385 386 self._call_kernel(call_details, values, cutoff, magnetic) 387 #print("returned",self.q_input.q, self.result) 388 pd_norm = self.result[self.q_input.nq] 389 scale = values[0]/(pd_norm if pd_norm != 0.0 else 1.0) 390 background = values[1] 391 #print("scale",scale,background) 392 return scale*self.result[:self.q_input.nq] + background 393 __call__ = Iq 394 395 def beta(self, call_details, values, cutoff, magnetic): 396 # type: (CallDetails, np.ndarray, np.ndarray, float, bool) -> np.ndarray 397 self._call_kernel(call_details, values, cutoff, magnetic) 398 w_norm = self.result[2*self.q_input.nq + 1] 399 pd_norm = self.result[self.q_input.nq] 400 if w_norm == 0.: 401 w_norm = 1. 402 F2 = self.result[:self.q_input.nq]/w_norm 403 F1 = self.result[self.q_input.nq+1:2*self.q_input.nq+1]/w_norm 404 volume_avg = pd_norm/w_norm 405 return F1, F2, volume_avg 406 407 def _call_kernel(self, call_details, values, cutoff, magnetic): 386 408 kernel = self.kernel[1 if magnetic else 0] 387 409 args = [ … … 390 412 None, # pd_stop pd_stride[MAX_PD] 391 413 call_details.buffer.ctypes.data, # problem 392 values.ctypes.data, # pars393 self.q_input.q.ctypes.data, # q414 values.ctypes.data, # pars 415 self.q_input.q.ctypes.data, # q 394 416 self.result.ctypes.data, # results 395 417 self.real(cutoff), # cutoff 396 418 ] 397 #print("Calling DLL") 419 #print(self.beta_result.ctypes.data) 420 # print("Calling DLL line 397") 421 # print("values", values) 398 422 #call_details.show(values) 399 423 step = 100 … … 403 427 kernel(*args) # type: ignore 404 428 405 #print("returned",self.q_input.q, self.result)406 pd_norm = self.result[self.q_input.nq]407 scale = values[0]/(pd_norm if pd_norm != 0.0 else 1.0)408 background = values[1]409 #print("scale",scale,background)410 return scale*self.result[:self.q_input.nq] + background411 412 429 def release(self): 413 430 # type: () -> None -
sasmodels/modelinfo.py
r95498a3 r01c8d9e 163 163 parameter.length = length 164 164 parameter.length_control = control 165 166 165 return parameter 167 166 … … 418 417 # scale and background are implicit parameters 419 418 COMMON = [Parameter(*p) for p in COMMON_PARAMETERS] 420 421 419 def __init__(self, parameters): 422 420 # type: (List[Parameter]) -> None 423 421 self.kernel_parameters = parameters 424 422 self._set_vector_lengths() 425 426 423 self.npars = sum(p.length for p in self.kernel_parameters) 427 424 self.nmagnetic = sum(p.length for p in self.kernel_parameters … … 430 427 if self.nmagnetic: 431 428 self.nvalues += 3 + 3*self.nmagnetic 432 433 429 self.call_parameters = self._get_call_parameters() 434 430 self.defaults = self._get_defaults() … … 444 440 self.form_volume_parameters = [p for p in self.kernel_parameters 445 441 if p.type == 'volume'] 446 447 442 # Theta offset 448 443 offset = 0 … … 466 461 self.magnetism_index = [k for k, p in enumerate(self.call_parameters) 467 462 if p.id.startswith('M0:')] 468 469 463 self.pd_1d = set(p.name for p in self.call_parameters 470 464 if p.polydisperse and p.type not in ('orientation', 'magnetic')) … … 770 764 # Custom sum/multi models 771 765 return kernel_module.model_info 766 772 767 info = ModelInfo() 773 768 #print("make parameter table", kernel_module.parameters) … … 822 817 info.lineno = {} 823 818 _find_source_lines(info, kernel_module) 824 825 819 return info 826 820 -
sasmodels/models/ellipsoid.c
r108e70e r01c8d9e 20 20 // i(h) = int_0^1 Phi^2(h a sqrt(1 + u^2(v^2-1)) du 21 21 const double v_square_minus_one = square(radius_polar/radius_equatorial) - 1.0; 22 22 23 23 // translate a point in [-1,1] to a point in [0, 1] 24 24 // const double u = GAUSS_Z[i]*(upper-lower)/2 + (upper+lower)/2; … … 36 36 const double s = (sld - sld_solvent) * form_volume(radius_polar, radius_equatorial); 37 37 return 1.0e-4 * s * s * form; 38 } 39 40 static void 41 Fq(double q, 42 double *F1, 43 double *F2, 44 double sld, 45 double sld_solvent, 46 double radius_polar, 47 double radius_equatorial) 48 { 49 // Using ratio v = Rp/Re, we can implement the form given in Guinier (1955) 50 // i(h) = int_0^pi/2 Phi^2(h a sqrt(cos^2 + v^2 sin^2) cos dT 51 // = int_0^pi/2 Phi^2(h a sqrt((1-sin^2) + v^2 sin^2) cos dT 52 // = int_0^pi/2 Phi^2(h a sqrt(1 + sin^2(v^2-1)) cos dT 53 // u-substitution of 54 // u = sin, du = cos dT 55 // i(h) = int_0^1 Phi^2(h a sqrt(1 + u^2(v^2-1)) du 56 const double v_square_minus_one = square(radius_polar/radius_equatorial) - 1.0; 57 // translate a point in [-1,1] to a point in [0, 1] 58 // const double u = GAUSS_Z[i]*(upper-lower)/2 + (upper+lower)/2; 59 const double zm = 0.5; 60 const double zb = 0.5; 61 double total_F2 = 0.0; 62 double total_F1 = 0.0; 63 for (int i=0;i<GAUSS_N;i++) { 64 const double u = GAUSS_Z[i]*zm + zb; 65 const double r = radius_equatorial*sqrt(1.0 + u*u*v_square_minus_one); 66 const double f = sas_3j1x_x(q*r); 67 total_F2 += GAUSS_W[i] * f * f; 68 total_F1 += GAUSS_W[i] * f; 69 } 70 // translate dx in [-1,1] to dx in [lower,upper] 71 const double form_squared_avg = total_F2*zm; 72 const double form_avg = total_F1*zm; 73 const double s = (sld - sld_solvent) * form_volume(radius_polar, radius_equatorial); 74 *F2 = 1e-4 * s * s * form_squared_avg; 75 *F1 = 1e-2 * s * form_avg; 38 76 } 77 78 79 80 81 39 82 40 83 static double -
sasmodels/models/lib/sphere_form.c
r925ad6e r01c8d9e 13 13 return 1.0e-4*square(contrast * fq); 14 14 } 15 -
sasmodels/models/sphere.py
ref07e95 r01c8d9e 67 67 ] 68 68 69 source = ["lib/sas_3j1x_x.c", "lib/sphere_form.c" ]69 source = ["lib/sas_3j1x_x.c", "lib/sphere_form.c", "sphere.c"] 70 70 71 # No volume normalization despite having a volume parameter72 # This should perhaps be volume normalized?73 form_volume = """74 return sphere_volume(radius);75 """76 77 Iq = """78 return sphere_form(q, radius, sld, sld_solvent);79 """80 71 81 72 def ER(radius): -
sasmodels/product.py
r2d81cfe r01c8d9e 16 16 import numpy as np # type: ignore 17 17 18 from .modelinfo import ParameterTable, ModelInfo 18 from .modelinfo import ParameterTable, ModelInfo, Parameter 19 19 from .kernel import KernelModel, Kernel 20 20 from .details import make_details, dispersion_mesh … … 74 74 translate_name = dict((old.id, new.id) for old, new 75 75 in zip(s_pars.kernel_parameters[1:], s_list)) 76 combined_pars = p_pars.kernel_parameters + s_list 76 beta_parameter = Parameter("beta_mode", "", 0, [["P*S"],["P*(1+beta*(S-1))"], "", "Structure factor dispersion calculation mode"]) 77 combined_pars = p_pars.kernel_parameters + s_list + [beta_parameter] 77 78 parameters = ParameterTable(combined_pars) 78 79 parameters.max_pd = p_pars.max_pd + s_pars.max_pd … … 151 152 #: Structure factor modelling interaction between particles. 152 153 self.S = S 154 153 155 #: Model precision. This is not really relevant, since it is the 154 156 #: individual P and S models that control the effective dtype, … … 168 170 # in opencl; or both in opencl, but one in single precision and the 169 171 # other in double precision). 172 170 173 p_kernel = self.P.make_kernel(q_vectors) 171 174 s_kernel = self.S.make_kernel(q_vectors) … … 193 196 # type: (CallDetails, np.ndarray, float, bool) -> np.ndarray 194 197 p_info, s_info = self.info.composition[1] 195 196 198 # if there are magnetic parameters, they will only be on the 197 199 # form factor P, not the structure factor S. … … 205 207 nweights = call_details.num_weights 206 208 weights = values[nvalues:nvalues + 2*nweights] 207 208 209 # Construct the calling parameters for P. 209 210 p_npars = p_info.parameters.npars … … 218 219 p_values.append([0.]*spacer) 219 220 p_values = np.hstack(p_values).astype(self.p_kernel.dtype) 220 221 221 # Call ER and VR for P since these are needed for S. 222 222 p_er, p_vr = calc_er_vr(p_info, p_details, p_values) 223 223 s_vr = (volfrac/p_vr if p_vr != 0. else volfrac) 224 224 #print("volfrac:%g p_er:%g p_vr:%g s_vr:%g"%(volfrac,p_er,p_vr,s_vr)) 225 226 225 # Construct the calling parameters for S. 227 226 # The effective radius is not in the combined parameter list, so … … 253 252 s_values.append([0.]*spacer) 254 253 s_values = np.hstack(s_values).astype(self.s_kernel.dtype) 255 254 # beta mode is the first parameter after the structure factor pars 255 beta_index = 2+p_npars+s_npars 256 beta_mode = values[beta_index] 256 257 # Call the kernels 257 p_result = self.p_kernel(p_details, p_values, cutoff, magnetic) 258 s_result = self.s_kernel(s_details, s_values, cutoff, False) 259 258 if beta_mode: # beta: 259 F1, F2, volume_avg = self.p_kernel.beta(p_details, p_values, cutoff, magnetic) 260 else: 261 p_result = self.p_kernel.Iq(p_details, p_values, cutoff, magnetic) 262 s_result = self.s_kernel.Iq(s_details, s_values, cutoff, False) 260 263 #print("p_npars",p_npars,s_npars,p_er,s_vr,values[2+p_npars+1:2+p_npars+s_npars]) 261 264 #call_details.show(values) … … 265 268 #s_details.show(s_values) 266 269 #print("=>", s_result) 267 268 # remember the parts for plotting later269 self.results = [p_result, s_result]270 271 270 #import pylab as plt 272 271 #plt.subplot(211); plt.loglog(self.p_kernel.q_input.q, p_result, '-') 273 272 #plt.subplot(212); plt.loglog(self.s_kernel.q_input.q, s_result, '-') 274 273 #plt.figure() 275 276 return values[0]*(p_result*s_result) + values[1] 274 if beta_mode:#beta 275 beta_factor = F1**2/F2 276 Sq_eff = 1+beta_factor*(s_result - 1) 277 self.results = [F2, Sq_eff,F1,s_result] 278 final_result = volfrac*values[0]*(F2 + (F1**2)*(s_result - 1))/volume_avg+values[1] 279 #final_result = volfrac * values[0] * F2 * Sq_eff / volume_avg + values[1] 280 else: 281 # remember the parts for plotting later 282 self.results = [p_result, s_result] 283 final_result = values[0]*(p_result*s_result) + values[1] 284 return final_result 277 285 278 286 def release(self): -
doc/guide/pd/polydispersity.rst
r29afc50 rd712a0f 20 20 P(q) = \text{scale} \langle F^* F \rangle / V + \text{background} 21 21 22 where $F$ is the scattering amplitude and $\langle\cdot\rangle$ denotes an 23 average over the size distribution. 22 where $F$ is the scattering amplitude and $\langle\cdot\rangle$ denotes an 23 average over the size distribution $f(x; \bar x, \sigma)$, giving 24 25 .. math:: 26 27 P(q) = \frac{\text{scale}}{V} \int_\mathbb{R} 28 f(x; \bar x, \sigma) F^2(q, x)\, dx + \text{background} 24 29 25 30 Each distribution is characterized by a center value $\bar x$ or … … 41 46 with larger values of $N_\sigma$ required for heavier tailed distributions. 42 47 The scattering in general falls rapidly with $qr$ so the usual assumption 43 that $ G(r - 3\sigma_r)$ is tiny and therefore $f(r - 3\sigma_r)G(r - 3\sigma_r)$48 that $f(r - 3\sigma_r)$ is tiny and therefore $f(r - 3\sigma_r)f(r - 3\sigma_r)$ 44 49 will not contribute much to the average may not hold when particles are large. 45 50 This, too, will require increasing $N_\sigma$. … … 63 68 64 69 Additional distributions are under consideration. 70 71 .. note:: In 2009 IUPAC decided to introduce the new term 'dispersity' to replace 72 the term 'polydispersity' (see `Pure Appl. Chem., (2009), 81(2), 73 351-353 <http://media.iupac.org/publications/pac/2009/pdf/8102x0351.pdf>`_ 74 in order to make the terminology describing distributions of properties 75 unambiguous. Throughout the SasView documentation we continue to use the 76 term polydispersity because one of the consequences of the IUPAC change is 77 that orientational polydispersity would not meet their new criteria (which 78 requires dispersity to be dimensionless). 65 79 66 80 Suggested Applications -
sasmodels/models/core_shell_sphere.py
r2d81cfe rdc76240 21 21 .. math:: 22 22 23 F ^2(q) = \frac{3}{V_s}\left[23 F(q) = \frac{3}{V_s}\left[ 24 24 V_c(\rho_c-\rho_s)\frac{\sin(qr_c)-qr_c\cos(qr_c)}{(qr_c)^3} + 25 25 V_s(\rho_s-\rho_\text{solv})\frac{\sin(qr_s)-qr_s\cos(qr_s)}{(qr_s)^3}
Note: See TracChangeset
for help on using the changeset viewer.