/* SimpleFit.c A simplified project designed to act as a template for your curve fitting function. The fitting function is a simple polynomial. It works but is of no practical use. */ #include "StandardHeaders.h" // Include ANSI headers, Mac headers #include "GaussWeights.h" #include "libSphere.h" static double gammln(double xx) { double x,y,tmp,ser; static double cof[6]={76.18009172947146,-86.50532032941677, 24.01409824083091,-1.231739572450155, 0.1208650973866179e-2,-0.5395239384953e-5}; int j; y=x=xx; tmp=x+5.5; tmp -= (x+0.5)*log(tmp); ser=1.000000000190015; for (j=0;j<=5;j++) ser += cof[j]/++y; return -tmp+log(2.5066282746310005*ser/x); } static double LogNormal_distr(double sig, double mu, double pt) { double retval,pi; pi = 4.0*atan(1.0); retval = (1.0/ (sig*pt*sqrt(2.0*pi)) )*exp( -0.5*(log(pt) - mu)*(log(pt) - mu)/sig/sig ); return(retval); } static double Gauss_distr(double sig, double avg, double pt) { double retval,Pi; Pi = 4.0*atan(1.0); retval = (1.0/ (sig*sqrt(2.0*Pi)) )*exp(-(avg-pt)*(avg-pt)/sig/sig/2.0); return(retval); } static double SchulzPoint(double x, double avg, double zz) { double dr; dr = zz*log(x) - gammln(zz+1.0)+(zz+1.0)*log((zz+1.0)/avg)-(x/avg*(zz+1.0)); return (exp(dr)); }; // scattering from a sphere - hardly needs to be an XOP... double SphereForm(double dp[], double q) { double scale,radius,delrho,bkg,sldSph,sldSolv; //my local names double bes,f,vol,f2,pi,qr; pi = 4.0*atan(1.0); scale = dp[0]; radius = dp[1]; sldSph = dp[2]; sldSolv = dp[3]; bkg = dp[4]; delrho = sldSph - sldSolv; //handle qr==0 separately qr = q*radius; if(qr == 0.0){ bes = 1.0; }else{ bes = 3.0*(sin(qr)-qr*cos(qr))/(qr*qr*qr); } vol = 4.0*pi/3.0*radius*radius*radius; f = vol*bes*delrho; // [=] A-1 // normalize to single particle volume, convert to 1/cm f2 = f * f / vol * 1.0e8; // [=] 1/cm return(scale*f2+bkg); //scale, and add in the background } // scattering from a monodisperse core-shell sphere - hardly needs to be an XOP... double CoreShellForm(double dp[], double q) { double x,pi; double scale,rcore,thick,rhocore,rhoshel,rhosolv,bkg; //my local names double bes,f,vol,qr,contr,f2; pi = 4.0*atan(1.0); x=q; scale = dp[0]; rcore = dp[1]; thick = dp[2]; rhocore = dp[3]; rhoshel = dp[4]; rhosolv = dp[5]; bkg = dp[6]; // core first, then add in shell qr=x*rcore; contr = rhocore-rhoshel; if(qr == 0.0){ bes = 1.0; }else{ bes = 3.0*(sin(qr)-qr*cos(qr))/(qr*qr*qr); } vol = 4.0*pi/3.0*rcore*rcore*rcore; f = vol*bes*contr; //now the shell qr=x*(rcore+thick); contr = rhoshel-rhosolv; if(qr == 0.0){ bes = 1.0; }else{ bes = 3.0*(sin(qr)-qr*cos(qr))/(qr*qr*qr); } vol = 4.0*pi/3.0*pow((rcore+thick),3); f += vol*bes*contr; // normalize to particle volume and rescale from [A-1] to [cm-1] f2 = f*f/vol*1.0e8; //scale if desired f2 *= scale; // then add in the background f2 += bkg; return(f2); } // scattering from a unilamellar vesicle - hardly needs to be an XOP... // same functional form as the core-shell sphere, but more intuitive for a vesicle double VesicleForm(double dp[], double q) { double x,pi; double scale,rcore,thick,rhocore,rhoshel,rhosolv,bkg; //my local names double bes,f,vol,qr,contr,f2; pi = 4.0*atan(1.0); x= q; scale = dp[0]; rcore = dp[1]; thick = dp[2]; rhocore = dp[3]; rhosolv = rhocore; rhoshel = dp[4]; bkg = dp[5]; // core first, then add in shell qr=x*rcore; contr = rhocore-rhoshel; if(qr == 0){ bes = 1.0; }else{ bes = 3.0*(sin(qr)-qr*cos(qr))/(qr*qr*qr); } vol = 4.0*pi/3.0*rcore*rcore*rcore; f = vol*bes*contr; //now the shell qr=x*(rcore+thick); contr = rhoshel-rhosolv; if(qr == 0.0){ bes = 1.0; }else{ bes = 3.0*(sin(qr)-qr*cos(qr))/(qr*qr*qr); } vol = 4.0*pi/3.0*pow((rcore+thick),3); f += vol*bes*contr; // normalize to the particle volume and rescale from [A-1] to [cm-1] //note that for the vesicle model, the volume is ONLY the shell volume vol = 4.0*pi/3.0*(pow((rcore+thick),3)-pow(rcore,3)); f2 = f*f/vol*1.0e8; //scale if desired f2 *= scale; // then add in the background f2 += bkg; return(f2); } // scattering from a core shell sphere with a (Schulz) polydisperse core and constant shell thickness // double PolyCoreForm(double dp[], double q) { double pi; double scale,corrad,sig,zz,del,drho1,drho2,form,bkg; //my local names double d, g ,h; double qq, x, y, c1, c2, c3, c4, c5, c6, c7, c8, c9, t1, t2, t3; double t4, t5, tb, cy, sy, tb1, tb2, tb3, c2y, zp1, zp2; double zp3,vpoly; double s2y, arg1, arg2, arg3, drh1, drh2; pi = 4.0*atan(1.0); qq= q; scale = dp[0]; corrad = dp[1]; sig = dp[2]; del = dp[3]; drho1 = dp[4]-dp[5]; //core-shell drho2 = dp[5]-dp[6]; //shell-solvent bkg = dp[7]; zz = (1.0/sig)*(1.0/sig) - 1.0; h=qq; drh1 = drho1; drh2 = drho2; g = drh2 * -1. / drh1; zp1 = zz + 1.; zp2 = zz + 2.; zp3 = zz + 3.; vpoly = 4*pi/3*zp3*zp2/zp1/zp1*pow((corrad+del),3); // remember that h is the passed in value of q for the calculation y = h *del; x = h *corrad; d = atan(x * 2. / zp1); arg1 = zp1 * d; arg2 = zp2 * d; arg3 = zp3 * d; sy = sin(y); cy = cos(y); s2y = sin(y * 2.); c2y = cos(y * 2.); c1 = .5 - g * (cy + y * sy) + g * g * .5 * (y * y + 1.); c2 = g * y * (g - cy); c3 = (g * g + 1.) * .5 - g * cy; c4 = g * g * (y * cy - sy) * (y * cy - sy) - c1; c5 = g * 2. * sy * (1. - g * (y * sy + cy)) + c2; c6 = c3 - g * g * sy * sy; c7 = g * sy - g * .5 * g * (y * y + 1.) * s2y - c5; c8 = c4 - .5 + g * cy - g * .5 * g * (y * y + 1.) * c2y; c9 = g * sy * (1. - g * cy); tb = log(zp1 * zp1 / (zp1 * zp1 + x * 4. * x)); tb1 = exp(zp1 * .5 * tb); tb2 = exp(zp2 * .5 * tb); tb3 = exp(zp3 * .5 * tb); t1 = c1 + c2 * x + c3 * x * x * zp2 / zp1; t2 = tb1 * (c4 * cos(arg1) + c7 * sin(arg1)); t3 = x * tb2 * (c5 * cos(arg2) + c8 * sin(arg2)); t4 = zp2 / zp1 * x * x * tb3 * (c6 * cos(arg3) + c9 * sin(arg3)); t5 = t1 + t2 + t3 + t4; form = t5 * 16. * pi * pi * drh1 * drh1 / pow(qq,6); // normalize by the average volume !!! corrected for polydispersity // and convert to cm-1 form /= vpoly; form *= 1.0e8; //Scale form *= scale; // then add in the background form += bkg; return(form); } // scattering from a uniform sphere with a (Schulz) size distribution // structure factor effects are explicitly and correctly included. // double PolyHardSphereIntensity(double dp[], double q) { double pi; double rad,z2,phi,cont,bkg,sigma; //my local names double mu,mu1,d1,d2,d3,d4,d5,d6,capd,rho; double ll,l1,bb,cc,chi,chi1,chi2,ee,t1,t2,t3,pp; double ka,zz,v1,v2,p1,p2; double h1,h2,h3,h4,e1,yy,y1,s1,s2,s3,hint1,hint2; double capl,capl1,capmu,capmu1,r3,pq; double ka2,r1,heff; double hh,k,slds,sld; pi = 4.0*atan(1.0); k= q; rad = dp[0]; // radius (A) z2 = dp[1]; //polydispersity (0, not cubed*/ r1 = sigma/2.0; r3 = r1*r1*r1; r3 *= (zz+2.0)*(zz+3.0)/((zz+1.0)*(zz+1.0)); rho=phi/(1.3333333333*pi*r3); t1 = rho*bb*cc; t2 = rho*bb*bb*cc*(cc+1.0); t3 = rho*bb*bb*bb*cc*(cc+1.0)*(cc+2.0); capd = 1.0-pi*t3/6.0; //************ v1=1.0/(1.0+bb*bb*k*k); v2=1.0/(4.0+bb*bb*k*k); pp=pow(v1,(cc/2.0))*sin(cc*atan(bb*k)); p1=bb*cc*pow(v1,((cc+1.0)/2.0))*sin((cc+1.0)*atan(bb*k)); p2=cc*(cc+1.0)*bb*bb*pow(v1,((cc+2.0)/2.0))*sin((cc+2.0)*atan(bb*k)); mu=pow(2,cc)*pow(v2,(cc/2.0))*sin(cc*atan(bb*k/2.0)); mu1=pow(2,(cc+1.0))*bb*cc*pow(v2,((cc+1.0)/2.0))*sin((cc+1.0)*atan(k*bb/2.0)); s1=bb*cc; s2=cc*(cc+1.0)*bb*bb; s3=cc*(cc+1.0)*(cc+2.0)*bb*bb*bb; chi=pow(v1,(cc/2.0))*cos(cc*atan(bb*k)); chi1=bb*cc*pow(v1,((cc+1.0)/2.0))*cos((cc+1.0)*atan(bb*k)); chi2=cc*(cc+1.0)*bb*bb*pow(v1,((cc+2.0)/2.0))*cos((cc+2.0)*atan(bb*k)); ll=pow(2,cc)*pow(v2,(cc/2.0))*cos(cc*atan(bb*k/2.0)); l1=pow(2,(cc+1.0))*bb*cc*pow(v2,((cc+1.0)/2.0))*cos((cc+1.0)*atan(k*bb/2.0)); d1=(pi/capd)*(2.0+(pi/capd)*(t3-(rho/k)*(k*s3-p2))); d2=pow((pi/capd),2)*(rho/k)*(k*s2-p1); d3=(-1.0)*pow((pi/capd),2)*(rho/k)*(k*s1-pp); d4=(pi/capd)*(k-(pi/capd)*(rho/k)*(chi1-s1)); d5=pow((pi/capd),2)*((rho/k)*(chi-1.0)+0.5*k*t2); d6=pow((pi/capd),2)*(rho/k)*(chi2-s2); e1=pow((pi/capd),2)*pow((rho/k/k),2)*((chi-1.0)*(chi2-s2)-(chi1-s1)*(chi1-s1)-(k*s1-pp)*(k*s3-p2)+pow((k*s2-p1),2)); ee=1.0-(2.0*pi/capd)*(1.0+0.5*pi*t3/capd)*(rho/k/k/k)*(k*s1-pp)-(2.0*pi/capd)*rho/k/k*((chi1-s1)+(0.25*pi*t2/capd)*(chi2-s2))-e1; y1=pow((pi/capd),2)*pow((rho/k/k),2)*((k*s1-pp)*(chi2-s2)-2.0*(k*s2-p1)*(chi1-s1)+(k*s3-p2)*(chi-1.0)); yy = (2.0*pi/capd)*(1.0+0.5*pi*t3/capd)*(rho/k/k/k)*(chi+0.5*k*k*s2-1.0)-(2.0*pi*rho/capd/k/k)*(k*s2-p1+(0.25*pi*t2/capd)*(k*s3-p2))-y1; capl=2.0*pi*cont*rho/k/k/k*(pp-0.5*k*(s1+chi1)); capl1=2.0*pi*cont*rho/k/k/k*(p1-0.5*k*(s2+chi2)); capmu=2.0*pi*cont*rho/k/k/k*(1.0-chi-0.5*k*p1); capmu1=2.0*pi*cont*rho/k/k/k*(s1-chi1-0.5*k*p2); h1=capl*(capl*(yy*d1-ee*d6)+capl1*(yy*d2-ee*d4)+capmu*(ee*d1+yy*d6)+capmu1*(ee*d2+yy*d4)); h2=capl1*(capl*(yy*d2-ee*d4)+capl1*(yy*d3-ee*d5)+capmu*(ee*d2+yy*d4)+capmu1*(ee*d3+yy*d5)); h3=capmu*(capl*(ee*d1+yy*d6)+capl1*(ee*d2+yy*d4)+capmu*(ee*d6-yy*d1)+capmu1*(ee*d4-yy*d2)); h4=capmu1*(capl*(ee*d2+yy*d4)+capl1*(ee*d3+yy*d5)+capmu*(ee*d4-yy*d2)+capmu1*(ee*d5-yy*d3)); //* This part computes the second integral in equation (1) of the paper.*/ hint1 = -2.0*(h1+h2+h3+h4)/(k*k*k*(ee*ee+yy*yy)); //* This part computes the first integral in equation (1). It also // generates the KC approximated effective structure factor.*/ pq=4.0*pi*cont*(sin(k*sigma/2.0)-0.5*k*sigma*cos(k*sigma/2.0)); hint2=8.0*pi*pi*rho*cont*cont/(k*k*k*k*k*k)*(1.0-chi-k*p1+0.25*k*k*(s2+chi2)); ka=k*(sigma/2.0); // hh=hint1+hint2; // this is the model intensity // heff=1.0+hint1/hint2; ka2=ka*ka; //* // heff is PY analytical solution for intensity divided by the // form factor. happ is the KC approximated effective S(q) //******************* // add in the background then return the intensity value return(hh+bkg); //scale, and add in the background } // scattering from a uniform sphere with a (Schulz) size distribution, bimodal population // NO CROSS TERM IS ACCOUNTED FOR == DILUTE SOLUTION!! // double BimodalSchulzSpheres(double dp[], double q) { double x,pq; double scale,ravg,pd,bkg,rho,rhos; //my local names double scale2,ravg2,pd2,rho2; //my local names x= q; scale = dp[0]; ravg = dp[1]; pd = dp[2]; rho = dp[3]; scale2 = dp[4]; ravg2 = dp[5]; pd2 = dp[6]; rho2 = dp[7]; rhos = dp[8]; bkg = dp[9]; pq = SchulzSphere_Fn( scale, ravg, pd, rho, rhos, x); pq += SchulzSphere_Fn( scale2, ravg2, pd2, rho2, rhos, x); // add in the background pq += bkg; return (pq); } // scattering from a uniform sphere with a (Schulz) size distribution // double SchulzSpheres(double dp[], double q) { double x,pq; double scale,ravg,pd,bkg,rho,rhos; //my local names x= q; scale = dp[0]; ravg = dp[1]; pd = dp[2]; rho = dp[3]; rhos = dp[4]; bkg = dp[5]; pq = SchulzSphere_Fn( scale, ravg, pd, rho, rhos, x); // add in the background pq += bkg; return(pq); } // calculates everything but the background double SchulzSphere_Fn(double scale, double ravg, double pd, double rho, double rhos, double x) { double zp1,zp2,zp3,zp4,zp5,zp6,zp7,vpoly; double aa,at1,at2,rt1,rt2,rt3,t1,t2,t3; double v1,v2,v3,g1,pq,pi,delrho,zz; double i_zero,Rg2,zp8; pi = 4.0*atan(1.0); delrho = rho-rhos; zz = (1.0/pd)*(1.0/pd) - 1.0; zp1 = zz + 1.0; zp2 = zz + 2.0; zp3 = zz + 3.0; zp4 = zz + 4.0; zp5 = zz + 5.0; zp6 = zz + 6.0; zp7 = zz + 7.0; // //small QR limit - use Guinier approx zp8 = zz+8.0; if(x*ravg < 0.1) { i_zero = scale*delrho*delrho*1.e8*4.*pi/3.*pow(ravg,3); i_zero *= zp6*zp5*zp4/zp1/zp1/zp1; //6th moment / 3rd moment Rg2 = 3.*zp8*zp7/5./(zp1*zp1)*ravg*ravg; pq = i_zero*exp(-x*x*Rg2/3.); //pq += bkg; //unlike the Igor code, the backgorund is added in the wrapper (above) return(pq); } // aa = (zz+1.0)/x/ravg; at1 = atan(1.0/aa); at2 = atan(2.0/aa); // // calculations are performed to avoid large # errors // - trick is to propogate the a^(z+7) term through the g1 // t1 = zp7*log10(aa) - zp1/2.0*log10(aa*aa+4.0); t2 = zp7*log10(aa) - zp3/2.0*log10(aa*aa+4.0); t3 = zp7*log10(aa) - zp2/2.0*log10(aa*aa+4.0); // print t1,t2,t3 rt1 = pow(10,t1); rt2 = pow(10,t2); rt3 = pow(10,t3); v1 = pow(aa,6) - rt1*cos(zp1*at2); v2 = zp1*zp2*( pow(aa,4) + rt2*cos(zp3*at2) ); v3 = -2.0*zp1*rt3*sin(zp2*at2); g1 = (v1+v2+v3); pq = log10(g1) - 6.0*log10(zp1) + 6.0*log10(ravg); pq = pow(10,pq)*8.0*pi*pi*delrho*delrho; // // beta factor is not used here, but could be for the // decoupling approximation // // g11 = g1 // gd = -zp7*log(aa) // g1 = log(g11) + gd // // t1 = zp1*at1 // t2 = zp2*at1 // g2 = sin( t1 ) - zp1/sqrt(aa*aa+1)*cos( t2 ) // g22 = g2*g2 // beta = zp1*log(aa) - zp1*log(aa*aa+1) - g1 + log(g22) // beta = 2*alog(beta) //re-normalize by the average volume vpoly = 4.0*pi/3.0*zp3*zp2/zp1/zp1*ravg*ravg*ravg; pq /= vpoly; //scale, convert to cm^-1 pq *= scale * 1.0e8; return(pq); } // scattering from a uniform sphere with a rectangular size distribution // double PolyRectSpheres(double dp[], double q) { double pi,x; double scale,rad,pd,cont,bkg; //my local names double inten,h1,qw,qr,width,sig,averad3,Rg2,slds,sld; pi = 4.0*atan(1.0); x= q; scale = dp[0]; rad = dp[1]; // radius (A) pd = dp[2]; //polydispersity of rectangular distribution slds = dp[3]; sld = dp[4]; cont = slds - sld; // contrast (A^-2) bkg = dp[5]; // as usual, poly = sig/ravg // for the rectangular distribution, sig = width/sqrt(3) // width is the HALF- WIDTH of the rectangular distrubution sig = pd*rad; width = sqrt(3.0)*sig; //x is the q-value qw = x*width; qr = x*rad; // as for the numerical inatabilities at low QR, the function is calculating the sines and cosines // just fine - the problem seems to be that the // leading terms nearly cancel with the last term (the -6*qr... term), to within machine // precision - the difference is on the order of 10^-20 // so just use the limiting Guiner value if(qr<0.1) { h1 = scale*cont*cont*1.e8*4.*pi/3.0*pow(rad,3); h1 *= (1. + 15.*pow(pd,2) + 27.*pow(pd,4) +27./7.*pow(pd,6) ); //6th moment h1 /= (1.+3.*pd*pd); //3rd moment Rg2 = 3.0/5.0*rad*rad*( 1.+28.*pow(pd,2)+126.*pow(pd,4)+108.*pow(pd,6)+27.*pow(pd,8) ); Rg2 /= (1.+15.*pow(pd,2)+27.*pow(pd,4)+27./7.*pow(pd,6)); h1 *= exp(-1./3.*Rg2*x*x); h1 += bkg; return(h1); } // normal calculation h1 = -0.5*qw + qr*qr*qw + (qw*qw*qw)/3.0; h1 -= 5.0/2.0*cos(2.0*qr)*sin(qw)*cos(qw); h1 += 0.5*qr*qr*cos(2.0*qr)*sin(2.0*qw); h1 += 0.5*qw*qw*cos(2.0*qr)*sin(2.0*qw); h1 += qw*qr*sin(2.0*qr)*cos(2.0*qw); h1 += 3.0*qw*(cos(qr)*cos(qw))*(cos(qr)*cos(qw)); h1+= 3.0*qw*(sin(qr)*sin(qw))*(sin(qr)*sin(qw)); h1 -= 6.0*qr*cos(qr)*sin(qr)*cos(qw)*sin(qw); // calculate P(q) = inten = 8.0*pi*pi*cont*cont/width/pow(x,7)*h1; // beta(q) would be calculated as 2/width/x/h1*h2*h2 // with // h2 = 2*sin(x*rad)*sin(x*width)-x*rad*cos(x*rad)*sin(x*width)-x*width*sin(x*rad)*cos(x*width) // normalize to the average volume // = ravg^3*(1+3*pd^2) // or... "zf" = (1 + 3*p^2), which will be greater than one averad3 = rad*rad*rad*(1.0+3.0*pd*pd); inten /= 4.0*pi/3.0*averad3; //resacle to 1/cm inten *= 1.0e8; //scale the result inten *= scale; // then add in the background inten += bkg; return(inten); } // scattering from a uniform sphere with a Gaussian size distribution // double GaussPolySphere(double dp[], double q) { double pi,x; double scale,rad,pd,sig,rho,rhos,bkg,delrho; //my local names double va,vb,zi,yy,summ,inten; int nord=20,ii; pi = 4.0*atan(1.0); x= q; scale=dp[0]; rad=dp[1]; pd=dp[2]; sig=pd*rad; rho=dp[3]; rhos=dp[4]; delrho=rho-rhos; bkg=dp[5]; va = -4.0*sig + rad; if (va<0.0) { va=0.0; //to avoid numerical error when va<0 (-ve q-value) } vb = 4.0*sig +rad; summ = 0.0; // initialize integral for(ii=0;ii directly inten /= (4.0*pi/3.0*r3); //polydisperse volume inten *= 1.0e8; inten *= scale; inten += bkg; return(inten); } /* static double LogNormal_distr(double sig, double mu, double pt) { double retval,pi; pi = 4.0*atan(1.0); retval = (1.0/ (sig*pt*sqrt(2.0*pi)) )*exp( -0.5*(log(pt) - mu)*(log(pt) - mu)/sig/sig ); return(retval); } static double Gauss_distr(double sig, double avg, double pt) { double retval,Pi; Pi = 4.0*atan(1.0); retval = (1.0/ (sig*sqrt(2.0*Pi)) )*exp(-(avg-pt)*(avg-pt)/sig/sig/2.0); return(retval); } */ // scattering from a core shell sphere with a (Schulz) polydisperse core and constant ratio (shell thickness)/(core radius) // - the polydispersity is of the WHOLE sphere // double PolyCoreShellRatio(double dp[], double q) { double pi,x; double scale,corrad,thick,shlrad,pp,drho1,drho2,sig,zz,bkg; //my local names double sld1,sld2,sld3,zp1,zp2,zp3,vpoly; double pi43,c1,c2,form,volume,arg1,arg2; pi = 4.0*atan(1.0); x= q; scale = dp[0]; corrad = dp[1]; thick = dp[2]; sig = dp[3]; sld1 = dp[4]; sld2 = dp[5]; sld3 = dp[6]; bkg = dp[7]; zz = (1.0/sig)*(1.0/sig) - 1.0; shlrad = corrad + thick; drho1 = sld1-sld2; //core-shell drho2 = sld2-sld3; //shell-solvent zp1 = zz + 1.; zp2 = zz + 2.; zp3 = zz + 3.; vpoly = 4.0*pi/3.0*zp3*zp2/zp1/zp1*pow((corrad+thick),3); // the beta factor is not calculated // the calculated form factor has units [length^2] // and must be multiplied by number density [l^-3] and the correct unit // conversion to get to absolute scale pi43=4.0/3.0*pi; pp=corrad/shlrad; volume=pi43*shlrad*shlrad*shlrad; c1=drho1*volume; c2=drho2*volume; arg1 = x*shlrad*pp; arg2 = x*shlrad; form=pow(pp,6)*c1*c1*fnt2(arg1,zz); form += c2*c2*fnt2(arg2,zz); form += 2.0*c1*c2*fnt3(arg2,pp,zz); //convert the result to [cm^-1] //scale the result // - divide by the polydisperse volume, mult by 10^8 form /= vpoly; form *= 1.0e8; form *= scale; //add in the background form += bkg; return(form); } //cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc //c //c function fnt2(y,z) //c double fnt2(double yy, double zz) { double z1,z2,z3,u,ww,term1,term2,term3,ans; z1=zz+1.0; z2=zz+2.0; z3=zz+3.0; u=yy/z1; ww=atan(2.0*u); term1=cos(z1*ww)/pow((1.0+4.0*u*u),(z1/2.0)); term2=2.0*yy*sin(z2*ww)/pow((1.0+4.0*u*u),(z2/2.0)); term3=1.0+cos(z3*ww)/pow((1.0+4.0*u*u),(z3/2.0)); ans=(4.50/z1/pow(yy,6))*(z1*(1.0-term1-term2)+yy*yy*z2*term3); return(ans); } //cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc //c //c function fnt3(y,p,z) //c double fnt3(double yy, double pp, double zz) { double z1,z2,z3,yp,yn,up,un,vp,vn,term1,term2,term3,term4,term5,term6,ans; z1=zz+1.0; z2=zz+2.0; z3=zz+3.0; yp=(1.0+pp)*yy; yn=(1.0-pp)*yy; up=yp/z1; un=yn/z1; vp=atan(up); vn=atan(un); term1=cos(z1*vn)/pow((1.0+un*un),(z1/2.0)); term2=cos(z1*vp)/pow((1.0+up*up),(z1/2.0)); term3=cos(z3*vn)/pow((1.0+un*un),(z3/2.0)); term4=cos(z3*vp)/pow((1.0+up*up),(z3/2.0)); term5=yn*sin(z2*vn)/pow((1.0+un*un),(z2/2.0)); term6=yp*sin(z2*vp)/pow((1.0+up*up),(z2/2.0)); ans=4.5/z1/pow(yy,6); ans *=(z1*(term1-term2)+yy*yy*pp*z2*(term3+term4)+z1*(term5-term6)); return(ans); } // scattering from a a binary population of hard spheres, 3 partial structure factors // are properly accounted for... // Input (fitting) variables are: // larger sphere radius(angstroms) = guess[0] // smaller sphere radius (A) = w[1] // number fraction of larger spheres = guess[2] // total volume fraction of spheres = guess[3] // size ratio, alpha(0= 0.3, making a<0 } if (pd>0.3) { range = range + (pd-0.3)*18.0; //stretch upper range to account for skewed tail } vb = rcore*(1.0+range*pd); // is this far enough past avg radius? //temp set scale=1 and bkg=0 for quadrature calc temp_1sf[0] = 1.0; temp_1sf[1] = dp[1]; //the core radius will be changed in the loop temp_1sf[2] = dp[3]; temp_1sf[3] = dp[4]; temp_1sf[4] = dp[5]; temp_1sf[5] = dp[6]; temp_1sf[6] = 0.0; summ = 0.0; // initialize integral for(ii=0;ii= 0.3, making a<0 } if (pd>0.3) { range = range + (pd-0.3)*18.0; //stretch upper range to account for skewed tail } vb = rcore*(1.0+range*pd); // is this far enough past avg radius? //temp set scale=1 and bkg=0 for quadrature calc temp_2sf[0] = 1.0; temp_2sf[1] = dp[1]; //the core radius will be changed in the loop temp_2sf[2] = dp[3]; temp_2sf[3] = dp[4]; temp_2sf[4] = dp[5]; temp_2sf[5] = dp[6]; temp_2sf[6] = dp[7]; temp_2sf[7] = dp[8]; temp_2sf[8] = 0.0; summ = 0.0; // initialize integral for(ii=0;ii= 0.3, making a<0 } if (pd>0.3) { range = range + (pd-0.3)*18.0; //stretch upper range to account for skewed tail } vb = rcore*(1.0+range*pd); // is this far enough past avg radius? //temp set scale=1 and bkg=0 for quadrature calc temp_3sf[0] = 1.0; temp_3sf[1] = dp[1]; //the core radius will be changed in the loop temp_3sf[2] = dp[3]; temp_3sf[3] = dp[4]; temp_3sf[4] = dp[5]; temp_3sf[5] = dp[6]; temp_3sf[6] = dp[7]; temp_3sf[7] = dp[8]; temp_3sf[8] = dp[9]; temp_3sf[9] = dp[10]; temp_3sf[10] = 0.0; summ = 0.0; // initialize integral for(ii=0;ii= 0.3, making a<0 } if (pd>0.3) { range = range + (pd-0.3)*18.0; //stretch upper range to account for skewed tail } vb = rcore*(1.0+range*pd); // is this far enough past avg radius? //temp set scale=1 and bkg=0 for quadrature calc temp_4sf[0] = 1.0; temp_4sf[1] = dp[1]; //the core radius will be changed in the loop temp_4sf[2] = dp[3]; temp_4sf[3] = dp[4]; temp_4sf[4] = dp[5]; temp_4sf[5] = dp[6]; temp_4sf[6] = dp[7]; temp_4sf[7] = dp[8]; temp_4sf[8] = dp[9]; temp_4sf[9] = dp[10]; temp_4sf[10] = dp[11]; temp_4sf[11] = dp[12]; temp_4sf[12] = 0.0; summ = 0.0; // initialize integral for(ii=0;iix Uses 150 pt Gaussian quadrature for both integrals */ double BCC_ParaCrystal(double w[], double x) { int i,j; double Pi; double scale,Dnn,gg,Rad,contrast,background,latticeScale,sld,sldSolv; //local variables of coefficient wave int nordi=150; //order of integration int nordj=150; double va,vb; //upper and lower integration limits double summ,zi,yyy,answer; //running tally of integration double summj,vaj,vbj,zij; //for the inner integration Pi = 4.0*atan(1.0); va = 0.0; vb = 2.0*Pi; //orintational average, outer integral vaj = 0.0; vbj = Pi; //endpoints of inner integral summ = 0.0; //initialize intergral scale = w[0]; Dnn = w[1]; //Nearest neighbor distance A gg = w[2]; //Paracrystal distortion factor Rad = w[3]; //Sphere radius sld = w[4]; sldSolv = w[5]; background = w[6]; contrast = sld - sldSolv; //Volume fraction calculated from lattice symmetry and sphere radius latticeScale = 2.0*(4.0/3.0)*Pi*(Rad*Rad*Rad)/pow(Dnn/sqrt(3.0/4.0),3); for(i=0;ix Uses 150 pt Gaussian quadrature for both integrals */ double FCC_ParaCrystal(double w[], double x) { int i,j; double Pi; double scale,Dnn,gg,Rad,contrast,background,latticeScale,sld,sldSolv; //local variables of coefficient wave int nordi=150; //order of integration int nordj=150; double va,vb; //upper and lower integration limits double summ,zi,yyy,answer; //running tally of integration double summj,vaj,vbj,zij; //for the inner integration Pi = 4.0*atan(1.0); va = 0.0; vb = 2.0*Pi; //orintational average, outer integral vaj = 0.0; vbj = Pi; //endpoints of inner integral summ = 0.0; //initialize intergral scale = w[0]; Dnn = w[1]; //Nearest neighbor distance A gg = w[2]; //Paracrystal distortion factor Rad = w[3]; //Sphere radius sld = w[4]; sldSolv = w[5]; background = w[6]; contrast = sld - sldSolv; //Volume fraction calculated from lattice symmetry and sphere radius latticeScale = 4.0*(4.0/3.0)*Pi*(Rad*Rad*Rad)/pow(Dnn*sqrt(2.0),3); for(i=0;ix Uses 150 pt Gaussian quadrature for both integrals */ double SC_ParaCrystal(double w[], double x) { int i,j; double Pi; double scale,Dnn,gg,Rad,contrast,background,latticeScale,sld,sldSolv; //local variables of coefficient wave int nordi=150; //order of integration int nordj=150; double va,vb; //upper and lower integration limits double summ,zi,yyy,answer; //running tally of integration double summj,vaj,vbj,zij; //for the inner integration Pi = 4.0*atan(1.0); va = 0.0; vb = Pi/2.0; //orintational average, outer integral vaj = 0.0; vbj = Pi/2.0; //endpoints of inner integral summ = 0.0; //initialize intergral scale = w[0]; Dnn = w[1]; //Nearest neighbor distance A gg = w[2]; //Paracrystal distortion factor Rad = w[3]; //Sphere radius sld = w[4]; sldSolv = w[5]; background = w[6]; contrast = sld - sldSolv; //Volume fraction calculated from lattice symmetry and sphere radius latticeScale = (4.0/3.0)*Pi*(Rad*Rad*Rad)/pow(Dnn,3); for(i=0;i intensity in [cm-1] i_micelle *= ndensity; //scale if desired i_micelle *= scale; // add in the background i_micelle += bkg; return(i_micelle); }