Ignore:
Timestamp:
Nov 6, 2017 2:51:30 PM (5 years ago)
Branches:
master, core_shell_microgels, magnetic_model, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
Children:
c11d09f, 4073633
Parents:
49eb251 (diff), eb87965 (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.
Message:

Merge branch 'ticket-776-orientation' into ticket-786

Files:
1 deleted
12 edited

Unmodified
Removed
• ## doc/guide/orientation/orientation.rst

 r3d40839 care for large ranges of angle. Note that the form factors for asymmetric particles are also performing numerical integrations over one or more variables, so care should be taken, especially with very large particles or more extreme aspect ratios. Users can experiment with the values of *Npts* and *Nsigs*, the number of steps used in the integration and the range spanned in number of standard deviations. The standard deviation is entered in units of degrees. For a rectangular (uniform) distribution the full width should be $\pm \sqrt(3)$ ~ 1.73 standard deviations (this may be changed soon). .. note:: Note that the form factors for oriented particles are also performing numerical integrations over one or more variables, so care should be taken, especially with very large particles or more extreme aspect ratios. In such cases results may not be accurate, particularly at very high Q, unless the model has been specifically coded to use limiting forms of the scattering equations. For best numerical results keep the $\theta$ distribution narrower than the $\phi$ distribution. Thus for asymmetric particles, such as elliptical_cylinder, you may need to reorder the sizes of the three axes to acheive the desired result. This is due to the issues of mapping a rectangular distribution onto the surface of a sphere. Where appropriate, for best numerical results, keep $a < b < c$ and the $\theta$ distribution narrower than the $\phi$ distribution. Users can experiment with the values of *Npts* and *Nsigs*, the number of steps used in the integration and the range spanned in number of standard deviations. The standard deviation is entered in units of degrees. For a "rectangular" distribution the full width should be $\pm \sqrt(3)$ ~ 1.73 standard deviations. The new "uniform" distribution avoids this by letting you directly specify the half width. The angular distributions will be truncated outside of the range -180 to +180 degrees, so beware of using saying a broad Gaussian distribution with large value of *Nsigs*, as the array of *Npts* may be truncated to many fewer points than would give a good integration,as well as becoming rather meaningless. (At some point in the future the actual polydispersity arrays may be made available to the user for inspection.) Some more detailed technical notes are provided in the developer section of *Document History* | 2017-10-27 Richard Heenan | 2017-11-06 Richard Heenan
• ## sasmodels/models/core_shell_bicelle_elliptical.c

 rbecded3 // Compute effective radius in rotated coordinates const double qr_hat = sqrt(square(r_major*qa) + square(r_minor*qb)); const double qrshell_hat = sqrt(square((r_major+thick_rim)*qa) + square((r_minor+thick_rim)*qb)); const double qr_hat = sqrt(square(r_major*qb) + square(r_minor*qa)); const double qrshell_hat = sqrt(square((r_major+thick_rim)*qb) + square((r_minor+thick_rim)*qa)); const double be1 = sas_2J1x_x( qr_hat ); const double be2 = sas_2J1x_x( qrshell_hat );
• ## sasmodels/models/core_shell_bicelle_elliptical_belt_rough.c

 r129bdc4 double sigma) { // THIS NEEDS TESTING // integrated 2d seems to match 1d reasonably well, except perhaps at very high Q // Vol1,2,3 and dr1,2,3 are now for Vcore, Vcore+rim, Vcore+face, const double dr1 = -rhor - rhoh + rhoc + rhosolv; // Compute effective radius in rotated coordinates const double qr_hat = sqrt(square(r_major*qa) + square(r_minor*qb)); const double qr_hat = sqrt(square(r_major*qb) + square(r_minor*qa)); // does this need to be changed for the "missing corners" where there there is no "belt" ? const double qrshell_hat = sqrt(square((r_major+thick_rim)*qa) + square((r_minor+thick_rim)*qb)); const double qrshell_hat = sqrt(square((r_major+thick_rim)*qb) + square((r_minor+thick_rim)*qa)); const double be1 = sas_2J1x_x( qr_hat ); const double be2 = sas_2J1x_x( qrshell_hat );
• ## sasmodels/models/elliptical_cylinder.c

 rbecded3 //const double arg = radius_minor*sin_val; double inner_sum=0; for(int j=0;j<20;j++) { //20 gauss points for the inner integral const double theta = ( Gauss20Z[j]*(vbj-vaj) + vaj + vbj )/2.0; for(int j=0;j<76;j++) { //20 gauss points for the inner integral, increase to 76, RKH 6Nov2017 const double theta = ( Gauss76Z[j]*(vbj-vaj) + vaj + vbj )/2.0; const double r = sin_val*sqrt(rA - rB*cos(theta)); const double be = sas_2J1x_x(q*r); inner_sum += Gauss20Wt[j] * be * be; inner_sum += Gauss76Wt[j] * be * be; } //now calculate the value of the inner integral // Compute:  r = sqrt((radius_major*cos_nu)^2 + (radius_minor*cos_mu)^2) // Given:    radius_major = r_ratio * radius_minor const double qr = radius_minor*sqrt(square(r_ratio*qa) + square(qb)); const double qr = radius_minor*sqrt(square(r_ratio*qb) + square(qa)); const double be = sas_2J1x_x(qr); const double si = sas_sinx_x(qc*0.5*length);
• ## explore/asymint.py

 r1820208 a, b, c = env.mpf(a), env.mpf(b), env.mpf(c) def Fq(qa, qb, qc): siA = env.sas_sinx_x(0.5*a*qa/2) siB = env.sas_sinx_x(0.5*b*qb/2) siC = env.sas_sinx_x(0.5*c*qc/2) siA = env.sas_sinx_x(a*qa/2) siB = env.sas_sinx_x(b*qb/2) siC = env.sas_sinx_x(c*qc/2) return siA * siB * siC Fq.__doc__ = "parallelepiped a=%g, b=%g c=%g"%(a, b, c) volume = a*b*c norm = CONTRAST**2*volume/10000 return norm, Fq def make_core_shell_parallelepiped(a, b, c, da, db, dc, slda, sldb, sldc, env=NPenv): a, b, c = env.mpf(a), env.mpf(b), env.mpf(c) da, db, dc = env.mpf(da), env.mpf(db), env.mpf(dc) slda, sldb, sldc = env.mpf(slda), env.mpf(sldb), env.mpf(sldc) drV0 = CONTRAST*a*b*c dra, drb, drc = slda-SLD_SOLVENT, sldb-SLD_SOLVENT, sldc-SLD_SOLVENT Aa, Ab, Ac = b*c, a*c, a*b Ta, Tb, Tc = a + 2*da, b + 2*db, c + 2*dc drVa, drVb, drVc = dra*a*Aa, drb*b*Ab, drc*c*Ac drVTa, drVTb, drVTc = dra*Ta*Aa, drb*Tb*Ab, drc*Tc*Ac def Fq(qa, qb, qc): siA = env.sas_sinx_x(a*qa/2) siB = env.sas_sinx_x(b*qb/2) siC = env.sas_sinx_x(c*qc/2) siAt = env.sas_sinx_x(Ta*qa/2) siBt = env.sas_sinx_x(Tb*qb/2) siCt = env.sas_sinx_x(Tc*qc/2) return (drV0*siA*siB*siC + (drVTa*siAt-drVa*siA)*siB*siC + siA*(drVTb*siBt-drVb*siB)*siC + siA*siB*(drVTc*siCt-drVc*siC)) Fq.__doc__ = "core-shell parallelepiped a=%g, b=%g c=%g"%(a, b, c) volume = a*b*c + 2*da*Aa + 2*db*Ab + 2*dc*Ac norm = 1/(volume*10000) return norm, Fq NORM, KERNEL = make_parallelepiped(A, B, C) NORM_MP, KERNEL_MP = make_parallelepiped(A, B, C, env=MPenv) elif shape == 'core_shell_parallelepiped': #A, B, C = 4450, 14000, 47 #A, B, C = 445, 140, 47  # integer for the sake of mpf A, B, C = 6800, 114, 1380 DA, DB, DC = 2300, 21, 58 SLDA, SLDB, SLDC = "5", "-0.3", "11.5" if 1: # C shortest B, C = C, B DB, DC = DC, DB SLDB, SLDC = SLDC, SLDB elif 0: # C longest A, C = C, A DA, DC = DC, DA SLDA, SLDC = SLDC, SLDA NORM, KERNEL = make_core_shell_parallelepiped(A, B, C, DA, DB, DC, SLDA, SLDB, SLDC) NORM_MP, KERNEL_MP = make_core_shell_parallelepiped(A, B, C, DA, DB, DC, SLDA, SLDB, SLDC, env=MPenv) elif shape == 'paracrystal': LATTICE = 'bcc' print("gauss-150", *gauss_quad_2d(Q, n=150)) print("gauss-500", *gauss_quad_2d(Q, n=500)) print("gauss-1025", *gauss_quad_2d(Q, n=1025)) print("gauss-2049", *gauss_quad_2d(Q, n=2049)) #gridded_2d(Q, n=2**8+1) gridded_2d(Q, n=2**10+1) #gridded_2d(Q, n=2**13+1) #gridded_2d(Q, n=2**12+1) #gridded_2d(Q, n=2**15+1) if shape != 'paracrystal':  # adaptive forms are too slow! if shape not in ('paracrystal', 'core_shell_parallelepiped'): # adaptive forms on models for which the calculations are fast enough print("dblquad", *scipy_dblquad_2d(Q)) print("semi-romberg-100", *semi_romberg_2d(Q, n=100))
• ## sasmodels/compare.py

 r3bfd924 data = empty_data2D(q, resolution=res) data.accuracy = opts['accuracy'] set_beam_stop(data, 0.0004) set_beam_stop(data, qmin) index = ~data.mask else: if model_info != model_info2: pars2 = randomize_pars(model_info2, pars2) limit_dimensions(model_info, pars2, maxdim) limit_dimensions(model_info2, pars2, maxdim) # Share values for parameters with the same name for k, v in pars.items():
• ## sasmodels/models/core_shell_parallelepiped.c

 r904cd9c // Set OVERLAPPING to 1 in order to fill in the edges of the box, with // c endcaps and b overlapping a.  With the proper choice of parameters, // (setting rim slds to sld, core sld to solvent, rim thickness to thickness // and subtracting 2*thickness from length, this should match the hollow // rectangular prism.)  Set it to 0 for the documented behaviour. #define OVERLAPPING 0 static double form_volume(double length_a, double length_b, double length_c, double thick_rim_a, double thick_rim_b, double thick_rim_c) { //return length_a * length_b * length_c; return length_a * length_b * length_c + 2.0 * thick_rim_a * length_b * length_c + 2.0 * thick_rim_b * length_a * length_c + 2.0 * thick_rim_c * length_a * length_b; return #if OVERLAPPING // Hollow rectangular prism only includes the volume of the shell // so uncomment the next line when comparing.  Solid rectangular // prism, or parallelepiped want filled cores, so comment when // comparing. //-length_a * length_b * length_c + (length_a + 2.0*thick_rim_a) * (length_b + 2.0*thick_rim_b) * (length_c + 2.0*thick_rim_c); #else length_a * length_b * length_c + 2.0 * thick_rim_a * length_b * length_c + 2.0 * length_a * thick_rim_b * length_c + 2.0 * length_a * length_b * thick_rim_c; #endif } double thick_rim_c) { // Code converted from functions CSPPKernel and CSParallelepiped in libCylinder.c_scaled // Code converted from functions CSPPKernel and CSParallelepiped in libCylinder.c // Did not understand the code completely, it should be rechecked (Miguel Gonzalez) //Code is rewritten,the code is compliant with Diva Singhs thesis now (Dirk Honecker) const double mu = 0.5 * q * length_b; //calculate volume before rescaling (in original code, but not used) //double vol = form_volume(length_a, length_b, length_c, thick_rim_a, thick_rim_b, thick_rim_c); //double vol = length_a * length_b * length_c + //       2.0 * thick_rim_a * length_b * length_c + //       2.0 * thick_rim_b * length_a * length_c + //       2.0 * thick_rim_c * length_a * length_b; // Scale sides by B const double a_over_b = length_a / length_b; const double c_over_b = length_c / length_b; // Scale sides by B const double a_scaled = length_a / length_b; const double c_scaled = length_c / length_b; double ta = a_scaled + 2.0*thick_rim_a/length_b; // incorrect ta = (a_scaled + 2.0*thick_rim_a)/length_b; double tb = 1+ 2.0*thick_rim_b/length_b; // incorrect tb = (a_scaled + 2.0*thick_rim_b)/length_b; double tc = c_scaled + 2.0*thick_rim_c/length_b; //not present double tA_over_b = a_over_b + 2.0*thick_rim_a/length_b; double tB_over_b = 1+ 2.0*thick_rim_b/length_b; double tC_over_b = c_over_b + 2.0*thick_rim_c/length_b; double Vin = length_a * length_b * length_c; //double Vot = (length_a * length_b * length_c + //            2.0 * thick_rim_a * length_b * length_c + //            2.0 * length_a * thick_rim_b * length_c + //            2.0 * length_a * length_b * thick_rim_c); double V1 = (2.0 * thick_rim_a * length_b * length_c);    // incorrect V1 (aa*bb*cc+2*ta*bb*cc) double V2 = (2.0 * length_a * thick_rim_b * length_c);    // incorrect V2(aa*bb*cc+2*aa*tb*cc) double V3 = (2.0 * length_a * length_b * thick_rim_c);    //not present #if OVERLAPPING const double capA_area = length_b*length_c; const double capB_area = (length_a+2.*thick_rim_a)*length_c; const double capC_area = (length_a+2.*thick_rim_a)*(length_b+2.*thick_rim_b); #else const double capA_area = length_b*length_c; const double capB_area = length_a*length_c; const double capC_area = length_a*length_b; #endif const double Va = length_a * capA_area; const double Vb = length_b * capB_area; const double Vc = length_c * capC_area; const double Vat = Va + 2.0 * thick_rim_a * capA_area; const double Vbt = Vb + 2.0 * thick_rim_b * capB_area; const double Vct = Vc + 2.0 * thick_rim_c * capC_area; // Scale factors (note that drC is not used later) const double drho0 = (core_sld-solvent_sld); const double drhoA = (arim_sld-solvent_sld); const double drhoB = (brim_sld-solvent_sld); const double drhoC = (crim_sld-solvent_sld);  // incorrect const double drC_Vot = (crim_sld-solvent_sld)*Vot; // Precompute scale factors for combining cross terms from the shape const double scale23 = drhoA*V1; const double scale14 = drhoB*V2; const double scale24 = drhoC*V3; const double scale11 = drho0*Vin; const double scale12 = drho0*Vin - scale23 - scale14 - scale24; const double dr0 = (core_sld-solvent_sld); const double drA = (arim_sld-solvent_sld); const double drB = (brim_sld-solvent_sld); const double drC = (crim_sld-solvent_sld); // outer integral (with gauss points), integration limits = 0, 1 double outer_total = 0; //initialize integral double outer_sum = 0; //initialize integral for( int i=0; i<76; i++) { double sigma = 0.5 * ( Gauss76Z[i] + 1.0 ); double mu_proj = mu * sqrt(1.0-sigma*sigma); // inner integral (with gauss points), integration limits = 0, 1 double inner_total = 0.0; double inner_total_crim = 0.0; // inner integral (with gauss points), integration limits = 0, pi/2 const double siC = sas_sinx_x(mu * sigma * c_over_b); const double siCt = sas_sinx_x(mu * sigma * tC_over_b); double inner_sum = 0.0; for(int j=0; j<76; j++) { const double uu = 0.5 * ( Gauss76Z[j] + 1.0 ); double sin_uu, cos_uu; SINCOS(M_PI_2*uu, sin_uu, cos_uu); const double si1 = sas_sinx_x(mu_proj * sin_uu * a_scaled); const double si2 = sas_sinx_x(mu_proj * cos_uu ); const double si3 = sas_sinx_x(mu_proj * sin_uu * ta); const double si4 = sas_sinx_x(mu_proj * cos_uu * tb); const double siA = sas_sinx_x(mu_proj * sin_uu * a_over_b); const double siB = sas_sinx_x(mu_proj * cos_uu ); const double siAt = sas_sinx_x(mu_proj * sin_uu * tA_over_b); const double siBt = sas_sinx_x(mu_proj * cos_uu * tB_over_b); // Expression in libCylinder.c (neither drC nor Vot are used) const double form = scale12*si1*si2 + scale23*si2*si3 + scale14*si1*si4; const double form_crim = scale11*si1*si2; #if OVERLAPPING const double f = dr0*Vin*siA*siB*siC + drA*(Vat*siAt-Va*siA)*siB*siC + drB*siAt*(Vbt*siBt-Vb*siB)*siC + drC*siAt*siBt*(Vct*siCt-Vc*siC); #else const double f = dr0*Vin*siA*siB*siC + drA*(Vat*siAt-Va*siA)*siB*siC + drB*siA*(Vbt*siBt-Vb*siB)*siC + drC*siA*siB*(Vct*siCt-Vc*siC); #endif //  correct FF : sum of square of phase factors inner_total += Gauss76Wt[j] * form * form; inner_total_crim += Gauss76Wt[j] * form_crim * form_crim; inner_sum += Gauss76Wt[j] * f * f; } inner_total *= 0.5; inner_total_crim *= 0.5; inner_sum *= 0.5; // now sum up the outer integral const double si = sas_sinx_x(mu * c_scaled * sigma); const double si_crim = sas_sinx_x(mu * tc * sigma); outer_total += Gauss76Wt[i] * (inner_total * si * si + inner_total_crim * si_crim * si_crim); outer_sum += Gauss76Wt[i] * inner_sum; } outer_total *= 0.5; outer_sum *= 0.5; //convert from [1e-12 A-1] to [cm-1] return 1.0e-4 * outer_total; return 1.0e-4 * outer_sum; } double Vin = length_a * length_b * length_c; double V1 = 2.0 * thick_rim_a * length_b * length_c;    // incorrect V1(aa*bb*cc+2*ta*bb*cc) double V2 = 2.0 * length_a * thick_rim_b * length_c;    // incorrect V2(aa*bb*cc+2*aa*tb*cc) double V3 = 2.0 * length_a * length_b * thick_rim_c; // As for the 1D case, Vot is not used //double Vot = (length_a * length_b * length_c + //              2.0 * thick_rim_a * length_b * length_c + //              2.0 * length_a * thick_rim_b * length_c + //              2.0 * length_a * length_b * thick_rim_c); #if OVERLAPPING const double capA_area = length_b*length_c; const double capB_area = (length_a+2.*thick_rim_a)*length_c; const double capC_area = (length_a+2.*thick_rim_a)*(length_b+2.*thick_rim_b); #else const double capA_area = length_b*length_c; const double capB_area = length_a*length_c; const double capC_area = length_a*length_b; #endif const double Va = length_a * capA_area; const double Vb = length_b * capB_area; const double Vc = length_c * capC_area; const double Vat = Va + 2.0 * thick_rim_a * capA_area; const double Vbt = Vb + 2.0 * thick_rim_b * capB_area; const double Vct = Vc + 2.0 * thick_rim_c * capC_area; // The definitions of ta, tb, tc are not the same as in the 1D case because there is no // the scaling by B. double ta = length_a + 2.0*thick_rim_a; double tb = length_b + 2.0*thick_rim_b; double tc = length_c + 2.0*thick_rim_c; //handle arg=0 separately, as sin(t)/t -> 1 as t->0 double siA = sas_sinx_x(0.5*length_a*qa); double siB = sas_sinx_x(0.5*length_b*qb); double siC = sas_sinx_x(0.5*length_c*qc); double siAt = sas_sinx_x(0.5*ta*qa); double siBt = sas_sinx_x(0.5*tb*qb); double siCt = sas_sinx_x(0.5*tc*qc); const double tA = length_a + 2.0*thick_rim_a; const double tB = length_b + 2.0*thick_rim_b; const double tC = length_c + 2.0*thick_rim_c; const double siA = sas_sinx_x(0.5*length_a*qa); const double siB = sas_sinx_x(0.5*length_b*qb); const double siC = sas_sinx_x(0.5*length_c*qc); const double siAt = sas_sinx_x(0.5*tA*qa); const double siBt = sas_sinx_x(0.5*tB*qb); const double siCt = sas_sinx_x(0.5*tC*qc); // f uses Vin, V1, V2, and V3 and it seems to have more sense than the value computed // in the 1D code, but should be checked! double f = ( dr0*siA*siB*siC*Vin + drA*(siAt-siA)*siB*siC*V1 + drB*siA*(siBt-siB)*siC*V2 + drC*siA*siB*(siCt-siC)*V3); #if OVERLAPPING const double f = dr0*Vin*siA*siB*siC + drA*(Vat*siAt-Va*siA)*siB*siC + drB*siAt*(Vbt*siBt-Vb*siB)*siC + drC*siAt*siBt*(Vct*siCt-Vc*siC); #else const double f = dr0*Vin*siA*siB*siC + drA*(Vat*siAt-Va*siA)*siB*siC + drB*siA*(Vbt*siBt-Vb*siB)*siC + drC*siA*siB*(Vct*siCt-Vc*siC); #endif return 1.0e-4 * f * f;
• ## sasmodels/models/core_shell_parallelepiped.py

 r904cd9c Calculates the form factor for a rectangular solid with a core-shell structure. The thickness and the scattering length density of the shell or "rim" can be different on each (pair) of faces. However at this time the 1D calculation does **NOT** actually calculate a c face rim despite the presence of the parameter. Some other aspects of the 1D calculation may be wrong. .. note:: This model was originally ported from NIST IGOR macros. However, it is not yet fully understood by the SasView developers and is currently under review. "rim" can be different on each (pair) of faces. The form factor is normalized by the particle volume $V$ such that V = ABC + 2t_ABC + 2t_BAC + 2t_CAB **meaning that there are "gaps" at the corners of the solid.**  Again note that $t_C = 0$ currently. **meaning that there are "gaps" at the corners of the solid.** The intensity calculated follows the :ref:parallelepiped model, with the core-shell intensity being calculated as the square of the sum of the amplitudes of the core and shell, in the same manner as a core-shell model. .. math:: F_{a}(Q,\alpha,\beta)= \left[\frac{\sin(\tfrac{1}{2}Q(L_A+2t_A)\sin\alpha \sin\beta)}{\tfrac{1}{2}Q(L_A+2t_A)\sin\alpha\sin\beta} - \frac{\sin(\tfrac{1}{2}QL_A\sin\alpha \sin\beta)}{\tfrac{1}{2}QL_A\sin\alpha \sin\beta} \right] \left[\frac{\sin(\tfrac{1}{2}QL_B\sin\alpha \sin\beta)}{\tfrac{1}{2}QL_B\sin\alpha \sin\beta} \right] \left[\frac{\sin(\tfrac{1}{2}QL_C\sin\alpha \sin\beta)}{\tfrac{1}{2}QL_C\sin\alpha \sin\beta} \right] .. note:: Why does t_B not appear in the above equation? For the calculation of the form factor to be valid, the sides of the solid MUST (perhaps not any more?) be chosen such that** $A < B < C$. If this inequality is not satisfied, the model will not report an error, but the calculation will not be correct and thus the result wrong. amplitudes of the core and the slabs on the edges. the scattering amplitude is computed for a particular orientation of the core-shell parallelepiped with respect to the scattering vector and then averaged over all possible orientations, where $\alpha$ is the angle between the $z$ axis and the longest axis $C$ of the parallelepiped, $\beta$ is the angle between projection of the particle in the $xy$ detector plane and the $y$ axis. .. math:: \begin{align*} F(Q)&=A B C (\rho_\text{core}-\rho_\text{solvent})  S(A \sin\alpha \sin\beta)S(B \sin\alpha \cos\beta)S(C \cos\alpha) \\ &+ 2t_A B C (\rho_\text{A}-\rho_\text{solvent})  \left[S((A+t_A) \sin\alpha \sin\beta)-S(A \sin\alpha \sin\beta)\right] S(B \sin\alpha \cos\beta) S(C \cos\alpha)\\ &+ 2 A t_B C (\rho_\text{B}-\rho_\text{solvent})  S(A \sin\alpha \sin\beta) \left[S((B+t_B) \sin\alpha \cos\beta)-S(B \sin\alpha \cos\beta)\right] S(C \cos\alpha)\\ &+ 2 A B t_C (\rho_\text{C}-\rho_\text{solvent}) S(A \sin\alpha \sin\beta) S(B \sin\alpha \cos\beta) \left[S((C+t_C) \cos\alpha)-S(C \cos\alpha)\right] \end{align*} with .. math:: S(x) = \frac{\sin \tfrac{1}{2}Q x}{\tfrac{1}{2}Q x} where $\rho_\text{core}$, $\rho_\text{A}$, $\rho_\text{B}$ and $\rho_\text{C}$ are the scattering length of the parallelepiped core, and the rectangular slabs of thickness $t_A$, $t_B$ and $t_C$, respectively. $\rho_\text{solvent}$ is the scattering length of the solvent. FITTING NOTES known values, or you will certainly end up at a solution that is unphysical. Constraints must be applied during fitting to ensure that the inequality $A < B < C$ is not violated. The calculation will not report an error, but the results will not be correct. The returned value is in units of |cm^-1|, on absolute scale. $\Psi = 0$ when the *short_b* axis is parallel to the *x*-axis of the detector. For 2d, constraints must be applied during fitting to ensure that the inequality $A < B < C$ is not violated, and hence the correct definition of angles is preserved. The calculation will not report an error, but the results may be not correct. .. figure:: img/parallelepiped_angle_definition.png Definition of the angles for oriented core-shell parallelepipeds. Note that rotation $\theta$, initially in the $xz$ plane, is carried out first, then rotation $\phi$ about the $z$ axis, finally rotation $\Psi$ is now around the axis of the cylinder. rotation $\phi$ about the $z$ axis, finally rotation $\Psi$ is now around the axis of the parallelepiped. The neutron or X-ray beam is along the $z$ axis. Equations (1), (13-14). (in German) .. [#] D Singh (2009). *Small angle scattering studies of self assembly in lipid mixtures*, John's Hopkins University Thesis (2009) 223-225. Available lipid mixtures*, Johns Hopkins University Thesis (2009) 223-225. Available from Proquest _
• ## sasmodels/models/hollow_rectangular_prism.c

 r1e7b0db0 double form_volume(double length_a, double b2a_ratio, double c2a_ratio, double thickness); double Iq(double q, double sld, double solvent_sld, double length_a, double Iq(double q, double sld, double solvent_sld, double length_a, double b2a_ratio, double c2a_ratio, double thickness); const double v2a = 0.0; const double v2b = M_PI_2;  //phi integration limits double outer_sum = 0.0; for(int i=0; i<76; i++) { return 1.0e-4 * delrho * delrho * form; } double Iqxy(double qa, double qb, double qc, double sld, double solvent_sld, double length_a, double b2a_ratio, double c2a_ratio, double thickness) { const double length_b = length_a * b2a_ratio; const double length_c = length_a * c2a_ratio; const double a_half = 0.5 * length_a; const double b_half = 0.5 * length_b; const double c_half = 0.5 * length_c; const double vol_total = length_a * length_b * length_c; const double vol_core = 8.0 * (a_half-thickness) * (b_half-thickness) * (c_half-thickness); // Amplitude AP from eqn. (13) const double termA1 = sas_sinx_x(qa * a_half); const double termA2 = sas_sinx_x(qa * (a_half-thickness)); const double termB1 = sas_sinx_x(qb * b_half); const double termB2 = sas_sinx_x(qb * (b_half-thickness)); const double termC1 = sas_sinx_x(qc * c_half); const double termC2 = sas_sinx_x(qc * (c_half-thickness)); const double AP1 = vol_total * termA1 * termB1 * termC1; const double AP2 = vol_core * termA2 * termB2 * termC2; // Multiply by contrast^2. Factor corresponding to volume^2 cancels with previous normalization. const double delrho = sld - solvent_sld; // Convert from [1e-12 A-1] to [cm-1] return 1.0e-4 * square(delrho * (AP1-AP2)); }
• ## sasmodels/models/hollow_rectangular_prism.py

 r30b60d2 This model provides the form factor, $P(q)$, for a hollow rectangular parallelepiped with a wall of thickness $\Delta$. It computes only the 1D scattering, not the 2D. Definition (which is unitless). **The 2D scattering intensity is not computed by this model.** For 2d data the orientation of the particle is required, described using angles $\theta$, $\phi$ and $\Psi$ as in the diagrams below, for further details of the calculation and angular dispersions see :ref:orientation . The angle $\Psi$ is the rotational angle around the long *C* axis. For example, $\Psi = 0$ when the *B* axis is parallel to the *x*-axis of the detector. For 2d, constraints must be applied during fitting to ensure that the inequality $A < B < C$ is not violated, and hence the correct definition of angles is preserved. The calculation will not report an error, but the results may be not correct. .. figure:: img/parallelepiped_angle_definition.png Definition of the angles for oriented hollow rectangular prism. Note that rotation $\theta$, initially in the $xz$ plane, is carried out first, then rotation $\phi$ about the $z$ axis, finally rotation $\Psi$ is now around the axis of the prism. The neutron or X-ray beam is along the $z$ axis. .. figure:: img/parallelepiped_angle_projection.png Examples of the angles for oriented hollow rectangular prisms against the detector plane. ["thickness", "Ang", 1, [0, inf], "volume", "Thickness of parallelepiped"], ["theta", "degrees", 0, [-360, 360], "orientation", "c axis to beam angle"], ["phi", "degrees", 0, [-360, 360], "orientation", "rotation about beam"], ["psi", "degrees", 0, [-360, 360], "orientation", "rotation about c axis"], ] [{}, [0.2], [0.76687283098]], ]
• ## sasmodels/models/rectangular_prism.c

 r1e7b0db0 double form_volume(double length_a, double b2a_ratio, double c2a_ratio); double Iq(double q, double sld, double solvent_sld, double length_a, double Iq(double q, double sld, double solvent_sld, double length_a, double b2a_ratio, double c2a_ratio); const double v2a = 0.0; const double v2b = M_PI_2;  //phi integration limits double outer_sum = 0.0; for(int i=0; i<76; i++) { double answer = 0.5*(v1b-v1a)*outer_sum; // Normalize by Pi (Eqn. 16). // The term (ABC)^2 does not appear because it was introduced before on // Normalize by Pi (Eqn. 16). // The term (ABC)^2 does not appear because it was introduced before on // the definitions of termA, termB, termC. // The factor 2 appears because the theta integral has been defined between // The factor 2 appears because the theta integral has been defined between // 0 and pi/2, instead of 0 to pi. answer /= M_PI_2; //Form factor P(q) answer *= square((sld-solvent_sld)*volume); // Convert from [1e-12 A-1] to [cm-1] // Convert from [1e-12 A-1] to [cm-1] answer *= 1.0e-4; return answer; } double Iqxy(double qa, double qb, double qc, double sld, double solvent_sld, double length_a, double b2a_ratio, double c2a_ratio) { const double length_b = length_a * b2a_ratio; const double length_c = length_a * c2a_ratio; const double a_half = 0.5 * length_a; const double b_half = 0.5 * length_b; const double c_half = 0.5 * length_c; const double volume = length_a * length_b * length_c; // Amplitude AP from eqn. (13) const double termA = sas_sinx_x(qa * a_half); const double termB = sas_sinx_x(qb * b_half); const double termC = sas_sinx_x(qc * c_half); const double AP = termA * termB * termC; // Multiply by contrast^2. Factor corresponding to volume^2 cancels with previous normalization. const double delrho = sld - solvent_sld; // Convert from [1e-12 A-1] to [cm-1] return 1.0e-4 * square(volume * delrho * AP); }
• ## sasmodels/models/rectangular_prism.py

 r31df0c9 the prism (e.g. setting $b/a = 1$ and $c/a = 1$ and applying polydispersity to *a* will generate a distribution of cubes of different sizes). Note also that, contrary to :ref:parallelepiped, it does not compute the 2D scattering. that reference), with $\theta$ corresponding to $\alpha$ in that paper, and not to the usual convention used for example in the :ref:parallelepiped model. As the present model does not compute the 2D scattering, this has no further consequences. :ref:parallelepiped model. In this model the scattering from a massive parallelepiped with an units) *scale* represents the volume fraction (which is unitless). **The 2D scattering intensity is not computed by this model.** For 2d data the orientation of the particle is required, described using angles $\theta$, $\phi$ and $\Psi$ as in the diagrams below, for further details of the calculation and angular dispersions see :ref:orientation` . The angle $\Psi$ is the rotational angle around the long *C* axis. For example, $\Psi = 0$ when the *B* axis is parallel to the *x*-axis of the detector. For 2d, constraints must be applied during fitting to ensure that the inequality $A < B < C$ is not violated, and hence the correct definition of angles is preserved. The calculation will not report an error, but the results may be not correct. .. figure:: img/parallelepiped_angle_definition.png Definition of the angles for oriented core-shell parallelepipeds. Note that rotation $\theta$, initially in the $xz$ plane, is carried out first, then rotation $\phi$ about the $z$ axis, finally rotation $\Psi$ is now around the axis of the cylinder. The neutron or X-ray beam is along the $z$ axis. .. figure:: img/parallelepiped_angle_projection.png Examples of the angles for oriented rectangular prisms against the detector plane. ["c2a_ratio", "", 1, [0, inf], "volume", "Ratio sides c/a"], ["theta", "degrees", 0, [-360, 360], "orientation", "c axis to beam angle"], ["phi", "degrees", 0, [-360, 360], "orientation", "rotation about beam"], ["psi", "degrees", 0, [-360, 360], "orientation", "rotation about c axis"], ]
Note: See TracChangeset for help on using the changeset viewer.