#include #include "parameters.hh" #include #include extern "C" { #include "libmultifunc/librefl.h" } #include "spheresld.h" using namespace std; // Convenience structure typedef struct { /// number of shells // [DEFAULT]=n_shells=1 int n_shells; /// Scale factor // [DEFAULT]=scale= 1.0 double scale; /// thick_inter0 [A] // [DEFAULT]=thick_inter0=50.0 [A] double thick_inter0; /// func_inter0 // [DEFAULT]=func_inter0= 0 double func_inter0; /// sld_core0 [1/A^(2)] // [DEFAULT]=sld_core0= 2.07e-6 [1/A^(2)] double sld_core0; /// sld_solv [1/A^(2)] // [DEFAULT]=sld_solv= 1.0e-6 [1/A^(2)] double sld_solv; /// Background // [DEFAULT]=background=0 double background; // [DEFAULT]=sld_flat1=4.0e-06 [1/A^(2)] double sld_flat1; // [DEFAULT]=sld_flat2=3.5e-06 [1/A^(2)] double sld_flat2; // [DEFAULT]=sld_flat3=4.0e-06 [1/A^(2)] double sld_flat3; // [DEFAULT]=sld_flat4=3.5e-06 [1/A^(2)] double sld_flat4; // [DEFAULT]=sld_flat5=4.0e-06 [1/A^(2)] double sld_flat5; // [DEFAULT]=sld_flat6=3.5e-06 [1/A^(2)] double sld_flat6; // [DEFAULT]=sld_flat7=4.0e-06 [1/A^(2)] double sld_flat7; // [DEFAULT]=sld_flat8=3.5e-06 [1/A^(2)] double sld_flat8; // [DEFAULT]=sld_flat9=4.0e-06 [1/A^(2)] double sld_flat9; // [DEFAULT]=sld_flat10=3.5e-06 [1/A^(2)] double sld_flat10; // [DEFAULT]=thick_inter1=50.0 [A] double thick_inter1; // [DEFAULT]=thick_inter2=50.0 [A] double thick_inter2; // [DEFAULT]=thick_inter3=50.0 [A] double thick_inter3; // [DEFAULT]=thick_inter4=50.0 [A] double thick_inter4; // [DEFAULT]=thick_inter5=50.0 [A] double thick_inter5; // [DEFAULT]=thick_inter6=50.0 [A] double thick_inter6; // [DEFAULT]=thick_inter7=50.0 [A] double thick_inter7; // [DEFAULT]=thick_inter8=50.0 [A] double thick_inter8; // [DEFAULT]=thick_inter9=50.0 [A] double thick_inter9; // [DEFAULT]=thick_inter10=50.0 [A] double thick_inter10; // [DEFAULT]=thick_flat1=100 [A] double thick_flat1; // [DEFAULT]=thick_flat2=100 [A] double thick_flat2; // [DEFAULT]=thick_flat3=100 [A] double thick_flat3; // [DEFAULT]=thick_flat4=100 [A] double thick_flat4; // [DEFAULT]=thick_flat5=100 [A] double thick_flat5; // [DEFAULT]=thick_flat6=100 [A] double thick_flat6; // [DEFAULT]=thick_flat7=100 [A] double thick_flat7; // [DEFAULT]=thick_flat8=100 [A] double thick_flat8; // [DEFAULT]=thick_flat9=100 [A] double thick_flat9; // [DEFAULT]=thick_flat10=100 [A] double thick_flat10; // [DEFAULT]=func_inter1=0 double func_inter1; // [DEFAULT]=func_inter2=0 double func_inter2; // [DEFAULT]=func_inter3=0 double func_inter3; // [DEFAULT]=func_inter4=0 double func_inter4; // [DEFAULT]=func_inter5=0 double func_inter5; // [DEFAULT]=func_inter6=0 double func_inter6; // [DEFAULT]=func_inter7=0 double func_inter7; // [DEFAULT]=func_inter8=0 double func_inter8; // [DEFAULT]=func_inter9=0 double func_inter9; // [DEFAULT]=func_inter10=0 double func_inter10; // [DEFAULT]=nu_inter1=2.5 double nu_inter1; // [DEFAULT]=nu_inter2=2.5 double nu_inter2; // [DEFAULT]=nu_inter3=2.5 double nu_inter3; // [DEFAULT]=nu_inter4=2.5 double nu_inter4; // [DEFAULT]=nu_inter5=2.5 double nu_inter5; // [DEFAULT]=nu_inter6=2.5 double nu_inter6; // [DEFAULT]=nu_inter7=2.5 double nu_inter7; // [DEFAULT]=nu_inter8=2.5 double nu_inter8; // [DEFAULT]=nu_inter9=2.5 double nu_inter9; // [DEFAULT]=nu_inter10=2.5 double nu_inter10; // [DEFAULT]=npts_inter=35.0 double npts_inter; // [DEFAULT]=nu_inter0=2.5 double nu_inter0; // [DEFAULT]=rad_core0=50.0 [A] double rad_core0; } SphereSLDParameters; static double sphere_sld_kernel(double dp[], double q) { int n = dp[0]; int i,j,k; double scale = dp[1]; double thick_inter_core = dp[2]; double sld_core = dp[4]; double sld_solv = dp[5]; double background = dp[6]; double npts = dp[57]; //number of sub_layers in each interface double nsl=npts;//21.0; //nsl = Num_sub_layer: MUST ODD number in double //no other number works now int n_s; double sld_i,sld_f,dz,bes,fun,f,vol,vol_pre,vol_sub,qr,r,contr,f2; double sign,slope=0.0; double pi; int* fun_type; double* sld; double* thick_inter; double* thick; double* fun_coef; double total_thick=0.0; fun_type = (int*)malloc((n+2)*sizeof(int)); sld = (double*)malloc((n+2)*sizeof(double)); thick_inter = (double*)malloc((n+2)*sizeof(double)); thick = (double*)malloc((n+2)*sizeof(double)); fun_coef = (double*)malloc((n+2)*sizeof(double)); fun_type[0] = dp[3]; fun_coef[0] = fabs(dp[58]); for (i =1; i<=n; i++){ sld[i] = dp[i+6]; thick_inter[i]= dp[i+16]; thick[i] = dp[i+26]; fun_type[i] = dp[i+36]; fun_coef[i] = fabs(dp[i+46]); total_thick += thick[i] + thick_inter[i]; } sld[0] = sld_core; sld[n+1] = sld_solv; thick[0] = dp[59]; thick[n+1] = total_thick/5.0; thick_inter[0] = thick_inter_core; thick_inter[n+1] = 0.0; fun_coef[n+1] = 0.0; pi = 4.0*atan(1.0); f = 0.0; r = 0.0; vol = 0.0; vol_pre = 0.0; vol_sub = 0.0; sld_f = sld_core; //floor_nsl = floor(nsl/2.0); dz = 0.0; // iteration for # of shells + core + solvent for (i=0;i<=n+1; i++){ //iteration for N sub-layers //if (fabs(thick[i]) <= 1e-24){ // continue; //} // iteration for flat and interface for (j=0;j<2;j++){ // iteration for sub_shells in the interface // starts from #1 sub-layer for (n_s=1;n_s<=nsl; n_s++){ // for solvent, it doesn't have an interface if (i==n+1 && j==1) break; // for flat layers if (j==0){ dz = thick[i]; sld_i = sld[i]; slope = 0.0; } // for interfacial sub_shells else{ dz = thick_inter[i]/nsl; // find sld_i at the outer boundary of sub-layer #n_s sld_i = intersldfunc(fun_type[i],nsl, n_s, fun_coef[i], sld[i], sld[i+1]); // calculate slope slope= (sld_i -sld_f)/dz; } contr = sld_f-slope*r; // iteration for the left and right boundary of the shells(or sub_shells) for (k=0; k<2; k++){ // At r=0, the contribution to I is zero, so skip it. if ( i == 0 && j == 0 && k == 0){ continue; } // On the top of slovent there is no interface; skip it. if (i == n+1 && k == 1){ continue; } // At the right side (outer) boundary if ( k == 1){ sign = 1.0; r += dz; } // At the left side (inner) boundary else{ sign = -1.0; } qr = q * r; fun = 0.0; if(qr == 0.0){ // sigular point bes = sign * 1.0; } else{ // for flat sub-layer bes = sign * 3.0 * (sin(qr) - qr * cos(qr)) / (qr * qr * qr); // with linear slope if (fabs(slope) > 0.0 ){ fun = sign * 3.0 * r * (2.0*qr*sin(qr)-((qr*qr)-2.0)*cos(qr))/(qr * qr * qr * qr); } } // update total volume vol = 4.0 * pi / 3.0 * r * r * r; // we won't do the following volume correction for now. // substrate empty area of volume //if (k == 1 && fabs(sld_in[i]-sld_solv) < 1e-04*fabs(sld_solv) && fun_type[i]==0){ // vol_sub += (vol_pre - vol); //} f += vol * (bes * contr + fun * slope); } // remember this sld as sld_f sld_f =sld_i; // no sub-layer iteration (n_s loop) for the flat layer if (j==0) break; } } } //vol += vol_sub; f2 = f * f / vol * 1.0e8; f2 *= scale; f2 += background; free(fun_type); free(sld); free(thick_inter); free(thick); free(fun_coef); return (f2); } SphereSLDModel :: SphereSLDModel() { n_shells = Parameter(1.0); scale = Parameter(1.0); thick_inter0 = Parameter(1.0, true); thick_inter0.set_min(0.0); func_inter0 = Parameter(0); sld_core0 = Parameter(2.07e-06); sld_solv = Parameter(1.0e-06); background = Parameter(0.0); sld_flat1 = Parameter(2.7e-06); sld_flat2 = Parameter(3.5e-06); sld_flat3 = Parameter(4.0e-06); sld_flat4 = Parameter(3.5e-06); sld_flat5 = Parameter(4.0e-06); sld_flat6 = Parameter(3.5e-06); sld_flat7 = Parameter(4.0e-06); sld_flat8 = Parameter(3.5e-06); sld_flat9 = Parameter(4.0e-06); sld_flat10 = Parameter(3.5e-06); thick_inter1 = Parameter(1.0); thick_inter2 = Parameter(1.0); thick_inter3 = Parameter(1.0); thick_inter4 = Parameter(1.0); thick_inter5 = Parameter(1.0); thick_inter6 = Parameter(1.0); thick_inter7 = Parameter(1.0); thick_inter8 = Parameter(1.0); thick_inter9 = Parameter(1.0); thick_inter10 = Parameter(1.0); thick_flat1 = Parameter(100.0); thick_flat2 = Parameter(100.0); thick_flat3 = Parameter(100.0); thick_flat4 = Parameter(100.0); thick_flat5 = Parameter(100.0); thick_flat6 = Parameter(100.0); thick_flat7 = Parameter(100.0); thick_flat8 = Parameter(100.0); thick_flat9 = Parameter(100.0); thick_flat10 = Parameter(100.0); func_inter1 = Parameter(0); func_inter2 = Parameter(0); func_inter3 = Parameter(0); func_inter4 = Parameter(0); func_inter5 = Parameter(0); func_inter6 = Parameter(0); func_inter7 = Parameter(0); func_inter8 = Parameter(0); func_inter9 = Parameter(0); func_inter10 = Parameter(0); nu_inter1 = Parameter(2.5); nu_inter2 = Parameter(2.5); nu_inter3 = Parameter(2.5); nu_inter4 = Parameter(2.5); nu_inter5 = Parameter(2.5); nu_inter6 = Parameter(2.5); nu_inter7 = Parameter(2.5); nu_inter8 = Parameter(2.5); nu_inter9 = Parameter(2.5); nu_inter10 = Parameter(2.5); npts_inter = Parameter(35.0); nu_inter0 = Parameter(2.5); rad_core0 = Parameter(60.0, true); rad_core0.set_min(0.0); } /** * Function to evaluate 1D SphereSLD function * @param q: q-value * @return: function value */ double SphereSLDModel :: operator()(double q) { double dp[60]; // Fill parameter array for IGOR library // Add the background after averaging dp[0] = n_shells(); dp[1] = scale(); dp[2] = thick_inter0(); dp[3] = func_inter0(); dp[4] = sld_core0(); dp[5] = sld_solv(); dp[6] = 0.0; dp[7] = sld_flat1(); dp[8] = sld_flat2(); dp[9] = sld_flat3(); dp[10] = sld_flat4(); dp[11] = sld_flat5(); dp[12] = sld_flat6(); dp[13] = sld_flat7(); dp[14] = sld_flat8(); dp[15] = sld_flat9(); dp[16] = sld_flat10(); dp[17] = thick_inter1(); dp[18] = thick_inter2(); dp[19] = thick_inter3(); dp[20] = thick_inter4(); dp[21] = thick_inter5(); dp[22] = thick_inter6(); dp[23] = thick_inter7(); dp[24] = thick_inter8(); dp[25] = thick_inter9(); dp[26] = thick_inter10(); dp[27] = thick_flat1(); dp[28] = thick_flat2(); dp[29] = thick_flat3(); dp[30] = thick_flat4(); dp[31] = thick_flat5(); dp[32] = thick_flat6(); dp[33] = thick_flat7(); dp[34] = thick_flat8(); dp[35] = thick_flat9(); dp[36] = thick_flat10(); dp[37] = func_inter1(); dp[38] = func_inter2(); dp[39] = func_inter3(); dp[40] = func_inter4(); dp[41] = func_inter5(); dp[42] = func_inter6(); dp[43] = func_inter7(); dp[44] = func_inter8(); dp[45] = func_inter9(); dp[46] = func_inter10(); dp[47] = nu_inter1(); dp[48] = nu_inter2(); dp[49] = nu_inter3(); dp[50] = nu_inter4(); dp[51] = nu_inter5(); dp[52] = nu_inter6(); dp[53] = nu_inter7(); dp[54] = nu_inter8(); dp[55] = nu_inter9(); dp[56] = nu_inter10(); dp[57] = npts_inter(); dp[58] = nu_inter0(); dp[59] = rad_core0(); // No polydispersion supported in this model. // Get the dispersion points for the radius vector weights_rad_core0; rad_core0.get_weights(weights_rad_core0); vector weights_thick_inter0; thick_inter0.get_weights(weights_thick_inter0); // Perform the computation, with all weight points double sum = 0.0; double norm = 0.0; double vol = 0.0; // Loop over core weight points for(size_t i=0; i weights_rad_core0; rad_core0.get_weights(weights_rad_core0); // Get the dispersion points for the thick 1 vector weights_thick_inter0; thick_inter0.get_weights(weights_thick_inter0); // Loop over radius weight points for(size_t i=0; i 0) rad_out += dp.thick_flat1 + dp.thick_inter1; if (dp.n_shells > 1) rad_out += dp.thick_flat2 + dp.thick_inter2; if (dp.n_shells > 2) rad_out += dp.thick_flat3 + dp.thick_inter3; if (dp.n_shells > 3) rad_out += dp.thick_flat4 + dp.thick_inter4; if (dp.n_shells > 4) rad_out += dp.thick_flat5 + dp.thick_inter5; if (dp.n_shells > 5) rad_out += dp.thick_flat6 + dp.thick_inter6; if (dp.n_shells > 6) rad_out += dp.thick_flat7 + dp.thick_inter7; if (dp.n_shells > 7) rad_out += dp.thick_flat8 + dp.thick_inter8; if (dp.n_shells > 8) rad_out += dp.thick_flat9 + dp.thick_inter9; if (dp.n_shells > 9) rad_out += dp.thick_flat10 + dp.thick_inter10; sum += weights_rad_core0[i].weight*weights_thick_inter0[j].weight * (rad_out); norm += weights_rad_core0[i].weight*weights_thick_inter0[j].weight; } } if (norm != 0){ //return the averaged value out = sum/norm;} else{ //return normal value out = dp.rad_core0 + dp.thick_inter0; if (dp.n_shells > 0) out += dp.thick_flat1 + dp.thick_inter1; if (dp.n_shells > 1) out += dp.thick_flat2 + dp.thick_inter2; if (dp.n_shells > 2) out += dp.thick_flat3 + dp.thick_inter3; if (dp.n_shells > 3) out += dp.thick_flat4 + dp.thick_inter4; if (dp.n_shells > 4) out += dp.thick_flat5 + dp.thick_inter5; if (dp.n_shells > 5) out += dp.thick_flat6 + dp.thick_inter6; if (dp.n_shells > 6) out += dp.thick_flat7 + dp.thick_inter7; if (dp.n_shells > 7) out += dp.thick_flat8 + dp.thick_inter8; if (dp.n_shells > 8) out += dp.thick_flat9 + dp.thick_inter9; if (dp.n_shells > 9) out += dp.thick_flat10 + dp.thick_inter10; } return out; } double SphereSLDModel :: calculate_VR() { return 1.0; }