コード例 #1
0
def efs_force(bond_array_1, c1, etypes1, bond_array_2, c2, etypes2, sig, ls,
              r_cut, cutoff_func):

    energy_kernels = np.zeros(3)
    force_kernels = np.zeros((3, 3))
    stress_kernels = np.zeros((6, 3))

    ls1 = 1 / (2 * ls * ls)
    ls2 = 1 / (ls * ls)
    ls3 = ls2 * ls2
    sig2 = sig * sig

    for m in range(bond_array_1.shape[0]):
        ri = bond_array_1[m, 0]
        fi, _ = cutoff_func(r_cut, ri, 0)
        e1 = etypes1[m]

        for n in range(bond_array_2.shape[0]):
            e2 = etypes2[n]

            # check if bonds agree
            if (c1 == c2 and e1 == e2) or (c1 == e2 and c2 == e1):
                rj = bond_array_2[n, 0]
                fj, _ = cutoff_func(r_cut, rj, 0)
                r11 = ri - rj
                D = r11 * r11

                for d1 in range(3):
                    cj = bond_array_2[n, d1 + 1]
                    _, fdj = cutoff_func(r_cut, rj, cj)

                    C = r11 * cj

                    energy_kernels[d1] += \
                        force_energy_helper(-C, D, fj, fi, fdj, ls1, ls2,
                                            sig2) / 2

                    stress_count = 0
                    for d3 in range(3):
                        ci = bond_array_1[m, d3 + 1]
                        _, fdi = cutoff_func(r_cut, ri, ci)
                        A = ci * cj
                        B = r11 * ci

                        force_kern = \
                            force_helper(A, B, C, D, fi, fj, fdi, fdj,
                                         ls1, ls2, ls3, sig2)
                        force_kernels[d3, d1] += force_kern

                        for d2 in range(d3, 3):
                            coordinate = bond_array_1[m, d2 + 1] * ri
                            stress_kernels[stress_count, d1] -= \
                                force_kern * coordinate / 2

                            stress_count += 1

    return energy_kernels, force_kernels, stress_kernels
コード例 #2
0
def efs_self(bond_array_1, c1, etypes1, sig, ls, r_cut, cutoff_func):

    energy_kernel = 0
    force_kernels = np.zeros(3)
    stress_kernels = np.zeros(6)

    ls1 = 1 / (2 * ls * ls)
    ls2 = 1 / (ls * ls)
    ls3 = ls2 * ls2
    sig2 = sig * sig

    for m in range(bond_array_1.shape[0]):
        ri = bond_array_1[m, 0]
        fi, _ = cutoff_func(r_cut, ri, 0)
        e1 = etypes1[m]

        for n in range(bond_array_1.shape[0]):
            e2 = etypes1[n]

            # check if bonds agree
            if (e1 == e2) or (c1 == e2 and c1 == e1):
                rj = bond_array_1[n, 0]
                fj, _ = cutoff_func(r_cut, rj, 0)
                r11 = ri - rj
                D = r11 * r11

                energy_kernel += fi * fj * sig2 * exp(-D * ls1) / 4

                stress_count = 0
                for d1 in range(3):
                    cj = bond_array_1[n, d1 + 1]
                    _, fdj = cutoff_func(r_cut, rj, cj)
                    C = r11 * cj

                    ci = bond_array_1[m, d1 + 1]
                    _, fdi = cutoff_func(r_cut, ri, ci)
                    A = ci * cj
                    B = r11 * ci

                    force_kern = \
                        force_helper(A, B, C, D, fi, fj, fdi, fdj,
                                     ls1, ls2, ls3, sig2)
                    force_kernels[d1] += force_kern

                    for d2 in range(d1, 3):
                        coord1 = bond_array_1[m, d2 + 1] * ri
                        coord2 = bond_array_1[n, d2 + 1] * rj
                        stress_kernels[stress_count] += \
                            force_kern * coord1 * coord2 / 4

                        stress_count += 1

    return energy_kernel, force_kernels, stress_kernels
コード例 #3
0
def self_two_body_mc_jit(bond_array, c, etypes,
                    d, sig, ls, r_cut, cutoff_func):

    """Multicomponent two-body force/force kernel accelerated with Numba's
    njit decorator.

    Loops over bonds in two environments and adds to the kernel if bonds are
    of the same type.
    """

    kern = 0

    ls1 = 1 / (2 * ls * ls)
    ls2 = 1 / (ls * ls)
    ls3 = ls2 * ls2
    sig2 = sig * sig

    for m in range(bond_array.shape[0]):
        ri = bond_array[m, 0]
        ci = bond_array[m, d]
        fi, fdi = cutoff_func(r_cut, ri, ci)
        e1 = etypes[m]

        for n in range(m, bond_array.shape[0]):
            e2 = etypes[n]

            # check if bonds agree
            if (c == c and e1 == e2) or (c == e2 and c == e1):
                rj = bond_array[n, 0]
                cj = bond_array[n, d]
                fj, fdj = cutoff_func(r_cut, rj, cj)
                r11 = ri - rj

                A = ci * cj
                B = r11 * ci
                C = r11 * cj
                D = r11 * r11

                kern0 = force_helper(A, B, C, D, fi, fj, fdi, fdj,
                                     ls1, ls2, ls3, sig2)
                kern += kern0 if m == n else 2 * kern0

    return kern
コード例 #4
0
def stress_stress(bond_array_1, c1, etypes1, bond_array_2, c2, etypes2, sig,
                  ls, r_cut, cutoff_func):
    """2-body multi-element kernel between two partial stress components
        accelerated with Numba.

    Args:
        bond_array_1 (np.ndarray): 2-body bond array of the first local
            environment.
        c1 (int): Species of the central atom of the first local environment.
        etypes1 (np.ndarray): Species of atoms in the first local
            environment.
        bond_array_2 (np.ndarray): 2-body bond array of the second local
            environment.
        c2 (int): Species of the central atom of the second local environment.
        etypes2 (np.ndarray): Species of atoms in the second local
            environment.
        sig (float): 2-body signal variance hyperparameter.
        ls (float): 2-body length scale hyperparameter.
        r_cut (float): 2-body cutoff radius.
        cutoff_func (Callable): Cutoff function.

    Return:
        float: Value of the 2-body kernel.
    """
    kernel_matrix = np.zeros((6, 6))

    ls1 = 1 / (2 * ls * ls)
    ls2 = 1 / (ls * ls)
    ls3 = ls2 * ls2
    sig2 = sig * sig

    for m in range(bond_array_1.shape[0]):
        ri = bond_array_1[m, 0]
        e1 = etypes1[m]

        for n in range(bond_array_2.shape[0]):
            e2 = etypes2[n]

            # check if bonds agree
            if (c1 == c2 and e1 == e2) or (c1 == e2 and c2 == e1):
                rj = bond_array_2[n, 0]
                r11 = ri - rj
                D = r11 * r11

                s1 = 0
                for d1 in range(3):
                    ci = bond_array_1[m, d1 + 1]
                    B = r11 * ci
                    fi, fdi = cutoff_func(r_cut, ri, ci)
                    for d2 in range(d1, 3):
                        coordinate_1 = bond_array_1[m, d2 + 1] * ri
                        s2 = 0
                        for d3 in range(3):
                            cj = bond_array_2[n, d3 + 1]
                            A = ci * cj
                            C = r11 * cj
                            fj, fdj = cutoff_func(r_cut, rj, cj)
                            for d4 in range(d3, 3):
                                coordinate_2 = bond_array_2[n, d4 + 1] * rj
                                force_kern = \
                                    force_helper(A, B, C, D, fi, fj, fdi, fdj,
                                                 ls1, ls2, ls3, sig2)
                                kernel_matrix[s1, s2] += \
                                    force_kern * coordinate_1 * \
                                    coordinate_2

                                s2 += 1
                        s1 += 1

    return kernel_matrix / 4
コード例 #5
0
def force_force(bond_array_1, c1, etypes1, bond_array_2, c2, etypes2, sig, ls,
                r_cut, cutoff_func):
    """2-body multi-element kernel between two force components accelerated
    with Numba.

    Args:
        bond_array_1 (np.ndarray): 2-body bond array of the first local
            environment.
        c1 (int): Species of the central atom of the first local environment.
        etypes1 (np.ndarray): Species of atoms in the first local
            environment.
        bond_array_2 (np.ndarray): 2-body bond array of the second local
            environment.
        c2 (int): Species of the central atom of the second local environment.
        etypes2 (np.ndarray): Species of atoms in the second local
            environment.
        d1 (int): Force component of the first environment (1=x, 2=y, 3=z).
        d2 (int): Force component of the second environment (1=x, 2=y, 3=z).
        sig (float): 2-body signal variance hyperparameter.
        ls (float): 2-body length scale hyperparameter.
        r_cut (float): 2-body cutoff radius.
        cutoff_func (Callable): Cutoff function.

    Return:
        float: Value of the 2-body kernel.
    """
    kernel_matrix = np.zeros((3, 3))

    ls1 = 1 / (2 * ls * ls)
    ls2 = 1 / (ls * ls)
    ls3 = ls2 * ls2
    sig2 = sig * sig

    for m in range(bond_array_1.shape[0]):
        ri = bond_array_1[m, 0]
        e1 = etypes1[m]

        for n in range(bond_array_2.shape[0]):
            e2 = etypes2[n]

            # check if bonds agree
            if (c1 == c2 and e1 == e2) or (c1 == e2 and c2 == e1):
                rj = bond_array_2[n, 0]
                r11 = ri - rj
                D = r11 * r11

                # Note: Some redundancy here; can move this higher up.
                for d1 in range(3):
                    ci = bond_array_1[m, d1 + 1]
                    fi, fdi = cutoff_func(r_cut, ri, ci)

                    for d2 in range(3):
                        cj = bond_array_2[n, d2 + 1]
                        fj, fdj = cutoff_func(r_cut, rj, cj)

                        A = ci * cj
                        B = r11 * ci
                        C = r11 * cj

                        kernel_matrix[d1, d2] += \
                            force_helper(A, B, C, D, fi, fj, fdi, fdj,
                                         ls1, ls2, ls3, sig2)

    return kernel_matrix