Changeset 54bcd4a in sasmodels for sasmodels/models/spherical_sld.c
- Timestamp:
- Aug 4, 2016 4:48:37 PM (8 years ago)
- Branches:
- master, core_shell_microgels, costrafo411, magnetic_model, release_v0.94, release_v0.95, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
- Children:
- 745b7bb
- Parents:
- bd49c79
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/models/spherical_sld.c
rdd71228 r54bcd4a 1 1 static double form_volume( 2 2 int n_shells, 3 double radius_core, 4 double thick_inter0, 5 double thick_flat[], 6 double thick_inter[]) 3 double thickness[], 4 double interface[]) 7 5 { 8 int i; 9 double r = radius_core; 10 r += thick_inter0; 11 for (i=0; i < n_shells; i++) { 12 r += thick_inter[i]; 13 r += thick_flat[i]; 6 double r = 0.0; 7 for (int i=0; i < n_shells; i++) { 8 r += thickness[i] + interface[i]; 14 9 } 15 10 return M_4PI_3*cube(r); 16 11 } 17 12 13 static double blend(int shape, double nu, double z) 14 { 15 if (shape==0) { 16 const double num = sas_erf(nu * M_SQRT1_2 * (2.0*z - 1.0)); 17 const double denom = 2.0 * sas_erf(nu * M_SQRT1_2); 18 return num/denom + 0.5; 19 } else if (shape==1) { 20 return pow(z, nu); 21 } else if (shape==2) { 22 return 1.0 - pow(1. - z, nu); 23 } else if (shape==3) { 24 return expm1(-nu*z)/expm1(-nu); 25 } else if (shape==4) { 26 return expm1(nu*z)/expm1(nu); 27 } else { 28 return NAN; 29 } 30 } 18 31 19 static double sphere_sld_kernel( 32 static double f_linear(double q, double r, double contrast, double slope) 33 { 34 const double qr = q * r; 35 const double qrsq = qr * qr; 36 const double bes = sph_j1c(qr); 37 double sinqr, cosqr; 38 SINCOS(qr, sinqr, cosqr); 39 const double fun = 3.0*r*(2.0*qr*sinqr - (qrsq-2.0)*cosqr)/(qrsq*qrsq); 40 const double vol = M_4PI_3 * cube(r); 41 return vol*(bes*contrast + fun*slope); 42 } 43 44 static double Iq( 20 45 double q, 21 46 int n_shells, 22 int npts_inter,23 double radius_core,24 double sld_core,25 47 double sld_solvent, 26 double func_inter_core, 27 double thick_inter_core, 28 double nu_inter_core, 29 double sld_flat[], 30 double thick_flat[], 31 double func_inter[], 32 double thick_inter[], 33 double nu_inter[] ) { 48 double sld[], 49 double thickness[], 50 double interface[], 51 double shape[], 52 double nu[], 53 int n_steps) 54 { 55 // iteration for # of shells + core + solvent 56 double f=0.0; 57 double r=0.0; 58 for (int shell=0; shell<n_shells; shell++){ 59 const double sld_l = sld[shell]; 34 60 35 int i,j,k; 36 int n_s; 61 // uniform shell; r=0 => r^3=0 => f=0, so works for core as well. 62 f -= M_4PI_3 * cube(r) * sld_l * sph_j1c(q*r); 63 r += thickness[shell]; 64 f += M_4PI_3 * cube(r) * sld_l * sph_j1c(q*r); 37 65 38 double sld_i,sld_f,dz,bes,fun,f,vol,qr,r,contr,f2; 39 double sign,slope=0.0; 40 double pi; 66 // iterate over sub_shells in the interface 67 const double dr = interface[shell]/n_steps; 68 const double delta = (shell==n_shells-1 ? sld_solvent : sld[shell+1]) - sld_l; 69 const double nu_shell = fmax(fabs(nu[shell]), 1.e-14); 70 const int shape_shell = (int)(shape[shell]); 41 71 42 double total_thick=0.0; 72 // if there is no interface the equations don't work 73 if (dr == 0.) continue; 43 74 44 //TODO: This part can be further simplified 45 int fun_type[12]; 46 double sld[12]; 47 double thick_internal[12]; 48 double thick[12]; 49 double fun_coef[12]; 75 double sld_in = sld_l; 76 for (int step=1; step <= n_steps; step++) { 77 // find sld_i at the outer boundary of sub-shell step 78 //const double z = (double)step/(double)n_steps; 79 const double z = (double)step/(double)n_steps; 80 const double fraction = blend(shape_shell, nu_shell, z); 81 const double sld_out = fraction*delta + sld_l; 82 // calculate slope 83 const double slope = (sld_out - sld_in)/dr; 84 const double contrast = sld_in - slope*r; 50 85 51 fun_type[0] = func_inter_core; 52 fun_coef[0] = fabs(nu_inter_core); 53 sld[0] = sld_core; 54 thick[0] = radius_core; 55 thick_internal[0] = thick_inter_core; 56 57 for (i =1; i<=n_shells; i++){ 58 sld[i] = sld_flat[i-1]; 59 thick_internal[i]= thick_inter[i-1]; 60 thick[i] = thick_flat[i-1]; 61 fun_type[i] = func_inter[i-1]; 62 fun_coef[i] = fabs(nu_inter[i-1]); 63 total_thick += thick[i]; 64 total_thick += thick_internal[i]; //doesn't account for core layer 65 } 66 67 sld[n_shells+1] = sld_solvent; 68 thick[n_shells+1] = total_thick/5.0; 69 thick_internal[n_shells+1] = 0.0; 70 fun_coef[n_shells+1] = 0.0; 71 fun_type[n_shells+1] = 0; 72 73 pi = 4.0*atan(1.0); 74 f = 0.0; 75 r = 0.0; 76 vol = 0.0; 77 sld_f = sld_core; 78 79 dz = 0.0; 80 // iteration for # of shells + core + solvent 81 for (i=0;i<=n_shells+1; i++){ 82 // iteration for flat and interface 83 for (j=0;j<2;j++){ 84 // iteration for sub_shells in the interface 85 // starts from #1 sub-layer 86 for (n_s=1;n_s<=npts_inter; n_s++){ 87 // for solvent, it doesn't have an interface 88 if (i==n_shells+1 && j==1) 89 break; 90 // for flat layers 91 if (j==0){ 92 dz = thick[i]; 93 sld_i = sld[i]; 94 slope = 0.0; 95 } 96 // for interfacial sub_shells 97 else{ 98 dz = thick_internal[i]/npts_inter; 99 // find sld_i at the outer boundary of sub-layer #n_s 100 sld_i = intersldfunc(fun_type[i], npts_inter, n_s, 101 fun_coef[i], sld[i], sld[i+1]); 102 // calculate slope 103 slope= (sld_i -sld_f)/dz; 104 } 105 contr = sld_f-slope*r; 106 // iteration for the left and right boundary of the shells 107 for (k=0; k<2; k++){ 108 // At r=0, the contribution to I is zero, so skip it. 109 if ( i == 0 && j == 0 && k == 0){ 110 continue; 111 } 112 // On the top of slovent there is no interface; skip it. 113 if (i == n_shells+1 && k == 1){ 114 continue; 115 } 116 // At the right side (outer) boundary 117 if ( k == 1){ 118 sign = 1.0; 119 r += dz; 120 } 121 // At the left side (inner) boundary 122 else{ 123 sign = -1.0; 124 } 125 126 qr = q * r; 127 fun = 0.0; 128 129 if(qr == 0.0){ 130 bes = sign * 1.0; 131 } 132 else{ 133 // for flat sub-layer 134 //TODO: Single precision calculation fails here 135 bes = sign * sph_j1c(qr); 136 if (fabs(slope) > 0.0 ){ 137 const double qrsq = qr*qr; 138 double sinqr, cosqr; 139 SINCOS(qr, sinqr, cosqr); 140 fun = sign * 3.0 * r * 141 (2.0*qr*sinqr - (qrsq-2.0)*cosqr)/(qrsq * qrsq); 142 // In the onion model Jae-He's formula is rederived 143 // and gives following: 144 //fun = 3.0 * sign * r * 145 //(2.0*cosqr + qr*sinqr)/(qrsq*qrsq); 146 //But this seems not to be working in this case... 147 } 148 } 149 150 // update total volume 151 vol = M_4PI_3 * cube(r); 152 f += vol * (bes * contr + fun * slope); 153 } 154 sld_f = sld_i; 155 // no sub-layer iteration (n_s loop) for the flat layer 156 if (j==0) 157 break; 158 } 86 // iteration for the left and right boundary of the shells 87 f -= f_linear(q, r, contrast, slope); 88 r += dr; 89 f += f_linear(q, r, contrast, slope); 90 sld_in = sld_out; 159 91 } 160 92 } 93 // add in solvent effect 94 f -= M_4PI_3 * cube(r) * sld_solvent * sph_j1c(q*r); 161 95 162 f2 = f * f * 1.0e-4;163 return (f2);96 const double f2 = f * f * 1.0e-4; 97 return f2; 164 98 } 165 99 166 167 /**168 * Function to evaluate 1D SphereSLD function169 * @param q: q-value170 * @return: function value171 */172 static double Iq(double q,173 int n_shells,174 int npts_inter,175 double radius_core,176 double sld_core,177 double sld_solvent,178 double func_inter0,179 double thick_inter0,180 double nu_inter0,181 double sld_flat[],182 double thick_flat[],183 double func_inter[],184 double thick_inter[],185 double nu_inter[] ) {186 187 double intensity = sphere_sld_kernel(q, n_shells, npts_inter, radius_core,188 sld_core, sld_solvent, func_inter0, thick_inter0, nu_inter0,189 sld_flat, thick_flat, func_inter, thick_inter, nu_inter);190 191 return intensity;192 }193 194 /**195 * Function to evaluate 2D SphereSLD function196 * @param q_x: value of Q along x197 * @param q_y: value of Q along y198 * @return: function value199 */200 201 /*static double Iqxy(double qx, double qy,202 int n_shells,203 int npts_inter,204 double radius_core205 double sld_core,206 double sld_solvent,207 double sld_flat[],208 double thick_flat[],209 double func_inter[],210 double thick_inter[],211 double nu_inter[],212 ) {213 214 double q = sqrt(qx*qx + qy*qy);215 return Iq(q, n_shells, npts_inter, radius_core, sld_core, sld_solvent,216 sld_flat[], thick_flat[], func_inter[], thick_inter[], nu_inter[])217 }*/218
Note: See TracChangeset
for help on using the changeset viewer.