Changeset 2126131 in sasmodels


Ignore:
Timestamp:
Oct 17, 2016 1:38:58 PM (8 years ago)
Author:
Paul Kienzle <pkienzle@…>
Branches:
master, core_shell_microgels, costrafo411, magnetic_model, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
Children:
f719764
Parents:
9762341
Message:

pearl necklace: code cleanup; use sph_j1c; force num_pearls to integer in form_volume

Location:
sasmodels/models
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • sasmodels/models/pearl_necklace.c

    r3a48772 r2126131  
    1 double _pearl_necklace_kernel(double q, double radius, double edge_sep, 
    2         double thick_string, double num_pearls, double sld_pearl, 
    3         double sld_string, double sld_solv); 
    41double form_volume(double radius, double edge_sep, 
    5         double thick_string, double num_pearls); 
    6  
     2    double thick_string, double num_pearls); 
    73double Iq(double q, double radius, double edge_sep, 
    8         double thick_string, double num_pearls, double sld,  
    9         double string_sld, double solvent_sld); 
     4    double thick_string, double num_pearls, double sld,  
     5    double string_sld, double solvent_sld); 
    106 
    117#define INVALID(v) (v.thick_string >= v.radius || v.num_pearls <= 0) 
    128 
    139// From Igor library 
    14 double _pearl_necklace_kernel(double q, double radius, double edge_sep, double thick_string, 
    15         double num_pearls, double sld_pearl, double sld_string, double sld_solv) 
     10static double 
     11_pearl_necklace_kernel(double q, double radius, double edge_sep, double thick_string, 
     12    double num_pearls, double sld_pearl, double sld_string, double sld_solv) 
    1613{ 
    17         //relative slds 
    18         double contrast_pearl = sld_pearl - sld_solv; 
    19         double contrast_string = sld_string - sld_solv; 
    20          
    21         // number of string segments 
    22         num_pearls = floor(num_pearls + 0.5); //Force integer number of pearls 
    23         double num_strings = num_pearls - 1.0; 
    24          
    25         // center to center distance between the neighboring pearls 
    26         double A_s = edge_sep + 2.0 * radius; 
    27          
    28         // Repeated Calculations 
    29         double sincasq = sinc(q*A_s); 
    30         double oneminussinc = 1 - sincasq; 
    31         double q_r = q * radius; 
    32         double q_edge = q * edge_sep; 
    33          
    34         // each volume 
    35         double string_vol = edge_sep * M_PI * thick_string * thick_string / 4.0; 
    36         double pearl_vol = M_4PI_3 * radius * radius * radius; 
     14    // number of string segments 
     15    num_pearls = floor(num_pearls + 0.5); //Force integer number of pearls 
     16    const double num_strings = num_pearls - 1.0; 
    3717 
    38         //total volume 
    39         double tot_vol; 
    40         //each masses 
    41         double m_r= contrast_string * string_vol; 
    42         double m_s= contrast_pearl * pearl_vol; 
    43         double psi, gamma, beta; 
    44         //form factors 
    45         double sss, srr, srs; //cross 
    46         double srr_1, srr_2, srr_3; 
    47         double form_factor; 
    48         tot_vol = num_strings * string_vol; 
    49         tot_vol += num_pearls * pearl_vol; 
     18    //each masses: contrast * volume 
     19    const double contrast_pearl = sld_pearl - sld_solv; 
     20    const double contrast_string = sld_string - sld_solv; 
     21    const double string_vol = edge_sep * M_PI_4 * thick_string * thick_string; 
     22    const double pearl_vol = M_4PI_3 * radius * radius * radius; 
     23    const double m_string = contrast_string * string_vol; 
     24    const double m_pearl = contrast_pearl * pearl_vol; 
    5025 
    51         //sine functions of a pearl 
    52         psi = sin(q_r); 
    53         psi -= q_r * cos(q_r); 
    54         psi *= 3.0; 
    55         psi /= q_r * q_r * q_r; 
     26    // center to center distance between the neighboring pearls 
     27    const double A_s = edge_sep + 2.0 * radius; 
    5628 
    57         // Note take only 20 terms in Si series: 10 terms may be enough though. 
    58         gamma = Si(q_edge); 
    59         gamma /= (q_edge); 
    60         beta = Si(q * (A_s - radius)); 
    61         beta -= Si(q_r); 
    62         beta /= q_edge; 
     29    //sine functions of a pearl 
     30    // Note: lim_(q->0) Si(q*a)/(q*b) = a/b 
     31    // So therefore: 
     32    //    beta = q==0. ? 1.0 : (Si(q*(A_s-radius)) - Si(q*radius))/q_edge; 
     33    //    gamma = q==0. ? 1.0 : Si(q_edge)/q_edge; 
     34    // But there is a 1/(1-sinc) term below which blows up so don't bother 
     35    const double q_edge = q * edge_sep; 
     36    const double beta = (Si(q*(A_s-radius)) - Si(q*radius)) / q_edge; 
     37    const double gamma = Si(q_edge) / q_edge; 
     38    const double psi = sph_j1c(q*radius); 
    6339 
    64         // form factor for num_pearls 
    65         sss = 1.0 - pow(sincasq, num_pearls); 
    66         sss /= oneminussinc * oneminussinc; 
    67         sss *= -sincasq; 
    68         sss -= num_pearls / 2.0; 
    69         sss += num_pearls / oneminussinc; 
    70         sss *= 2.0 * m_s * psi * m_s * psi; 
     40    // Precomputed sinc terms 
     41    const double si = sinc(q*A_s); 
     42    const double omsi = 1.0 - si; 
     43    const double pow_si = pow(si, num_pearls); 
    7144 
    72         // form factor for num_strings (like thin rods) 
    73         srr_1 = -sinc(q_edge/2.0) * sinc(q_edge/2.0); 
     45    // form factor for num_pearls 
     46    const double sss = 2.0*square(m_pearl*psi) * ( 
     47        - si * (1.0 - pow_si) / (omsi*omsi) 
     48        + num_pearls / omsi 
     49        - 0.5 * num_pearls 
     50        ); 
    7451 
    75         srr_1 += 2.0 * gamma; 
    76         srr_1 *= num_strings; 
    77         srr_2 = 2.0/oneminussinc; 
    78         srr_2 *= num_strings; 
    79         srr_2 *= beta * beta; 
    80         srr_3 = 1.0 - pow(sincasq, num_strings); 
    81         srr_3 /= oneminussinc * oneminussinc; 
    82         srr_3 *= beta * beta; 
    83         srr_3 *= -2.0; 
     52    // form factor for num_strings (like thin rods) 
     53    const double srr = m_string * m_string * ( 
     54        - 2.0 * (1.0 - pow_si/si)*beta*beta / (omsi*omsi) 
     55        + 2.0 * num_strings*beta*beta / omsi 
     56        + num_strings * (2.0*gamma - square(sinc(q_edge/2.0))) 
     57        ); 
    8458 
    85         // total srr 
    86         srr = srr_1 + srr_2 + srr_3; 
    87         srr *= m_r * m_r; 
     59    // form factor for correlations 
     60    const double srs = 4.0 * m_string * m_pearl * beta * psi * ( 
     61        - si * (1.0 - pow_si/si) / (omsi*omsi) 
     62        + num_strings / omsi 
     63        ); 
    8864 
    89         // form factor for correlations 
    90         srs = 1.0; 
    91         srs -= pow(sincasq, num_strings); 
    92         srs /= oneminussinc * oneminussinc; 
    93         srs *= -sincasq; 
    94         srs += num_strings/oneminussinc; 
    95         srs *= 4.0; 
    96         srs *= (m_r * m_s * beta * psi); 
     65    const double form = sss + srr + srs; 
    9766 
    98         form_factor = sss + srr + srs; 
    99         form_factor /= (tot_vol * 1.0e4); // norm by volume and A^-1 to cm^-1 
    100  
    101         return (form_factor); 
     67    return 1.0e-4 * form; 
    10268} 
    10369 
    10470double form_volume(double radius, double edge_sep, 
    105         double thick_string, double num_pearls) 
     71    double thick_string, double num_pearls) 
    10672{ 
    107         double total_vol; 
     73    num_pearls = floor(num_pearls + 0.5); //Force integer number of pearls 
    10874 
    109         double number_of_strings = num_pearls - 1.0; 
    110          
    111         double string_vol = edge_sep * M_PI * thick_string * thick_string / 4.0; 
    112         double pearl_vol = M_4PI_3 * radius * radius * radius; 
     75    const double num_strings = num_pearls - 1.0; 
     76    const double string_vol = edge_sep * M_PI_4 * thick_string * thick_string; 
     77    const double pearl_vol = M_4PI_3 * radius * radius * radius; 
     78    const double volume = num_strings*string_vol + num_pearls*pearl_vol; 
    11379 
    114         total_vol = number_of_strings * string_vol; 
    115         total_vol += num_pearls * pearl_vol; 
    116  
    117         return(total_vol); 
     80    return volume; 
    11881} 
    11982 
    12083double Iq(double q, double radius, double edge_sep, 
    121         double thick_string, double num_pearls, double sld,  
    122         double string_sld, double solvent_sld) 
     84    double thick_string, double num_pearls, double sld,  
     85    double string_sld, double solvent_sld) 
    12386{ 
    124         double value, tot_vol; 
    125          
    126         value = _pearl_necklace_kernel(q, radius, edge_sep, thick_string, 
    127                 num_pearls, sld, string_sld, solvent_sld); 
    128         tot_vol = form_volume(radius, edge_sep, thick_string, num_pearls); 
     87    const double form = _pearl_necklace_kernel(q, radius, edge_sep, 
     88        thick_string, num_pearls, sld, string_sld, solvent_sld); 
    12989 
    130         return value*tot_vol; 
     90    return form; 
    13191} 
  • sasmodels/models/pearl_necklace.py

    r4962519 r2126131  
    9292             ] 
    9393 
    94 source = ["lib/Si.c", "pearl_necklace.c"] 
     94source = ["lib/Si.c", "lib/sph_j1c.c", "pearl_necklace.c"] 
    9595single = False  # use double precision unless told otherwise 
    9696 
Note: See TracChangeset for help on using the changeset viewer.