Changeset 9a7ef88 in sasmodels
- Timestamp:
- Apr 17, 2018 8:16:45 AM (7 years ago)
- Branches:
- master, core_shell_microgels, magnetic_model, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
- Children:
- 5400ad4
- Parents:
- 17a8c94 (diff), 7c3fb15 (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:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/guide/pd/polydispersity.rst
rf4ae8c4 r29afc50 28 28 sigmas $N_\sigma$ to include from the tails of the distribution, and the 29 29 number of points used to compute the average. The center of the distribution 30 is set by the value of the model parameter. 31 32 Volume parameters have polydispersity *PD* (not to be confused with a 33 molecular weight distributions in polymer science), but orientation parameters 34 use angular distributions of width $\sigma$. 30 is set by the value of the model parameter. The meaning of a polydispersity 31 parameter *PD* (not to be confused with a molecular weight distributions 32 in polymer science) in a model depends on the type of parameter it is being 33 applied too. 34 35 The distribution width applied to *volume* (ie, shape-describing) parameters 36 is relative to the center value such that $\sigma = \mathrm{PD} \cdot \bar x$. 37 However, the distribution width applied to *orientation* (ie, angle-describing) 38 parameters is just $\sigma = \mathrm{PD}$. 35 39 36 40 $N_\sigma$ determines how far into the tails to evaluate the distribution, … … 69 73 or angular orientations, use the Gaussian or Boltzmann distributions. 70 74 75 If applying polydispersion to parameters describing angles, use the Uniform 76 distribution. Beware of using distributions that are always positive (eg, the 77 Lognormal) because angles can be negative! 78 71 79 The array distribution allows a user-defined distribution to be applied. 72 80 … … 215 223 The polydispersity in sasmodels is given by 216 224 217 .. math:: \text{PD} = p = \sigma/ x_\text{med}218 219 The mean value of the distribution is given by $\bar x = \exp(\mu+ p^2/2)$220 and the peak value by $\max x = \exp(\mu - p^2)$.225 .. math:: \text{PD} = \sigma = p / x_\text{med} 226 227 The mean value of the distribution is given by $\bar x = \exp(\mu+ \sigma^2/2)$ 228 and the peak value by $\max x = \exp(\mu - \sigma^2)$. 221 229 222 230 The variance (the square of the standard deviation) of the *lognormal* … … 232 240 .. figure:: pd_lognormal.jpg 233 241 234 Lognormal distribution .242 Lognormal distribution for PD=0.1. 235 243 236 244 For further information on the Lognormal distribution see: … … 334 342 | 2017-05-08 Paul Kienzle 335 343 | 2018-03-20 Steve King 344 | 2018-04-04 Steve King -
explore/asymint.py
ra1c32c2 rc462169 30 30 import numpy as np 31 31 import mpmath as mp 32 from numpy import pi, sin, cos, sqrt, exp, expm1, degrees, log10 32 from numpy import pi, sin, cos, sqrt, exp, expm1, degrees, log10, arccos 33 33 from numpy.polynomial.legendre import leggauss 34 34 from scipy.integrate import dblquad, simps, romb, romberg … … 41 41 shape = 'parallelepiped' if len(sys.argv) < 2 else sys.argv[1] 42 42 Qstr = '0.005' if len(sys.argv) < 3 else sys.argv[2] 43 44 DTYPE = 'd' 43 45 44 46 class MPenv: … … 72 74 sas_sinx_x = staticmethod(sp.sas_sinx_x) 73 75 pi = np.pi 74 mpf = staticmethod(float) 76 #mpf = staticmethod(float) 77 mpf = staticmethod(lambda x: np.array(x, DTYPE)) 75 78 76 79 SLD = 3 … … 220 223 #A, B, C = 4450, 14000, 47 221 224 #A, B, C = 445, 140, 47 # integer for the sake of mpf 222 A, B, C = 6800, 114, 1380223 DA, DB, DC = 2 300, 21, 58225 A, B, C = 114, 1380, 6800 226 DA, DB, DC = 21, 58, 2300 224 227 SLDA, SLDB, SLDC = "5", "-0.3", "11.5" 228 ## default parameters from sasmodels 229 #A,B,C,DA,DB,DC,SLDA,SLDB,SLDC = 400,75,35,10,10,10,2,4,2 230 ## swap A-B-C to C-B-A 231 #A, B, C, DA, DB, DC, SLDA, SLDB, SLDC = C, B, A, DC, DB, DA, SLDC, SLDB, SLDA 225 232 #A,B,C,DA,DB,DC,SLDA,SLDB,SLDC = 10,20,30,100,200,300,1,2,3 226 233 #SLD_SOLVENT,CONTRAST = 0, 4 … … 233 240 DA, DC = DC, DA 234 241 SLDA, SLDC = SLDC, SLDA 242 #NORM, KERNEL = make_core_shell_parallelepiped(A, B, C, DA, DB, DC, SLDA, SLDB, SLDC) 235 243 NORM, KERNEL = make_core_shell_parallelepiped(A, B, C, DA, DB, DC, SLDA, SLDB, SLDC) 236 244 NORM_MP, KERNEL_MP = make_core_shell_parallelepiped(A, B, C, DA, DB, DC, SLDA, SLDB, SLDC, env=MPenv) … … 348 356 return n**2, Iq 349 357 358 def gauss_quad_usub(q, n=150, dtype=DTYPE): 359 """ 360 Compute the integral using gaussian quadrature for n = 20, 76 or 150. 361 362 Use *u = sin theta* substitution, and restrict integration over a single 363 quadrant for shapes that are mirror symmetric about AB, AC and BC planes. 364 365 Note that this doesn't work for fcc/bcc paracrystals, which instead step 366 over the entire 4 pi surface uniformly in theta-phi. 367 """ 368 z, w = leggauss(n) 369 cos_theta = 0.5 * (z + 1) 370 theta = arccos(cos_theta) 371 phi = pi/2*(0.5 * (z + 1)) 372 Atheta, Aphi = np.meshgrid(theta, phi) 373 Aw = w[None, :] * w[:, None] 374 q, Atheta, Aphi, Aw = [np.asarray(v, dtype=dtype) for v in (q, Atheta, Aphi, Aw)] 375 Zq = kernel_2d(q=q, theta=Atheta, phi=Aphi) 376 Iq = np.sum(Zq*Aw)*0.25 377 return n**2, Iq 378 350 379 def gridded_2d(q, n=300): 351 380 """ … … 395 424 print("gauss-1025", *gauss_quad_2d(Q, n=1025)) 396 425 print("gauss-2049", *gauss_quad_2d(Q, n=2049)) 426 print("gauss-20 usub", *gauss_quad_usub(Q, n=20)) 427 print("gauss-76 usub", *gauss_quad_usub(Q, n=76)) 428 print("gauss-150 usub", *gauss_quad_usub(Q, n=150)) 397 429 #gridded_2d(Q, n=2**8+1) 398 430 gridded_2d(Q, n=2**10+1) -
sasmodels/compare.py
rd86f0fc r5770493 752 752 """ 753 753 for k in range(opts['sets']): 754 if k > 1:754 if k > 0: 755 755 # print a separate seed for each dataset for better reproducibility 756 756 new_seed = np.random.randint(1000000) 757 print(" Set %d uses -random=%i"%(k+1, new_seed))757 print("=== Set %d uses -random=%i ==="%(k+1, new_seed)) 758 758 np.random.seed(new_seed) 759 759 opts['pars'] = parse_pars(opts, maxdim=maxdim) … … 762 762 result = run_models(opts, verbose=True) 763 763 if opts['plot']: 764 if opts['is2d'] and k > 0: 765 import matplotlib.pyplot as plt 766 plt.figure() 764 767 limits = plot_models(opts, result, limits=limits, setnum=k) 765 768 if opts['show_weights']: … … 1329 1332 1330 1333 # Evaluate preset parameter expressions 1334 # Note: need to replace ':' with '_' in parameter names and expressions 1335 # in order to support math on magnetic parameters. 1331 1336 context = MATH.copy() 1332 1337 context['np'] = np 1333 context.update( pars)1338 context.update((k.replace(':', '_'), v) for k, v in pars.items()) 1334 1339 context.update((k, v) for k, v in presets.items() if isinstance(v, float)) 1340 #for k,v in sorted(context.items()): print(k, v) 1335 1341 for k, v in presets.items(): 1336 1342 if not isinstance(v, float) and not k.endswith('_type'): 1337 presets[k] = eval(v , context)1343 presets[k] = eval(v.replace(':', '_'), context) 1338 1344 context.update(presets) 1339 context.update((k , v) for k, v in presets2.items() if isinstance(v, float))1345 context.update((k.replace(':', '_'), v) for k, v in presets2.items() if isinstance(v, float)) 1340 1346 for k, v in presets2.items(): 1341 1347 if not isinstance(v, float) and not k.endswith('_type'): 1342 presets2[k] = eval(v , context)1348 presets2[k] = eval(v.replace(':', '_'), context) 1343 1349 1344 1350 # update parameters with presets -
sasmodels/details.py
r108e70e r885753a 243 243 offset = np.cumsum(np.hstack((0, length))) 244 244 call_details = make_details(kernel.info, length, offset[:-1], offset[-1]) 245 # Pad value array to a 32 value boundary d245 # Pad value array to a 32 value boundary 246 246 data_len = nvalues + 2*sum(len(v) for v in dispersity) 247 247 extra = (32 - data_len%32)%32 … … 250 250 is_magnetic = convert_magnetism(kernel.info.parameters, data) 251 251 #call_details.show() 252 #print("data", data) 252 253 return call_details, data, is_magnetic 253 254 … … 296 297 mag = values[parameters.nvalues-3*parameters.nmagnetic:parameters.nvalues] 297 298 mag = mag.reshape(-1, 3) 298 scale = mag[:, 0]299 if np.any(scale):299 if np.any(mag[:, 0] != 0.0): 300 M0 = mag[:, 0].copy() 300 301 theta, phi = radians(mag[:, 1]), radians(mag[:, 2]) 301 cos_theta = cos(theta) 302 mag[:, 0] = scale*cos_theta*cos(phi) # mx 303 mag[:, 1] = scale*sin(theta) # my 304 mag[:, 2] = -scale*cos_theta*sin(phi) # mz 302 mag[:, 0] = +M0*cos(theta)*cos(phi) # mx 303 mag[:, 1] = +M0*sin(theta) # my 304 mag[:, 2] = -M0*cos(theta)*sin(phi) # mz 305 305 return True 306 306 else: -
sasmodels/kernel_iq.c
rd86f0fc rdc6f601 79 79 // du * (m_sigma_y + 1j*m_sigma_z); 80 80 // weights for spin crosssections: dd du real, ud real, uu, du imag, ud imag 81 static void set_spin_weights(double in_spin, double out_spin, double spins[4])81 static void set_spin_weights(double in_spin, double out_spin, double weight[6]) 82 82 { 83 83 in_spin = clip(in_spin, 0.0, 1.0); 84 84 out_spin = clip(out_spin, 0.0, 1.0); 85 spins[0] = sqrt(sqrt((1.0-in_spin) * (1.0-out_spin))); // dd 86 spins[1] = sqrt(sqrt((1.0-in_spin) * out_spin)); // du real 87 spins[2] = sqrt(sqrt(in_spin * (1.0-out_spin))); // ud real 88 spins[3] = sqrt(sqrt(in_spin * out_spin)); // uu 89 spins[4] = spins[1]; // du imag 90 spins[5] = spins[2]; // ud imag 85 // Note: sasview 3.1 scaled all slds by sqrt(weight) and assumed that 86 // w*I(q, rho1, rho2, ...) = I(q, sqrt(w)*rho1, sqrt(w)*rho2, ...) 87 // which is likely to be the case for simple models. 88 weight[0] = sqrt((1.0-in_spin) * (1.0-out_spin)); // dd 89 weight[1] = sqrt((1.0-in_spin) * out_spin); // du.real 90 weight[2] = sqrt(in_spin * (1.0-out_spin)); // ud.real 91 weight[3] = sqrt(in_spin * out_spin); // uu 92 weight[4] = weight[1]; // du.imag 93 weight[5] = weight[2]; // ud.imag 91 94 } 92 95 93 96 // Compute the magnetic sld 94 97 static double mag_sld( 95 const unsigned int xs, // 0=dd, 1=du real, 2=ud real, 3=uu, 4=du imag, 5=upimag98 const unsigned int xs, // 0=dd, 1=du.real, 2=ud.real, 3=uu, 4=du.imag, 5=ud.imag 96 99 const double qx, const double qy, 97 100 const double px, const double py, … … 106 109 case 0: // uu => sld - D M_perpx 107 110 return sld - px*perp; 108 case 1: // ud 111 case 1: // ud.real => -D M_perpy 109 112 return py*perp; 110 case 2: // du 113 case 2: // du.real => -D M_perpy 111 114 return py*perp; 112 case 3: // dd real=> sld + D M_perpx115 case 3: // dd => sld + D M_perpx 113 116 return sld + px*perp; 114 117 } 115 118 } else { 116 119 if (xs== 4) { 117 return -mz; // ud imag => -D M_perpz120 return -mz; // du.imag => +D M_perpz 118 121 } else { // index == 5 119 return mz; // du imag =>D M_perpz122 return +mz; // ud.imag => -D M_perpz 120 123 } 121 124 } … … 312 315 // up_angle = values[NUM_PARS+4]; 313 316 // TODO: could precompute more magnetism parameters before calling the kernel. 314 double spins[8]; // uu, ud real, du real, dd, ud imag, du imag, fill, fill317 double xs_weights[8]; // uu, ud real, du real, dd, ud imag, du imag, fill, fill 315 318 double cos_mspin, sin_mspin; 316 set_spin_weights(values[NUM_PARS+2], values[NUM_PARS+3], spins);319 set_spin_weights(values[NUM_PARS+2], values[NUM_PARS+3], xs_weights); 317 320 SINCOS(-values[NUM_PARS+4]*M_PI_180, sin_mspin, cos_mspin); 318 321 #endif // MAGNETIC … … 661 664 // loop over uu, ud real, du real, dd, ud imag, du imag 662 665 for (unsigned int xs=0; xs<6; xs++) { 663 const double xs_weight = spins[xs];666 const double xs_weight = xs_weights[xs]; 664 667 if (xs_weight > 1.e-8) { 665 668 // Since the cross section weight is significant, set the slds … … 674 677 local_values.vector[sld_index] = 675 678 mag_sld(xs, qx, qy, px, py, values[sld_index+2], mx, my, mz); 679 //if (q_index==0) printf("%d: (qx,qy)=(%g,%g) xs=%d sld%d=%g p=(%g,%g) m=(%g,%g,%g)\n", 680 // q_index, qx, qy, xs, sk, local_values.vector[sld_index], px, py, mx, my, mz); 676 681 } 677 682 scattering += xs_weight * CALL_KERNEL(); -
sasmodels/sasview_model.py
r3221de0 r7c3fb15 593 593 # Check whether we have a list of ndarrays [qx,qy] 594 594 qx, qy = qdist 595 if not self._model_info.parameters.has_2d: 596 return self.calculate_Iq(np.sqrt(qx ** 2 + qy ** 2)) 597 else: 598 return self.calculate_Iq(qx, qy) 595 return self.calculate_Iq(qx, qy) 599 596 600 597 elif isinstance(qdist, np.ndarray): … … 677 674 call_details, values, is_magnetic = make_kernel_args(calculator, pairs) 678 675 #call_details.show() 679 #print("pairs", pairs) 676 #print("================ parameters ==================") 677 #for p, v in zip(parameters.call_parameters, pairs): print(p.name, v[0]) 680 678 #for k, p in enumerate(self._model_info.parameters.call_parameters): 681 679 # print(k, p.name, *pairs[k]) … … 721 719 722 720 def set_dispersion(self, parameter, dispersion): 723 # type: (str, weights.Dispersion) -> Dict[str, Any]721 # type: (str, weights.Dispersion) -> None 724 722 """ 725 723 Set the dispersion object for a model parameter … … 744 742 self.dispersion[parameter] = dispersion.get_pars() 745 743 else: 746 raise ValueError("%r is not a dispersity or orientation parameter") 744 raise ValueError("%r is not a dispersity or orientation parameter" 745 % parameter) 747 746 748 747 def _dispersion_mesh(self): … … 871 870 CylinderModel().evalDistribution([0.1, 0.1]) 872 871 872 def magnetic_demo(): 873 Model = _make_standard_model('sphere') 874 model = Model() 875 model.setParam('M0:sld', 8) 876 q = np.linspace(-0.35, 0.35, 500) 877 qx, qy = np.meshgrid(q, q) 878 result = model.calculate_Iq(qx.flatten(), qy.flatten()) 879 result = result.reshape(qx.shape) 880 881 import pylab 882 pylab.imshow(np.log(result + 0.001)) 883 pylab.show() 884 873 885 if __name__ == "__main__": 874 886 print("cylinder(0.1,0.1)=%g"%test_cylinder()) 887 #magnetic_demo() 875 888 #test_product() 876 889 #test_structure_factor() -
sasmodels/models/core_shell_parallelepiped.c
re077231 rdbf1a60 59 59 60 60 // outer integral (with gauss points), integration limits = 0, 1 61 // substitute d_cos_alpha for sin_alpha d_alpha 61 62 double outer_sum = 0; //initialize integral 62 63 for( int i=0; i<GAUSS_N; i++) { 63 64 const double cos_alpha = 0.5 * ( GAUSS_Z[i] + 1.0 ); 64 65 const double mu = half_q * sqrt(1.0-cos_alpha*cos_alpha); 65 66 // inner integral (with gauss points), integration limits = 0, pi/267 66 const double siC = length_c * sas_sinx_x(length_c * cos_alpha * half_q); 68 67 const double siCt = tC * sas_sinx_x(tC * cos_alpha * half_q); 68 69 // inner integral (with gauss points), integration limits = 0, 1 70 // substitute beta = PI/2 u (so 2/PI * d_(PI/2 * beta) = d_beta) 69 71 double inner_sum = 0.0; 70 72 for(int j=0; j<GAUSS_N; j++) { 71 const double beta= 0.5 * ( GAUSS_Z[j] + 1.0 );73 const double u = 0.5 * ( GAUSS_Z[j] + 1.0 ); 72 74 double sin_beta, cos_beta; 73 SINCOS(M_PI_2* beta, sin_beta, cos_beta);75 SINCOS(M_PI_2*u, sin_beta, cos_beta); 74 76 const double siA = length_a * sas_sinx_x(length_a * mu * sin_beta); 75 77 const double siB = length_b * sas_sinx_x(length_b * mu * cos_beta); … … 91 93 inner_sum += GAUSS_W[j] * f * f; 92 94 } 95 // now complete change of inner integration variable (1-0)/(1-(-1))= 0.5 93 96 inner_sum *= 0.5; 94 97 // now sum up the outer integral 95 98 outer_sum += GAUSS_W[i] * inner_sum; 96 99 } 100 // now complete change of outer integration variable (1-0)/(1-(-1))= 0.5 97 101 outer_sum *= 0.5; 98 102 -
sasmodels/models/core_shell_parallelepiped.py
r97be877 r5bc6d21 11 11 .. math:: 12 12 13 I(q) = \text{scale}\frac{\langle f^2 \rangle}{V} + \text{background} 13 I(q) = \frac{\text{scale}}{V} \langle P(q,\alpha,\beta) \rangle 14 + \text{background} 14 15 15 16 where $\langle \ldots \rangle$ is an average over all possible orientations 16 of the rectangular solid .17 18 The function calculated is the form factor of the rectangular solid below. 17 of the rectangular solid, and the usual $\Delta \rho^2 \ V^2$ term cannot be 18 pulled out of the form factor term due to the multiple slds in the model. 19 19 20 The core of the solid is defined by the dimensions $A$, $B$, $C$ such that 20 21 $A < B < C$. 21 22 22 .. image:: img/core_shell_parallelepiped_geometry.jpg 23 .. figure:: img/parallelepiped_geometry.jpg 24 25 Core of the core shell parallelepiped with the corresponding definition 26 of sides. 27 23 28 24 29 There are rectangular "slabs" of thickness $t_A$ that add to the $A$ dimension 25 30 (on the $BC$ faces). There are similar slabs on the $AC$ $(=t_B)$ and $AB$ 26 $(=t_C)$ faces. The projection in the $AB$ plane is then 27 28 .. image:: img/core_shell_parallelepiped_projection.jpg 29 30 The volume of the solid is 31 $(=t_C)$ faces. The projection in the $AB$ plane is 32 33 .. figure:: img/core_shell_parallelepiped_projection.jpg 34 35 AB cut through the core-shell parallelipiped showing the cross secion of 36 four of the six shell slabs. As can be seen, this model leaves **"gaps"** 37 at the corners of the solid. 38 39 40 The total volume of the solid is thus given as 31 41 32 42 .. math:: 33 43 34 44 V = ABC + 2t_ABC + 2t_BAC + 2t_CAB 35 36 **meaning that there are "gaps" at the corners of the solid.**37 45 38 46 The intensity calculated follows the :ref:`parallelepiped` model, with the 39 47 core-shell intensity being calculated as the square of the sum of the 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) 48 amplitudes of the core and the slabs on the edges. The scattering amplitude is 49 computed for a particular orientation of the core-shell parallelepiped with 50 respect to the scattering vector and then averaged over all possible 51 orientations, where $\alpha$ is the angle between the $z$ axis and the $C$ axis 52 of the parallelepiped, and $\beta$ is the angle between the projection of the 53 particle in the $xy$ detector plane and the $y$ axis. 54 55 .. math:: 56 57 P(q)=\frac {\int_{0}^{\pi/2}\int_{0}^{\pi/2}F^2(q,\alpha,\beta) \ sin\alpha 58 \ d\alpha \ d\beta} {\int_{0}^{\pi/2} \ sin\alpha \ d\alpha \ d\beta} 59 60 and 61 62 .. math:: 63 64 F(q,\alpha,\beta) 52 65 &= (\rho_\text{core}-\rho_\text{solvent}) 53 66 S(Q_A, A) S(Q_B, B) S(Q_C, C) \\ 54 67 &+ (\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) \\68 \left[S(Q_A, A+2t_A) - S(Q_A, A)\right] S(Q_B, B) S(Q_C, C) \\ 56 69 &+ (\rho_\text{B}-\rho_\text{solvent}) 57 70 S(Q_A, A) \left[S(Q_B, B+2t_B) - S(Q_B, B)\right] S(Q_C, C) \\ … … 63 76 .. math:: 64 77 65 S(Q , L) = L \frac{\sin \tfrac{1}{2} Q L}{\tfrac{1}{2} QL}78 S(Q_X, L) = L \frac{\sin (\tfrac{1}{2} Q_X L)}{\tfrac{1}{2} Q_X L} 66 79 67 80 and … … 69 82 .. math:: 70 83 71 Q_A &= \sin\alpha \sin\beta \\72 Q_B &= \sin\alpha \cos\beta \\73 Q_C &= \cos\alpha84 Q_A &= q \sin\alpha \sin\beta \\ 85 Q_B &= q \sin\alpha \cos\beta \\ 86 Q_C &= q \cos\alpha 74 87 75 88 76 89 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 rectangular90 are the scattering lengths of the parallelepiped core, and the rectangular 78 91 slabs of thickness $t_A$, $t_B$ and $t_C$, respectively. $\rho_\text{solvent}$ 79 92 is the scattering length of the solvent. 93 94 .. note:: 95 96 the code actually implements two substitutions: $d(cos\alpha)$ is 97 substituted for -$sin\alpha \ d\alpha$ (note that in the 98 :ref:`parallelepiped` code this is explicitly implemented with 99 $\sigma = cos\alpha$), and $\beta$ is set to $\beta = u \pi/2$ so that 100 $du = \pi/2 \ d\beta$. Thus both integrals go from 0 to 1 rather than 0 101 to $\pi/2$. 80 102 81 103 FITTING NOTES … … 94 116 based on the the averaged effective radius $(=\sqrt{(A+2t_A)(B+2t_B)/\pi})$ 95 117 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.118 to give an oblate or prolate particle, to give an effective radius 119 for $S(q)$ when $P(q) * S(q)$ is applied. 98 120 99 121 For 2d data the orientation of the particle is required, described using 100 angles $\theta$, $\phi$ and $\Psi$ as in the diagrams below , for further122 angles $\theta$, $\phi$ and $\Psi$ as in the diagrams below. For further 101 123 details of the calculation and angular dispersions see :ref:`orientation`. 102 124 The angle $\Psi$ is the rotational angle around the *long_c* axis. For example, 103 125 $\Psi = 0$ when the *short_b* axis is parallel to the *x*-axis of the detector. 104 126 105 For 2d, constraints must be applied during fitting to ensure that the106 inequality $A < B < C$ is not violated, and hence the correct definition107 of angles is preserved. The calculation will not report an error,108 but the results may be not correct.127 .. note:: For 2d, constraints must be applied during fitting to ensure that the 128 inequality $A < B < C$ is not violated, and hence the correct definition 129 of angles is preserved. The calculation will not report an error, 130 but the results may be not correct. 109 131 110 132 .. figure:: img/parallelepiped_angle_definition.png … … 113 135 Note that rotation $\theta$, initially in the $xz$ plane, is carried 114 136 out first, then rotation $\phi$ about the $z$ axis, finally rotation 115 $\Psi$ is now around the axis of the cylinder. The neutron or X-ray137 $\Psi$ is now around the axis of the particle. The neutron or X-ray 116 138 beam is along the $z$ axis. 117 139 … … 120 142 Examples of the angles for oriented core-shell parallelepipeds against the 121 143 detector plane. 144 145 146 Validation 147 ---------- 148 149 Cross-checked against hollow rectangular prism and rectangular prism for equal 150 thickness overlapping sides, and by Monte Carlo sampling of points within the 151 shape for non-uniform, non-overlapping sides. 152 122 153 123 154 References … … 135 166 136 167 * **Author:** NIST IGOR/DANSE **Date:** pre 2010 137 * **Converted to sasmodels by:** Miguel Gonzale s**Date:** February 26, 2016168 * **Converted to sasmodels by:** Miguel Gonzalez **Date:** February 26, 2016 138 169 * **Last Modified by:** Paul Kienzle **Date:** October 17, 2017 139 * Cross-checked against hollow rectangular prism and rectangular prism for140 equal thickness overlapping sides, and by Monte Carlo sampling of points141 within the shape for non-uniform, non-overlapping sides.142 170 """ 143 171 -
sasmodels/models/parallelepiped.c
r108e70e rdbf1a60 38 38 inner_total += GAUSS_W[j] * square(si1 * si2); 39 39 } 40 // now complete change of inner integration variable (1-0)/(1-(-1))= 0.5 40 41 inner_total *= 0.5; 41 42 … … 43 44 outer_total += GAUSS_W[i] * inner_total * si * si; 44 45 } 46 // now complete change of outer integration variable (1-0)/(1-(-1))= 0.5 45 47 outer_total *= 0.5; 46 48 -
sasmodels/models/parallelepiped.py
ref07e95 r5bc6d21 2 2 # Note: model title and parameter table are inserted automatically 3 3 r""" 4 The form factor is normalized by the particle volume.5 For information about polarised and magnetic scattering, see6 the :ref:`magnetism` documentation.7 8 4 Definition 9 5 ---------- 10 6 11 7 This model calculates the scattering from a rectangular parallelepiped 12 (\:numref:`parallelepiped-image`\). 13 If you need to apply polydispersity, see also :ref:`rectangular-prism`. 8 (:numref:`parallelepiped-image`). 9 If you need to apply polydispersity, see also :ref:`rectangular-prism`. For 10 information about polarised and magnetic scattering, see 11 the :ref:`magnetism` documentation. 14 12 15 13 .. _parallelepiped-image: … … 26 24 error, or fixing of some dimensions at expected values, may help. 27 25 28 The 1D scattering intensity $I(q)$ is calculated as: 26 The form factor is normalized by the particle volume and the 1D scattering 27 intensity $I(q)$ is then calculated as: 29 28 30 29 .. Comment by Miguel Gonzalez: … … 39 38 40 39 I(q) = \frac{\text{scale}}{V} (\Delta\rho \cdot V)^2 41 \left< P(q, \alpha ) \right> + \text{background}40 \left< P(q, \alpha, \beta) \right> + \text{background} 42 41 43 42 where the volume $V = A B C$, the contrast is defined as 44 $\Delta\rho = \rho_\text{p} - \rho_\text{solvent}$, 45 $P(q, \alpha)$ is the form factor corresponding to a parallelepiped oriented 46 at an angle $\alpha$ (angle between the long axis C and $\vec q$), 47 and the averaging $\left<\ldots\right>$ is applied over all orientations. 43 $\Delta\rho = \rho_\text{p} - \rho_\text{solvent}$, $P(q, \alpha, \beta)$ 44 is the form factor corresponding to a parallelepiped oriented 45 at an angle $\alpha$ (angle between the long axis C and $\vec q$), and $\beta$ 46 ( the angle between the projection of the particle in the $xy$ detector plane 47 and the $y$ axis) and the averaging $\left<\ldots\right>$ is applied over all 48 orientations. 48 49 49 50 Assuming $a = A/B < 1$, $b = B /B = 1$, and $c = C/B > 1$, the 50 form factor is given by (Mittelbach and Porod, 1961 )51 form factor is given by (Mittelbach and Porod, 1961 [#Mittelbach]_) 51 52 52 53 .. math:: … … 66 67 \mu &= qB 67 68 68 The scattering intensity per unit volume is returned in units of |cm^-1|. 69 where substitution of $\sigma = cos\alpha$ and $\beta = \pi/2 \ u$ have been 70 applied. 69 71 70 72 NB: The 2nd virial coefficient of the parallelepiped is calculated based on … … 120 122 .. math:: 121 123 122 P(q_x, q_y) = \left[\frac{\sin(\tfrac{1}{2}qA\cos\alpha)}{(\tfrac{1}{2}qA\cos\alpha)}\right]^2 123 \left[\frac{\sin(\tfrac{1}{2}qB\cos\beta)}{(\tfrac{1}{2}qB\cos\beta)}\right]^2 124 \left[\frac{\sin(\tfrac{1}{2}qC\cos\gamma)}{(\tfrac{1}{2}qC\cos\gamma)}\right]^2 124 P(q_x, q_y) = \left[\frac{\sin(\tfrac{1}{2}qA\cos\alpha)}{(\tfrac{1} 125 {2}qA\cos\alpha)}\right]^2 126 \left[\frac{\sin(\tfrac{1}{2}qB\cos\beta)}{(\tfrac{1} 127 {2}qB\cos\beta)}\right]^2 128 \left[\frac{\sin(\tfrac{1}{2}qC\cos\gamma)}{(\tfrac{1} 129 {2}qC\cos\gamma)}\right]^2 125 130 126 131 with … … 160 165 ---------- 161 166 162 P Mittelbach and G Porod, *Acta Physica Austriaca*, 14 (1961) 185-211 163 164 R Nayuk and K Huber, *Z. Phys. Chem.*, 226 (2012) 837-854167 .. [#Mittelbach] P Mittelbach and G Porod, *Acta Physica Austriaca*, 168 14 (1961) 185-211 169 .. [#] R Nayuk and K Huber, *Z. Phys. Chem.*, 226 (2012) 837-854 165 170 166 171 Authorship and Verification
Note: See TracChangeset
for help on using the changeset viewer.