#include #include "parameters.hh" #include using namespace std; #include "linearpearls.h" extern "C" { #include "libmultifunc/libfunc.h" } static double linear_pearls_kernel(double dp[], double q) { //fit parameters double scale = dp[0]; double radius = dp[1]; double edge_separation = dp[2]; double num_pearls = dp[3]; double sld_pearl = dp[4]; double sld_solv = dp[5]; double background = dp[6]; //others double psi = 0.0; double n_contrib = 0.0; double form_factor = 0.0; //Pi double pi = 4.0 * atan(1.0); //relative sld double contrast_pearl = sld_pearl - sld_solv; //each volume double pearl_vol = 4.0 /3.0 * pi * pow(radius, 3.0); //total volume double tot_vol = num_pearls * pearl_vol; //mass double m_s = contrast_pearl * pearl_vol; //center to center distance between the neighboring pearls double separation = edge_separation + 2.0 * radius; //integer int num = 0; int n_max = 0; // constraints if (scale<=0 || radius<=0 || edge_separation<0 || num_pearls<=0){ return 0.0; } //sine functions of a pearl psi = sin(q * radius); psi -= q * radius * cos(q * radius); psi /= pow((q * radius), 3.0); // N pearls contribution n_max = num_pearls - 1; for(num=0; num<=n_max; num++) { if (num == 0){ n_contrib = num_pearls; continue; } n_contrib += (2.0*(num_pearls-double(num))*sinc(q*separation*double(num))); } // form factor for num_pearls form_factor = n_contrib; form_factor *= pow((m_s*psi*3.0), 2.0); form_factor /= (tot_vol * 1.0e-8); // norm by volume and A^-1 to cm^-1 // scale and background form_factor *= scale; form_factor += background; return (form_factor); } LinearPearlsModel :: LinearPearlsModel() { scale = Parameter(1.0); radius = Parameter(80.0, true); radius.set_min(0.0); edge_separation = Parameter(350.0, true); edge_separation.set_min(0.0); num_pearls = Parameter(3); num_pearls.set_min(0.0); sld_pearl = Parameter(1.0e-06); sld_solv = Parameter(6.3e-06); background = Parameter(0.0); } /** * Function to evaluate 1D LinearPearlsModel function * @param q: q-value * @return: function value */ double LinearPearlsModel :: operator()(double q) { double dp[7]; // Add the background after averaging dp[0] = scale(); dp[1] = radius(); dp[2] = edge_separation(); dp[3] = num_pearls(); dp[4] = sld_pearl(); dp[5] = sld_solv(); dp[6] = 0.0; double pi = 4.0*atan(1.0); // No polydispersion supported in this model. // Get the dispersion points for the radius vector weights_radius; radius.get_weights(weights_radius); vector weights_edge_separation; edge_separation.get_weights(weights_edge_separation); // Perform the computation, with all weight points double sum = 0.0; double norm = 0.0; double vol = 0.0; double pearl_vol = 0.0; double tot_vol = 0.0; // Loop over core weight points for(size_t i=0; i weights_radius; radius.get_weights(weights_radius); vector weights_edge_separation; edge_separation.get_weights(weights_edge_separation); // Perform the computation, with all weight points double pearl_vol = 0.0; double tot_vol = 0.0; // Loop over core weight points for(size_t i=0; i