def df_d_params(self):
   result = []
   tphkl = 2 * math.pi * matrix.col(self.hkl)
   h,k,l = self.hkl
   d_exp_huh_d_u_star = matrix.col([h**2, k**2, l**2, 2*h*k, 2*h*l, 2*k*l])
   for scatterer in self.scatterers:
     assert scatterer.scattering_type == "const"
     w = scatterer.occupancy
     if (not scatterer.flags.use_u_aniso()):
       huh = scatterer.u_iso * self.d_star_sq
       dw = math.exp(mtps * huh)
     ffp = 1 + scatterer.fp
     fdp = scatterer.fdp
     ff = ffp + 1j * fdp
     d_site = matrix.col([0,0,0])
     if (not scatterer.flags.use_u_aniso()):
       d_u_iso = 0
       d_u_star = None
     else:
       d_u_iso = None
       d_u_star = matrix.col([0,0,0,0,0,0])
     d_occ = 0
     d_fp = 0
     d_fdp = 0
     for s in self.space_group:
       r = s.r().as_rational().as_float()
       s_site = s * scatterer.site
       alpha = matrix.col(s_site).dot(tphkl)
       if (scatterer.flags.use_u_aniso()):
         s_u_star_s = r*matrix.sym(sym_mat3=scatterer.u_star)*r.transpose()
         huh = (matrix.row(self.hkl) * s_u_star_s).dot(matrix.col(self.hkl))
         dw = math.exp(mtps * huh)
       e = cmath.exp(1j*alpha)
       site_gtmx = r.transpose()
       d_site += site_gtmx * (
         w * dw * ff * e * 1j * tphkl)
       if (not scatterer.flags.use_u_aniso()):
         d_u_iso += w * dw * ff * e * mtps * self.d_star_sq
       else:
         u_star_gtmx = matrix.sqr(tensor_rank_2_gradient_transform_matrix(r))
         d_u_star += u_star_gtmx * (
           w * dw * ff * e * mtps * d_exp_huh_d_u_star)
       d_occ += dw * ff * e
       d_fp += w * dw * e
       d_fdp += w * dw * e * 1j
     result.append(gradients(
       site=d_site,
       u_iso=d_u_iso,
       u_star=d_u_star,
       occupancy=d_occ,
       fp=d_fp,
       fdp=d_fdp))
   return result
 def df_d_params(self):
   result = []
   tphkl = 2 * math.pi * matrix.col(self.hkl)
   h,k,l = self.hkl
   d_exp_huh_d_u_star = matrix.col([h**2, k**2, l**2, 2*h*k, 2*h*l, 2*k*l])
   for scatterer in self.scatterers:
     assert scatterer.scattering_type == "const"
     w = scatterer.occupancy
     if (not scatterer.flags.use_u_aniso()):
       huh = scatterer.u_iso * self.d_star_sq
       dw = math.exp(mtps * huh)
     ffp = 1 + scatterer.fp
     fdp = scatterer.fdp
     ff = ffp + 1j * fdp
     d_site = matrix.col([0,0,0])
     if (not scatterer.flags.use_u_aniso()):
       d_u_iso = 0
       d_u_star = None
     else:
       d_u_iso = None
       d_u_star = matrix.col([0,0,0,0,0,0])
     d_occ = 0
     d_fp = 0
     d_fdp = 0
     for s in self.space_group:
       r = s.r().as_rational().as_float()
       s_site = s * scatterer.site
       alpha = matrix.col(s_site).dot(tphkl)
       if (scatterer.flags.use_u_aniso()):
         s_u_star_s = r*matrix.sym(sym_mat3=scatterer.u_star)*r.transpose()
         huh = (matrix.row(self.hkl) * s_u_star_s).dot(matrix.col(self.hkl))
         dw = math.exp(mtps * huh)
       e = cmath.exp(1j*alpha)
       site_gtmx = r.transpose()
       d_site += site_gtmx * (
         w * dw * ff * e * 1j * tphkl)
       if (not scatterer.flags.use_u_aniso()):
         d_u_iso += w * dw * ff * e * mtps * self.d_star_sq
       else:
         u_star_gtmx = matrix.sqr(tensor_rank_2_gradient_transform_matrix(r))
         d_u_star += u_star_gtmx * (
           w * dw * ff * e * mtps * d_exp_huh_d_u_star)
       d_occ += dw * ff * e
       d_fp += w * dw * e
       d_fdp += w * dw * e * 1j
     result.append(gradients(
       site=d_site,
       u_iso=d_u_iso,
       u_star=d_u_star,
       occupancy=d_occ,
       fp=d_fp,
       fdp=d_fdp))
   return result
예제 #3
0
 def d_u(self):
   result = flex.double(6, 0)
   h,k,l = self.hkl
   d_exp_huh_d_u = matrix.col([h**2, k**2, l**2, 2*h*k, 2*h*l, 2*k*l])
   for op in self.ops:
     op_u = (op*matrix.sym(sym_mat3=self.u)*op.transpose()).as_sym_mat3()
     huh = (matrix.row(self.hkl) \
         * matrix.sym(sym_mat3=op_u)).dot(matrix.col(self.hkl))
     d_op_u = math.exp(mtps * huh) * mtps * d_exp_huh_d_u
     gtmx = tensor_rank_2_gradient_transform_matrix(op)
     d_u = gtmx.matrix_multiply(flex.double(d_op_u))
     result += d_u
   return result
예제 #4
0
 def d_u(self):
     result = flex.double(6, 0)
     h, k, l = self.hkl
     d_exp_huh_d_u = matrix.col(
         [h**2, k**2, l**2, 2 * h * k, 2 * h * l, 2 * k * l])
     for op in self.ops:
         op_u = (op * matrix.sym(sym_mat3=self.u) *
                 op.transpose()).as_sym_mat3()
         huh = (matrix.row(self.hkl) \
             * matrix.sym(sym_mat3=op_u)).dot(matrix.col(self.hkl))
         d_op_u = math.exp(mtps * huh) * mtps * d_exp_huh_d_u
         gtmx = tensor_rank_2_gradient_transform_matrix(op)
         d_u = gtmx.matrix_multiply(flex.double(d_op_u))
         result += d_u
     return result
예제 #5
0
 def d2_u(self):
   result = flex.double(flex.grid(6,6), 0)
   h,k,l = self.hkl
   d_exp_huh_d_u = flex.double([h**2, k**2, l**2, 2*h*k, 2*h*l, 2*k*l])
   d2_exp_huh_d_uu = d_exp_huh_d_u.matrix_outer_product(d_exp_huh_d_u)
   for op in self.ops:
     op_u = (op*matrix.sym(sym_mat3=self.u)*op.transpose()).as_sym_mat3()
     huh = (matrix.row(self.hkl) \
         * matrix.sym(sym_mat3=op_u)).dot(matrix.col(self.hkl))
     d2_op_u = math.exp(mtps * huh) * mtps**2 * d2_exp_huh_d_uu
     gtmx = tensor_rank_2_gradient_transform_matrix(op)
     d2_u = gtmx.matrix_multiply(d2_op_u).matrix_multiply(
       gtmx.matrix_transpose())
     result += d2_u
   return result
예제 #6
0
 def d2_u(self):
     result = flex.double(flex.grid(6, 6), 0)
     h, k, l = self.hkl
     d_exp_huh_d_u = flex.double(
         [h**2, k**2, l**2, 2 * h * k, 2 * h * l, 2 * k * l])
     d2_exp_huh_d_uu = d_exp_huh_d_u.matrix_outer_product(d_exp_huh_d_u)
     for op in self.ops:
         op_u = (op * matrix.sym(sym_mat3=self.u) *
                 op.transpose()).as_sym_mat3()
         huh = (matrix.row(self.hkl) \
             * matrix.sym(sym_mat3=op_u)).dot(matrix.col(self.hkl))
         d2_op_u = math.exp(mtps * huh) * mtps**2 * d2_exp_huh_d_uu
         gtmx = tensor_rank_2_gradient_transform_matrix(op)
         d2_u = gtmx.matrix_multiply(d2_op_u).matrix_multiply(
             gtmx.matrix_transpose())
         result += d2_u
     return result
 def d2f_d_params(self):
   tphkl = 2 * math.pi * matrix.col(self.hkl)
   tphkl_outer = tphkl.outer_product()
   h,k,l = self.hkl
   d_exp_huh_d_u_star = matrix.col([h**2, k**2, l**2, 2*h*k, 2*h*l, 2*k*l])
   d2_exp_huh_d_u_star_u_star = d_exp_huh_d_u_star.outer_product()
   for scatterer in self.scatterers:
     assert scatterer.scattering_type == "const"
     w = scatterer.occupancy
     if (not scatterer.flags.use_u_aniso()):
       huh = scatterer.u_iso * self.d_star_sq
       dw = math.exp(mtps * huh)
     ffp = 1 + scatterer.fp
     fdp = scatterer.fdp
     ff = (ffp + 1j * fdp)
     d2_site_site = flex.complex_double(flex.grid(3,3), 0j)
     if (not scatterer.flags.use_u_aniso()):
       d2_site_u_iso = flex.complex_double(flex.grid(3,1), 0j)
       d2_site_u_star = None
     else:
       d2_site_u_iso = None
       d2_site_u_star = flex.complex_double(flex.grid(3,6), 0j)
     d2_site_occ = flex.complex_double(flex.grid(3,1), 0j)
     d2_site_fp = flex.complex_double(flex.grid(3,1), 0j)
     d2_site_fdp = flex.complex_double(flex.grid(3,1), 0j)
     if (not scatterer.flags.use_u_aniso()):
       d2_u_iso_u_iso = 0j
       d2_u_iso_occ = 0j
       d2_u_iso_fp = 0j
       d2_u_iso_fdp = 0j
     else:
       d2_u_star_u_star = flex.complex_double(flex.grid(6,6), 0j)
       d2_u_star_occ = flex.complex_double(flex.grid(6,1), 0j)
       d2_u_star_fp = flex.complex_double(flex.grid(6,1), 0j)
       d2_u_star_fdp = flex.complex_double(flex.grid(6,1), 0j)
     d2_occ_fp = 0j
     d2_occ_fdp = 0j
     for s in self.space_group:
       r = s.r().as_rational().as_float()
       s_site = s * scatterer.site
       alpha = matrix.col(s_site).dot(tphkl)
       if (scatterer.flags.use_u_aniso()):
         s_u_star_s = r*matrix.sym(sym_mat3=scatterer.u_star)*r.transpose()
         huh = (matrix.row(self.hkl) * s_u_star_s).dot(matrix.col(self.hkl))
         dw = math.exp(mtps * huh)
       e = cmath.exp(1j*alpha)
       site_gtmx = r.transpose()
       d2_site_site += flex.complex_double(
         site_gtmx *
           (w * dw * ff * e * (-1) * tphkl_outer)
              * site_gtmx.transpose())
       if (not scatterer.flags.use_u_aniso()):
         d2_site_u_iso += flex.complex_double(site_gtmx * (
           w * dw * ff * e * 1j * mtps * self.d_star_sq * tphkl))
       else:
         u_star_gtmx = matrix.sqr(tensor_rank_2_gradient_transform_matrix(r))
         d2_site_u_star += flex.complex_double(
             site_gtmx
           * ((w * dw * ff * e * 1j * tphkl).outer_product(
               mtps * d_exp_huh_d_u_star))
           * u_star_gtmx.transpose())
       d2_site_occ += flex.complex_double(site_gtmx * (
         dw * ff * e * 1j * tphkl))
       d2_site_fp += flex.complex_double(site_gtmx * (
         w * dw * e * 1j * tphkl))
       d2_site_fdp += flex.complex_double(site_gtmx * (
         w * dw * e * (-1) * tphkl))
       if (not scatterer.flags.use_u_aniso()):
         d2_u_iso_u_iso += w * dw * ff * e * (mtps * self.d_star_sq)**2
         d2_u_iso_occ += dw * ff * e * mtps * self.d_star_sq
         d2_u_iso_fp += w * dw * e * mtps * self.d_star_sq
         d2_u_iso_fdp += 1j * w * dw * e * mtps * self.d_star_sq
       else:
         d2_u_star_u_star += flex.complex_double(
             u_star_gtmx
           * (w * dw * ff * e * mtps**2 * d2_exp_huh_d_u_star_u_star)
           * u_star_gtmx.transpose())
         d2_u_star_occ += flex.complex_double(u_star_gtmx * (
           dw * ff * e * mtps * d_exp_huh_d_u_star))
         d2_u_star_fp += flex.complex_double(u_star_gtmx * (
           w * dw * e * mtps * d_exp_huh_d_u_star))
         d2_u_star_fdp += flex.complex_double(u_star_gtmx * (
           w * dw * 1j * e * mtps * d_exp_huh_d_u_star))
       d2_occ_fp += dw * e
       d2_occ_fdp += dw * e * 1j
     if (not scatterer.flags.use_u_aniso()):
       i_occ, i_fp, i_fdp, np = 4, 5, 6, 7
     else:
       i_occ, i_fp, i_fdp, np = 9, 10, 11, 12
     dp = flex.complex_double(flex.grid(np,np), 0j)
     paste = dp.matrix_paste_block_in_place
     paste(d2_site_site, 0,0)
     if (not scatterer.flags.use_u_aniso()):
       paste(d2_site_u_iso, 0,3)
       paste(d2_site_u_iso.matrix_transpose(), 3,0)
     else:
       paste(d2_site_u_star, 0,3)
       paste(d2_site_u_star.matrix_transpose(), 3,0)
     paste(d2_site_occ, 0,i_occ)
     paste(d2_site_occ.matrix_transpose(), i_occ,0)
     paste(d2_site_fp, 0,i_fp)
     paste(d2_site_fp.matrix_transpose(), i_fp,0)
     paste(d2_site_fdp, 0,i_fdp)
     paste(d2_site_fdp.matrix_transpose(), i_fdp,0)
     if (not scatterer.flags.use_u_aniso()):
       dp[3*7+3] = d2_u_iso_u_iso
       dp[3*7+4] = d2_u_iso_occ
       dp[4*7+3] = d2_u_iso_occ
       dp[3*7+5] = d2_u_iso_fp
       dp[5*7+3] = d2_u_iso_fp
       dp[3*7+6] = d2_u_iso_fdp
       dp[6*7+3] = d2_u_iso_fdp
     else:
       paste(d2_u_star_u_star, 3,3)
       paste(d2_u_star_occ, 3, 9)
       paste(d2_u_star_occ.matrix_transpose(), 9, 3)
       paste(d2_u_star_fp, 3, 10)
       paste(d2_u_star_fp.matrix_transpose(), 10, 3)
       paste(d2_u_star_fdp, 3, 11)
       paste(d2_u_star_fdp.matrix_transpose(), 11, 3)
     dp[i_occ*np+i_fp] = d2_occ_fp
     dp[i_fp*np+i_occ] = d2_occ_fp
     dp[i_occ*np+i_fdp] = d2_occ_fdp
     dp[i_fdp*np+i_occ] = d2_occ_fdp
     yield dp
예제 #8
0
 def df_d_params(self):
     tphkl = 2 * math.pi * matrix.col(self.hkl)
     h, k, l = self.hkl
     d_exp_huh_d_u_star = matrix.col(
         [h**2, k**2, l**2, 2 * h * k, 2 * h * l, 2 * k * l])
     for i_scatterer, scatterer in enumerate(self.scatterers):
         site_symmetry_ops = None
         if (self.site_symmetry_table.is_special_position(i_scatterer)):
             site_symmetry_ops = self.site_symmetry_table.get(i_scatterer)
             site_constraints = site_symmetry_ops.site_constraints()
             if (scatterer.flags.use_u_aniso()):
                 adp_constraints = site_symmetry_ops.adp_constraints()
         w = scatterer.weight()
         wwo = scatterer.weight_without_occupancy()
         if (not scatterer.flags.use_u_aniso()):
             huh = scatterer.u_iso * self.d_star_sq
             dw = math.exp(mtps * huh)
         gaussian = self.scattering_type_registry.gaussian_not_optional(
             scattering_type=scatterer.scattering_type)
         f0 = gaussian.at_d_star_sq(self.d_star_sq)
         ffp = f0 + scatterer.fp
         fdp = scatterer.fdp
         ff = ffp + 1j * fdp
         d_site = matrix.col([0, 0, 0])
         if (not scatterer.flags.use_u_aniso()):
             d_u_iso = 0
             d_u_star = None
         else:
             d_u_iso = None
             d_u_star = matrix.col([0, 0, 0, 0, 0, 0])
         d_occ = 0j
         d_fp = 0j
         d_fdp = 0j
         for s in self.space_group:
             r = s.r().as_rational().as_float()
             s_site = s * scatterer.site
             alpha = matrix.col(s_site).dot(tphkl)
             if (scatterer.flags.use_u_aniso()):
                 s_u_star_s = r * matrix.sym(
                     sym_mat3=scatterer.u_star) * r.transpose()
                 huh = (matrix.row(self.hkl) * s_u_star_s).dot(
                     matrix.col(self.hkl))
                 dw = math.exp(mtps * huh)
             e = cmath.exp(1j * alpha)
             site_gtmx = r.transpose()
             d_site += site_gtmx * (w * dw * ff * e * 1j * tphkl)
             if (not scatterer.flags.use_u_aniso()):
                 d_u_iso += w * dw * ff * e * mtps * self.d_star_sq
             else:
                 u_star_gtmx = matrix.sqr(
                     tensor_rank_2_gradient_transform_matrix(r))
                 d_u_star += u_star_gtmx * (w * dw * ff * e * mtps *
                                            d_exp_huh_d_u_star)
             d_occ += wwo * dw * ff * e
             d_fp += w * dw * e
             d_fdp += w * dw * e * 1j
         if (site_symmetry_ops is not None):
             gsm = site_constraints.gradient_sum_matrix()
             gsm = matrix.rec(elems=gsm, n=gsm.focus())
             d_site = gsm * d_site
             if (scatterer.flags.use_u_aniso()):
                 gsm = adp_constraints.gradient_sum_matrix()
                 gsm = matrix.rec(elems=gsm, n=gsm.focus())
                 d_u_star = gsm * d_u_star
         result = flex.complex_double(d_site)
         if (not scatterer.flags.use_u_aniso()):
             result.append(d_u_iso)
         else:
             result.extend(flex.complex_double(d_u_star))
         result.extend(flex.complex_double([d_occ, d_fp, d_fdp]))
         yield result
예제 #9
0
    def d2f_d_params_diag(self):
        tphkl = 2 * math.pi * flex.double(self.hkl)
        tphkl_outer = tphkl.matrix_outer_product(tphkl) \
          .matrix_symmetric_as_packed_u()
        h, k, l = self.hkl
        d_exp_huh_d_u_star = flex.double(
            [h**2, k**2, l**2, 2 * h * k, 2 * h * l, 2 * k * l])
        d2_exp_huh_d_u_star_u_star = d_exp_huh_d_u_star.matrix_outer_product(
            d_exp_huh_d_u_star).matrix_symmetric_as_packed_u()
        for i_scatterer, scatterer in enumerate(self.scatterers):
            site_symmetry_ops = None
            if (self.site_symmetry_table.is_special_position(i_scatterer)):
                site_symmetry_ops = self.site_symmetry_table.get(i_scatterer)
                site_constraints = site_symmetry_ops.site_constraints()
                if (scatterer.flags.use_u_aniso()):
                    adp_constraints = site_symmetry_ops.adp_constraints()
            w = scatterer.weight()
            if (not scatterer.flags.use_u_aniso()):
                huh = scatterer.u_iso * self.d_star_sq
                dw = math.exp(mtps * huh)
            gaussian = self.scattering_type_registry.gaussian_not_optional(
                scattering_type=scatterer.scattering_type)
            f0 = gaussian.at_d_star_sq(self.d_star_sq)
            ffp = f0 + scatterer.fp
            fdp = scatterer.fdp
            ff = (ffp + 1j * fdp)
            d2_site_site = flex.complex_double(3 * (3 + 1) // 2, 0j)
            if (not scatterer.flags.use_u_aniso()):
                d2_u_iso_u_iso = 0j
            else:
                d2_u_star_u_star = flex.complex_double(6 * (6 + 1) // 2, 0j)
            for s in self.space_group:
                r = s.r().as_rational().as_float()
                s_site = s * scatterer.site
                alpha = tphkl.dot(flex.double(s_site))
                if (scatterer.flags.use_u_aniso()):
                    s_u_star_s = r * matrix.sym(
                        sym_mat3=scatterer.u_star) * r.transpose()
                    huh = (matrix.row(self.hkl) * s_u_star_s).dot(
                        matrix.col(self.hkl))
                    dw = math.exp(mtps * huh)
                e = cmath.exp(1j * alpha)
                site_gtmx = flex.double(r.transpose())
                site_gtmx.reshape(flex.grid(3, 3))
                d2_site_site += (w * dw * ff * e * (-1)) * (
                    site_gtmx.matrix_multiply_packed_u_multiply_lhs_transpose(
                        tphkl_outer))
                if (not scatterer.flags.use_u_aniso()):
                    d2_u_iso_u_iso += w * dw * ff * e * (mtps *
                                                         self.d_star_sq)**2
                else:
                    u_star_gtmx = tensor_rank_2_gradient_transform_matrix(r)
                    d2_u_star_u_star +=(w * dw * ff * e * mtps**2) \
                      * u_star_gtmx.matrix_multiply_packed_u_multiply_lhs_transpose(
                          d2_exp_huh_d_u_star_u_star)
            if (site_symmetry_ops is None):
                i_u = 3
            else:
                i_u = site_constraints.n_independent_params()
            if (not scatterer.flags.use_u_aniso()):
                i_occ = i_u + 1
            elif (site_symmetry_ops is None):
                i_occ = i_u + 6
            else:
                i_occ = i_u + adp_constraints.n_independent_params()
            np = i_occ + 3
            if (site_symmetry_ops is not None):
                gsm = site_constraints.gradient_sum_matrix()
                d2_site_site = gsm.matrix_multiply_packed_u_multiply_lhs_transpose(
                    packed_u=d2_site_site)
                if (scatterer.flags.use_u_aniso()):
                    gsm = adp_constraints.gradient_sum_matrix()
                    d2_u_star_u_star = gsm \
                      .matrix_multiply_packed_u_multiply_lhs_transpose(
                        packed_u=d2_u_star_u_star)
            #
            dpd = flex.complex_double(flex.grid(np, 1), 0j)

            def paste(d, i):
                d.reshape(flex.grid(d.size(), 1))
                dpd.matrix_paste_block_in_place(d, i, 0)

            paste(d2_site_site.matrix_packed_u_diagonal(), 0)
            if (not scatterer.flags.use_u_aniso()):
                dpd[i_u] = d2_u_iso_u_iso
            else:
                paste(d2_u_star_u_star.matrix_packed_u_diagonal(), i_u)
            yield dpd
예제 #10
0
 def d2f_d_params(self):
     tphkl = 2 * math.pi * flex.double(self.hkl)
     tphkl_outer = tphkl.matrix_outer_product(tphkl) \
       .matrix_symmetric_as_packed_u()
     h, k, l = self.hkl
     d_exp_huh_d_u_star = flex.double(
         [h**2, k**2, l**2, 2 * h * k, 2 * h * l, 2 * k * l])
     d2_exp_huh_d_u_star_u_star = d_exp_huh_d_u_star.matrix_outer_product(
         d_exp_huh_d_u_star).matrix_symmetric_as_packed_u()
     for i_scatterer, scatterer in enumerate(self.scatterers):
         site_symmetry_ops = None
         if (self.site_symmetry_table.is_special_position(i_scatterer)):
             site_symmetry_ops = self.site_symmetry_table.get(i_scatterer)
             site_constraints = site_symmetry_ops.site_constraints()
             if (scatterer.flags.use_u_aniso()):
                 adp_constraints = site_symmetry_ops.adp_constraints()
         w = scatterer.weight()
         wwo = scatterer.weight_without_occupancy()
         if (not scatterer.flags.use_u_aniso()):
             huh = scatterer.u_iso * self.d_star_sq
             dw = math.exp(mtps * huh)
         gaussian = self.scattering_type_registry.gaussian_not_optional(
             scattering_type=scatterer.scattering_type)
         f0 = gaussian.at_d_star_sq(self.d_star_sq)
         ffp = f0 + scatterer.fp
         fdp = scatterer.fdp
         ff = (ffp + 1j * fdp)
         d2_site_site = flex.complex_double(3 * (3 + 1) // 2, 0j)
         if (not scatterer.flags.use_u_aniso()):
             d2_site_u_iso = flex.complex_double(flex.grid(3, 1), 0j)
             d2_site_u_star = None
         else:
             d2_site_u_iso = None
             d2_site_u_star = flex.complex_double(flex.grid(3, 6), 0j)
         d2_site_occ = flex.complex_double(flex.grid(3, 1), 0j)
         d2_site_fp = flex.complex_double(flex.grid(3, 1), 0j)
         d2_site_fdp = flex.complex_double(flex.grid(3, 1), 0j)
         if (not scatterer.flags.use_u_aniso()):
             d2_u_iso_u_iso = 0j
             d2_u_iso_occ = 0j
             d2_u_iso_fp = 0j
             d2_u_iso_fdp = 0j
         else:
             d2_u_star_u_star = flex.complex_double(6 * (6 + 1) // 2, 0j)
             d2_u_star_occ = flex.complex_double(flex.grid(6, 1), 0j)
             d2_u_star_fp = flex.complex_double(flex.grid(6, 1), 0j)
             d2_u_star_fdp = flex.complex_double(flex.grid(6, 1), 0j)
         d2_occ_fp = 0j
         d2_occ_fdp = 0j
         for s in self.space_group:
             r = s.r().as_rational().as_float()
             s_site = s * scatterer.site
             alpha = tphkl.dot(flex.double(s_site))
             if (scatterer.flags.use_u_aniso()):
                 s_u_star_s = r * matrix.sym(
                     sym_mat3=scatterer.u_star) * r.transpose()
                 huh = (matrix.row(self.hkl) * s_u_star_s).dot(
                     matrix.col(self.hkl))
                 dw = math.exp(mtps * huh)
             e = cmath.exp(1j * alpha)
             site_gtmx = flex.double(r.transpose())
             site_gtmx.reshape(flex.grid(3, 3))
             d2_site_site += (w * dw * ff * e * (-1)) * (
                 site_gtmx.matrix_multiply_packed_u_multiply_lhs_transpose(
                     tphkl_outer))
             if (not scatterer.flags.use_u_aniso()):
                 d2_site_u_iso += (w * dw * ff * e * 1j * mtps * self.d_star_sq) \
                   * site_gtmx.matrix_multiply(tphkl)
             else:
                 u_star_gtmx = tensor_rank_2_gradient_transform_matrix(r)
                 d2_site_u_star += (w * dw * ff * e * 1j * mtps) \
                   * site_gtmx.matrix_multiply(
                       tphkl.matrix_outer_product(d_exp_huh_d_u_star)) \
                         .matrix_multiply(u_star_gtmx.matrix_transpose())
             site_gtmx_tphkl = site_gtmx.matrix_multiply(tphkl)
             d2_site_occ += (wwo * dw * ff * e * 1j) * site_gtmx_tphkl
             d2_site_fp += (w * dw * e * 1j) * site_gtmx_tphkl
             d2_site_fdp += (w * dw * e * (-1)) * site_gtmx_tphkl
             if (not scatterer.flags.use_u_aniso()):
                 d2_u_iso_u_iso += w * dw * ff * e * (mtps *
                                                      self.d_star_sq)**2
                 d2_u_iso_occ += wwo * dw * ff * e * mtps * self.d_star_sq
                 d2_u_iso_fp += w * dw * e * mtps * self.d_star_sq
                 d2_u_iso_fdp += 1j * w * dw * e * mtps * self.d_star_sq
             else:
                 d2_u_star_u_star +=(w * dw * ff * e * mtps**2) \
                   * u_star_gtmx.matrix_multiply_packed_u_multiply_lhs_transpose(
                       d2_exp_huh_d_u_star_u_star)
                 u_star_gtmx_d_exp_huh_d_u_star = u_star_gtmx.matrix_multiply(
                     d_exp_huh_d_u_star)
                 d2_u_star_occ += (wwo * dw * ff * e * mtps) \
                   * u_star_gtmx_d_exp_huh_d_u_star
                 d2_u_star_fp += (w * dw * e * mtps) \
                   * u_star_gtmx_d_exp_huh_d_u_star
                 d2_u_star_fdp += (w * dw * 1j * e * mtps) \
                   * u_star_gtmx_d_exp_huh_d_u_star
             d2_occ_fp += wwo * dw * e
             d2_occ_fdp += wwo * dw * e * 1j
         if (site_symmetry_ops is None):
             i_u = 3
         else:
             i_u = site_constraints.n_independent_params()
         if (not scatterer.flags.use_u_aniso()):
             i_occ = i_u + 1
         elif (site_symmetry_ops is None):
             i_occ = i_u + 6
         else:
             i_occ = i_u + adp_constraints.n_independent_params()
         i_fp, i_fdp, np = i_occ + 1, i_occ + 2, i_occ + 3
         if (site_symmetry_ops is not None):
             gsm = site_constraints.gradient_sum_matrix()
             d2_site_site = gsm.matrix_multiply_packed_u_multiply_lhs_transpose(
                 packed_u=d2_site_site)
             if (not scatterer.flags.use_u_aniso()):
                 d2_site_u_iso = gsm.matrix_multiply(d2_site_u_iso)
             else:
                 d2_site_u_star = gsm.matrix_multiply(d2_site_u_star)
             d2_site_occ = gsm.matrix_multiply(d2_site_occ)
             d2_site_fp = gsm.matrix_multiply(d2_site_fp)
             d2_site_fdp = gsm.matrix_multiply(d2_site_fdp)
             if (scatterer.flags.use_u_aniso()):
                 gsm = adp_constraints.gradient_sum_matrix()
                 d2_site_u_star = d2_site_u_star.matrix_multiply(
                     gsm.matrix_transpose())
                 d2_u_star_u_star = gsm \
                   .matrix_multiply_packed_u_multiply_lhs_transpose(
                     packed_u=d2_u_star_u_star)
                 d2_u_star_occ = gsm.matrix_multiply(d2_u_star_occ)
                 d2_u_star_fp = gsm.matrix_multiply(d2_u_star_fp)
                 d2_u_star_fdp = gsm.matrix_multiply(d2_u_star_fdp)
         dp = flex.complex_double(flex.grid(np, np), 0j)
         paste = dp.matrix_paste_block_in_place
         paste(d2_site_site.matrix_packed_u_as_symmetric(), 0, 0)
         if (not scatterer.flags.use_u_aniso()):
             paste(d2_site_u_iso, 0, i_u)
             paste(d2_site_u_iso.matrix_transpose(), i_u, 0)
         else:
             paste(d2_site_u_star, 0, i_u)
             paste(d2_site_u_star.matrix_transpose(), i_u, 0)
         paste(d2_site_occ, 0, i_occ)
         paste(d2_site_occ.matrix_transpose(), i_occ, 0)
         paste(d2_site_fp, 0, i_fp)
         paste(d2_site_fp.matrix_transpose(), i_fp, 0)
         paste(d2_site_fdp, 0, i_fdp)
         paste(d2_site_fdp.matrix_transpose(), i_fdp, 0)
         if (not scatterer.flags.use_u_aniso()):
             dp[i_u * np + i_u] = d2_u_iso_u_iso
             dp[i_u * np + i_occ] = d2_u_iso_occ
             dp[i_occ * np + i_u] = d2_u_iso_occ
             dp[i_u * np + i_fp] = d2_u_iso_fp
             dp[i_fp * np + i_u] = d2_u_iso_fp
             dp[i_u * np + i_fdp] = d2_u_iso_fdp
             dp[i_fdp * np + i_u] = d2_u_iso_fdp
         else:
             paste(d2_u_star_u_star.matrix_packed_u_as_symmetric(), i_u,
                   i_u)
             paste(d2_u_star_occ, i_u, i_occ)
             paste(d2_u_star_occ.matrix_transpose(), i_occ, i_u)
             paste(d2_u_star_fp, i_u, i_fp)
             paste(d2_u_star_fp.matrix_transpose(), i_fp, i_u)
             paste(d2_u_star_fdp, i_u, i_fdp)
             paste(d2_u_star_fdp.matrix_transpose(), i_fdp, i_u)
         dp[i_occ * np + i_fp] = d2_occ_fp
         dp[i_fp * np + i_occ] = d2_occ_fp
         dp[i_occ * np + i_fdp] = d2_occ_fdp
         dp[i_fdp * np + i_occ] = d2_occ_fdp
         yield dp
 def d2f_d_params(self):
   tphkl = 2 * math.pi * matrix.col(self.hkl)
   tphkl_outer = tphkl.outer_product()
   h,k,l = self.hkl
   d_exp_huh_d_u_star = matrix.col([h**2, k**2, l**2, 2*h*k, 2*h*l, 2*k*l])
   d2_exp_huh_d_u_star_u_star = d_exp_huh_d_u_star.outer_product()
   for scatterer in self.scatterers:
     assert scatterer.scattering_type == "const"
     w = scatterer.occupancy
     if (not scatterer.flags.use_u_aniso()):
       huh = scatterer.u_iso * self.d_star_sq
       dw = math.exp(mtps * huh)
     ffp = 1 + scatterer.fp
     fdp = scatterer.fdp
     ff = (ffp + 1j * fdp)
     d2_site_site = flex.complex_double(flex.grid(3,3), 0j)
     if (not scatterer.flags.use_u_aniso()):
       d2_site_u_iso = flex.complex_double(flex.grid(3,1), 0j)
       d2_site_u_star = None
     else:
       d2_site_u_iso = None
       d2_site_u_star = flex.complex_double(flex.grid(3,6), 0j)
     d2_site_occ = flex.complex_double(flex.grid(3,1), 0j)
     d2_site_fp = flex.complex_double(flex.grid(3,1), 0j)
     d2_site_fdp = flex.complex_double(flex.grid(3,1), 0j)
     if (not scatterer.flags.use_u_aniso()):
       d2_u_iso_u_iso = 0j
       d2_u_iso_occ = 0j
       d2_u_iso_fp = 0j
       d2_u_iso_fdp = 0j
     else:
       d2_u_star_u_star = flex.complex_double(flex.grid(6,6), 0j)
       d2_u_star_occ = flex.complex_double(flex.grid(6,1), 0j)
       d2_u_star_fp = flex.complex_double(flex.grid(6,1), 0j)
       d2_u_star_fdp = flex.complex_double(flex.grid(6,1), 0j)
     d2_occ_fp = 0j
     d2_occ_fdp = 0j
     for s in self.space_group:
       r = s.r().as_rational().as_float()
       s_site = s * scatterer.site
       alpha = matrix.col(s_site).dot(tphkl)
       if (scatterer.flags.use_u_aniso()):
         s_u_star_s = r*matrix.sym(sym_mat3=scatterer.u_star)*r.transpose()
         huh = (matrix.row(self.hkl) * s_u_star_s).dot(matrix.col(self.hkl))
         dw = math.exp(mtps * huh)
       e = cmath.exp(1j*alpha)
       site_gtmx = r.transpose()
       d2_site_site += flex.complex_double(
         site_gtmx *
           (w * dw * ff * e * (-1) * tphkl_outer)
              * site_gtmx.transpose())
       if (not scatterer.flags.use_u_aniso()):
         d2_site_u_iso += flex.complex_double(site_gtmx * (
           w * dw * ff * e * 1j * mtps * self.d_star_sq * tphkl))
       else:
         u_star_gtmx = matrix.sqr(tensor_rank_2_gradient_transform_matrix(r))
         d2_site_u_star += flex.complex_double(
             site_gtmx
           * ((w * dw * ff * e * 1j * tphkl).outer_product(
               mtps * d_exp_huh_d_u_star))
           * u_star_gtmx.transpose())
       d2_site_occ += flex.complex_double(site_gtmx * (
         dw * ff * e * 1j * tphkl))
       d2_site_fp += flex.complex_double(site_gtmx * (
         w * dw * e * 1j * tphkl))
       d2_site_fdp += flex.complex_double(site_gtmx * (
         w * dw * e * (-1) * tphkl))
       if (not scatterer.flags.use_u_aniso()):
         d2_u_iso_u_iso += w * dw * ff * e * (mtps * self.d_star_sq)**2
         d2_u_iso_occ += dw * ff * e * mtps * self.d_star_sq
         d2_u_iso_fp += w * dw * e * mtps * self.d_star_sq
         d2_u_iso_fdp += 1j * w * dw * e * mtps * self.d_star_sq
       else:
         d2_u_star_u_star += flex.complex_double(
             u_star_gtmx
           * (w * dw * ff * e * mtps**2 * d2_exp_huh_d_u_star_u_star)
           * u_star_gtmx.transpose())
         d2_u_star_occ += flex.complex_double(u_star_gtmx * (
           dw * ff * e * mtps * d_exp_huh_d_u_star))
         d2_u_star_fp += flex.complex_double(u_star_gtmx * (
           w * dw * e * mtps * d_exp_huh_d_u_star))
         d2_u_star_fdp += flex.complex_double(u_star_gtmx * (
           w * dw * 1j * e * mtps * d_exp_huh_d_u_star))
       d2_occ_fp += dw * e
       d2_occ_fdp += dw * e * 1j
     if (not scatterer.flags.use_u_aniso()):
       i_occ, i_fp, i_fdp, np = 4, 5, 6, 7
     else:
       i_occ, i_fp, i_fdp, np = 9, 10, 11, 12
     dp = flex.complex_double(flex.grid(np,np), 0j)
     paste = dp.matrix_paste_block_in_place
     paste(d2_site_site, 0,0)
     if (not scatterer.flags.use_u_aniso()):
       paste(d2_site_u_iso, 0,3)
       paste(d2_site_u_iso.matrix_transpose(), 3,0)
     else:
       paste(d2_site_u_star, 0,3)
       paste(d2_site_u_star.matrix_transpose(), 3,0)
     paste(d2_site_occ, 0,i_occ)
     paste(d2_site_occ.matrix_transpose(), i_occ,0)
     paste(d2_site_fp, 0,i_fp)
     paste(d2_site_fp.matrix_transpose(), i_fp,0)
     paste(d2_site_fdp, 0,i_fdp)
     paste(d2_site_fdp.matrix_transpose(), i_fdp,0)
     if (not scatterer.flags.use_u_aniso()):
       dp[3*7+3] = d2_u_iso_u_iso
       dp[3*7+4] = d2_u_iso_occ
       dp[4*7+3] = d2_u_iso_occ
       dp[3*7+5] = d2_u_iso_fp
       dp[5*7+3] = d2_u_iso_fp
       dp[3*7+6] = d2_u_iso_fdp
       dp[6*7+3] = d2_u_iso_fdp
     else:
       paste(d2_u_star_u_star, 3,3)
       paste(d2_u_star_occ, 3, 9)
       paste(d2_u_star_occ.matrix_transpose(), 9, 3)
       paste(d2_u_star_fp, 3, 10)
       paste(d2_u_star_fp.matrix_transpose(), 10, 3)
       paste(d2_u_star_fdp, 3, 11)
       paste(d2_u_star_fdp.matrix_transpose(), 11, 3)
     dp[i_occ*np+i_fp] = d2_occ_fp
     dp[i_fp*np+i_occ] = d2_occ_fp
     dp[i_occ*np+i_fdp] = d2_occ_fdp
     dp[i_fdp*np+i_occ] = d2_occ_fdp
     yield dp
 def df_d_params(self):
   tphkl = 2 * math.pi * matrix.col(self.hkl)
   h,k,l = self.hkl
   d_exp_huh_d_u_star = matrix.col([h**2, k**2, l**2, 2*h*k, 2*h*l, 2*k*l])
   for i_scatterer,scatterer in enumerate(self.scatterers):
     site_symmetry_ops = None
     if (self.site_symmetry_table.is_special_position(i_scatterer)):
       site_symmetry_ops = self.site_symmetry_table.get(i_scatterer)
       site_constraints = site_symmetry_ops.site_constraints()
       if (scatterer.flags.use_u_aniso()):
         adp_constraints = site_symmetry_ops.adp_constraints()
     w = scatterer.weight()
     wwo = scatterer.weight_without_occupancy()
     if (not scatterer.flags.use_u_aniso()):
       huh = scatterer.u_iso * self.d_star_sq
       dw = math.exp(mtps * huh)
     gaussian = self.scattering_type_registry.gaussian_not_optional(
       scattering_type=scatterer.scattering_type)
     f0 = gaussian.at_d_star_sq(self.d_star_sq)
     ffp = f0 + scatterer.fp
     fdp = scatterer.fdp
     ff = ffp + 1j * fdp
     d_site = matrix.col([0,0,0])
     if (not scatterer.flags.use_u_aniso()):
       d_u_iso = 0
       d_u_star = None
     else:
       d_u_iso = None
       d_u_star = matrix.col([0,0,0,0,0,0])
     d_occ = 0j
     d_fp = 0j
     d_fdp = 0j
     for s in self.space_group:
       r = s.r().as_rational().as_float()
       s_site = s * scatterer.site
       alpha = matrix.col(s_site).dot(tphkl)
       if (scatterer.flags.use_u_aniso()):
         s_u_star_s = r*matrix.sym(sym_mat3=scatterer.u_star)*r.transpose()
         huh = (matrix.row(self.hkl) * s_u_star_s).dot(matrix.col(self.hkl))
         dw = math.exp(mtps * huh)
       e = cmath.exp(1j*alpha)
       site_gtmx = r.transpose()
       d_site += site_gtmx * (
         w * dw * ff * e * 1j * tphkl)
       if (not scatterer.flags.use_u_aniso()):
         d_u_iso += w * dw * ff * e * mtps * self.d_star_sq
       else:
         u_star_gtmx = matrix.sqr(tensor_rank_2_gradient_transform_matrix(r))
         d_u_star += u_star_gtmx * (
           w * dw * ff * e * mtps * d_exp_huh_d_u_star)
       d_occ += wwo * dw * ff * e
       d_fp += w * dw * e
       d_fdp += w * dw * e * 1j
     if (site_symmetry_ops is not None):
       gsm = site_constraints.gradient_sum_matrix()
       gsm = matrix.rec(elems=gsm, n=gsm.focus())
       d_site = gsm * d_site
       if (scatterer.flags.use_u_aniso()):
         gsm = adp_constraints.gradient_sum_matrix()
         gsm = matrix.rec(elems=gsm, n=gsm.focus())
         d_u_star = gsm * d_u_star
     result = flex.complex_double(d_site)
     if (not scatterer.flags.use_u_aniso()):
       result.append(d_u_iso)
     else:
       result.extend(flex.complex_double(d_u_star))
     result.extend(flex.complex_double([d_occ, d_fp, d_fdp]))
     yield result
 def d2f_d_params_diag(self):
   tphkl = 2 * math.pi * flex.double(self.hkl)
   tphkl_outer = tphkl.matrix_outer_product(tphkl) \
     .matrix_symmetric_as_packed_u()
   h,k,l = self.hkl
   d_exp_huh_d_u_star = flex.double([h**2, k**2, l**2, 2*h*k, 2*h*l, 2*k*l])
   d2_exp_huh_d_u_star_u_star = d_exp_huh_d_u_star.matrix_outer_product(
     d_exp_huh_d_u_star).matrix_symmetric_as_packed_u()
   for i_scatterer,scatterer in enumerate(self.scatterers):
     site_symmetry_ops = None
     if (self.site_symmetry_table.is_special_position(i_scatterer)):
       site_symmetry_ops = self.site_symmetry_table.get(i_scatterer)
       site_constraints = site_symmetry_ops.site_constraints()
       if (scatterer.flags.use_u_aniso()):
         adp_constraints = site_symmetry_ops.adp_constraints()
     w = scatterer.weight()
     if (not scatterer.flags.use_u_aniso()):
       huh = scatterer.u_iso * self.d_star_sq
       dw = math.exp(mtps * huh)
     gaussian = self.scattering_type_registry.gaussian_not_optional(
       scattering_type=scatterer.scattering_type)
     f0 = gaussian.at_d_star_sq(self.d_star_sq)
     ffp = f0 + scatterer.fp
     fdp = scatterer.fdp
     ff = (ffp + 1j * fdp)
     d2_site_site = flex.complex_double(3*(3+1)//2, 0j)
     if (not scatterer.flags.use_u_aniso()):
       d2_u_iso_u_iso = 0j
     else:
       d2_u_star_u_star = flex.complex_double(6*(6+1)//2, 0j)
     for s in self.space_group:
       r = s.r().as_rational().as_float()
       s_site = s * scatterer.site
       alpha = tphkl.dot(flex.double(s_site))
       if (scatterer.flags.use_u_aniso()):
         s_u_star_s = r*matrix.sym(sym_mat3=scatterer.u_star)*r.transpose()
         huh = (matrix.row(self.hkl) * s_u_star_s).dot(matrix.col(self.hkl))
         dw = math.exp(mtps * huh)
       e = cmath.exp(1j*alpha)
       site_gtmx = flex.double(r.transpose())
       site_gtmx.reshape(flex.grid(3,3))
       d2_site_site += (w * dw * ff * e * (-1)) * (
         site_gtmx.matrix_multiply_packed_u_multiply_lhs_transpose(
           tphkl_outer))
       if (not scatterer.flags.use_u_aniso()):
         d2_u_iso_u_iso += w * dw * ff * e * (mtps * self.d_star_sq)**2
       else:
         u_star_gtmx = tensor_rank_2_gradient_transform_matrix(r)
         d2_u_star_u_star +=(w * dw * ff * e * mtps**2) \
           * u_star_gtmx.matrix_multiply_packed_u_multiply_lhs_transpose(
               d2_exp_huh_d_u_star_u_star)
     if (site_symmetry_ops is None):
       i_u = 3
     else:
       i_u = site_constraints.n_independent_params()
     if (not scatterer.flags.use_u_aniso()):
       i_occ = i_u + 1
     elif (site_symmetry_ops is None):
       i_occ = i_u + 6
     else:
       i_occ = i_u + adp_constraints.n_independent_params()
     np = i_occ+3
     if (site_symmetry_ops is not None):
       gsm = site_constraints.gradient_sum_matrix()
       d2_site_site = gsm.matrix_multiply_packed_u_multiply_lhs_transpose(
         packed_u=d2_site_site)
       if (scatterer.flags.use_u_aniso()):
         gsm = adp_constraints.gradient_sum_matrix()
         d2_u_star_u_star = gsm \
           .matrix_multiply_packed_u_multiply_lhs_transpose(
             packed_u=d2_u_star_u_star)
     #
     dpd = flex.complex_double(flex.grid(np,1), 0j)
     def paste(d, i):
       d.reshape(flex.grid(d.size(),1))
       dpd.matrix_paste_block_in_place(d, i,0)
     paste(d2_site_site.matrix_packed_u_diagonal(), 0)
     if (not scatterer.flags.use_u_aniso()):
       dpd[i_u] = d2_u_iso_u_iso
     else:
       paste(d2_u_star_u_star.matrix_packed_u_diagonal(), i_u)
     yield dpd
 def d2f_d_params(self):
   tphkl = 2 * math.pi * flex.double(self.hkl)
   tphkl_outer = tphkl.matrix_outer_product(tphkl) \
     .matrix_symmetric_as_packed_u()
   h,k,l = self.hkl
   d_exp_huh_d_u_star = flex.double([h**2, k**2, l**2, 2*h*k, 2*h*l, 2*k*l])
   d2_exp_huh_d_u_star_u_star = d_exp_huh_d_u_star.matrix_outer_product(
     d_exp_huh_d_u_star).matrix_symmetric_as_packed_u()
   for i_scatterer,scatterer in enumerate(self.scatterers):
     site_symmetry_ops = None
     if (self.site_symmetry_table.is_special_position(i_scatterer)):
       site_symmetry_ops = self.site_symmetry_table.get(i_scatterer)
       site_constraints = site_symmetry_ops.site_constraints()
       if (scatterer.flags.use_u_aniso()):
         adp_constraints = site_symmetry_ops.adp_constraints()
     w = scatterer.weight()
     wwo = scatterer.weight_without_occupancy()
     if (not scatterer.flags.use_u_aniso()):
       huh = scatterer.u_iso * self.d_star_sq
       dw = math.exp(mtps * huh)
     gaussian = self.scattering_type_registry.gaussian_not_optional(
       scattering_type=scatterer.scattering_type)
     f0 = gaussian.at_d_star_sq(self.d_star_sq)
     ffp = f0 + scatterer.fp
     fdp = scatterer.fdp
     ff = (ffp + 1j * fdp)
     d2_site_site = flex.complex_double(3*(3+1)//2, 0j)
     if (not scatterer.flags.use_u_aniso()):
       d2_site_u_iso = flex.complex_double(flex.grid(3,1), 0j)
       d2_site_u_star = None
     else:
       d2_site_u_iso = None
       d2_site_u_star = flex.complex_double(flex.grid(3,6), 0j)
     d2_site_occ = flex.complex_double(flex.grid(3,1), 0j)
     d2_site_fp = flex.complex_double(flex.grid(3,1), 0j)
     d2_site_fdp = flex.complex_double(flex.grid(3,1), 0j)
     if (not scatterer.flags.use_u_aniso()):
       d2_u_iso_u_iso = 0j
       d2_u_iso_occ = 0j
       d2_u_iso_fp = 0j
       d2_u_iso_fdp = 0j
     else:
       d2_u_star_u_star = flex.complex_double(6*(6+1)//2, 0j)
       d2_u_star_occ = flex.complex_double(flex.grid(6,1), 0j)
       d2_u_star_fp = flex.complex_double(flex.grid(6,1), 0j)
       d2_u_star_fdp = flex.complex_double(flex.grid(6,1), 0j)
     d2_occ_fp = 0j
     d2_occ_fdp = 0j
     for s in self.space_group:
       r = s.r().as_rational().as_float()
       s_site = s * scatterer.site
       alpha = tphkl.dot(flex.double(s_site))
       if (scatterer.flags.use_u_aniso()):
         s_u_star_s = r*matrix.sym(sym_mat3=scatterer.u_star)*r.transpose()
         huh = (matrix.row(self.hkl) * s_u_star_s).dot(matrix.col(self.hkl))
         dw = math.exp(mtps * huh)
       e = cmath.exp(1j*alpha)
       site_gtmx = flex.double(r.transpose())
       site_gtmx.reshape(flex.grid(3,3))
       d2_site_site += (w * dw * ff * e * (-1)) * (
         site_gtmx.matrix_multiply_packed_u_multiply_lhs_transpose(
           tphkl_outer))
       if (not scatterer.flags.use_u_aniso()):
         d2_site_u_iso += (w * dw * ff * e * 1j * mtps * self.d_star_sq) \
           * site_gtmx.matrix_multiply(tphkl)
       else:
         u_star_gtmx = tensor_rank_2_gradient_transform_matrix(r)
         d2_site_u_star += (w * dw * ff * e * 1j * mtps) \
           * site_gtmx.matrix_multiply(
               tphkl.matrix_outer_product(d_exp_huh_d_u_star)) \
                 .matrix_multiply(u_star_gtmx.matrix_transpose())
       site_gtmx_tphkl = site_gtmx.matrix_multiply(tphkl)
       d2_site_occ += (wwo * dw * ff * e * 1j) * site_gtmx_tphkl
       d2_site_fp += (w * dw * e * 1j) * site_gtmx_tphkl
       d2_site_fdp += (w * dw * e * (-1)) * site_gtmx_tphkl
       if (not scatterer.flags.use_u_aniso()):
         d2_u_iso_u_iso += w * dw * ff * e * (mtps * self.d_star_sq)**2
         d2_u_iso_occ += wwo * dw * ff * e * mtps * self.d_star_sq
         d2_u_iso_fp += w * dw * e * mtps * self.d_star_sq
         d2_u_iso_fdp += 1j * w * dw * e * mtps * self.d_star_sq
       else:
         d2_u_star_u_star +=(w * dw * ff * e * mtps**2) \
           * u_star_gtmx.matrix_multiply_packed_u_multiply_lhs_transpose(
               d2_exp_huh_d_u_star_u_star)
         u_star_gtmx_d_exp_huh_d_u_star = u_star_gtmx.matrix_multiply(
           d_exp_huh_d_u_star)
         d2_u_star_occ += (wwo * dw * ff * e * mtps) \
           * u_star_gtmx_d_exp_huh_d_u_star
         d2_u_star_fp += (w * dw * e * mtps) \
           * u_star_gtmx_d_exp_huh_d_u_star
         d2_u_star_fdp += (w * dw * 1j * e * mtps) \
           * u_star_gtmx_d_exp_huh_d_u_star
       d2_occ_fp += wwo * dw * e
       d2_occ_fdp += wwo * dw * e * 1j
     if (site_symmetry_ops is None):
       i_u = 3
     else:
       i_u = site_constraints.n_independent_params()
     if (not scatterer.flags.use_u_aniso()):
       i_occ = i_u + 1
     elif (site_symmetry_ops is None):
       i_occ = i_u + 6
     else:
       i_occ = i_u + adp_constraints.n_independent_params()
     i_fp, i_fdp, np = i_occ+1, i_occ+2, i_occ+3
     if (site_symmetry_ops is not None):
       gsm = site_constraints.gradient_sum_matrix()
       d2_site_site = gsm.matrix_multiply_packed_u_multiply_lhs_transpose(
         packed_u=d2_site_site)
       if (not scatterer.flags.use_u_aniso()):
         d2_site_u_iso = gsm.matrix_multiply(d2_site_u_iso)
       else:
         d2_site_u_star = gsm.matrix_multiply(d2_site_u_star)
       d2_site_occ = gsm.matrix_multiply(d2_site_occ)
       d2_site_fp = gsm.matrix_multiply(d2_site_fp)
       d2_site_fdp = gsm.matrix_multiply(d2_site_fdp)
       if (scatterer.flags.use_u_aniso()):
         gsm = adp_constraints.gradient_sum_matrix()
         d2_site_u_star = d2_site_u_star.matrix_multiply(
           gsm.matrix_transpose())
         d2_u_star_u_star = gsm \
           .matrix_multiply_packed_u_multiply_lhs_transpose(
             packed_u=d2_u_star_u_star)
         d2_u_star_occ = gsm.matrix_multiply(d2_u_star_occ)
         d2_u_star_fp = gsm.matrix_multiply(d2_u_star_fp)
         d2_u_star_fdp = gsm.matrix_multiply(d2_u_star_fdp)
     dp = flex.complex_double(flex.grid(np,np), 0j)
     paste = dp.matrix_paste_block_in_place
     paste(d2_site_site.matrix_packed_u_as_symmetric(), 0,0)
     if (not scatterer.flags.use_u_aniso()):
       paste(d2_site_u_iso, 0,i_u)
       paste(d2_site_u_iso.matrix_transpose(), i_u,0)
     else:
       paste(d2_site_u_star, 0,i_u)
       paste(d2_site_u_star.matrix_transpose(), i_u,0)
     paste(d2_site_occ, 0,i_occ)
     paste(d2_site_occ.matrix_transpose(), i_occ,0)
     paste(d2_site_fp, 0,i_fp)
     paste(d2_site_fp.matrix_transpose(), i_fp,0)
     paste(d2_site_fdp, 0,i_fdp)
     paste(d2_site_fdp.matrix_transpose(), i_fdp,0)
     if (not scatterer.flags.use_u_aniso()):
       dp[i_u*np+i_u] = d2_u_iso_u_iso
       dp[i_u*np+i_occ] = d2_u_iso_occ
       dp[i_occ*np+i_u] = d2_u_iso_occ
       dp[i_u*np+i_fp] = d2_u_iso_fp
       dp[i_fp*np+i_u] = d2_u_iso_fp
       dp[i_u*np+i_fdp] = d2_u_iso_fdp
       dp[i_fdp*np+i_u] = d2_u_iso_fdp
     else:
       paste(d2_u_star_u_star.matrix_packed_u_as_symmetric(), i_u, i_u)
       paste(d2_u_star_occ, i_u, i_occ)
       paste(d2_u_star_occ.matrix_transpose(), i_occ, i_u)
       paste(d2_u_star_fp, i_u, i_fp)
       paste(d2_u_star_fp.matrix_transpose(), i_fp, i_u)
       paste(d2_u_star_fdp, i_u, i_fdp)
       paste(d2_u_star_fdp.matrix_transpose(), i_fdp, i_u)
     dp[i_occ*np+i_fp] = d2_occ_fp
     dp[i_fp*np+i_occ] = d2_occ_fp
     dp[i_occ*np+i_fdp] = d2_occ_fdp
     dp[i_fdp*np+i_occ] = d2_occ_fdp
     yield dp