Changeset 345cc8f in sasmodels


Ignore:
Timestamp:
Mar 31, 2019 7:55:49 AM (5 months ago)
Author:
GitHub <noreply@…>
Parents:
1dd78a2b (diff), bd91e8f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
git-author:
Paul Kienzle <pkienzle@…> (03/31/19 07:55:49)
git-committer:
GitHub <noreply@…> (03/31/19 07:55:49)
Message:

Merge bd91e8f66b044c54b5d8cb15ae644f1af300e5d2 into 1dd78a2b6501dbd20963af88b80e45c6b89beda5

Files:
1 deleted
10 edited

Legend:

Unmodified
Added
Removed
  • explore/realspace.py

    r362a66f r5778279  
    99import numpy as np 
    1010from numpy import pi, radians, sin, cos, sqrt 
    11 from numpy.random import poisson, uniform, randn, rand 
     11from numpy.random import poisson, uniform, randn, rand, randint 
    1212from numpy.polynomial.legendre import leggauss 
    1313from scipy.integrate import simps 
     
    7878 
    7979 
     80I3 = np.matrix([[1., 0, 0], [0, 1, 0], [0, 0, 1]]) 
     81 
    8082class Shape: 
    81     rotation = np.matrix([[1., 0, 0], [0, 1, 0], [0, 0, 1]]) 
     83    rotation = I3 
    8284    center = np.array([0., 0., 0.])[:, None] 
    8385    r_max = None 
     86    lattice_size = np.array((1, 1, 1)) 
     87    lattice_spacing = np.array((1., 1., 1.)) 
     88    lattice_distortion = 0.0 
     89    lattice_rotation = 0.0 
     90    lattice_type = "" 
    8491 
    8592    def volume(self): 
     
    96103 
    97104    def rotate(self, theta, phi, psi): 
    98         self.rotation = rotation(theta, phi, psi) * self.rotation 
     105        if theta != 0. or phi != 0. or psi != 0.: 
     106            self.rotation = rotation(theta, phi, psi) * self.rotation 
    99107        return self 
    100108 
     
    103111        return self 
    104112 
     113    def lattice(self, size=(1, 1, 1), spacing=(2, 2, 2), type="sc", 
     114                distortion=0.0, rotation=0.0): 
     115        self.lattice_size = np.asarray(size, 'i') 
     116        self.lattice_spacing = np.asarray(spacing, 'd') 
     117        self.lattice_type = type 
     118        self.lattice_distortion = distortion 
     119        self.lattice_rotation = rotation 
     120 
    105121    def _adjust(self, points): 
    106         points = np.asarray(self.rotation * np.matrix(points.T)) + self.center 
     122        if self.rotation is I3: 
     123            points = points.T + self.center 
     124        else: 
     125            points = np.asarray(self.rotation * np.matrix(points.T)) + self.center 
     126        if self.lattice_type: 
     127            points = self._apply_lattice(points) 
    107128        return points.T 
    108129 
    109     def r_bins(self, q, over_sampling=1, r_step=0.): 
    110         r_max = min(2 * pi / q[0], self.r_max) 
     130    def r_bins(self, q, over_sampling=10, r_step=0.): 
     131        if self.lattice_type: 
     132            r_max = np.sqrt(np.sum(self.lattice_size*self.lattice_spacing*self.dims)**2)/2 
     133        else: 
     134            r_max = self.r_max 
     135        #r_max = min(2 * pi / q[0], r_max) 
    111136        if r_step == 0.: 
    112137            r_step = 2 * pi / q[-1] / over_sampling 
    113138        #r_step = 0.01 
    114139        return np.arange(r_step, r_max, r_step) 
     140 
     141    def _apply_lattice(self, points): 
     142        """Spread points to different lattice positions""" 
     143        size = self.lattice_size 
     144        spacing = self.lattice_spacing 
     145        shuffle = self.lattice_distortion 
     146        rotate = self.lattice_rotation 
     147        lattice = self.lattice_type 
     148 
     149        if rotate != 0: 
     150            # To vectorize the rotations we will need to unwrap the matrix multiply 
     151            raise NotImplementedError("don't handle rotations yet") 
     152 
     153        # Determine the number of lattice points in the lattice 
     154        shapes_per_cell = 2 if lattice == "bcc" else 4 if lattice == "fcc" else 1 
     155        number_of_lattice_points = np.prod(size) * shapes_per_cell 
     156 
     157        # For each point in the original shape, figure out which lattice point 
     158        # to translate it to.  This is both cell index (i*ny*nz + j*nz  + k) as 
     159        # well as the point in the cell (corner, body center or face center). 
     160        nsamples = points.shape[1] 
     161        lattice_point = randint(number_of_lattice_points, size=nsamples) 
     162 
     163        # Translate the cell index into the i,j,k coordinates of the senter 
     164        cell_index = lattice_point // shapes_per_cell 
     165        center = np.vstack((cell_index//(size[1]*size[2]), 
     166                            (cell_index%(size[1]*size[2]))//size[2], 
     167                            cell_index%size[2])) 
     168        center = np.asarray(center, dtype='d') 
     169        if lattice == "bcc": 
     170            center[:, lattice_point % shapes_per_cell == 1] += [[0.5], [0.5], [0.5]] 
     171        elif lattice == "fcc": 
     172            center[:, lattice_point % shapes_per_cell == 1] += [[0.0], [0.5], [0.5]] 
     173            center[:, lattice_point % shapes_per_cell == 2] += [[0.5], [0.0], [0.5]] 
     174            center[:, lattice_point % shapes_per_cell == 3] += [[0.5], [0.5], [0.0]] 
     175 
     176        # Each lattice point has its own displacement from the ideal position. 
     177        # Not checking that shapes do not overlap if displacement is too large. 
     178        offset = shuffle*(randn(3, number_of_lattice_points) if shuffle < 0.3 
     179                          else rand(3, number_of_lattice_points)) 
     180        center += offset[:, cell_index] 
     181 
     182        # Each lattice point has its own rotation.  Rotate the point prior to 
     183        # applying any displacement. 
     184        # rotation = rotate*(randn(size=(shapes, 3)) if shuffle < 30 else rand(size=(nsamples, 3))) 
     185        # for k in shapes: points[k] = rotation[k]*points[k] 
     186        points += center*(np.array([spacing])*np.array(self.dims)).T 
     187        return points 
    115188 
    116189class Composite(Shape): 
     
    669742    Iq = 100 * np.ones_like(qx) 
    670743    data = Data2D(x=qx, y=qy, z=Iq, dx=None, dy=None, dz=np.sqrt(Iq)) 
    671     data.x_bins = qx[0,:] 
    672     data.y_bins = qy[:,0] 
     744    data.x_bins = qx[0, :] 
     745    data.y_bins = qy[:, 0] 
    673746    data.filename = "fake data" 
    674747 
     
    695768    return shape, fn, fn_xy 
    696769 
    697 def build_sphere(radius=125, rho=2): 
     770DEFAULT_SPHERE_RADIUS = 125 
     771DEFAULT_SPHERE_CONTRAST = 2 
     772def build_sphere(radius=DEFAULT_SPHERE_RADIUS, rho=DEFAULT_SPHERE_CONTRAST): 
    698773    shape = TriaxialEllipsoid(radius, radius, radius, rho) 
    699774    fn = lambda q: sphere_Iq(q, radius)*rho**2 
     
    751826    return shape, fn, fn_xy 
    752827 
    753 def build_cubic_lattice(shape, nx=1, ny=1, nz=1, dx=2, dy=2, dz=2, 
    754                   shuffle=0, rotate=0): 
     828def build_sc_lattice(shape, nx=1, ny=1, nz=1, dx=2, dy=2, dz=2, 
     829                        shuffle=0, rotate=0): 
    755830    a, b, c = shape.dims 
    756     shapes = [copy(shape) 
     831    corners= [copy(shape) 
    757832              .shift((ix+(randn() if shuffle < 0.3 else rand())*shuffle)*dx*a, 
    758833                     (iy+(randn() if shuffle < 0.3 else rand())*shuffle)*dy*b, 
     
    762837              for iy in range(ny) 
    763838              for iz in range(nz)] 
    764     lattice = Composite(shapes) 
     839    lattice = Composite(corners) 
    765840    return lattice 
    766841 
     842def build_bcc_lattice(shape, nx=1, ny=1, nz=1, dx=2, dy=2, dz=2, 
     843                      shuffle=0, rotate=0): 
     844    a, b, c = shape.dims 
     845    corners = [copy(shape) 
     846               .shift((ix+(randn() if shuffle < 0.3 else rand())*shuffle)*dx*a, 
     847                      (iy+(randn() if shuffle < 0.3 else rand())*shuffle)*dy*b, 
     848                      (iz+(randn() if shuffle < 0.3 else rand())*shuffle)*dz*c) 
     849               .rotate(*((randn(3) if rotate < 30 else rand(3))*rotate)) 
     850               for ix in range(nx) 
     851               for iy in range(ny) 
     852               for iz in range(nz)] 
     853    centers = [copy(shape) 
     854               .shift((ix+0.5+(randn() if shuffle < 0.3 else rand())*shuffle)*dx*a, 
     855                      (iy+0.5+(randn() if shuffle < 0.3 else rand())*shuffle)*dy*b, 
     856                      (iz+0.5+(randn() if shuffle < 0.3 else rand())*shuffle)*dz*c) 
     857               .rotate(*((randn(3) if rotate < 30 else rand(3))*rotate)) 
     858               for ix in range(nx) 
     859               for iy in range(ny) 
     860               for iz in range(nz)] 
     861    lattice = Composite(corners + centers) 
     862    return lattice 
     863 
     864def build_fcc_lattice(shape, nx=1, ny=1, nz=1, dx=2, dy=2, dz=2, 
     865                      shuffle=0, rotate=0): 
     866    a, b, c = shape.dims 
     867    corners = [copy(shape) 
     868               .shift((ix+(randn() if shuffle < 0.3 else rand())*shuffle)*dx*a, 
     869                      (iy+(randn() if shuffle < 0.3 else rand())*shuffle)*dy*b, 
     870                      (iz+(randn() if shuffle < 0.3 else rand())*shuffle)*dz*c) 
     871               .rotate(*((randn(3) if rotate < 30 else rand(3))*rotate)) 
     872               for ix in range(nx) 
     873               for iy in range(ny) 
     874               for iz in range(nz)] 
     875    faces_a = [copy(shape) 
     876               .shift((ix+0.0+(randn() if shuffle < 0.3 else rand())*shuffle)*dx*a, 
     877                      (iy+0.5+(randn() if shuffle < 0.3 else rand())*shuffle)*dy*b, 
     878                      (iz+0.5+(randn() if shuffle < 0.3 else rand())*shuffle)*dz*c) 
     879               .rotate(*((randn(3) if rotate < 30 else rand(3))*rotate)) 
     880               for ix in range(nx) 
     881               for iy in range(ny) 
     882               for iz in range(nz)] 
     883    faces_b = [copy(shape) 
     884               .shift((ix+0.5+(randn() if shuffle < 0.3 else rand())*shuffle)*dx*a, 
     885                      (iy+0.0+(randn() if shuffle < 0.3 else rand())*shuffle)*dy*b, 
     886                      (iz+0.5+(randn() if shuffle < 0.3 else rand())*shuffle)*dz*c) 
     887               .rotate(*((randn(3) if rotate < 30 else rand(3))*rotate)) 
     888               for ix in range(nx) 
     889               for iy in range(ny) 
     890               for iz in range(nz)] 
     891    faces_c = [copy(shape) 
     892               .shift((ix+0.5+(randn() if shuffle < 0.3 else rand())*shuffle)*dx*a, 
     893                      (iy+0.5+(randn() if shuffle < 0.3 else rand())*shuffle)*dy*b, 
     894                      (iz+0.0+(randn() if shuffle < 0.3 else rand())*shuffle)*dz*c) 
     895               .rotate(*((randn(3) if rotate < 30 else rand(3))*rotate)) 
     896               for ix in range(nx) 
     897               for iy in range(ny) 
     898               for iz in range(nz)] 
     899    lattice = Composite(corners + faces_a + faces_b + faces_c) 
     900    return lattice 
    767901 
    768902SHAPE_FUNCTIONS = OrderedDict([ 
     
    775909]) 
    776910SHAPES = list(SHAPE_FUNCTIONS.keys()) 
     911LATTICE_FUNCTIONS = OrderedDict([ 
     912    ("sc", build_sc_lattice), 
     913    ("bcc", build_bcc_lattice), 
     914    ("fcc", build_fcc_lattice), 
     915]) 
     916LATTICE_TYPES = list(LATTICE_FUNCTIONS.keys()) 
    777917 
    778918def check_shape(title, shape, fn=None, show_points=False, 
     
    783923    r = shape.r_bins(q, r_step=r_step) 
    784924    sampling_density = samples / shape.volume 
     925    print("sampling points") 
    785926    rho, points = shape.sample(sampling_density) 
     927    print("calculating Pr") 
    786928    t0 = time.time() 
    787929    Pr = calc_Pr(r, rho-rho_solvent, points) 
     
    792934    import pylab 
    793935    if show_points: 
    794          plot_points(rho, points); pylab.figure() 
     936        plot_points(rho, points); pylab.figure() 
    795937    plot_calc(r, Pr, q, Iq, theory=theory, title=title) 
    796938    pylab.gcf().canvas.set_window_title(title) 
     
    806948    Qx, Qy = np.meshgrid(qx, qy) 
    807949    sampling_density = samples / shape.volume 
     950    print("sampling points") 
    808951    t0 = time.time() 
    809952    rho, points = shape.sample(sampling_density) 
     
    844987                        help='lattice size') 
    845988    parser.add_argument('-z', '--spacing', type=str, default='2,2,2', 
    846                         help='lattice spacing') 
     989                        help='lattice spacing (relative to shape)') 
     990    parser.add_argument('-t', '--type', choices=LATTICE_TYPES, 
     991                        default=LATTICE_TYPES[0], 
     992                        help='lattice type') 
    847993    parser.add_argument('-r', '--rotate', type=float, default=0., 
    848994                        help="rotation relative to lattice, gaussian < 30 degrees, uniform otherwise") 
     
    8581004    nx, ny, nz = [int(v) for v in opts.lattice.split(',')] 
    8591005    dx, dy, dz = [float(v) for v in opts.spacing.split(',')] 
    860     shuffle, rotate = opts.shuffle, opts.rotate 
     1006    distortion, rotation = opts.shuffle, opts.rotate 
    8611007    shape, fn, fn_xy = SHAPE_FUNCTIONS[opts.shape](**pars) 
    862     if nx > 1 or ny > 1 or nz > 1: 
    863         shape = build_cubic_lattice(shape, nx, ny, nz, dx, dy, dz, shuffle, rotate) 
     1008    view = tuple(float(v) for v in opts.view.split(',')) 
     1009    # If comparing a sphere in a cubic lattice, compare against the 
     1010    # corresponding paracrystalline model. 
     1011    if opts.shape == "sphere" and dx == dy == dz and nx*ny*nz > 1: 
     1012        radius = pars.get('radius', DEFAULT_SPHERE_RADIUS) 
     1013        model_name = opts.type + "_paracrystal" 
     1014        model_pars = { 
     1015            "scale": 1., 
     1016            "background": 0., 
     1017            "lattice_spacing": 2*radius*dx, 
     1018            "lattice_distortion": distortion, 
     1019            "radius": radius, 
     1020            "sld": pars.get('rho', DEFAULT_SPHERE_CONTRAST), 
     1021            "sld_solvent": 0., 
     1022            "theta": view[0], 
     1023            "phi": view[1], 
     1024            "psi": view[2], 
     1025        } 
     1026        fn, fn_xy = wrap_sasmodel(model_name, **model_pars) 
     1027    if nx*ny*nz > 1: 
     1028        if rotation != 0: 
     1029            print("building %s lattice"%opts.type) 
     1030            build_lattice = LATTICE_FUNCTIONS[opts.type] 
     1031            shape = build_lattice(shape, nx, ny, nz, dx, dy, dz, 
     1032                                  distortion, rotation) 
     1033        else: 
     1034            shape.lattice(size=(nx, ny, nz), spacing=(dx, dy, dz), 
     1035                          type=opts.type, 
     1036                          rotation=rotation, distortion=distortion) 
     1037 
    8641038    title = "%s(%s)" % (opts.shape, " ".join(opts.pars)) 
    8651039    if opts.dim == 1: 
     
    8671041                    mesh=opts.mesh, qmax=opts.qmax, samples=opts.samples) 
    8681042    else: 
    869         view = tuple(float(v) for v in opts.view.split(',')) 
    8701043        check_shape_2d(title, shape, fn_xy, view=view, show_points=opts.plot, 
    8711044                       mesh=opts.mesh, qmax=opts.qmax, samples=opts.samples) 
  • sasmodels/convert.py

    ref476e6 rbd91e8f  
    169169        oldpars = _hand_convert_3_1_2_to_4_1(name, oldpars) 
    170170    if version < (4, 2, 0): 
     171        oldpars = _hand_convert_4_1_to_4_2(name, oldpars) 
    171172        oldpars = _rename_magnetic_pars(oldpars) 
     173    return oldpars 
     174 
     175def _hand_convert_4_1_to_4_2(name, oldpars): 
     176    if name in ('bcc_paracrystal', 'fcc_paracrystal', 'sc_paracrystal'): 
     177        oldpars['lattice_spacing'] = oldpars.pop('dnn') 
     178        oldpars['lattice_distortion'] = oldpars.pop('d_factor') 
    172179    return oldpars 
    173180 
  • sasmodels/models/bcc_paracrystal.c

    r108e70e r642046e  
    11static double 
    2 bcc_Zq(double qa, double qb, double qc, double dnn, double d_factor) 
     2bcc_Zq(double qa, double qb, double qc, double lattice_spacing, double lattice_distortion) 
    33{ 
    44    // Equations from Matsuoka 26-27-28, multiplied by |q| 
     
    1717    //         => exp(a)^2 - 2 cos(d ak) exp(a) + 1) 
    1818    //         => (exp(a) - 2 cos(d ak)) * exp(a) + 1 
    19     const double arg = -0.5*square(dnn*d_factor)*(a1*a1 + a2*a2 + a3*a3); 
     19    const double arg = -0.5*square(lattice_spacing*lattice_distortion)*(a1*a1 + a2*a2 + a3*a3); 
    2020    const double exp_arg = exp(arg); 
    2121    const double Zq = -cube(expm1(2.0*arg)) 
    22         / ( ((exp_arg - 2.0*cos(dnn*a1))*exp_arg + 1.0) 
    23           * ((exp_arg - 2.0*cos(dnn*a2))*exp_arg + 1.0) 
    24           * ((exp_arg - 2.0*cos(dnn*a3))*exp_arg + 1.0)); 
     22        / ( ((exp_arg - 2.0*cos(lattice_spacing*a1))*exp_arg + 1.0) 
     23          * ((exp_arg - 2.0*cos(lattice_spacing*a2))*exp_arg + 1.0) 
     24          * ((exp_arg - 2.0*cos(lattice_spacing*a3))*exp_arg + 1.0)); 
    2525 
    2626#elif 0 
     
    3636    //            = tanh(-a) / [1 - cos(d a_k)/cosh(-a)] 
    3737    // 
    38     const double arg = 0.5*square(dnn*d_factor)*(a1*a1 + a2*a2 + a3*a3); 
     38    const double arg = 0.5*square(lattice_spacing*lattice_distortion)*(a1*a1 + a2*a2 + a3*a3); 
    3939    const double sinh_qd = sinh(arg); 
    4040    const double cosh_qd = cosh(arg); 
    41     const double Zq = sinh_qd/(cosh_qd - cos(dnn*a1)) 
    42                     * sinh_qd/(cosh_qd - cos(dnn*a2)) 
    43                     * sinh_qd/(cosh_qd - cos(dnn*a3)); 
     41    const double Zq = sinh_qd/(cosh_qd - cos(lattice_spacing*a1)) 
     42                    * sinh_qd/(cosh_qd - cos(lattice_spacing*a2)) 
     43                    * sinh_qd/(cosh_qd - cos(lattice_spacing*a3)); 
    4444#else 
    45     const double arg = 0.5*square(dnn*d_factor)*(a1*a1 + a2*a2 + a3*a3); 
     45    const double arg = 0.5*square(lattice_spacing*lattice_distortion)*(a1*a1 + a2*a2 + a3*a3); 
    4646    const double tanh_qd = tanh(arg); 
    4747    const double cosh_qd = cosh(arg); 
    48     const double Zq = tanh_qd/(1.0 - cos(dnn*a1)/cosh_qd) 
    49                     * tanh_qd/(1.0 - cos(dnn*a2)/cosh_qd) 
    50                     * tanh_qd/(1.0 - cos(dnn*a3)/cosh_qd); 
     48    const double Zq = tanh_qd/(1.0 - cos(lattice_spacing*a1)/cosh_qd) 
     49                    * tanh_qd/(1.0 - cos(lattice_spacing*a2)/cosh_qd) 
     50                    * tanh_qd/(1.0 - cos(lattice_spacing*a3)/cosh_qd); 
    5151#endif 
    5252 
     
    5757// occupied volume fraction calculated from lattice symmetry and sphere radius 
    5858static double 
    59 bcc_volume_fraction(double radius, double dnn) 
     59bcc_volume_fraction(double radius, double lattice_spacing) 
    6060{ 
    61     return 2.0*sphere_volume(sqrt(0.75)*radius/dnn); 
     61    return 2.0*sphere_volume(radius/lattice_spacing); 
    6262} 
    6363 
     
    6969 
    7070 
    71 static double Iq(double q, double dnn, 
    72     double d_factor, double radius, 
     71static double Iq(double q, double lattice_spacing, 
     72    double lattice_distortion, double radius, 
    7373    double sld, double solvent_sld) 
    7474{ 
     
    9494            const double qa = qab*cos_phi; 
    9595            const double qb = qab*sin_phi; 
    96             const double form = bcc_Zq(qa, qb, qc, dnn, d_factor); 
     96            const double form = bcc_Zq(qa, qb, qc, lattice_spacing, lattice_distortion); 
    9797            inner_sum += GAUSS_W[j] * form; 
    9898        } 
     
    103103    const double Zq = outer_sum/(4.0*M_PI); 
    104104    const double Pq = sphere_form(q, radius, sld, solvent_sld); 
    105     return bcc_volume_fraction(radius, dnn) * Pq * Zq; 
     105    return bcc_volume_fraction(radius, lattice_spacing) * Pq * Zq; 
    106106} 
    107107 
    108108 
    109109static double Iqabc(double qa, double qb, double qc, 
    110     double dnn, double d_factor, double radius, 
     110    double lattice_spacing, double lattice_distortion, double radius, 
    111111    double sld, double solvent_sld) 
    112112{ 
    113113    const double q = sqrt(qa*qa + qb*qb + qc*qc); 
    114     const double Zq = bcc_Zq(qa, qb, qc, dnn, d_factor); 
     114    const double Zq = bcc_Zq(qa, qb, qc, lattice_spacing, lattice_distortion); 
    115115    const double Pq = sphere_form(q, radius, sld, solvent_sld); 
    116     return bcc_volume_fraction(radius, dnn) * Pq * Zq; 
     116    return bcc_volume_fraction(radius, lattice_spacing) * Pq * Zq; 
    117117} 
  • sasmodels/models/bcc_paracrystal.py

    r0507e09 rbd91e8f  
    3434.. math:: 
    3535 
    36     V_\text{lattice} = \frac{16\pi}{3} \frac{R^3}{\left(D\sqrt{2}\right)^3} 
     36    V_\text{lattice} = \frac{8\pi}{3} \frac{R^3}{\left(2D/\sqrt{3}\right)^3} 
    3737 
    3838 
     
    111111 
    112112* **Author:** NIST IGOR/DANSE **Date:** pre 2010 
    113 * **Last Modified by:** Paul Butler **Date:** September 29, 2016 
    114 * **Last Reviewed by:** Richard Heenan **Date:** March 21, 2016 
    115 * **Source added by :** Steve King **Date:** March 25, 2019 
     113* **Last Modified by:** Paul Butler **Date:** September 16, 2018 
     114* **Last Reviewed by:** Paul Butler **Date:** September 16, 2018 
    116115""" 
    117116 
     
    135134# pylint: disable=bad-whitespace, line-too-long 
    136135#             ["name", "units", default, [lower, upper], "type","description" ], 
    137 parameters = [["dnn",         "Ang",       220,    [-inf, inf], "",            "Nearest neighbour distance"], 
    138               ["d_factor",    "",            0.06, [-inf, inf], "",            "Paracrystal distortion factor"], 
     136parameters = [["lattice_spacing",         "Ang",       220,    [-inf, inf], "",            "Lattice spacing"], 
     137              ["lattice_distortion",    "",            0.06, [-inf, inf], "",            "Paracrystal distortion factor"], 
    139138              ["radius",      "Ang",        40,    [0, inf],    "volume",      "Particle radius"], 
    140139              ["sld",         "1e-6/Ang^2",  4,    [-inf, inf], "sld",         "Particle scattering length density"], 
     
    158157    # in this range 'cuz its easy. 
    159158    radius = 10**np.random.uniform(1.3, 4) 
    160     d_factor = 10**np.random.uniform(-2, -0.7)  # sigma_d in 0.01-0.7 
    161     dnn_fraction = np.random.beta(a=10, b=1) 
    162     dnn = radius*4/np.sqrt(3)/dnn_fraction 
     159    lattice_distortion = 10**np.random.uniform(-2, -0.7)  # sigma_d in 0.01-0.7 
     160    lattice_spacing_fraction = np.random.beta(a=10, b=1) 
     161    lattice_spacing = radius*4/np.sqrt(3)/lattice_spacing_fraction 
    163162    pars = dict( 
    164163        #sld=1, sld_solvent=0, scale=1, background=1e-32, 
    165         dnn=dnn, 
    166         d_factor=d_factor, 
     164        lattice_spacing=lattice_spacing, 
     165        lattice_distortion=lattice_distortion, 
    167166        radius=radius, 
    168167    ) 
  • sasmodels/models/fcc_paracrystal.c

    r71b751d rcc8b183  
    11static double 
    2 fcc_Zq(double qa, double qb, double qc, double dnn, double d_factor) 
     2fcc_Zq(double qa, double qb, double qc, double lattice_spacing, double lattice_distortion) 
    33{ 
    44    // Equations from Matsuoka 17-18-19, multiplied by |q| 
     
    1616    //         => exp(a)^2 - 2 cos(d ak) exp(a) + 1) 
    1717    //         => (exp(a) - 2 cos(d ak)) * exp(a) + 1 
    18     const double arg = -0.5*square(dnn*d_factor)*(a1*a1 + a2*a2 + a3*a3); 
     18    const double arg = -0.5*square(lattice_spacing*lattice_distortion)*(a1*a1 + a2*a2 + a3*a3); 
    1919    const double exp_arg = exp(arg); 
    2020    const double Zq = -cube(expm1(2.0*arg)) 
    21         / ( ((exp_arg - 2.0*cos(dnn*a1))*exp_arg + 1.0) 
    22           * ((exp_arg - 2.0*cos(dnn*a2))*exp_arg + 1.0) 
    23           * ((exp_arg - 2.0*cos(dnn*a3))*exp_arg + 1.0)); 
     21        / ( ((exp_arg - 2.0*cos(lattice_spacing*a1))*exp_arg + 1.0) 
     22          * ((exp_arg - 2.0*cos(lattice_spacing*a2))*exp_arg + 1.0) 
     23          * ((exp_arg - 2.0*cos(lattice_spacing*a3))*exp_arg + 1.0)); 
    2424 
    2525    return Zq; 
     
    2929// occupied volume fraction calculated from lattice symmetry and sphere radius 
    3030static double 
    31 fcc_volume_fraction(double radius, double dnn) 
     31fcc_volume_fraction(double radius, double lattice_spacing) 
    3232{ 
    33     return 4.0*sphere_volume(M_SQRT1_2*radius/dnn); 
     33    return 4.0*sphere_volume(radius/lattice_spacing); 
    3434} 
    3535 
     
    4141 
    4242 
    43 static double Iq(double q, double dnn, 
    44   double d_factor, double radius, 
     43static double Iq(double q, double lattice_spacing, 
     44  double lattice_distortion, double radius, 
    4545  double sld, double solvent_sld) 
    4646{ 
     
    6666            const double qa = qab*cos_phi; 
    6767            const double qb = qab*sin_phi; 
    68             const double form = fcc_Zq(qa, qb, qc, dnn, d_factor); 
     68            const double form = fcc_Zq(qa, qb, qc, lattice_spacing, lattice_distortion); 
    6969            inner_sum += GAUSS_W[j] * form; 
    7070        } 
     
    7676    const double Pq = sphere_form(q, radius, sld, solvent_sld); 
    7777 
    78     return fcc_volume_fraction(radius, dnn) * Pq * Zq; 
     78    return fcc_volume_fraction(radius, lattice_spacing) * Pq * Zq; 
    7979} 
    8080 
    8181static double Iqabc(double qa, double qb, double qc, 
    82     double dnn, double d_factor, double radius, 
     82    double lattice_spacing, double lattice_distortion, double radius, 
    8383    double sld, double solvent_sld) 
    8484{ 
    8585    const double q = sqrt(qa*qa + qb*qb + qc*qc); 
    8686    const double Pq = sphere_form(q, radius, sld, solvent_sld); 
    87     const double Zq = fcc_Zq(qa, qb, qc, dnn, d_factor); 
    88     return fcc_volume_fraction(radius, dnn) * Pq * Zq; 
     87    const double Zq = fcc_Zq(qa, qb, qc, lattice_spacing, lattice_distortion); 
     88    return fcc_volume_fraction(radius, lattice_spacing) * Pq * Zq; 
    8989} 
  • sasmodels/models/fcc_paracrystal.py

    r0507e09 rbd91e8f  
    107107 
    108108Authorship and Verification 
    109 --------------------------- 
     109---------------------------- 
    110110 
    111111* **Author:** NIST IGOR/DANSE **Date:** pre 2010 
    112 * **Last Modified by:** Paul Butler **Date:** September 29, 2016 
    113 * **Last Reviewed by:** Richard Heenan **Date:** March 21, 2016 
    114 * **Source added by :** Steve King **Date:** March 25, 2019 
     112* **Last Modified by:** Paul Butler **Date:** September 16, 2018 
     113* **Last Reviewed by:** Paul Butler **Date:** September 16, 2018 
    115114""" 
    116115 
     
    131130# pylint: disable=bad-whitespace, line-too-long 
    132131#             ["name", "units", default, [lower, upper], "type","description"], 
    133 parameters = [["dnn", "Ang", 220, [-inf, inf], "", "Nearest neighbour distance"], 
    134               ["d_factor", "", 0.06, [-inf, inf], "", "Paracrystal distortion factor"], 
     132parameters = [["lattice_spacing", "Ang", 220, [-inf, inf], "", "Lattice spacing"], 
     133              ["lattice_distortion", "", 0.06, [-inf, inf], "", "Paracrystal distortion factor"], 
    135134              ["radius", "Ang", 40, [0, inf], "volume", "Particle radius"], 
    136135              ["sld", "1e-6/Ang^2", 4, [-inf, inf], "sld", "Particle scattering length density"], 
     
    148147    # copied from bcc_paracrystal 
    149148    radius = 10**np.random.uniform(1.3, 4) 
    150     d_factor = 10**np.random.uniform(-2, -0.7)  # sigma_d in 0.01-0.7 
    151     dnn_fraction = np.random.beta(a=10, b=1) 
    152     dnn = radius*4/np.sqrt(2)/dnn_fraction 
     149    lattice_distortion = 10**np.random.uniform(-2, -0.7)  # sigma_d in 0.01-0.7 
     150    lattice_spacing_fraction = np.random.beta(a=10, b=1) 
     151    lattice_spacing = radius*4/np.sqrt(2)/lattice_spacing_fraction 
    153152    pars = dict( 
    154153        #sld=1, sld_solvent=0, scale=1, background=1e-32, 
    155         dnn=dnn, 
    156         d_factor=d_factor, 
     154        latice_spacing=lattice_spacing, 
     155        lattice_distortion=d_factor, 
    157156        radius=radius, 
    158157    ) 
  • sasmodels/models/sc_paracrystal.c

    r71b751d rcc8b183  
    11static double 
    2 sc_Zq(double qa, double qb, double qc, double dnn, double d_factor) 
     2sc_Zq(double qa, double qb, double qc, double lattice_spacing, double lattice_distortion) 
    33{ 
    44    // Equations from Matsuoka 9-10-11, multiplied by |q| 
     
    1616    //         => exp(a)^2 - 2 cos(d ak) exp(a) + 1) 
    1717    //         => (exp(a) - 2 cos(d ak)) * exp(a) + 1 
    18     const double arg = -0.5*square(dnn*d_factor)*(a1*a1 + a2*a2 + a3*a3); 
     18    const double arg = -0.5*square(lattice_spacing*lattice_distortion)*(a1*a1 + a2*a2 + a3*a3); 
    1919    const double exp_arg = exp(arg); 
    2020    const double Zq = -cube(expm1(2.0*arg)) 
    21         / ( ((exp_arg - 2.0*cos(dnn*a1))*exp_arg + 1.0) 
    22           * ((exp_arg - 2.0*cos(dnn*a2))*exp_arg + 1.0) 
    23           * ((exp_arg - 2.0*cos(dnn*a3))*exp_arg + 1.0)); 
     21        / ( ((exp_arg - 2.0*cos(lattice_spacing*a1))*exp_arg + 1.0) 
     22          * ((exp_arg - 2.0*cos(lattice_spacing*a2))*exp_arg + 1.0) 
     23          * ((exp_arg - 2.0*cos(lattice_spacing*a3))*exp_arg + 1.0)); 
    2424 
    2525    return Zq; 
     
    2828// occupied volume fraction calculated from lattice symmetry and sphere radius 
    2929static double 
    30 sc_volume_fraction(double radius, double dnn) 
     30sc_volume_fraction(double radius, double lattice_spacing) 
    3131{ 
    32     return sphere_volume(radius/dnn); 
     32    return sphere_volume(radius/lattice_spacing); 
    3333} 
    3434 
     
    4141 
    4242static double 
    43 Iq(double q, double dnn, 
    44     double d_factor, double radius, 
     43Iq(double q, double lattice_spacing, 
     44    double lattice_distortion, double radius, 
    4545    double sld, double solvent_sld) 
    4646{ 
     
    6767            const double qa = qab*cos_phi; 
    6868            const double qb = qab*sin_phi; 
    69             const double form = sc_Zq(qa, qb, qc, dnn, d_factor); 
     69            const double form = sc_Zq(qa, qb, qc, lattice_spacing, lattice_distortion); 
    7070            inner_sum += GAUSS_W[j] * form; 
    7171        } 
     
    7777    const double Pq = sphere_form(q, radius, sld, solvent_sld); 
    7878 
    79     return sc_volume_fraction(radius, dnn) * Pq * Zq; 
     79    return sc_volume_fraction(radius, lattice_spacing) * Pq * Zq; 
    8080} 
    8181 
    8282static double 
    8383Iqabc(double qa, double qb, double qc, 
    84     double dnn, double d_factor, double radius, 
     84    double lattice_spacing, double lattice_distortion, double radius, 
    8585    double sld, double solvent_sld) 
    8686{ 
    8787    const double q = sqrt(qa*qa + qb*qb + qc*qc); 
    8888    const double Pq = sphere_form(q, radius, sld, solvent_sld); 
    89     const double Zq = sc_Zq(qa, qb, qc, dnn, d_factor); 
    90     return sc_volume_fraction(radius, dnn) * Pq * Zq; 
     89    const double Zq = sc_Zq(qa, qb, qc, lattice_spacing, lattice_distortion); 
     90    return sc_volume_fraction(radius, lattice_spacing) * Pq * Zq; 
    9191} 
  • sasmodels/models/sc_paracrystal.py

    r0507e09 rbd91e8f  
    109109 
    110110Authorship and Verification 
    111 --------------------------- 
     111---------------------------- 
    112112 
    113113* **Author:** NIST IGOR/DANSE **Date:** pre 2010 
    114 * **Last Modified by:** Steve King **Date:** March 25, 2019 
    115 * **Last Reviewed by:** Richard Heenan **Date:** March 21, 2016 
    116 * **Source added by :** Steve King **Date:** March 25, 2019 
     114* **Last Modified by:** Paul Butler **Date:** September 16, 2018 
     115* **Last Reviewed by:** Paul Butler **Date:** September 16, 2018 
    117116""" 
    118117 
     
    135134        scale: volume fraction of spheres 
    136135        bkg:background, R: radius of sphere 
    137         dnn: Nearest neighbor distance 
    138         d_factor: Paracrystal distortion factor 
     136        lattice_spacing: Nearest neighbor distance 
     137        lattice_distortion: Paracrystal distortion factor 
    139138        radius: radius of the spheres 
    140139        sldSph: SLD of the sphere 
     
    145144# pylint: disable=bad-whitespace, line-too-long 
    146145#             ["name", "units", default, [lower, upper], "type","description"], 
    147 parameters = [["dnn",         "Ang",       220.0, [0.0, inf],  "",            "Nearest neighbor distance"], 
    148               ["d_factor",    "",           0.06, [-inf, inf], "",            "Paracrystal distortion factor"], 
     146parameters = [["lattice_spacing",         "Ang",       220.0, [0.0, inf],  "",  "Lattice spacing"], 
     147              ["lattice_distortion",    "",           0.06, [-inf, inf], "",   "Paracrystal distortion factor"], 
    149148              ["radius",      "Ang",        40.0, [0.0, inf],  "volume",      "Radius of sphere"], 
    150149              ["sld",  "1e-6/Ang^2",         3.0, [0.0, inf],  "sld",         "Sphere scattering length density"], 
     
    162161    # copied from bcc_paracrystal 
    163162    radius = 10**np.random.uniform(1.3, 4) 
    164     d_factor = 10**np.random.uniform(-2, -0.7)  # sigma_d in 0.01-0.7 
    165     dnn_fraction = np.random.beta(a=10, b=1) 
    166     dnn = radius*4/np.sqrt(4)/dnn_fraction 
     163    lattice_distortion = 10**np.random.uniform(-2, -0.7)  # sigma_d in 0.01-0.7 
     164    lattice_spacing_fraction = np.random.beta(a=10, b=1) 
     165    lattice_spacing = radius*4/np.sqrt(4)/lattice_spacing_fraction 
    167166    pars = dict( 
    168167        #sld=1, sld_solvent=0, scale=1, background=1e-32, 
    169         dnn=dnn, 
    170         d_factor=d_factor, 
     168        lattice_spacing=lattice_spacing, 
     169        lattice_distortion=lattice_distortion, 
    171170        radius=radius, 
    172171    ) 
  • doc/guide/fitting_sq.rst

    re62c019 r1423ddb  
    1616.. figure:: p_and_s_buttons.png 
    1717 
    18 **Product models**, or $P@S$ models for short, multiply the structure factor 
    19 $S(Q)$ by the form factor $P(Q)$, modulated by the **effective radius** of the 
    20 form factor. 
    21  
    22 Many of the parameters in $P@S$ models take on specific meanings so that they 
    23 can be handled correctly inside SasView: 
     18**Product models**, or $P@S$ models for short, multiply the form factor 
     19$P(Q)$ by the structure factor $S(Q)$, modulated by the **effective radius** 
     20of the form factor. 
     21 
     22 
     23Scattering at vector $\mathbf Q$ for an individual particle with 
     24shape parameters $\mathbf\xi$ and contrast $\rho_c(\mathbf r, \mathbf\xi)$ 
     25is computed from the square of the amplitude, $F(\mathbf Q, \mathbf\xi)$, as 
     26 
     27.. math:: 
     28    I(\mathbf Q) = F(\mathbf Q, \mathbf\xi) F^*(\mathbf Q, \mathbf\xi) 
     29        \big/ V(\mathbf\xi) 
     30 
     31with particle volume $V(\mathbf \xi)$ and 
     32 
     33.. math:: 
     34    F(\mathbf Q, \mathbf\xi) = \int_{\mathbb R^3} \rho_c(\mathbf r, \mathbf\xi) 
     35        e^{i \mathbf Q \cdot \mathbf r} \,\mathrm d \mathbf r 
     36 
     37The 1-D scattering pattern for monodisperse particles uses the orientation 
     38average in spherical coordinates, 
     39 
     40.. math:: 
     41    I(Q) = n \langle F F^*\rangle = \frac{n}{4\pi} 
     42    \int_{\theta=0}^{\pi} \int_{\phi=0}^{2\pi} 
     43    F F^* \sin(\theta) \,\mathrm d\phi \mathrm d\theta 
     44 
     45where $F(\mathbf Q,\mathbf\xi)$ uses 
     46$\mathbf Q = [Q \sin\theta\cos\phi, Q \sin\theta\sin\phi, Q \cos\theta]^T$. 
     47A $u$-substitution may be used, with $\alpha = \cos \theta$, 
     48$\surd(1 - \alpha^2) = \sin \theta$, and 
     49$\mathrm d\alpha = -\sin\theta\,\mathrm d\theta$. 
     50Here, 
     51 
     52.. math:: n = V_f/V(\mathbf\xi) 
     53 
     54is the number density of scatterers estimated from the volume fraction 
     55of particles in solution. In this formalism, each incoming 
     56wave interacts with exactly one particle before being scattered into the 
     57detector. All interference effects are within the particle itself. 
     58The detector accumulates counts in proportion to the relative probability 
     59at each pixel. The extension to heterogeneous systems is simply a matter of 
     60adding the scattering patterns in proportion to the number density of each 
     61particle. That is, given shape parameters $\mathbf\xi$ with probability 
     62$P_\mathbf{\xi}$, 
     63 
     64.. math:: 
     65 
     66    I(Q) = \int_\Xi n(\mathbf\xi) \langle F F^* \rangle \,\mathrm d\xi 
     67         = V_f\frac{\int_\Xi P_\mathbf{\xi} \langle F F^* \rangle 
     68         \,\mathrm d\mathbf\xi}{\int_\Xi P_\mathbf\xi V(\mathbf\xi)\,\mathrm d\mathbf\xi} 
     69 
     70This approximation is valid in the dilute limit, where particles are 
     71sufficiently far apart that the interaction between them can be ignored. 
     72 
     73As concentration increases, a structure factor term $S(Q)$ can be included, 
     74giving the monodisperse approximation for the interaction between particles, 
     75with 
     76 
     77.. math:: I(Q) = n \langle F F^* \rangle S(Q) 
     78 
     79For particles without spherical symmetry, the decoupling approximation (DA) 
     80is more accurate, with 
     81 
     82.. math:: 
     83 
     84    I(Q) = n [\langle F F^* \rangle 
     85        + \langle F \rangle \langle F \rangle^* (S(Q) - 1)] 
     86 
     87Or equivalently, 
     88 
     89.. math:: I(Q) = P(Q)[1 + \beta\,(S(Q) - 1)] 
     90 
     91with form factor $P(Q) = n \langle F F^* \rangle$ and 
     92$\beta = \langle F \rangle \langle F \rangle^* \big/ \langle F F^* \rangle$. 
     93These approximations can be extended to heterogeneous systems using averages 
     94over size, $\langle \cdot \rangle_\mathbf\xi = \int_\Xi P_\mathbf\xi \langle\cdot\rangle\,\mathrm d\mathbf\xi \big/ \int_\Xi P_\mathbf\xi \,\mathrm d\mathbf\xi$ and setting 
     95$n = V_f\big/\langle V \rangle_\mathbf\xi$. 
     96Further improvements can be made using the local monodisperse 
     97approximation (LMA) or using partial structure factors, as described 
     98in \cite{bresler_sasfit:_2015}. 
     99 
     100Many parameters are common amongst $P@S$ models, and take on specific meanings: 
    24101 
    25102* *scale*: 
    26103 
    27   In simple $P(Q)$ models **scale** often represents the volume fraction of 
    28   material. 
    29    
    30   In $P@S$ models **scale** should be set to 1.0, as the $P@S$ model contains a 
    31   **volfraction** parameter. 
     104    Overall model scale factor. 
     105 
     106    To compute number density $n$ the volume fraction $V_f$ is needed.  In 
     107    most $P(Q)$ models $V_f$ is not defined and **scale** is used instead. 
     108    Some $P(Q)$ models, such as *vesicle*, do define **volfraction** and so 
     109    can leave **scale** at 1.0. 
     110 
     111    The structure factor model $S(Q)$ has **volfraction**.  This is also used 
     112    as the volume fraction for the form factor model $P(Q)$, replacing the 
     113    **volfraction** parameter if it exists in $P$. This means that 
     114    $P@S$ models can leave **scale** at 1.0. 
     115 
     116    If the volume fraction required for $S(Q)$ is *not* the volume fraction 
     117    needed to compute the number density for $P(Q)$, then leave 
     118    **volfraction** as the volume fraction for $S(Q)$ and use 
     119    **scale** to define the volume fraction for $P(Q)$ as 
     120    $V_f$ = **scale**  $\cdot$  **volfraction**.  This situation may 
     121    occur in a mixed phase system where the effective volume 
     122    fraction needed to compute the structure is much higher than the 
     123    true volume fraction. 
    32124 
    33125* *volfraction*: 
    34126 
    35   The volume fraction of material. 
    36  
    37   For hollow shapes, **volfraction** still represents the volume fraction of 
    38   material but the $S(Q)$ calculation needs the volume fraction *enclosed by* 
    39   *the shape.* SasView scales the user-specified volume fraction by the ratio 
    40   form:shell computed from the average form volume and average shell volume 
    41   returned from the $P(Q)$ calculation (the original volfraction is divided 
    42   by the shell volume to compute the number density, and then $P@S$ is scaled 
    43   by that to get the absolute scaling on the final $I(Q)$). 
     127    The volume fraction of material. 
     128 
     129    For hollow shapes, **volfraction** still represents the volume fraction of 
     130    material but the $S(Q)$ calculation needs the volume fraction *enclosed by* 
     131    *the shape.*  Thus the user-specified **volfraction** is scaled by the ratio 
     132    form:shell computed from the average form volume and average shell volume 
     133    returned from the $P(Q)$ calculation when calculating $S(Q)$.  The original 
     134    **volfraction** is divided by the shell volume to compute the number 
     135    density $n$ used in $P@S$ to get the absolute scaling on the final $I(Q)$. 
    44136 
    45137* *radius_effective*: 
    46138 
    47   The radial distance determining the range of the $S(Q)$ interaction. 
    48    
    49   This may, or may not, be the same as any "size" parameters describing the 
    50   form of the shape. For example, in a system containing freely-rotating 
    51   cylinders, the volume of space each cylinder requires to tumble will be 
    52   much larger than the volume of the cylinder itself. Thus the effective 
    53   radius will be larger than either the radius or half-length of the 
    54   cylinder. It may be sensible to tie or constrain **radius_effective** to one 
    55   or other of these "size" parameters. 
    56  
    57   If just part of the $S(Q)$ calculation, the value of **radius_effective** may 
    58   be polydisperse. If it is calculated by $P(Q)$, then it will be the weighted 
    59   average of the effective radii computed for the polydisperse shape 
    60   parameters. 
     139    The radial distance determining the range of the $S(Q)$ interaction. 
     140 
     141    This may be estimated from the "size" parameters $\mathbf \xi$ describing 
     142    the form of the shape.  For example, in a system containing freely-rotating 
     143    cylinders, the volume of space each cylinder requires to tumble will be 
     144    much larger than the volume of the cylinder itself.  Thus the effective 
     145    radius will be larger than either the radius or the half-length of the 
     146    cylinder.  It may be sensible to tie or constrain **radius_effective** 
     147    to one or other of these "size" parameters. **radius_effective** may 
     148    also be specified directly, independent of the estimate from $P(Q)$. 
     149 
     150    If it is calculated by $P(Q)$, **radius_effective** will be the 
     151    weighted average of the effective radii computed for the polydisperse 
     152    shape parameters, and that average used to compute $S(Q)$.  When 
     153    specified directly, the value of **radius_effective** may be 
     154    polydisperse, and $S(Q)$ will be averaged over a range of effective 
     155    radii.  Whether this makes any physical sense will depend on the system. 
     156 
     157* *radius_effective_mode*: 
     158 
     159    Selects the **radius_effective** value to use. 
     160 
     161    When **radius_effective_mode = 0** then the **radius_effective** 
     162    parameter in the $P@S$ model is used.  Otherwise 
     163    **radius_effective_mode = k** is the index into the list of 
     164    **radius_effective_modes** defined by the model indicating how the 
     165    effective radius should be computed from the parameters of the shape. 
     166    For example, the *ellipsoid* model defines the following:: 
     167 
     168        1 => average curvature 
     169        2 => equivalent volume sphere 
     170        3 => min radius 
     171        4 => max radius 
     172 
     173    **radius_effective_mode** will only appear in the parameter table if 
     174    the model defines the list of modes, otherwise it will be set permanently 
     175    to 0 for user defined effective radius. 
    61176 
    62177* *structure_factor_mode*: 
    63178 
    64   If the $P@S$ model supports the $\beta(Q)$ *decoupling correction* [1] then 
    65   **structure_factor_mode** will appear in the parameter table after the $S(Q)$ 
    66   parameters. 
    67    
    68   If **structure_factor_mode = 0** then the *local monodisperse approximation* 
    69   will be used, i.e.: 
    70  
    71     $I(Q)$ = $(scale$ / $volume)$ x $P(Q)$ x $S(Q)$ + $background$ 
    72  
    73   If **structure_factor_mode = 1** then the $\beta(q)$ correction will be 
    74   used, i.e.: 
    75  
    76     $I(Q)$ = $(scale$ x $volfraction$ / $volume)$ x $( <F(Q)^2>$ + $<F(Q)>^2$ x $(S(Q)$ - $1) )$ + $background$ 
    77  
    78     where $P(Q)$ = $<|F(Q)|^2>$. 
    79      
    80   This is equivalent to: 
    81    
    82     $I(Q)$ = $(scale$ / $volume)$ x $P(Q)$ x $( 1$ + $\beta(Q)$ x $(S(Q)$ - $1) )$ + $background$ 
    83  
    84   The $\beta(Q)$ decoupling approximation has the effect of damping the 
    85   oscillations in the normal (local monodisperse) $S(Q)$. When $\beta(Q)$ = 1 
    86   the local monodisperse approximation is recovered. 
    87  
    88   More mode options may appear in future as more complicated operations are 
    89   added. 
     179    The type of structure factor calculation to use. 
     180 
     181    If the $P@S$ model supports the $\beta(Q)$ *decoupling correction* [1] 
     182    then **structure_factor_mode** will appear in the parameter table after 
     183    the $S(Q)$ parameters. 
     184 
     185    If **structure_factor_mode = 0** then the 
     186    *local monodisperse approximation* will be used, i.e.: 
     187 
     188    .. math:: 
     189        I(Q) = \text{scale} \frac{V_f}{V} P(Q) S(Q) + \text{background} 
     190 
     191    where $P(Q) = \langle F(Q)^2 \rangle$. 
     192 
     193    If **structure_factor_mode = 1** then the $\beta(Q)$ correction will be 
     194    used, i.e.: 
     195 
     196    .. math:: 
     197        I(Q) = \text{scale} \frac{V_f}{V} P(Q) [ 1 + \beta(Q) (S(Q) - 1) ] 
     198        + \text{background} 
     199 
     200    The $\beta(Q)$ decoupling approximation has the effect of damping the 
     201    oscillations in the normal (local monodisperse) $S(Q)$. When $\beta(Q) = 1$ 
     202    the local monodisperse approximation is recovered. 
     203 
     204    More mode options may appear in future as more complicated operations are 
     205    added. 
    90206 
    91207References 
  • sasmodels/kernelcl.py

    ra34b811 r9fac5f5  
    158158ENV = None 
    159159def reset_environment(): 
    160     # type: () -> None 
    161     """ 
    162     Call to create a new OpenCL context, such as after a change to SAS_OPENCL. 
     160    # type: () -> "GpuEnvironment" 
     161    """ 
     162    Return a new OpenCL context, such as after a change to SAS_OPENCL. 
    163163    """ 
    164164    global ENV 
    165165    ENV = GpuEnvironment() if use_opencl() else None 
    166  
     166    return ENV 
    167167 
    168168def environment(): 
Note: See TracChangeset for help on using the changeset viewer.