Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • sasmodels/models/core_shell_parallelepiped.c

    rc69d6d6 rfc0b7aa  
    1 double form_volume(double length_a, double length_b, double length_c, 
    2                    double thick_rim_a, double thick_rim_b, double thick_rim_c); 
    3 double Iq(double q, double core_sld, double arim_sld, double brim_sld, double crim_sld, 
    4           double solvent_sld, double length_a, double length_b, double length_c, 
    5           double thick_rim_a, double thick_rim_b, double thick_rim_c); 
    6 double Iqxy(double qx, double qy, double core_sld, double arim_sld, double brim_sld, 
    7             double crim_sld, double solvent_sld, double length_a, double length_b, 
    8             double length_c, double thick_rim_a, double thick_rim_b, 
    9             double thick_rim_c, double theta, double phi, double psi); 
    10  
    11 double form_volume(double length_a, double length_b, double length_c, 
    12                    double thick_rim_a, double thick_rim_b, double thick_rim_c) 
     1// Set OVERLAPPING to 1 in order to fill in the edges of the box, with 
     2// c endcaps and b overlapping a.  With the proper choice of parameters, 
     3// (setting rim slds to sld, core sld to solvent, rim thickness to thickness 
     4// and subtracting 2*thickness from length, this should match the hollow 
     5// rectangular prism.)  Set it to 0 for the documented behaviour. 
     6#define OVERLAPPING 0 
     7static double 
     8form_volume(double length_a, double length_b, double length_c, 
     9    double thick_rim_a, double thick_rim_b, double thick_rim_c) 
    1310{ 
    14     //return length_a * length_b * length_c; 
    15     return length_a * length_b * length_c + 
    16            2.0 * thick_rim_a * length_b * length_c + 
    17            2.0 * thick_rim_b * length_a * length_c + 
    18            2.0 * thick_rim_c * length_a * length_b; 
     11    return 
     12#if OVERLAPPING 
     13        // Hollow rectangular prism only includes the volume of the shell 
     14        // so uncomment the next line when comparing.  Solid rectangular 
     15        // prism, or parallelepiped want filled cores, so comment when 
     16        // comparing. 
     17        //-length_a * length_b * length_c + 
     18        (length_a + 2.0*thick_rim_a) * 
     19        (length_b + 2.0*thick_rim_b) * 
     20        (length_c + 2.0*thick_rim_c); 
     21#else 
     22        length_a * length_b * length_c + 
     23        2.0 * thick_rim_a * length_b * length_c + 
     24        2.0 * length_a * thick_rim_b * length_c + 
     25        2.0 * length_a * length_b * thick_rim_c; 
     26#endif 
    1927} 
    2028 
    21 double Iq(double q, 
     29static double 
     30Iq(double q, 
    2231    double core_sld, 
    2332    double arim_sld, 
     
    3241    double thick_rim_c) 
    3342{ 
    34     // Code converted from functions CSPPKernel and CSParallelepiped in libCylinder.c_scaled 
     43    // Code converted from functions CSPPKernel and CSParallelepiped in libCylinder.c 
    3544    // Did not understand the code completely, it should be rechecked (Miguel Gonzalez) 
    3645    //Code is rewritten,the code is compliant with Diva Singhs thesis now (Dirk Honecker) 
     
    3847    const double mu = 0.5 * q * length_b; 
    3948 
    40     //calculate volume before rescaling (in original code, but not used) 
    41     //double vol = form_volume(length_a, length_b, length_c, thick_rim_a, thick_rim_b, thick_rim_c); 
    42     //double vol = length_a * length_b * length_c + 
    43     //       2.0 * thick_rim_a * length_b * length_c + 
    44     //       2.0 * thick_rim_b * length_a * length_c + 
    45     //       2.0 * thick_rim_c * length_a * length_b; 
     49    // Scale sides by B 
     50    const double a_over_b = length_a / length_b; 
     51    const double c_over_b = length_c / length_b; 
    4652 
    47     // Scale sides by B 
    48     const double a_scaled = length_a / length_b; 
    49     const double c_scaled = length_c / length_b; 
    50  
    51     double ta = a_scaled + 2.0*thick_rim_a/length_b; // incorrect ta = (a_scaled + 2.0*thick_rim_a)/length_b; 
    52     double tb = 1+ 2.0*thick_rim_b/length_b; // incorrect tb = (a_scaled + 2.0*thick_rim_b)/length_b; 
    53     double tc = c_scaled + 2.0*thick_rim_c/length_b; //not present 
     53    double tA_over_b = a_over_b + 2.0*thick_rim_a/length_b; 
     54    double tB_over_b = 1+ 2.0*thick_rim_b/length_b; 
     55    double tC_over_b = c_over_b + 2.0*thick_rim_c/length_b; 
    5456 
    5557    double Vin = length_a * length_b * length_c; 
    56     //double Vot = (length_a * length_b * length_c + 
    57     //            2.0 * thick_rim_a * length_b * length_c + 
    58     //            2.0 * length_a * thick_rim_b * length_c + 
    59     //            2.0 * length_a * length_b * thick_rim_c); 
    60     double V1 = (2.0 * thick_rim_a * length_b * length_c);    // incorrect V1 (aa*bb*cc+2*ta*bb*cc) 
    61     double V2 = (2.0 * length_a * thick_rim_b * length_c);    // incorrect V2(aa*bb*cc+2*aa*tb*cc) 
    62     double V3 = (2.0 * length_a * length_b * thick_rim_c);    //not present 
    63     double Vot = Vin + V1 + V2 + V3; 
     58#if OVERLAPPING 
     59    const double capA_area = length_b*length_c; 
     60    const double capB_area = (length_a+2.*thick_rim_a)*length_c; 
     61    const double capC_area = (length_a+2.*thick_rim_a)*(length_b+2.*thick_rim_b); 
     62#else 
     63    const double capA_area = length_b*length_c; 
     64    const double capB_area = length_a*length_c; 
     65    const double capC_area = length_a*length_b; 
     66#endif 
     67    const double Va = length_a * capA_area; 
     68    const double Vb = length_b * capB_area; 
     69    const double Vc = length_c * capC_area; 
     70    const double Vat = Va + 2.0 * thick_rim_a * capA_area; 
     71    const double Vbt = Vb + 2.0 * thick_rim_b * capB_area; 
     72    const double Vct = Vc + 2.0 * thick_rim_c * capC_area; 
    6473 
    6574    // Scale factors (note that drC is not used later) 
    66     const double drho0 = (core_sld-solvent_sld); 
    67     const double drhoA = (arim_sld-solvent_sld); 
    68     const double drhoB = (brim_sld-solvent_sld); 
    69     const double drhoC = (crim_sld-solvent_sld);  // incorrect const double drC_Vot = (crim_sld-solvent_sld)*Vot; 
    70  
    71  
    72     // Precompute scale factors for combining cross terms from the shape 
    73     const double scale23 = drhoA*V1; 
    74     const double scale14 = drhoB*V2; 
    75     const double scale24 = drhoC*V3; 
    76     const double scale11 = drho0*Vin; 
    77     const double scale12 = drho0*Vin - scale23 - scale14 - scale24; 
     75    const double dr0 = (core_sld-solvent_sld); 
     76    const double drA = (arim_sld-solvent_sld); 
     77    const double drB = (brim_sld-solvent_sld); 
     78    const double drC = (crim_sld-solvent_sld); 
    7879 
    7980    // outer integral (with gauss points), integration limits = 0, 1 
    80     double outer_total = 0; //initialize integral 
    81  
     81    double outer_sum = 0; //initialize integral 
    8282    for( int i=0; i<76; i++) { 
    8383        double sigma = 0.5 * ( Gauss76Z[i] + 1.0 ); 
    8484        double mu_proj = mu * sqrt(1.0-sigma*sigma); 
    8585 
    86         // inner integral (with gauss points), integration limits = 0, 1 
    87         double inner_total = 0.0; 
    88         double inner_total_crim = 0.0; 
     86        // inner integral (with gauss points), integration limits = 0, pi/2 
     87        const double siC = sas_sinx_x(mu * sigma * c_over_b); 
     88        const double siCt = sas_sinx_x(mu * sigma * tC_over_b); 
     89        double inner_sum = 0.0; 
    8990        for(int j=0; j<76; j++) { 
    9091            const double uu = 0.5 * ( Gauss76Z[j] + 1.0 ); 
    9192            double sin_uu, cos_uu; 
    9293            SINCOS(M_PI_2*uu, sin_uu, cos_uu); 
    93             const double si1 = sas_sinx_x(mu_proj * sin_uu * a_scaled); 
    94             const double si2 = sas_sinx_x(mu_proj * cos_uu ); 
    95             const double si3 = sas_sinx_x(mu_proj * sin_uu * ta); 
    96             const double si4 = sas_sinx_x(mu_proj * cos_uu * tb); 
     94            const double siA = sas_sinx_x(mu_proj * sin_uu * a_over_b); 
     95            const double siB = sas_sinx_x(mu_proj * cos_uu ); 
     96            const double siAt = sas_sinx_x(mu_proj * sin_uu * tA_over_b); 
     97            const double siBt = sas_sinx_x(mu_proj * cos_uu * tB_over_b); 
    9798 
    98             // Expression in libCylinder.c (neither drC nor Vot are used) 
    99             const double form = scale12*si1*si2 + scale23*si2*si3 + scale14*si1*si4; 
    100             const double form_crim = scale11*si1*si2; 
     99#if OVERLAPPING 
     100            const double f = dr0*Vin*siA*siB*siC 
     101                + drA*(Vat*siAt-Va*siA)*siB*siC 
     102                + drB*siAt*(Vbt*siBt-Vb*siB)*siC 
     103                + drC*siAt*siBt*(Vct*siCt-Vc*siC); 
     104#else 
     105            const double f = dr0*Vin*siA*siB*siC 
     106                + drA*(Vat*siAt-Va*siA)*siB*siC 
     107                + drB*siA*(Vbt*siBt-Vb*siB)*siC 
     108                + drC*siA*siB*(Vct*siCt-Vc*siC); 
     109#endif 
    101110 
    102  
    103             //  correct FF : sum of square of phase factors 
    104             inner_total += Gauss76Wt[j] * form * form; 
    105             inner_total_crim += Gauss76Wt[j] * form_crim * form_crim; 
     111            inner_sum += Gauss76Wt[j] * f * f; 
    106112        } 
    107         inner_total *= 0.5; 
    108         inner_total_crim *= 0.5; 
     113        inner_sum *= 0.5; 
    109114        // now sum up the outer integral 
    110         const double si = sas_sinx_x(mu * c_scaled * sigma); 
    111         const double si_crim = sas_sinx_x(mu * tc * sigma); 
    112         outer_total += Gauss76Wt[i] * (inner_total * si * si + inner_total_crim * si_crim * si_crim); 
     115        outer_sum += Gauss76Wt[i] * inner_sum; 
    113116    } 
    114     outer_total *= 0.5; 
     117    outer_sum *= 0.5; 
    115118 
    116119    //convert from [1e-12 A-1] to [cm-1] 
    117     return 1.0e-4 * outer_total; 
     120    return 1.0e-4 * outer_sum; 
    118121} 
    119122 
    120 double Iqxy(double qx, double qy, 
     123static double 
     124Iqxy(double qa, double qb, double qc, 
    121125    double core_sld, 
    122126    double arim_sld, 
     
    129133    double thick_rim_a, 
    130134    double thick_rim_b, 
    131     double thick_rim_c, 
    132     double theta, 
    133     double phi, 
    134     double psi) 
     135    double thick_rim_c) 
    135136{ 
    136     double q, zhat, yhat, xhat; 
    137     ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, xhat, yhat, zhat); 
    138  
    139137    // cspkernel in csparallelepiped recoded here 
    140138    const double dr0 = core_sld-solvent_sld; 
     
    144142 
    145143    double Vin = length_a * length_b * length_c; 
    146     double V1 = 2.0 * thick_rim_a * length_b * length_c;    // incorrect V1(aa*bb*cc+2*ta*bb*cc) 
    147     double V2 = 2.0 * length_a * thick_rim_b * length_c;    // incorrect V2(aa*bb*cc+2*aa*tb*cc) 
    148     double V3 = 2.0 * length_a * length_b * thick_rim_c; 
    149     // As for the 1D case, Vot is not used 
    150     //double Vot = (length_a * length_b * length_c + 
    151     //              2.0 * thick_rim_a * length_b * length_c + 
    152     //              2.0 * length_a * thick_rim_b * length_c + 
    153     //              2.0 * length_a * length_b * thick_rim_c); 
     144#if OVERLAPPING 
     145    const double capA_area = length_b*length_c; 
     146    const double capB_area = (length_a+2.*thick_rim_a)*length_c; 
     147    const double capC_area = (length_a+2.*thick_rim_a)*(length_b+2.*thick_rim_b); 
     148#else 
     149    const double capA_area = length_b*length_c; 
     150    const double capB_area = length_a*length_c; 
     151    const double capC_area = length_a*length_b; 
     152#endif 
     153    const double Va = length_a * capA_area; 
     154    const double Vb = length_b * capB_area; 
     155    const double Vc = length_c * capC_area; 
     156    const double Vat = Va + 2.0 * thick_rim_a * capA_area; 
     157    const double Vbt = Vb + 2.0 * thick_rim_b * capB_area; 
     158    const double Vct = Vc + 2.0 * thick_rim_c * capC_area; 
    154159 
    155160    // The definitions of ta, tb, tc are not the same as in the 1D case because there is no 
    156161    // the scaling by B. 
    157     double ta = length_a + 2.0*thick_rim_a; 
    158     double tb = length_b + 2.0*thick_rim_b; 
    159     double tc = length_c + 2.0*thick_rim_c; 
    160     //handle arg=0 separately, as sin(t)/t -> 1 as t->0 
    161     double siA = sas_sinx_x(0.5*q*length_a*xhat); 
    162     double siB = sas_sinx_x(0.5*q*length_b*yhat); 
    163     double siC = sas_sinx_x(0.5*q*length_c*zhat); 
    164     double siAt = sas_sinx_x(0.5*q*ta*xhat); 
    165     double siBt = sas_sinx_x(0.5*q*tb*yhat); 
    166     double siCt = sas_sinx_x(0.5*q*tc*zhat); 
     162    const double tA = length_a + 2.0*thick_rim_a; 
     163    const double tB = length_b + 2.0*thick_rim_b; 
     164    const double tC = length_c + 2.0*thick_rim_c; 
     165    const double siA = sas_sinx_x(0.5*length_a*qa); 
     166    const double siB = sas_sinx_x(0.5*length_b*qb); 
     167    const double siC = sas_sinx_x(0.5*length_c*qc); 
     168    const double siAt = sas_sinx_x(0.5*tA*qa); 
     169    const double siBt = sas_sinx_x(0.5*tB*qb); 
     170    const double siCt = sas_sinx_x(0.5*tC*qc); 
    167171 
    168  
    169     // f uses Vin, V1, V2, and V3 and it seems to have more sense than the value computed 
    170     // in the 1D code, but should be checked! 
    171     double f = ( dr0*siA*siB*siC*Vin 
    172                + drA*(siAt-siA)*siB*siC*V1 
    173                + drB*siA*(siBt-siB)*siC*V2 
    174                + drC*siA*siB*(siCt-siC)*V3); 
     172#if OVERLAPPING 
     173    const double f = dr0*Vin*siA*siB*siC 
     174        + drA*(Vat*siAt-Va*siA)*siB*siC 
     175        + drB*siAt*(Vbt*siBt-Vb*siB)*siC 
     176        + drC*siAt*siBt*(Vct*siCt-Vc*siC); 
     177#else 
     178    const double f = dr0*Vin*siA*siB*siC 
     179        + drA*(Vat*siAt-Va*siA)*siB*siC 
     180        + drB*siA*(Vbt*siBt-Vb*siB)*siC 
     181        + drC*siA*siB*(Vct*siCt-Vc*siC); 
     182#endif 
    175183 
    176184    return 1.0e-4 * f * f; 
Note: See TracChangeset for help on using the changeset viewer.