예제 #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 force_energy(bond_array_1, c1, etypes1, bond_array_2, c2, etypes2, sig, ls,
                 r_cut, cutoff_func):
    """2-body multi-element kernel between a force component and a local
    energy 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).
        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.

    Returns:
        float:
            Value of the 2-body force/energy kernel.
    """

    kern = np.zeros(3)

    ls1 = 1 / (2 * ls * ls)
    ls2 = 1 / (ls * ls)
    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 species 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):
                    ci = bond_array_1[m, d1 + 1]
                    fi, fdi = cutoff_func(r_cut, ri, ci)
                    B = r11 * ci
                    kern[d1] += \
                        force_energy_helper(B, D, fi, fj, fdi, ls1, ls2,
                                            sig2)

    return kern / 2
예제 #3
0
def efs_energy(bond_array_1, c1, etypes1, bond_array_2, c2, etypes2, sig, ls,
               r_cut, cutoff_func):

    energy_kernel = 0
    # TODO: add dtype to other zeros
    force_kernels = np.zeros(3)
    stress_kernels = np.zeros(6)

    ls1 = 1 / (2 * ls * ls)
    ls2 = 1 / (ls * ls)
    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 the species 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

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

                # Compute the force kernel.
                stress_count = 0
                for d1 in range(3):
                    ci = bond_array_1[m, d1 + 1]
                    B = r11 * ci
                    _, fdi = cutoff_func(r_cut, ri, ci)
                    force_kern = \
                        force_energy_helper(B, D, fi, fj, fdi, ls1, ls2,
                                            sig2)
                    force_kernels[d1] += force_kern / 2

                    # Compute the stress kernel from the force kernel.
                    for d2 in range(d1, 3):
                        coordinate = bond_array_1[m, d2 + 1] * ri
                        stress_kernels[stress_count] -= \
                            force_kern * coordinate / 4
                        stress_count += 1

    return energy_kernel, force_kernels, stress_kernels
예제 #4
0
def stress_energy(bond_array_1, c1, etypes1, bond_array_2, c2, etypes2, sig,
                  ls, r_cut, cutoff_func):
    """2-body multi-element kernel between a partial stress component and a
    local energy 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.

    Returns:
        float:
            Value of the 2-body partial-stress/energy kernel.
    """

    kern = np.zeros(6)

    ls1 = 1 / (2 * ls * ls)
    ls2 = 1 / (ls * ls)
    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 the species 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

                # Compute the force kernel.
                stress_count = 0
                for d1 in range(3):
                    ci = bond_array_1[m, d1 + 1]
                    B = r11 * ci
                    fi, fdi = cutoff_func(r_cut, ri, ci)
                    force_kern = \
                        force_energy_helper(B, D, fi, fj, fdi, ls1, ls2,
                                            sig2)

                    # Compute the stress kernel from the force kernel.
                    for d2 in range(d1, 3):
                        coordinate = bond_array_1[m, d2 + 1] * ri
                        kern[stress_count] -= force_kern * coordinate
                        stress_count += 1

    return kern / 4