static double bcc_Zq(double qa, double qb, double qc, double lattice_spacing, double lattice_distortion) { // Equations from Matsuoka 26-27-28, multiplied by |q| const double a1 = (-qa + qb + qc)/2.0; const double a2 = (+qa - qb + qc)/2.0; const double a3 = (+qa + qb - qc)/2.0; #if 1 // Matsuoka 29-30-31 // Z_k numerator: 1 - exp(a)^2 // Z_k denominator: 1 - 2 cos(d a_k) exp(a) + exp(2a) // Rewriting numerator // => -(exp(2a) - 1) // => -expm1(2a) // Rewriting denominator // => exp(a)^2 - 2 cos(d ak) exp(a) + 1) // => (exp(a) - 2 cos(d ak)) * exp(a) + 1 const double arg = -0.5*square(lattice_spacing*lattice_distortion)*(a1*a1 + a2*a2 + a3*a3); const double exp_arg = exp(arg); const double Zq = -cube(expm1(2.0*arg)) / ( ((exp_arg - 2.0*cos(lattice_spacing*a1))*exp_arg + 1.0) * ((exp_arg - 2.0*cos(lattice_spacing*a2))*exp_arg + 1.0) * ((exp_arg - 2.0*cos(lattice_spacing*a3))*exp_arg + 1.0)); #elif 0 // ** Alternate form, which perhaps is more approachable // Z_k numerator => -[(exp(2a) - 1) / 2.exp(a)] 2.exp(a) // => -[sinh(a)] exp(a) // Z_k denominator => [(exp(2a) + 1) / 2.exp(a) - cos(d a_k)] 2.exp(a) // => [cosh(a) - cos(d a_k)] 2.exp(a) // => Z_k = -sinh(a) / [cosh(a) - cos(d a_k)] // = sinh(-a) / [cosh(-a) - cos(d a_k)] // // One more step leads to the form in sasview 3.x for 2d models // = tanh(-a) / [1 - cos(d a_k)/cosh(-a)] // const double arg = 0.5*square(lattice_spacing*lattice_distortion)*(a1*a1 + a2*a2 + a3*a3); const double sinh_qd = sinh(arg); const double cosh_qd = cosh(arg); const double Zq = sinh_qd/(cosh_qd - cos(lattice_spacing*a1)) * sinh_qd/(cosh_qd - cos(lattice_spacing*a2)) * sinh_qd/(cosh_qd - cos(lattice_spacing*a3)); #else const double arg = 0.5*square(lattice_spacing*lattice_distortion)*(a1*a1 + a2*a2 + a3*a3); const double tanh_qd = tanh(arg); const double cosh_qd = cosh(arg); const double Zq = tanh_qd/(1.0 - cos(lattice_spacing*a1)/cosh_qd) * tanh_qd/(1.0 - cos(lattice_spacing*a2)/cosh_qd) * tanh_qd/(1.0 - cos(lattice_spacing*a3)/cosh_qd); #endif return Zq; } // occupied volume fraction calculated from lattice symmetry and sphere radius static double bcc_volume_fraction(double radius, double lattice_spacing) { return 2.0*sphere_volume(radius/lattice_spacing); } static double form_volume(double radius) { return sphere_volume(radius); } static double Iq(double q, double lattice_spacing, double lattice_distortion, double radius, double sld, double solvent_sld) { // translate a point in [-1,1] to a point in [0, 2 pi] const double phi_m = M_PI; const double phi_b = M_PI; // translate a point in [-1,1] to a point in [0, pi] const double theta_m = M_PI_2; const double theta_b = M_PI_2; double outer_sum = 0.0; for(int i=0; i