Changes in sasmodels/models/core_shell_parallelepiped.c [c69d6d6:fc0b7aa] in sasmodels
- 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 7 static double 8 form_volume(double length_a, double length_b, double length_c, 9 double thick_rim_a, double thick_rim_b, double thick_rim_c) 13 10 { 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 19 27 } 20 28 21 double Iq(double q, 29 static double 30 Iq(double q, 22 31 double core_sld, 23 32 double arim_sld, … … 32 41 double thick_rim_c) 33 42 { 34 // Code converted from functions CSPPKernel and CSParallelepiped in libCylinder.c _scaled43 // Code converted from functions CSPPKernel and CSParallelepiped in libCylinder.c 35 44 // Did not understand the code completely, it should be rechecked (Miguel Gonzalez) 36 45 //Code is rewritten,the code is compliant with Diva Singhs thesis now (Dirk Honecker) … … 38 47 const double mu = 0.5 * q * length_b; 39 48 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; 46 52 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; 54 56 55 57 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; 64 73 65 74 // 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); 78 79 79 80 // outer integral (with gauss points), integration limits = 0, 1 80 double outer_total = 0; //initialize integral 81 81 double outer_sum = 0; //initialize integral 82 82 for( int i=0; i<76; i++) { 83 83 double sigma = 0.5 * ( Gauss76Z[i] + 1.0 ); 84 84 double mu_proj = mu * sqrt(1.0-sigma*sigma); 85 85 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; 89 90 for(int j=0; j<76; j++) { 90 91 const double uu = 0.5 * ( Gauss76Z[j] + 1.0 ); 91 92 double sin_uu, cos_uu; 92 93 SINCOS(M_PI_2*uu, sin_uu, cos_uu); 93 const double si 1 = sas_sinx_x(mu_proj * sin_uu * a_scaled);94 const double si 2= sas_sinx_x(mu_proj * cos_uu );95 const double si 3 = sas_sinx_x(mu_proj * sin_uu * ta);96 const double si 4 = 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); 97 98 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 101 110 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; 106 112 } 107 inner_total *= 0.5; 108 inner_total_crim *= 0.5; 113 inner_sum *= 0.5; 109 114 // 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; 113 116 } 114 outer_ total*= 0.5;117 outer_sum *= 0.5; 115 118 116 119 //convert from [1e-12 A-1] to [cm-1] 117 return 1.0e-4 * outer_ total;120 return 1.0e-4 * outer_sum; 118 121 } 119 122 120 double Iqxy(double qx, double qy, 123 static double 124 Iqxy(double qa, double qb, double qc, 121 125 double core_sld, 122 126 double arim_sld, … … 129 133 double thick_rim_a, 130 134 double thick_rim_b, 131 double thick_rim_c, 132 double theta, 133 double phi, 134 double psi) 135 double thick_rim_c) 135 136 { 136 double q, zhat, yhat, xhat;137 ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, xhat, yhat, zhat);138 139 137 // cspkernel in csparallelepiped recoded here 140 138 const double dr0 = core_sld-solvent_sld; … … 144 142 145 143 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; 154 159 155 160 // The definitions of ta, tb, tc are not the same as in the 1D case because there is no 156 161 // 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); 167 171 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 175 183 176 184 return 1.0e-4 * f * f;
Note: See TracChangeset
for help on using the changeset viewer.