Changes in / [e0de72f:69ef533] in sasmodels
- Location:
- sasmodels/models
- Files:
-
- 2 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/models/core_shell_ellipsoid.c
r5031ca3 r2222134 1 1 double form_volume(double radius_equat_core, 2 double polar_core,3 double equat_shell,4 double polar_shell);2 double radius_polar_core, 3 double radius_equat_shell, 4 double radius_polar_shell); 5 5 double Iq(double q, 6 6 double radius_equat_core, 7 double x_core,8 double thick_shell,9 double x_polar_shell,10 double core_sld,11 double s hell_sld,12 double s olvent_sld);7 double radius_polar_core, 8 double radius_equat_shell, 9 double radius_polar_shell, 10 double sld_core, 11 double sld_shell, 12 double sld_solvent); 13 13 14 14 15 15 double Iqxy(double qx, double qy, 16 16 double radius_equat_core, 17 double x_core,18 double thick_shell,19 double x_polar_shell,20 double core_sld,21 double s hell_sld,22 double s olvent_sld,17 double radius_polar_core, 18 double radius_equat_shell, 19 double radius_polar_shell, 20 double sld_core, 21 double sld_shell, 22 double sld_solvent, 23 23 double theta, 24 24 double phi); … … 26 26 27 27 double form_volume(double radius_equat_core, 28 double x_core,29 double thick_shell,30 double x_polar_shell)28 double radius_polar_core, 29 double radius_equat_shell, 30 double radius_polar_shell) 31 31 { 32 const double equat_shell = radius_equat_core + thick_shell; 33 const double polar_shell = radius_equat_core*x_core + thick_shell*x_polar_shell; 34 double vol = 4.0*M_PI/3.0*equat_shell*equat_shell*polar_shell; 32 double vol = 4.0*M_PI/3.0*radius_equat_shell*radius_equat_shell*radius_polar_shell; 35 33 return vol; 36 34 } 37 35 38 36 static double 39 core_shell_ellipsoid_ xt_kernel(double q,37 core_shell_ellipsoid_kernel(double q, 40 38 double radius_equat_core, 41 double x_core,42 double thick_shell,43 double x_polar_shell,44 double core_sld,45 double s hell_sld,46 double s olvent_sld)39 double radius_polar_core, 40 double radius_equat_shell, 41 double radius_polar_shell, 42 double sld_core, 43 double sld_shell, 44 double sld_solvent) 47 45 { 46 47 //upper and lower integration limits 48 48 const double lolim = 0.0; 49 49 const double uplim = 1.0; … … 51 51 double summ = 0.0; //initialize intergral 52 52 53 const double delpc = core_sld - shell_sld; //core - shell 54 const double delps = shell_sld - solvent_sld; //shell - solvent 55 56 57 const double polar_core = radius_equat_core*x_core; 58 const double equat_shell = radius_equat_core + thick_shell; 59 const double polar_shell = radius_equat_core*x_core + thick_shell*x_polar_shell; 53 const double delpc = sld_core - sld_shell; //core - shell 54 const double delps = sld_shell - sld_solvent; //shell - solvent 60 55 61 56 for(int i=0;i<N_POINTS_76;i++) { … … 63 58 double yyy = Gauss76Wt[i] * gfn4(zi, 64 59 radius_equat_core, 65 polar_core,66 equat_shell,67 polar_shell,60 radius_polar_core, 61 radius_equat_shell, 62 radius_polar_shell, 68 63 delpc, 69 64 delps, … … 73 68 74 69 double answer = (uplim-lolim)/2.0*summ; 70 75 71 //convert to [cm-1] 76 72 answer *= 1.0e-4; … … 80 76 81 77 static double 82 core_shell_ellipsoid_ xt_kernel_2d(double q, double q_x, double q_y,78 core_shell_ellipsoid_kernel_2d(double q, double q_x, double q_y, 83 79 double radius_equat_core, 84 double x_core,85 double thick_shell,86 double x_polar_shell,87 double core_sld,88 double s hell_sld,89 double s olvent_sld,80 double radius_polar_core, 81 double radius_equat_shell, 82 double radius_polar_shell, 83 double sld_core, 84 double sld_shell, 85 double sld_solvent, 90 86 double theta, 91 87 double phi) … … 95 91 phi = phi * M_PI_180; 96 92 93 97 94 // ellipsoid orientation, the axis of the rotation is consistent with the ploar axis. 98 95 const double cyl_x = cos(theta) * cos(phi); 99 96 const double cyl_y = sin(theta); 100 97 101 const double sldcs = core_sld - shell_sld;102 const double sldss = s hell_sld- solvent_sld;98 const double sldcs = sld_core - sld_shell; 99 const double sldss = sld_shell- sld_solvent; 103 100 104 101 // Compute the angle btw vector q and the … … 106 103 const double cos_val = cyl_x*q_x + cyl_y*q_y; 107 104 108 const double polar_core = radius_equat_core*x_core; 109 const double equat_shell = radius_equat_core + thick_shell; 110 const double polar_shell = radius_equat_core*x_core + thick_shell*x_polar_shell; 111 112 // Call the IGOR library function to get the kernel: 113 // MUST use gfn4 not gf2 because of the def of params. 105 // Call the IGOR library function to get the kernel: MUST use gfn4 not gf2 because of the def of params. 114 106 double answer = gfn4(cos_val, 115 107 radius_equat_core, 116 polar_core,117 equat_shell,118 polar_shell,108 radius_polar_core, 109 radius_equat_shell, 110 radius_polar_shell, 119 111 sldcs, 120 112 sldss, … … 129 121 double Iq(double q, 130 122 double radius_equat_core, 131 double x_core,132 double thick_shell,133 double x_polar_shell,134 double core_sld,135 double s hell_sld,136 double s olvent_sld)123 double radius_polar_core, 124 double radius_equat_shell, 125 double radius_polar_shell, 126 double sld_core, 127 double sld_shell, 128 double sld_solvent) 137 129 { 138 double intensity = core_shell_ellipsoid_ xt_kernel(q,130 double intensity = core_shell_ellipsoid_kernel(q, 139 131 radius_equat_core, 140 x_core,141 thick_shell,142 x_polar_shell,143 core_sld,144 s hell_sld,145 s olvent_sld);132 radius_polar_core, 133 radius_equat_shell, 134 radius_polar_shell, 135 sld_core, 136 sld_shell, 137 sld_solvent); 146 138 147 139 return intensity; … … 151 143 double Iqxy(double qx, double qy, 152 144 double radius_equat_core, 153 double x_core,154 double thick_shell,155 double x_polar_shell,156 double core_sld,157 double s hell_sld,158 double s olvent_sld,145 double radius_polar_core, 146 double radius_equat_shell, 147 double radius_polar_shell, 148 double sld_core, 149 double sld_shell, 150 double sld_solvent, 159 151 double theta, 160 152 double phi) … … 162 154 double q; 163 155 q = sqrt(qx*qx+qy*qy); 164 double intensity = core_shell_ellipsoid_ xt_kernel_2d(q, qx/q, qy/q,156 double intensity = core_shell_ellipsoid_kernel_2d(q, qx/q, qy/q, 165 157 radius_equat_core, 166 x_core,167 thick_shell,168 x_polar_shell,169 core_sld,170 s hell_sld,171 s olvent_sld,158 radius_polar_core, 159 radius_equat_shell, 160 radius_polar_shell, 161 sld_core, 162 sld_shell, 163 sld_solvent, 172 164 theta, 173 165 phi); -
sasmodels/models/core_shell_ellipsoid.py
r5031ca3 r2222134 1 1 r""" 2 An alternative version of $P(q)$ for the core_shell_ellipsoid 3 having as parameters the core axial ratio X and a shell thickness, 4 which are more often what we would like to determine. 2 This model provides the form factor, $P(q)$, for a core shell ellipsoid (below) 3 where the form factor is normalized by the volume of the outer [CHECK]. 5 4 6 This model is also better behaved when polydispersity is applied than the four 7 independent radii in core_shell_ellipsoid model. 5 .. math:: 6 7 P(q) = \text{scale} * \left<f^2\right>/V + \text{background} 8 9 where the volume $V = (4/3)\pi(r_\text{major outer} r_\text{minor outer}^2)$ 10 and the averaging $< >$ is applied over all orientations for 1D. 11 12 .. figure:: img/core_shell_ellipsoid_geometry.png 13 14 The returned value is in units of |cm^-1|, on absolute scale. 8 15 9 16 Definition 10 17 ---------- 11 18 12 .. figure:: img/core_shell_ellipsoid_geometry.png 19 The form factor calculated is 13 20 14 The geometric parameters of this model are 21 .. math:: 15 22 16 *radius_equat_core =* equatorial core radius *= R_minor_core* 23 P(q) &= \frac{\text{scale}}{V}\int_0^1 24 \left|F(q,r_\text{minor core},r_\text{major core},\alpha) 25 + F(q,r_\text{minor outer},r_\text{major outer},\alpha)\right|^2 26 d\alpha 27 + \text{background} 17 28 18 *X_core = polar_core / radius_equat_core = Rmajor_core / Rminor_core* 29 \left|F(q,r_\text{minor},r_\text{major},\alpha)\right| 30 &=(4\pi/3)r_\text{major}r_\text{minor}^2 \Delta \rho \cdot (3j_1(u)/u) 19 31 20 *Thick_shell = equat_outer - radius_equat_core = Rminor_outer - Rminor_core* 32 u &= q\left[ r_\text{major}^2\alpha ^2 33 + r_\text{minor}^2(1-\alpha ^2)\right]^{1/2} 21 34 22 *XpolarShell = Tpolar_shell / Thick_shell = (Rmajor_outer - Rmajor_core)/ 23 (Rminor_outer - Rminor_core)* 35 where 24 36 25 In terms of the original radii 37 .. math:: 26 38 27 *polar_core = radius_equat_core * X_core* 39 j_1(u)=(\sin x - x \cos x)/x^2 28 40 29 *equat_shell = radius_equat_core + Thick_shell* 41 To provide easy access to the orientation of the core-shell ellipsoid, 42 we define the axis of the solid ellipsoid using two angles $\theta$ and $\phi$. 43 These angles are defined as for 44 :ref:`cylinder orientation <cylinder-angle-definition>`. 45 The contrast is defined as SLD(core) - SLD(shell) and SLD(shell) - SLD(solvent). 30 46 31 *polar_shell = radius_equat_core * X_core + Thick_shell * XpolarShell* 47 Note: It is the users' responsibility to ensure that shell radii are larger than 48 the core radii, especially if both are polydisperse, in which case the 49 core_shell_ellipsoid_xt model may be much better. 32 50 33 (where we note that "shell" perhaps confusingly, relates to the outer radius)34 When *X_core < 1* the core is oblate; when *X_core > 1* it is prolate.35 *X_core = 1* is a spherical core.36 51 37 For a fixed shell thickness *XpolarShell = 1*, to scale the shell thickness 38 pro-rata with the radius *XpolarShell = X_core*. 52 .. note:: 53 The 2nd virial coefficient of the solid ellipsoid is calculated based on 54 the *radius_a* (= *radius_polar_shell)* and *radius_b (= radius_equat_shell)* values, 55 and used as the effective radius for *S(Q)* when $P(Q) * S(Q)$ is applied. 39 56 40 When including an $S(q)$, the radius in $S(q)$ is calculated to be that of 41 a sphere with the same 2nd virial coefficient of the outer surface of the 42 ellipsoid. This may have some undesirable effects if the aspect ratio of the 43 ellipsoid is large (ie, if $X << 1$ or $X >> 1$ ), when the $S(q)$ 44 - which assumes spheres - will not in any case be valid. 57 .. figure:: img/core_shell_ellipsoid_angle_projection.jpg 45 58 46 If SAS data are in absolute units, and the SLDs are correct, then scale should 47 be the total volume fraction of the "outer particle". When $S(q)$ is introduced 48 this moves to the $S(q)$ volume fraction, and scale should then be 1.0, 49 or contain some other units conversion factor (for example, if you have SAXS data).59 The angles for oriented core_shell_ellipsoid. 60 61 Our model uses the form factor calculations implemented in a c-library provided 62 by the NIST Center for Neutron Research (Kline, 2006). 50 63 51 64 References 52 65 ---------- 53 66 54 R K Heenan, 2015, reparametrised the core_shell_ellipsoid model 67 M Kotlarchyk, S H Chen, *J. Chem. Phys.*, 79 (1983) 2461 55 68 69 S J Berr, *Phys. Chem.*, 91 (1987) 4760 56 70 """ 57 71 58 72 from numpy import inf, sin, cos, pi 59 73 60 name = "core_shell_ellipsoid _xt"74 name = "core_shell_ellipsoid" 61 75 title = "Form factor for an spheroid ellipsoid particle with a core shell structure." 62 76 description = """ 63 [core_shell_ellipsoid_xt] Calculates the form factor for an spheroid64 65 66 67 68 69 70 radius_equat_core = equatorial radius ofcore,71 x_core = ratio of core polar/equatorial radii,72 thick_shell = equatorial radius of outer surface,73 x_polar_shell = ratio of polar shell thickness to equatorial shell thickness,74 sld_core = SLD_core75 sld_shell = SLD_shell76 sld_solvent = SLD_solvent77 78 79 80 that shell radii are larger than core radii.81 oblate: polar radius < equatorial radius82 prolate : polar radius > equatorial radius - this new model will make this easier83 and polydispersity integrals more logical (as previously the shell could disappear).77 [SpheroidCoreShellModel] Calculates the form factor for an spheroid 78 ellipsoid particle with a core_shell structure. 79 The form factor is averaged over all possible 80 orientations of the ellipsoid such that P(q) 81 = scale*<f^2>/Vol + bkg, where f is the 82 single particle scattering amplitude. 83 [Parameters]: 84 radius_equat_core = equatorial radius of core, Rminor_core, 85 radius_polar_core = polar radius of core, Rmajor_core, 86 radius_equat_shell = equatorial radius of shell, Rminor_outer, 87 radius_polar_shell = polar radius of shell, Rmajor_outer, 88 sld_core = scattering length density of core, 89 sld_shell = scattering length density of shell, 90 sld_solvent = scattering length density of solvent, 91 background = Incoherent bkg 92 scale =scale 93 Note:It is the users' responsibility to ensure 94 that shell radii are larger than core radii, 95 especially if both are polydisperse. 96 oblate: polar radius < equatorial radius 97 prolate : polar radius > equatorial radius 84 98 """ 85 99 category = "shape:ellipsoid" 86 100 87 101 # pylint: disable=bad-whitespace, line-too-long 88 # 102 # ["name", "units", default, [lower, upper], "type", "description"], 89 103 parameters = [ 90 ["radius_equat_core", "Ang", 20, [0, inf], "volume", "Equatorial radius ofcore"],91 [" x_core", "None", 3, [0, inf], "volume", "axial ratio of core, X = r_polar/r_equatorial"],92 [" thick_shell", "Ang", 30, [0, inf], "volume", "thickness of shell at equator"],93 [" x_polar_shell", "", 1, [0, inf], "volume", "ratio of thickness of shell at pole to that at equator"],94 ["sld_core", 95 ["sld_shell", 96 ["sld_solvent", 97 ["theta", 98 ["phi", 104 ["radius_equat_core", "Ang", 200, [0, inf], "volume", "Equatorial radius of core, r minor core"], 105 ["radius_polar_core", "Ang", 10, [0, inf], "volume", "Polar radius of core, r major core"], 106 ["radius_equat_shell", "Ang", 250, [0, inf], "volume", "Equatorial radius of shell, r minor outer"], 107 ["radius_polar_shell", "Ang", 30, [0, inf], "volume", "Polar radius of shell, r major outer"], 108 ["sld_core", "1e-6/Ang^2", 2, [-inf, inf], "sld", "Core scattering length density"], 109 ["sld_shell", "1e-6/Ang^2", 1, [-inf, inf], "sld", "Shell scattering length density"], 110 ["sld_solvent", "1e-6/Ang^2", 6.3, [-inf, inf], "sld", "Solvent scattering length density"], 111 ["theta", "degrees", 0, [-inf, inf], "orientation", "Oblate orientation wrt incoming beam"], 112 ["phi", "degrees", 0, [-inf, inf], "orientation", "Oblate orientation in the plane of the detector"], 99 113 ] 100 114 # pylint: enable=bad-whitespace, line-too-long 101 115 102 source = ["lib/sph_j1c.c", "lib/gfn.c", "lib/gauss76.c", 103 "core_shell_ellipsoid_xt.c"] 116 source = ["lib/sph_j1c.c", "lib/gfn.c", "lib/gauss76.c", "core_shell_ellipsoid.c"] 104 117 105 def ER(radius_equat_core, x_core, thick_shell, x_polar_shell):118 def ER(radius_equat_core, radius_polar_core, radius_equat_shell, radius_polar_shell): 106 119 """ 107 120 Returns the effective radius used in the S*P calculation 108 121 """ 109 122 from .ellipsoid import ER as ellipsoid_ER 110 polar_outer = radius_equat_core*x_core + thick_shell*x_polar_shell 111 equat_outer = radius_equat_core + thick_shell 112 return ellipsoid_ER(polar_outer, equat_outer) 123 return ellipsoid_ER(radius_polar_shell, radius_equat_shell) 113 124 114 125 115 demo = dict(scale= 0.05, background=0.001,116 radius_equat_core=20 .0,117 x_core=3.0,118 thick_shell=30.0,119 x_polar_shell=1.0,126 demo = dict(scale=1, background=0.001, 127 radius_equat_core=200.0, 128 radius_polar_core=10.0, 129 radius_equat_shell=250.0, 130 radius_polar_shell=30.0, 120 131 sld_core=2.0, 121 132 sld_shell=1.0, … … 130 141 131 142 tests = [ 132 # Accuracy tests based on content in test/utest_ coreshellellipsoidXTmodel.py143 # Accuracy tests based on content in test/utest_other_models.py 133 144 [{'radius_equat_core': 200.0, 134 ' x_core': 0.1,135 ' thick_shell':50.0,136 ' x_polar_shell': 0.2,145 'radius_polar_core': 20.0, 146 'radius_equat_shell': 250.0, 147 'radius_polar_shell': 30.0, 137 148 'sld_core': 2.0, 138 149 'sld_shell': 1.0, … … 143 154 144 155 # Additional tests with larger range of parameters 145 [{'background': 0.01}, 0.1, 11.6915],156 [{'background': 0.01}, 0.1, 8.86741], 146 157 147 158 [{'radius_equat_core': 20.0, 148 ' x_core': 200.0,149 ' thick_shell': 54.0,150 ' x_polar_shell': 3.0,159 'radius_polar_core': 200.0, 160 'radius_equat_shell': 54.0, 161 'radius_polar_shell': 3.0, 151 162 'sld_core': 20.0, 152 163 'sld_shell': 10.0, … … 154 165 'background': 0.0, 155 166 'scale': 1.0, 156 }, 0.01, 8688.53],167 }, 0.01, 26150.4], 157 168 158 [{'background': 0.001}, (0.4, 0.5), 0.00 690673],169 [{'background': 0.001}, (0.4, 0.5), 0.00170471], 159 170 160 171 [{'radius_equat_core': 20.0, 161 ' x_core': 200.0,162 ' thick_shell': 54.0,163 ' x_polar_shell': 3.0,172 'radius_polar_core': 200.0, 173 'radius_equat_shell': 54.0, 174 'radius_polar_shell': 3.0, 164 175 'sld_core': 20.0, 165 176 'sld_shell': 10.0, … … 167 178 'background': 0.01, 168 179 'scale': 0.01, 169 }, (qx, qy), 0. 0100002],180 }, (qx, qy), 0.105764], 170 181 ]
Note: See TracChangeset
for help on using the changeset viewer.